blob: f87da9a42091f1beb84f18285aa8c21e3df02d54 [file] [log] [blame]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
5from test import test_support
Bill Janssen934b16d2008-06-28 22:19:33 +00006import asyncore
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00007import socket
Bill Janssen934b16d2008-06-28 22:19:33 +00008import select
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00009import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000010import subprocess
11import time
Antoine Pitroud4030da2010-04-23 23:35:01 +000012import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import os
Antoine Pitroud4030da2010-04-23 23:35:01 +000014import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000016import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000017import shutil
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000018import traceback
Antoine Pitrou3df58d12010-04-23 23:07:37 +000019import weakref
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000020
Bill Janssen296a59d2007-09-16 22:06:00 +000021from BaseHTTPServer import HTTPServer
22from SimpleHTTPServer import SimpleHTTPRequestHandler
23
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000024# Optionally test SSL support, if we have it in the tested platform
25skip_expected = False
26try:
27 import ssl
28except ImportError:
29 skip_expected = True
30
Trent Nelsone41b0062008-04-08 23:47:30 +000031HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000032CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000033SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000034
Neal Norwitz3e533c22007-08-27 01:03:18 +000035def handle_error(prefix):
36 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000037 if test_support.verbose:
38 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000039
Antoine Pitrou77a1c362010-04-27 09:54:14 +000040
41class BasicTests(unittest.TestCase):
42
Bill Jansseneb257ac2008-09-29 18:56:38 +000043 def testSimpleSSLwrap(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +000044 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000045 try:
46 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
47 except IOError, e:
48 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
49 pass
50 else:
51 raise
52 try:
53 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
54 except IOError, e:
55 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
56 pass
57 else:
58 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000059
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000060 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000061 if not test_support.is_resource_enabled('network'):
62 return
Bill Janssen296a59d2007-09-16 22:06:00 +000063 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
64 cert_reqs=ssl.CERT_NONE)
65 s.connect(("svn.python.org", 443))
66 c = s.getpeercert()
67 if c:
68 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
69 s.close()
70
71 # this should fail because we have no verification certs
72 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
73 cert_reqs=ssl.CERT_REQUIRED)
74 try:
75 s.connect(("svn.python.org", 443))
76 except ssl.SSLError:
77 pass
78 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000079 s.close()
80
Bill Janssen98d19da2007-09-10 21:51:02 +000081 def testCrucialConstants(self):
82 ssl.PROTOCOL_SSLv2
83 ssl.PROTOCOL_SSLv23
84 ssl.PROTOCOL_SSLv3
85 ssl.PROTOCOL_TLSv1
86 ssl.CERT_NONE
87 ssl.CERT_OPTIONAL
88 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000089
Bill Janssen98d19da2007-09-10 21:51:02 +000090 def testRAND(self):
91 v = ssl.RAND_status()
92 if test_support.verbose:
93 sys.stdout.write("\n RAND_status is %d (%s)\n"
94 % (v, (v and "sufficient randomness") or
95 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000096 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000097 ssl.RAND_egd(1)
98 except TypeError:
99 pass
Guido van Rossume4729332007-08-26 19:35:09 +0000100 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 print "didn't raise TypeError"
102 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000103
Bill Janssen98d19da2007-09-10 21:51:02 +0000104 def testParseCert(self):
105 # note that this uses an 'unofficial' function in _ssl.c,
106 # provided solely for this test, to exercise the certificate
107 # parsing code
108 p = ssl._ssl._test_decode_cert(CERTFILE, False)
109 if test_support.verbose:
110 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000111
Bill Janssen296a59d2007-09-16 22:06:00 +0000112 def testDERtoPEM(self):
113
114 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
115 d1 = ssl.PEM_cert_to_DER_cert(pem)
116 p2 = ssl.DER_cert_to_PEM_cert(d1)
117 d2 = ssl.PEM_cert_to_DER_cert(p2)
118 if (d1 != d2):
119 raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
120
Antoine Pitrou3df58d12010-04-23 23:07:37 +0000121 def test_refcycle(self):
122 # Issue #7943: an SSL object doesn't create reference cycles with
123 # itself.
124 s = socket.socket(socket.AF_INET)
125 ss = ssl.wrap_socket(s)
126 wr = weakref.ref(ss)
127 del ss
128 self.assertEqual(wr(), None)
129
Antoine Pitroud4030da2010-04-23 23:35:01 +0000130
Bill Janssen934b16d2008-06-28 22:19:33 +0000131class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000132
133 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000134 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
135 cert_reqs=ssl.CERT_NONE)
136 s.connect(("svn.python.org", 443))
137 c = s.getpeercert()
138 if c:
139 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
140 s.close()
141
142 # this should fail because we have no verification certs
143 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
144 cert_reqs=ssl.CERT_REQUIRED)
145 try:
146 s.connect(("svn.python.org", 443))
147 except ssl.SSLError:
148 pass
149 finally:
150 s.close()
151
152 # this should succeed because we specify the root cert
153 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
154 cert_reqs=ssl.CERT_REQUIRED,
155 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
156 try:
157 s.connect(("svn.python.org", 443))
158 except ssl.SSLError, x:
159 raise test_support.TestFailed("Unexpected exception %s" % x)
160 finally:
161 s.close()
162
Antoine Pitrou0753d942010-04-24 11:09:52 +0000163 def test_makefile_close(self):
164 # Issue #5238: creating a file-like object with makefile() shouldn't
165 # delay closing the underlying "real socket" (here tested with its
166 # file descriptor, hence skipping the test under Windows).
167 if os.name == "nt":
168 if test_support.verbose:
169 print "Skipped: can't use a socket as a file under Windows"
170 return
171 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
172 ss.connect(("svn.python.org", 443))
173 fd = ss.fileno()
174 f = ss.makefile()
175 f.close()
176 # The fd is still open
177 os.read(fd, 0)
178 # Closing the SSL socket should close the fd too
179 ss.close()
180 gc.collect()
181 try:
182 os.read(fd, 0)
183 except OSError, e:
184 self.assertEqual(e.errno, errno.EBADF)
185 else:
186 self.fail("OSError wasn't raised")
Bill Janssen934b16d2008-06-28 22:19:33 +0000187
188 def testNonBlockingHandshake(self):
189 s = socket.socket(socket.AF_INET)
190 s.connect(("svn.python.org", 443))
191 s.setblocking(False)
192 s = ssl.wrap_socket(s,
193 cert_reqs=ssl.CERT_NONE,
194 do_handshake_on_connect=False)
195 count = 0
196 while True:
197 try:
198 count += 1
199 s.do_handshake()
200 break
201 except ssl.SSLError, err:
202 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
203 select.select([s], [], [])
204 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
205 select.select([], [s], [])
206 else:
207 raise
208 s.close()
209 if test_support.verbose:
210 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
211
Bill Janssen296a59d2007-09-16 22:06:00 +0000212 def testFetchServerCert(self):
213
214 pem = ssl.get_server_certificate(("svn.python.org", 443))
215 if not pem:
216 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
217
218 try:
219 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
220 except ssl.SSLError:
221 #should fail
222 pass
223 else:
224 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
225
226 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
227 if not pem:
228 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
229 if test_support.verbose:
230 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
231
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000232 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000233 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000234 if test_support.verbose:
235 sys.stdout.write("test_algorithms disabled, "
236 "as it fails on some old OpenSSL versions")
237 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000238 # Issue #8484: all algorithms should be available when verifying a
239 # certificate.
240 # NOTE: https://sha256.tbs-internet.com is another possible test host
241 remote = ("sha2.hboeck.de", 443)
242 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
243 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
244 cert_reqs=ssl.CERT_REQUIRED,
245 ca_certs=sha256_cert,)
246 with test_support.transient_internet():
247 try:
248 s.connect(remote)
249 if test_support.verbose:
250 sys.stdout.write("\nCipher with %r is %r\n" %
251 (remote, s.cipher()))
252 sys.stdout.write("Certificate is:\n%s\n" %
253 pprint.pformat(s.getpeercert()))
254 finally:
255 s.close()
256
Bill Janssen296a59d2007-09-16 22:06:00 +0000257
Bill Janssen98d19da2007-09-10 21:51:02 +0000258try:
259 import threading
260except ImportError:
261 _have_threads = False
262else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000263
Bill Janssen98d19da2007-09-10 21:51:02 +0000264 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000265
Bill Janssen98d19da2007-09-10 21:51:02 +0000266 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000267
Bill Janssen98d19da2007-09-10 21:51:02 +0000268 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000269
Bill Janssen98d19da2007-09-10 21:51:02 +0000270 """A mildly complicated class, because we want it to work both
271 with and without the SSL wrapper around the socket connection, so
272 that we can test the STARTTLS functionality."""
273
274 def __init__(self, server, connsock):
275 self.server = server
276 self.running = False
277 self.sock = connsock
278 self.sock.setblocking(1)
279 self.sslconn = None
280 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000281 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000282
Bill Janssen934b16d2008-06-28 22:19:33 +0000283 def show_conn_details(self):
284 if self.server.certreqs == ssl.CERT_REQUIRED:
285 cert = self.sslconn.getpeercert()
286 if test_support.verbose and self.server.chatty:
287 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
288 cert_binary = self.sslconn.getpeercert(True)
289 if test_support.verbose and self.server.chatty:
290 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
291 cipher = self.sslconn.cipher()
292 if test_support.verbose and self.server.chatty:
293 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
294
Bill Janssen98d19da2007-09-10 21:51:02 +0000295 def wrap_conn (self):
296 try:
297 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
298 certfile=self.server.certificate,
299 ssl_version=self.server.protocol,
300 ca_certs=self.server.cacerts,
301 cert_reqs=self.server.certreqs)
302 except:
303 if self.server.chatty:
304 handle_error("\n server: bad connection attempt from " +
305 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000306 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000307 if not self.server.expect_bad_connects:
308 # here, we want to stop the server, because this shouldn't
309 # happen in the context of our test case
310 self.running = False
311 # normally, we'd just stop here, but for the test
312 # harness, we want to stop the server
313 self.server.stop()
314 return False
315
316 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000317 return True
318
319 def read(self):
320 if self.sslconn:
321 return self.sslconn.read()
322 else:
323 return self.sock.recv(1024)
324
325 def write(self, bytes):
326 if self.sslconn:
327 return self.sslconn.write(bytes)
328 else:
329 return self.sock.send(bytes)
330
331 def close(self):
332 if self.sslconn:
333 self.sslconn.close()
334 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000335 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000336
337 def run (self):
338 self.running = True
339 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000340 if isinstance(self.sock, ssl.SSLSocket):
341 self.sslconn = self.sock
342 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000343 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000344 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000345 while self.running:
346 try:
347 msg = self.read()
348 if not msg:
349 # eof, so quit this handler
350 self.running = False
351 self.close()
352 elif msg.strip() == 'over':
353 if test_support.verbose and self.server.connectionchatty:
354 sys.stdout.write(" server: client closed connection\n")
355 self.close()
356 return
357 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
358 if test_support.verbose and self.server.connectionchatty:
359 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
360 self.write("OK\n")
361 if not self.wrap_conn():
362 return
Bill Janssen39295c22008-08-12 16:31:21 +0000363 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
364 if test_support.verbose and self.server.connectionchatty:
365 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
366 self.write("OK\n")
367 self.sslconn.unwrap()
368 self.sslconn = None
369 if test_support.verbose and self.server.connectionchatty:
370 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000371 else:
372 if (test_support.verbose and
373 self.server.connectionchatty):
374 ctype = (self.sslconn and "encrypted") or "unencrypted"
375 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
376 % (repr(msg), ctype, repr(msg.lower()), ctype))
377 self.write(msg.lower())
378 except ssl.SSLError:
379 if self.server.chatty:
380 handle_error("Test server failure:\n")
381 self.close()
382 self.running = False
383 # normally, we'd just stop here, but for the test
384 # harness, we want to stop the server
385 self.server.stop()
386 except:
387 handle_error('')
388
Trent Nelsone41b0062008-04-08 23:47:30 +0000389 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000390 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000391 chatty=True, connectionchatty=False, starttls_server=False,
392 wrap_accepting_socket=False):
393
Bill Janssen98d19da2007-09-10 21:51:02 +0000394 if ssl_version is None:
395 ssl_version = ssl.PROTOCOL_TLSv1
396 if certreqs is None:
397 certreqs = ssl.CERT_NONE
398 self.certificate = certificate
399 self.protocol = ssl_version
400 self.certreqs = certreqs
401 self.cacerts = cacerts
402 self.expect_bad_connects = expect_bad_connects
403 self.chatty = chatty
404 self.connectionchatty = connectionchatty
405 self.starttls_server = starttls_server
406 self.sock = socket.socket()
407 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000408 if wrap_accepting_socket:
409 self.sock = ssl.wrap_socket(self.sock, server_side=True,
410 certfile=self.certificate,
411 cert_reqs = self.certreqs,
412 ca_certs = self.cacerts,
413 ssl_version = self.protocol)
414 if test_support.verbose and self.chatty:
415 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
416 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000417 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000418 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000419 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000420
421 def start (self, flag=None):
422 self.flag = flag
423 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000424
425 def run (self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000426 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000427 self.sock.listen(5)
428 self.active = True
429 if self.flag:
430 # signal an event
431 self.flag.set()
432 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000433 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000434 newconn, connaddr = self.sock.accept()
435 if test_support.verbose and self.chatty:
436 sys.stdout.write(' server: new connection from '
437 + str(connaddr) + '\n')
438 handler = self.ConnectionHandler(self, newconn)
439 handler.start()
440 except socket.timeout:
441 pass
442 except KeyboardInterrupt:
443 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000444 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000445 if self.chatty:
446 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000447 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000448
Bill Janssen98d19da2007-09-10 21:51:02 +0000449 def stop (self):
450 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000451
Bill Janssen934b16d2008-06-28 22:19:33 +0000452 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000453
Bill Janssen934b16d2008-06-28 22:19:33 +0000454 class EchoServer (asyncore.dispatcher):
455
456 class ConnectionHandler (asyncore.dispatcher_with_send):
457
458 def __init__(self, conn, certfile):
459 asyncore.dispatcher_with_send.__init__(self, conn)
460 self.socket = ssl.wrap_socket(conn, server_side=True,
461 certfile=certfile,
Antoine Pitrouc689d962010-04-24 20:13:37 +0000462 do_handshake_on_connect=False)
463 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000464
465 def readable(self):
466 if isinstance(self.socket, ssl.SSLSocket):
467 while self.socket.pending() > 0:
468 self.handle_read_event()
469 return True
470
Antoine Pitrouc689d962010-04-24 20:13:37 +0000471 def _do_ssl_handshake(self):
472 try:
473 self.socket.do_handshake()
474 except ssl.SSLError, err:
475 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
476 ssl.SSL_ERROR_WANT_WRITE):
477 return
478 elif err.args[0] == ssl.SSL_ERROR_EOF:
479 return self.handle_close()
480 raise
481 except socket.error, err:
482 if err.args[0] == errno.ECONNABORTED:
483 return self.handle_close()
484 else:
485 self._ssl_accepting = False
486
Bill Janssen934b16d2008-06-28 22:19:33 +0000487 def handle_read(self):
Antoine Pitrouc689d962010-04-24 20:13:37 +0000488 if self._ssl_accepting:
489 self._do_ssl_handshake()
490 else:
491 data = self.recv(1024)
492 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000493
494 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000495 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000496 if test_support.verbose:
497 sys.stdout.write(" server: closed connection %s\n" % self.socket)
498
499 def handle_error(self):
500 raise
501
502 def __init__(self, certfile):
503 self.certfile = certfile
504 asyncore.dispatcher.__init__(self)
505 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
506 self.port = test_support.bind_port(self.socket)
507 self.listen(5)
508
509 def handle_accept(self):
510 sock_obj, addr = self.accept()
511 if test_support.verbose:
512 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
513 self.ConnectionHandler(sock_obj, self.certfile)
514
515 def handle_error(self):
516 raise
517
518 def __init__(self, certfile):
519 self.flag = None
520 self.active = False
521 self.server = self.EchoServer(certfile)
522 self.port = self.server.port
523 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000524 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000525
526 def __str__(self):
527 return "<%s %s>" % (self.__class__.__name__, self.server)
528
529 def start (self, flag=None):
530 self.flag = flag
531 threading.Thread.start(self)
532
533 def run (self):
534 self.active = True
535 if self.flag:
536 self.flag.set()
537 while self.active:
538 try:
539 asyncore.loop(1)
540 except:
541 pass
542
543 def stop (self):
544 self.active = False
545 self.server.close()
546
547 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000548
549 class HTTPSServer(HTTPServer):
550
551 def __init__(self, server_address, RequestHandlerClass, certfile):
552
553 HTTPServer.__init__(self, server_address, RequestHandlerClass)
554 # we assume the certfile contains both private key and certificate
555 self.certfile = certfile
556 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000557 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000558 self.allow_reuse_address = True
559
Bill Janssen934b16d2008-06-28 22:19:33 +0000560 def __str__(self):
561 return ('<%s %s:%s>' %
562 (self.__class__.__name__,
563 self.server_name,
564 self.server_port))
565
Bill Janssen296a59d2007-09-16 22:06:00 +0000566 def get_request (self):
567 # override this to wrap socket with SSL
568 sock, addr = self.socket.accept()
569 sslconn = ssl.wrap_socket(sock, server_side=True,
570 certfile=self.certfile)
571 return sslconn, addr
572
Bill Janssen296a59d2007-09-16 22:06:00 +0000573 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
574
575 # need to override translate_path to get a known root,
576 # instead of using os.curdir, since the test could be
577 # run from anywhere
578
579 server_version = "TestHTTPS/1.0"
580
581 root = None
582
583 def translate_path(self, path):
584 """Translate a /-separated PATH to the local filename syntax.
585
586 Components that mean special things to the local file system
587 (e.g. drive or directory names) are ignored. (XXX They should
588 probably be diagnosed.)
589
590 """
591 # abandon query parameters
592 path = urlparse.urlparse(path)[2]
593 path = os.path.normpath(urllib.unquote(path))
594 words = path.split('/')
595 words = filter(None, words)
596 path = self.root
597 for word in words:
598 drive, word = os.path.splitdrive(word)
599 head, word = os.path.split(word)
600 if word in self.root: continue
601 path = os.path.join(path, word)
602 return path
603
604 def log_message(self, format, *args):
605
606 # we override this to suppress logging unless "verbose"
607
608 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000609 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
610 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000611 self.server.server_port,
612 self.request.cipher(),
613 self.log_date_time_string(),
614 format%args))
615
616
Trent Nelsone41b0062008-04-08 23:47:30 +0000617 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000618 self.flag = None
619 self.active = False
620 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
621 self.server = self.HTTPSServer(
Antoine Pitrou6535b312010-04-27 08:43:11 +0000622 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
623 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000624 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000625 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000626
627 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000628 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000629
630 def start (self, flag=None):
631 self.flag = flag
632 threading.Thread.start(self)
633
634 def run (self):
635 self.active = True
636 if self.flag:
637 self.flag.set()
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000638 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000639 self.active = False
640
641 def stop (self):
642 self.active = False
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000643 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000644
645
Bill Janssen98d19da2007-09-10 21:51:02 +0000646 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000647 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000648 certreqs=ssl.CERT_REQUIRED,
649 cacerts=CERTFILE, chatty=False)
650 flag = threading.Event()
651 server.start(flag)
652 # wait for it to start
653 flag.wait()
654 # try to connect
655 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000656 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000657 s = ssl.wrap_socket(socket.socket(),
658 certfile=certfile,
659 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000660 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000661 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000662 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000663 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000664 except socket.error, x:
665 if test_support.verbose:
666 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000667 else:
668 raise test_support.TestFailed(
669 "Use of invalid cert should have failed!")
670 finally:
671 server.stop()
672 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000673
Bill Janssen98d19da2007-09-10 21:51:02 +0000674 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
675 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000676 chatty=True, connectionchatty=False,
677 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000678
Trent Nelsone41b0062008-04-08 23:47:30 +0000679 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000680 certreqs=certreqs,
681 ssl_version=protocol,
682 cacerts=cacertsfile,
683 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000684 connectionchatty=connectionchatty,
685 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000686 flag = threading.Event()
687 server.start(flag)
688 # wait for it to start
689 flag.wait()
690 # try to connect
691 if client_protocol is None:
692 client_protocol = protocol
693 try:
694 try:
695 s = ssl.wrap_socket(socket.socket(),
696 certfile=client_certfile,
697 ca_certs=cacertsfile,
698 cert_reqs=certreqs,
699 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000700 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000701 except ssl.SSLError, x:
702 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
703 except Exception, x:
704 raise test_support.TestFailed("Unexpected exception: " + str(x))
705 else:
706 if connectionchatty:
707 if test_support.verbose:
708 sys.stdout.write(
709 " client: sending %s...\n" % (repr(indata)))
710 s.write(indata)
711 outdata = s.read()
712 if connectionchatty:
713 if test_support.verbose:
714 sys.stdout.write(" client: read %s\n" % repr(outdata))
715 if outdata != indata.lower():
716 raise test_support.TestFailed(
717 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
718 % (outdata[:min(len(outdata),20)], len(outdata),
719 indata[:min(len(indata),20)].lower(), len(indata)))
720 s.write("over\n")
721 if connectionchatty:
722 if test_support.verbose:
723 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000724 s.close()
725 finally:
726 server.stop()
727 server.join()
728
729 def tryProtocolCombo (server_protocol,
730 client_protocol,
731 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000732 certsreqs=None):
733
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000734 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000735 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000736
737 if certsreqs == ssl.CERT_NONE:
738 certtype = "CERT_NONE"
739 elif certsreqs == ssl.CERT_OPTIONAL:
740 certtype = "CERT_OPTIONAL"
741 elif certsreqs == ssl.CERT_REQUIRED:
742 certtype = "CERT_REQUIRED"
743 if test_support.verbose:
744 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
745 sys.stdout.write(formatstr %
746 (ssl.get_protocol_name(client_protocol),
747 ssl.get_protocol_name(server_protocol),
748 certtype))
749 try:
750 serverParamsTest(CERTFILE, server_protocol, certsreqs,
751 CERTFILE, CERTFILE, client_protocol, chatty=False)
752 except test_support.TestFailed:
753 if expectedToWork:
754 raise
755 else:
756 if not expectedToWork:
757 raise test_support.TestFailed(
758 "Client protocol %s succeeded with server protocol %s!"
759 % (ssl.get_protocol_name(client_protocol),
760 ssl.get_protocol_name(server_protocol)))
761
762
Bill Janssen934b16d2008-06-28 22:19:33 +0000763 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000764
765 def testRudeShutdown(self):
766
767 listener_ready = threading.Event()
768 listener_gone = threading.Event()
769
Antoine Pitrou6535b312010-04-27 08:43:11 +0000770 s = socket.socket()
771 port = test_support.bind_port(s, HOST)
772
773 # `listener` runs in a thread. It sits in an accept() until
774 # the main thread connects. Then it rudely closes the socket,
775 # and sets Event `listener_gone` to let the main thread know
776 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000777 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000778 s.listen(5)
779 listener_ready.set()
780 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000781 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000782 listener_gone.set()
783
784 def connector():
785 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000786 c = socket.socket()
787 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000788 listener_gone.wait()
789 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000790 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000791 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000792 pass
793 else:
794 raise test_support.TestFailed(
795 'connecting to closed SSL socket should have failed')
796
797 t = threading.Thread(target=listener)
798 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000799 try:
800 connector()
801 finally:
802 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000803
804 def testEcho (self):
805
806 if test_support.verbose:
807 sys.stdout.write("\n")
808 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
809 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
810 chatty=True, connectionchatty=True)
811
812 def testReadCert(self):
813
814 if test_support.verbose:
815 sys.stdout.write("\n")
816 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000817 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000818 certreqs=ssl.CERT_NONE,
819 ssl_version=ssl.PROTOCOL_SSLv23,
820 cacerts=CERTFILE,
821 chatty=False)
822 flag = threading.Event()
823 server.start(flag)
824 # wait for it to start
825 flag.wait()
826 # try to connect
827 try:
828 try:
829 s = ssl.wrap_socket(socket.socket(),
830 certfile=CERTFILE,
831 ca_certs=CERTFILE,
832 cert_reqs=ssl.CERT_REQUIRED,
833 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000834 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000835 except ssl.SSLError, x:
836 raise test_support.TestFailed(
837 "Unexpected SSL error: " + str(x))
838 except Exception, x:
839 raise test_support.TestFailed(
840 "Unexpected exception: " + str(x))
841 else:
842 if not s:
843 raise test_support.TestFailed(
844 "Can't SSL-handshake with test server")
845 cert = s.getpeercert()
846 if not cert:
847 raise test_support.TestFailed(
848 "Can't get peer certificate.")
849 cipher = s.cipher()
850 if test_support.verbose:
851 sys.stdout.write(pprint.pformat(cert) + '\n')
852 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
853 if not cert.has_key('subject'):
854 raise test_support.TestFailed(
855 "No subject field in certificate: %s." %
856 pprint.pformat(cert))
857 if ((('organizationName', 'Python Software Foundation'),)
858 not in cert['subject']):
859 raise test_support.TestFailed(
860 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000861 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000862 s.close()
863 finally:
864 server.stop()
865 server.join()
866
867 def testNULLcert(self):
868 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
869 "nullcert.pem"))
870 def testMalformedCert(self):
871 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
872 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000873 def testWrongCert(self):
874 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
875 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000876 def testMalformedKey(self):
877 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
878 "badkey.pem"))
879
880 def testProtocolSSL2(self):
881 if test_support.verbose:
882 sys.stdout.write("\n")
883 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
884 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
885 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
886 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
887 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
888 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
889
890 def testProtocolSSL23(self):
891 if test_support.verbose:
892 sys.stdout.write("\n")
893 try:
894 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
895 except test_support.TestFailed, x:
896 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
897 if test_support.verbose:
898 sys.stdout.write(
899 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
900 % str(x))
901 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
902 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
903 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
904
905 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
906 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
907 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
908
909 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
910 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
911 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
912
913 def testProtocolSSL3(self):
914 if test_support.verbose:
915 sys.stdout.write("\n")
916 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
917 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
918 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
919 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
920 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
921 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
922
923 def testProtocolTLS1(self):
924 if test_support.verbose:
925 sys.stdout.write("\n")
926 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
927 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
928 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
929 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
930 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
931 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
932
933 def testSTARTTLS (self):
934
Bill Janssen39295c22008-08-12 16:31:21 +0000935 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000936
Trent Nelsone41b0062008-04-08 23:47:30 +0000937 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000938 ssl_version=ssl.PROTOCOL_TLSv1,
939 starttls_server=True,
940 chatty=True,
941 connectionchatty=True)
942 flag = threading.Event()
943 server.start(flag)
944 # wait for it to start
945 flag.wait()
946 # try to connect
947 wrapped = False
948 try:
949 try:
950 s = socket.socket()
951 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000952 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000953 except Exception, x:
954 raise test_support.TestFailed("Unexpected exception: " + str(x))
955 else:
956 if test_support.verbose:
957 sys.stdout.write("\n")
958 for indata in msgs:
959 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000960 sys.stdout.write(
961 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000962 if wrapped:
963 conn.write(indata)
964 outdata = conn.read()
965 else:
966 s.send(indata)
967 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +0000968 if (indata == "STARTTLS" and
969 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000970 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000971 sys.stdout.write(
972 " client: read %s from server, starting TLS...\n"
973 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000974 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000975 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +0000976 elif (indata == "ENDTLS" and
977 outdata.strip().lower().startswith("ok")):
978 if test_support.verbose:
979 sys.stdout.write(
980 " client: read %s from server, ending TLS...\n"
981 % repr(outdata))
982 s = conn.unwrap()
983 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000984 else:
985 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000986 sys.stdout.write(
987 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000988 if test_support.verbose:
989 sys.stdout.write(" client: closing connection.\n")
990 if wrapped:
991 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000992 else:
993 s.send("over\n")
994 s.close()
995 finally:
996 server.stop()
997 server.join()
998
Bill Janssen934b16d2008-06-28 22:19:33 +0000999 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001000
Bill Janssen934b16d2008-06-28 22:19:33 +00001001 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001002 flag = threading.Event()
1003 server.start(flag)
1004 # wait for it to start
1005 flag.wait()
1006 # try to connect
1007 try:
1008 if test_support.verbose:
1009 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001010 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001011 d2 = ''
1012 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001013 url = 'https://127.0.0.1:%d/%s' % (
1014 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +00001015 f = urllib.urlopen(url)
1016 dlen = f.info().getheader("content-length")
1017 if dlen and (int(dlen) > 0):
1018 d2 = f.read(int(dlen))
1019 if test_support.verbose:
1020 sys.stdout.write(
1021 " client: read %d bytes from remote server '%s'\n"
1022 % (len(d2), server))
1023 f.close()
1024 except:
1025 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1026 if test_support.verbose:
1027 sys.stdout.write('\n' + msg)
1028 raise test_support.TestFailed(msg)
1029 else:
1030 if not (d1 == d2):
1031 raise test_support.TestFailed(
1032 "Couldn't fetch data from HTTPS server")
1033 finally:
1034 server.stop()
1035 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001036
Bill Janssen934b16d2008-06-28 22:19:33 +00001037 def testWrappedAccept (self):
1038
1039 if test_support.verbose:
1040 sys.stdout.write("\n")
1041 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1042 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1043 chatty=True, connectionchatty=True,
1044 wrap_accepting_socket=True)
1045
1046
1047 def testAsyncoreServer (self):
1048
1049 indata = "TEST MESSAGE of mixed case\n"
1050
1051 if test_support.verbose:
1052 sys.stdout.write("\n")
1053 server = AsyncoreEchoServer(CERTFILE)
1054 flag = threading.Event()
1055 server.start(flag)
1056 # wait for it to start
1057 flag.wait()
1058 # try to connect
1059 try:
1060 try:
1061 s = ssl.wrap_socket(socket.socket())
1062 s.connect(('127.0.0.1', server.port))
1063 except ssl.SSLError, x:
1064 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1065 except Exception, x:
1066 raise test_support.TestFailed("Unexpected exception: " + str(x))
1067 else:
1068 if test_support.verbose:
1069 sys.stdout.write(
1070 " client: sending %s...\n" % (repr(indata)))
1071 s.write(indata)
1072 outdata = s.read()
1073 if test_support.verbose:
1074 sys.stdout.write(" client: read %s\n" % repr(outdata))
1075 if outdata != indata.lower():
1076 raise test_support.TestFailed(
1077 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1078 % (outdata[:min(len(outdata),20)], len(outdata),
1079 indata[:min(len(indata),20)].lower(), len(indata)))
1080 s.write("over\n")
1081 if test_support.verbose:
1082 sys.stdout.write(" client: closing connection.\n")
1083 s.close()
1084 finally:
1085 server.stop()
1086 # wait for server thread to end
1087 server.join()
1088
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001089
Bill Janssen61c001a2008-09-08 16:37:24 +00001090 def testAllRecvAndSendMethods(self):
1091
1092 if test_support.verbose:
1093 sys.stdout.write("\n")
1094
1095 server = ThreadedEchoServer(CERTFILE,
1096 certreqs=ssl.CERT_NONE,
1097 ssl_version=ssl.PROTOCOL_TLSv1,
1098 cacerts=CERTFILE,
1099 chatty=True,
1100 connectionchatty=False)
1101 flag = threading.Event()
1102 server.start(flag)
1103 # wait for it to start
1104 flag.wait()
1105 # try to connect
1106 try:
1107 s = ssl.wrap_socket(socket.socket(),
1108 server_side=False,
1109 certfile=CERTFILE,
1110 ca_certs=CERTFILE,
1111 cert_reqs=ssl.CERT_NONE,
1112 ssl_version=ssl.PROTOCOL_TLSv1)
1113 s.connect((HOST, server.port))
1114 except ssl.SSLError as x:
1115 raise support.TestFailed("Unexpected SSL error: " + str(x))
1116 except Exception as x:
1117 raise support.TestFailed("Unexpected exception: " + str(x))
1118 else:
1119 # helper methods for standardising recv* method signatures
1120 def _recv_into():
1121 b = bytearray("\0"*100)
1122 count = s.recv_into(b)
1123 return b[:count]
1124
1125 def _recvfrom_into():
1126 b = bytearray("\0"*100)
1127 count, addr = s.recvfrom_into(b)
1128 return b[:count]
1129
1130 # (name, method, whether to expect success, *args)
1131 send_methods = [
1132 ('send', s.send, True, []),
1133 ('sendto', s.sendto, False, ["some.address"]),
1134 ('sendall', s.sendall, True, []),
1135 ]
1136 recv_methods = [
1137 ('recv', s.recv, True, []),
1138 ('recvfrom', s.recvfrom, False, ["some.address"]),
1139 ('recv_into', _recv_into, True, []),
1140 ('recvfrom_into', _recvfrom_into, False, []),
1141 ]
1142 data_prefix = u"PREFIX_"
1143
1144 for meth_name, send_meth, expect_success, args in send_methods:
1145 indata = data_prefix + meth_name
1146 try:
1147 send_meth(indata.encode('ASCII', 'strict'), *args)
1148 outdata = s.read()
1149 outdata = outdata.decode('ASCII', 'strict')
1150 if outdata != indata.lower():
1151 raise support.TestFailed(
1152 "While sending with <<%s>> bad data "
1153 "<<%r>> (%d) received; "
1154 "expected <<%r>> (%d)\n" % (
1155 meth_name, outdata[:20], len(outdata),
1156 indata[:20], len(indata)
1157 )
1158 )
1159 except ValueError as e:
1160 if expect_success:
1161 raise support.TestFailed(
1162 "Failed to send with method <<%s>>; "
1163 "expected to succeed.\n" % (meth_name,)
1164 )
1165 if not str(e).startswith(meth_name):
1166 raise support.TestFailed(
1167 "Method <<%s>> failed with unexpected "
1168 "exception message: %s\n" % (
1169 meth_name, e
1170 )
1171 )
1172
1173 for meth_name, recv_meth, expect_success, args in recv_methods:
1174 indata = data_prefix + meth_name
1175 try:
1176 s.send(indata.encode('ASCII', 'strict'))
1177 outdata = recv_meth(*args)
1178 outdata = outdata.decode('ASCII', 'strict')
1179 if outdata != indata.lower():
1180 raise support.TestFailed(
1181 "While receiving with <<%s>> bad data "
1182 "<<%r>> (%d) received; "
1183 "expected <<%r>> (%d)\n" % (
1184 meth_name, outdata[:20], len(outdata),
1185 indata[:20], len(indata)
1186 )
1187 )
1188 except ValueError as e:
1189 if expect_success:
1190 raise support.TestFailed(
1191 "Failed to receive with method <<%s>>; "
1192 "expected to succeed.\n" % (meth_name,)
1193 )
1194 if not str(e).startswith(meth_name):
1195 raise support.TestFailed(
1196 "Method <<%s>> failed with unexpected "
1197 "exception message: %s\n" % (
1198 meth_name, e
1199 )
1200 )
1201 # consume data
1202 s.read()
1203
1204 s.write("over\n".encode("ASCII", "strict"))
1205 s.close()
1206 finally:
1207 server.stop()
1208 server.join()
1209
Antoine Pitrouc689d962010-04-24 20:13:37 +00001210 def test_handshake_timeout(self):
1211 # Issue #5103: SSL handshake must respect the socket timeout
1212 server = socket.socket(socket.AF_INET)
1213 host = "127.0.0.1"
1214 port = test_support.bind_port(server)
1215 started = threading.Event()
1216 finish = False
1217
1218 def serve():
1219 server.listen(5)
1220 started.set()
1221 conns = []
1222 while not finish:
1223 r, w, e = select.select([server], [], [], 0.1)
1224 if server in r:
1225 # Let the socket hang around rather than having
1226 # it closed by garbage collection.
1227 conns.append(server.accept()[0])
1228
1229 t = threading.Thread(target=serve)
1230 t.start()
1231 started.wait()
1232
1233 try:
1234 try:
1235 c = socket.socket(socket.AF_INET)
1236 c.settimeout(0.2)
1237 c.connect((host, port))
1238 # Will attempt handshake and time out
1239 try:
1240 ssl.wrap_socket(c)
1241 except ssl.SSLError, e:
1242 self.assertTrue("timed out" in str(e), str(e))
1243 else:
1244 self.fail("SSLError wasn't raised")
1245 finally:
1246 c.close()
1247 try:
1248 c = socket.socket(socket.AF_INET)
1249 c.settimeout(0.2)
1250 c = ssl.wrap_socket(c)
1251 # Will attempt handshake and time out
1252 try:
1253 c.connect((host, port))
1254 except ssl.SSLError, e:
1255 self.assertTrue("timed out" in str(e), str(e))
1256 else:
1257 self.fail("SSLError wasn't raised")
1258 finally:
1259 c.close()
1260 finally:
1261 finish = True
1262 t.join()
1263 server.close()
1264
Bill Janssen61c001a2008-09-08 16:37:24 +00001265
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001266def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001267 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001268 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001269
Trent Nelsone41b0062008-04-08 23:47:30 +00001270 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001271 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001272 "keycert.pem")
1273 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1274 os.path.dirname(__file__) or os.curdir,
1275 "https_svn_python_org_root.pem")
1276
1277 if (not os.path.exists(CERTFILE) or
1278 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001279 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001280
1281 tests = [BasicTests]
1282
Bill Janssen296a59d2007-09-16 22:06:00 +00001283 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001284 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001285
Bill Janssen98d19da2007-09-10 21:51:02 +00001286 if _have_threads:
1287 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001288 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001289 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001290
Bill Janssen98d19da2007-09-10 21:51:02 +00001291 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001292
Bill Janssen98d19da2007-09-10 21:51:02 +00001293 if _have_threads:
1294 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001295
1296if __name__ == "__main__":
1297 test_main()