blob: f2ffab5293b7f83b3a842795c69549656f42a5c3 [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,
Antoine Pitrouc689d962010-04-24 20:13:37 +0000460 do_handshake_on_connect=False)
461 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000462
463 def readable(self):
464 if isinstance(self.socket, ssl.SSLSocket):
465 while self.socket.pending() > 0:
466 self.handle_read_event()
467 return True
468
Antoine Pitrouc689d962010-04-24 20:13:37 +0000469 def _do_ssl_handshake(self):
470 try:
471 self.socket.do_handshake()
472 except ssl.SSLError, err:
473 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
474 ssl.SSL_ERROR_WANT_WRITE):
475 return
476 elif err.args[0] == ssl.SSL_ERROR_EOF:
477 return self.handle_close()
478 raise
479 except socket.error, err:
480 if err.args[0] == errno.ECONNABORTED:
481 return self.handle_close()
482 else:
483 self._ssl_accepting = False
484
Bill Janssen934b16d2008-06-28 22:19:33 +0000485 def handle_read(self):
Antoine Pitrouc689d962010-04-24 20:13:37 +0000486 if self._ssl_accepting:
487 self._do_ssl_handshake()
488 else:
489 data = self.recv(1024)
490 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000491
492 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000493 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000494 if test_support.verbose:
495 sys.stdout.write(" server: closed connection %s\n" % self.socket)
496
497 def handle_error(self):
498 raise
499
500 def __init__(self, certfile):
501 self.certfile = certfile
502 asyncore.dispatcher.__init__(self)
503 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
504 self.port = test_support.bind_port(self.socket)
505 self.listen(5)
506
507 def handle_accept(self):
508 sock_obj, addr = self.accept()
509 if test_support.verbose:
510 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
511 self.ConnectionHandler(sock_obj, self.certfile)
512
513 def handle_error(self):
514 raise
515
516 def __init__(self, certfile):
517 self.flag = None
518 self.active = False
519 self.server = self.EchoServer(certfile)
520 self.port = self.server.port
521 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000522 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000523
524 def __str__(self):
525 return "<%s %s>" % (self.__class__.__name__, self.server)
526
527 def start (self, flag=None):
528 self.flag = flag
529 threading.Thread.start(self)
530
531 def run (self):
532 self.active = True
533 if self.flag:
534 self.flag.set()
535 while self.active:
536 try:
537 asyncore.loop(1)
538 except:
539 pass
540
541 def stop (self):
542 self.active = False
543 self.server.close()
544
545 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000546
547 class HTTPSServer(HTTPServer):
548
549 def __init__(self, server_address, RequestHandlerClass, certfile):
550
551 HTTPServer.__init__(self, server_address, RequestHandlerClass)
552 # we assume the certfile contains both private key and certificate
553 self.certfile = certfile
554 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000555 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000556 self.allow_reuse_address = True
557
Bill Janssen934b16d2008-06-28 22:19:33 +0000558 def __str__(self):
559 return ('<%s %s:%s>' %
560 (self.__class__.__name__,
561 self.server_name,
562 self.server_port))
563
Bill Janssen296a59d2007-09-16 22:06:00 +0000564 def get_request (self):
565 # override this to wrap socket with SSL
566 sock, addr = self.socket.accept()
567 sslconn = ssl.wrap_socket(sock, server_side=True,
568 certfile=self.certfile)
569 return sslconn, addr
570
571 # The methods overridden below this are mainly so that we
572 # can run it in a thread and be able to stop it from another
573 # You probably wouldn't need them in other uses.
574
575 def server_activate(self):
576 # We want to run this in a thread for testing purposes,
577 # so we override this to set timeout, so that we get
578 # a chance to stop the server
579 self.socket.settimeout(0.5)
580 HTTPServer.server_activate(self)
581
582 def serve_forever(self):
583 # We want this to run in a thread, so we use a slightly
584 # modified version of "forever".
585 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000586 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000587 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000588 # We need to lock while handling the request.
589 # Another thread can close the socket after self.active
590 # has been checked and before the request is handled.
591 # This causes an exception when using the closed socket.
592 with self.active_lock:
593 if not self.active:
594 break
595 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000596 except socket.timeout:
597 pass
598 except KeyboardInterrupt:
599 self.server_close()
600 return
601 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000602 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
603 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000604 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000605
606 def server_close(self):
607 # Again, we want this to run in a thread, so we need to override
608 # close to clear the "active" flag, so that serve_forever() will
609 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000610 with self.active_lock:
611 HTTPServer.server_close(self)
612 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000613
614 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
615
616 # need to override translate_path to get a known root,
617 # instead of using os.curdir, since the test could be
618 # run from anywhere
619
620 server_version = "TestHTTPS/1.0"
621
622 root = None
623
624 def translate_path(self, path):
625 """Translate a /-separated PATH to the local filename syntax.
626
627 Components that mean special things to the local file system
628 (e.g. drive or directory names) are ignored. (XXX They should
629 probably be diagnosed.)
630
631 """
632 # abandon query parameters
633 path = urlparse.urlparse(path)[2]
634 path = os.path.normpath(urllib.unquote(path))
635 words = path.split('/')
636 words = filter(None, words)
637 path = self.root
638 for word in words:
639 drive, word = os.path.splitdrive(word)
640 head, word = os.path.split(word)
641 if word in self.root: continue
642 path = os.path.join(path, word)
643 return path
644
645 def log_message(self, format, *args):
646
647 # we override this to suppress logging unless "verbose"
648
649 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000650 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
651 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000652 self.server.server_port,
653 self.request.cipher(),
654 self.log_date_time_string(),
655 format%args))
656
657
Trent Nelsone41b0062008-04-08 23:47:30 +0000658 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000659 self.flag = None
660 self.active = False
661 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
662 self.server = self.HTTPSServer(
Antoine Pitrou6535b312010-04-27 08:43:11 +0000663 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
664 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000665 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000666 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000667
668 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000669 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000670
671 def start (self, flag=None):
672 self.flag = flag
673 threading.Thread.start(self)
674
675 def run (self):
676 self.active = True
677 if self.flag:
678 self.flag.set()
679 self.server.serve_forever()
680 self.active = False
681
682 def stop (self):
683 self.active = False
684 self.server.server_close()
685
686
Bill Janssen98d19da2007-09-10 21:51:02 +0000687 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000688 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000689 certreqs=ssl.CERT_REQUIRED,
690 cacerts=CERTFILE, chatty=False)
691 flag = threading.Event()
692 server.start(flag)
693 # wait for it to start
694 flag.wait()
695 # try to connect
696 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000697 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000698 s = ssl.wrap_socket(socket.socket(),
699 certfile=certfile,
700 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000701 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000702 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000703 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000704 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000705 except socket.error, x:
706 if test_support.verbose:
707 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000708 else:
709 raise test_support.TestFailed(
710 "Use of invalid cert should have failed!")
711 finally:
712 server.stop()
713 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000714
Bill Janssen98d19da2007-09-10 21:51:02 +0000715 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
716 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000717 chatty=True, connectionchatty=False,
718 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000719
Trent Nelsone41b0062008-04-08 23:47:30 +0000720 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000721 certreqs=certreqs,
722 ssl_version=protocol,
723 cacerts=cacertsfile,
724 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000725 connectionchatty=connectionchatty,
726 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000727 flag = threading.Event()
728 server.start(flag)
729 # wait for it to start
730 flag.wait()
731 # try to connect
732 if client_protocol is None:
733 client_protocol = protocol
734 try:
735 try:
736 s = ssl.wrap_socket(socket.socket(),
737 certfile=client_certfile,
738 ca_certs=cacertsfile,
739 cert_reqs=certreqs,
740 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000741 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000742 except ssl.SSLError, x:
743 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
744 except Exception, x:
745 raise test_support.TestFailed("Unexpected exception: " + str(x))
746 else:
747 if connectionchatty:
748 if test_support.verbose:
749 sys.stdout.write(
750 " client: sending %s...\n" % (repr(indata)))
751 s.write(indata)
752 outdata = s.read()
753 if connectionchatty:
754 if test_support.verbose:
755 sys.stdout.write(" client: read %s\n" % repr(outdata))
756 if outdata != indata.lower():
757 raise test_support.TestFailed(
758 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
759 % (outdata[:min(len(outdata),20)], len(outdata),
760 indata[:min(len(indata),20)].lower(), len(indata)))
761 s.write("over\n")
762 if connectionchatty:
763 if test_support.verbose:
764 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000765 s.close()
766 finally:
767 server.stop()
768 server.join()
769
770 def tryProtocolCombo (server_protocol,
771 client_protocol,
772 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000773 certsreqs=None):
774
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000775 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000776 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000777
778 if certsreqs == ssl.CERT_NONE:
779 certtype = "CERT_NONE"
780 elif certsreqs == ssl.CERT_OPTIONAL:
781 certtype = "CERT_OPTIONAL"
782 elif certsreqs == ssl.CERT_REQUIRED:
783 certtype = "CERT_REQUIRED"
784 if test_support.verbose:
785 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
786 sys.stdout.write(formatstr %
787 (ssl.get_protocol_name(client_protocol),
788 ssl.get_protocol_name(server_protocol),
789 certtype))
790 try:
791 serverParamsTest(CERTFILE, server_protocol, certsreqs,
792 CERTFILE, CERTFILE, client_protocol, chatty=False)
793 except test_support.TestFailed:
794 if expectedToWork:
795 raise
796 else:
797 if not expectedToWork:
798 raise test_support.TestFailed(
799 "Client protocol %s succeeded with server protocol %s!"
800 % (ssl.get_protocol_name(client_protocol),
801 ssl.get_protocol_name(server_protocol)))
802
803
Bill Janssen934b16d2008-06-28 22:19:33 +0000804 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000805
806 def testRudeShutdown(self):
807
808 listener_ready = threading.Event()
809 listener_gone = threading.Event()
810
Antoine Pitrou6535b312010-04-27 08:43:11 +0000811 s = socket.socket()
812 port = test_support.bind_port(s, HOST)
813
814 # `listener` runs in a thread. It sits in an accept() until
815 # the main thread connects. Then it rudely closes the socket,
816 # and sets Event `listener_gone` to let the main thread know
817 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000818 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000819 s.listen(5)
820 listener_ready.set()
821 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000822 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000823 listener_gone.set()
824
825 def connector():
826 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000827 c = socket.socket()
828 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000829 listener_gone.wait()
830 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000831 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000832 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000833 pass
834 else:
835 raise test_support.TestFailed(
836 'connecting to closed SSL socket should have failed')
837
838 t = threading.Thread(target=listener)
839 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000840 try:
841 connector()
842 finally:
843 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000844
845 def testEcho (self):
846
847 if test_support.verbose:
848 sys.stdout.write("\n")
849 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
850 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
851 chatty=True, connectionchatty=True)
852
853 def testReadCert(self):
854
855 if test_support.verbose:
856 sys.stdout.write("\n")
857 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000858 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000859 certreqs=ssl.CERT_NONE,
860 ssl_version=ssl.PROTOCOL_SSLv23,
861 cacerts=CERTFILE,
862 chatty=False)
863 flag = threading.Event()
864 server.start(flag)
865 # wait for it to start
866 flag.wait()
867 # try to connect
868 try:
869 try:
870 s = ssl.wrap_socket(socket.socket(),
871 certfile=CERTFILE,
872 ca_certs=CERTFILE,
873 cert_reqs=ssl.CERT_REQUIRED,
874 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000875 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000876 except ssl.SSLError, x:
877 raise test_support.TestFailed(
878 "Unexpected SSL error: " + str(x))
879 except Exception, x:
880 raise test_support.TestFailed(
881 "Unexpected exception: " + str(x))
882 else:
883 if not s:
884 raise test_support.TestFailed(
885 "Can't SSL-handshake with test server")
886 cert = s.getpeercert()
887 if not cert:
888 raise test_support.TestFailed(
889 "Can't get peer certificate.")
890 cipher = s.cipher()
891 if test_support.verbose:
892 sys.stdout.write(pprint.pformat(cert) + '\n')
893 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
894 if not cert.has_key('subject'):
895 raise test_support.TestFailed(
896 "No subject field in certificate: %s." %
897 pprint.pformat(cert))
898 if ((('organizationName', 'Python Software Foundation'),)
899 not in cert['subject']):
900 raise test_support.TestFailed(
901 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000902 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000903 s.close()
904 finally:
905 server.stop()
906 server.join()
907
908 def testNULLcert(self):
909 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
910 "nullcert.pem"))
911 def testMalformedCert(self):
912 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
913 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000914 def testWrongCert(self):
915 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
916 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000917 def testMalformedKey(self):
918 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
919 "badkey.pem"))
920
921 def testProtocolSSL2(self):
922 if test_support.verbose:
923 sys.stdout.write("\n")
924 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
925 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
926 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
927 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
928 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
929 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
930
931 def testProtocolSSL23(self):
932 if test_support.verbose:
933 sys.stdout.write("\n")
934 try:
935 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
936 except test_support.TestFailed, x:
937 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
938 if test_support.verbose:
939 sys.stdout.write(
940 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
941 % str(x))
942 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
943 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
944 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
945
946 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
947 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
948 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
949
950 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
951 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
952 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
953
954 def testProtocolSSL3(self):
955 if test_support.verbose:
956 sys.stdout.write("\n")
957 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
958 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
959 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
960 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
961 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
962 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
963
964 def testProtocolTLS1(self):
965 if test_support.verbose:
966 sys.stdout.write("\n")
967 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
968 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
969 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
970 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
971 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
972 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
973
974 def testSTARTTLS (self):
975
Bill Janssen39295c22008-08-12 16:31:21 +0000976 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000977
Trent Nelsone41b0062008-04-08 23:47:30 +0000978 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000979 ssl_version=ssl.PROTOCOL_TLSv1,
980 starttls_server=True,
981 chatty=True,
982 connectionchatty=True)
983 flag = threading.Event()
984 server.start(flag)
985 # wait for it to start
986 flag.wait()
987 # try to connect
988 wrapped = False
989 try:
990 try:
991 s = socket.socket()
992 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000993 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000994 except Exception, x:
995 raise test_support.TestFailed("Unexpected exception: " + str(x))
996 else:
997 if test_support.verbose:
998 sys.stdout.write("\n")
999 for indata in msgs:
1000 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001001 sys.stdout.write(
1002 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001003 if wrapped:
1004 conn.write(indata)
1005 outdata = conn.read()
1006 else:
1007 s.send(indata)
1008 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001009 if (indata == "STARTTLS" and
1010 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001011 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001012 sys.stdout.write(
1013 " client: read %s from server, starting TLS...\n"
1014 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001015 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001016 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001017 elif (indata == "ENDTLS" and
1018 outdata.strip().lower().startswith("ok")):
1019 if test_support.verbose:
1020 sys.stdout.write(
1021 " client: read %s from server, ending TLS...\n"
1022 % repr(outdata))
1023 s = conn.unwrap()
1024 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001025 else:
1026 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001027 sys.stdout.write(
1028 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001029 if test_support.verbose:
1030 sys.stdout.write(" client: closing connection.\n")
1031 if wrapped:
1032 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001033 else:
1034 s.send("over\n")
1035 s.close()
1036 finally:
1037 server.stop()
1038 server.join()
1039
Bill Janssen934b16d2008-06-28 22:19:33 +00001040 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001041
Bill Janssen934b16d2008-06-28 22:19:33 +00001042 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001043 flag = threading.Event()
1044 server.start(flag)
1045 # wait for it to start
1046 flag.wait()
1047 # try to connect
1048 try:
1049 if test_support.verbose:
1050 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001051 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001052 d2 = ''
1053 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001054 url = 'https://127.0.0.1:%d/%s' % (
1055 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +00001056 f = urllib.urlopen(url)
1057 dlen = f.info().getheader("content-length")
1058 if dlen and (int(dlen) > 0):
1059 d2 = f.read(int(dlen))
1060 if test_support.verbose:
1061 sys.stdout.write(
1062 " client: read %d bytes from remote server '%s'\n"
1063 % (len(d2), server))
1064 f.close()
1065 except:
1066 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1067 if test_support.verbose:
1068 sys.stdout.write('\n' + msg)
1069 raise test_support.TestFailed(msg)
1070 else:
1071 if not (d1 == d2):
1072 raise test_support.TestFailed(
1073 "Couldn't fetch data from HTTPS server")
1074 finally:
1075 server.stop()
1076 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001077
Bill Janssen934b16d2008-06-28 22:19:33 +00001078 def testWrappedAccept (self):
1079
1080 if test_support.verbose:
1081 sys.stdout.write("\n")
1082 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1083 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1084 chatty=True, connectionchatty=True,
1085 wrap_accepting_socket=True)
1086
1087
1088 def testAsyncoreServer (self):
1089
1090 indata = "TEST MESSAGE of mixed case\n"
1091
1092 if test_support.verbose:
1093 sys.stdout.write("\n")
1094 server = AsyncoreEchoServer(CERTFILE)
1095 flag = threading.Event()
1096 server.start(flag)
1097 # wait for it to start
1098 flag.wait()
1099 # try to connect
1100 try:
1101 try:
1102 s = ssl.wrap_socket(socket.socket())
1103 s.connect(('127.0.0.1', server.port))
1104 except ssl.SSLError, x:
1105 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1106 except Exception, x:
1107 raise test_support.TestFailed("Unexpected exception: " + str(x))
1108 else:
1109 if test_support.verbose:
1110 sys.stdout.write(
1111 " client: sending %s...\n" % (repr(indata)))
1112 s.write(indata)
1113 outdata = s.read()
1114 if test_support.verbose:
1115 sys.stdout.write(" client: read %s\n" % repr(outdata))
1116 if outdata != indata.lower():
1117 raise test_support.TestFailed(
1118 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1119 % (outdata[:min(len(outdata),20)], len(outdata),
1120 indata[:min(len(indata),20)].lower(), len(indata)))
1121 s.write("over\n")
1122 if test_support.verbose:
1123 sys.stdout.write(" client: closing connection.\n")
1124 s.close()
1125 finally:
1126 server.stop()
1127 # wait for server thread to end
1128 server.join()
1129
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001130
Bill Janssen61c001a2008-09-08 16:37:24 +00001131 def testAllRecvAndSendMethods(self):
1132
1133 if test_support.verbose:
1134 sys.stdout.write("\n")
1135
1136 server = ThreadedEchoServer(CERTFILE,
1137 certreqs=ssl.CERT_NONE,
1138 ssl_version=ssl.PROTOCOL_TLSv1,
1139 cacerts=CERTFILE,
1140 chatty=True,
1141 connectionchatty=False)
1142 flag = threading.Event()
1143 server.start(flag)
1144 # wait for it to start
1145 flag.wait()
1146 # try to connect
1147 try:
1148 s = ssl.wrap_socket(socket.socket(),
1149 server_side=False,
1150 certfile=CERTFILE,
1151 ca_certs=CERTFILE,
1152 cert_reqs=ssl.CERT_NONE,
1153 ssl_version=ssl.PROTOCOL_TLSv1)
1154 s.connect((HOST, server.port))
1155 except ssl.SSLError as x:
1156 raise support.TestFailed("Unexpected SSL error: " + str(x))
1157 except Exception as x:
1158 raise support.TestFailed("Unexpected exception: " + str(x))
1159 else:
1160 # helper methods for standardising recv* method signatures
1161 def _recv_into():
1162 b = bytearray("\0"*100)
1163 count = s.recv_into(b)
1164 return b[:count]
1165
1166 def _recvfrom_into():
1167 b = bytearray("\0"*100)
1168 count, addr = s.recvfrom_into(b)
1169 return b[:count]
1170
1171 # (name, method, whether to expect success, *args)
1172 send_methods = [
1173 ('send', s.send, True, []),
1174 ('sendto', s.sendto, False, ["some.address"]),
1175 ('sendall', s.sendall, True, []),
1176 ]
1177 recv_methods = [
1178 ('recv', s.recv, True, []),
1179 ('recvfrom', s.recvfrom, False, ["some.address"]),
1180 ('recv_into', _recv_into, True, []),
1181 ('recvfrom_into', _recvfrom_into, False, []),
1182 ]
1183 data_prefix = u"PREFIX_"
1184
1185 for meth_name, send_meth, expect_success, args in send_methods:
1186 indata = data_prefix + meth_name
1187 try:
1188 send_meth(indata.encode('ASCII', 'strict'), *args)
1189 outdata = s.read()
1190 outdata = outdata.decode('ASCII', 'strict')
1191 if outdata != indata.lower():
1192 raise support.TestFailed(
1193 "While sending with <<%s>> bad data "
1194 "<<%r>> (%d) received; "
1195 "expected <<%r>> (%d)\n" % (
1196 meth_name, outdata[:20], len(outdata),
1197 indata[:20], len(indata)
1198 )
1199 )
1200 except ValueError as e:
1201 if expect_success:
1202 raise support.TestFailed(
1203 "Failed to send with method <<%s>>; "
1204 "expected to succeed.\n" % (meth_name,)
1205 )
1206 if not str(e).startswith(meth_name):
1207 raise support.TestFailed(
1208 "Method <<%s>> failed with unexpected "
1209 "exception message: %s\n" % (
1210 meth_name, e
1211 )
1212 )
1213
1214 for meth_name, recv_meth, expect_success, args in recv_methods:
1215 indata = data_prefix + meth_name
1216 try:
1217 s.send(indata.encode('ASCII', 'strict'))
1218 outdata = recv_meth(*args)
1219 outdata = outdata.decode('ASCII', 'strict')
1220 if outdata != indata.lower():
1221 raise support.TestFailed(
1222 "While receiving with <<%s>> bad data "
1223 "<<%r>> (%d) received; "
1224 "expected <<%r>> (%d)\n" % (
1225 meth_name, outdata[:20], len(outdata),
1226 indata[:20], len(indata)
1227 )
1228 )
1229 except ValueError as e:
1230 if expect_success:
1231 raise support.TestFailed(
1232 "Failed to receive with method <<%s>>; "
1233 "expected to succeed.\n" % (meth_name,)
1234 )
1235 if not str(e).startswith(meth_name):
1236 raise support.TestFailed(
1237 "Method <<%s>> failed with unexpected "
1238 "exception message: %s\n" % (
1239 meth_name, e
1240 )
1241 )
1242 # consume data
1243 s.read()
1244
1245 s.write("over\n".encode("ASCII", "strict"))
1246 s.close()
1247 finally:
1248 server.stop()
1249 server.join()
1250
Antoine Pitrouc689d962010-04-24 20:13:37 +00001251 def test_handshake_timeout(self):
1252 # Issue #5103: SSL handshake must respect the socket timeout
1253 server = socket.socket(socket.AF_INET)
1254 host = "127.0.0.1"
1255 port = test_support.bind_port(server)
1256 started = threading.Event()
1257 finish = False
1258
1259 def serve():
1260 server.listen(5)
1261 started.set()
1262 conns = []
1263 while not finish:
1264 r, w, e = select.select([server], [], [], 0.1)
1265 if server in r:
1266 # Let the socket hang around rather than having
1267 # it closed by garbage collection.
1268 conns.append(server.accept()[0])
1269
1270 t = threading.Thread(target=serve)
1271 t.start()
1272 started.wait()
1273
1274 try:
1275 try:
1276 c = socket.socket(socket.AF_INET)
1277 c.settimeout(0.2)
1278 c.connect((host, port))
1279 # Will attempt handshake and time out
1280 try:
1281 ssl.wrap_socket(c)
1282 except ssl.SSLError, e:
1283 self.assertTrue("timed out" in str(e), str(e))
1284 else:
1285 self.fail("SSLError wasn't raised")
1286 finally:
1287 c.close()
1288 try:
1289 c = socket.socket(socket.AF_INET)
1290 c.settimeout(0.2)
1291 c = ssl.wrap_socket(c)
1292 # Will attempt handshake and time out
1293 try:
1294 c.connect((host, port))
1295 except ssl.SSLError, e:
1296 self.assertTrue("timed out" in str(e), str(e))
1297 else:
1298 self.fail("SSLError wasn't raised")
1299 finally:
1300 c.close()
1301 finally:
1302 finish = True
1303 t.join()
1304 server.close()
1305
Bill Janssen61c001a2008-09-08 16:37:24 +00001306
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001307def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001308 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001309 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001310
Trent Nelsone41b0062008-04-08 23:47:30 +00001311 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001312 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001313 "keycert.pem")
1314 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1315 os.path.dirname(__file__) or os.curdir,
1316 "https_svn_python_org_root.pem")
1317
1318 if (not os.path.exists(CERTFILE) or
1319 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001320 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001321
1322 tests = [BasicTests]
1323
Bill Janssen296a59d2007-09-16 22:06:00 +00001324 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001325 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001326
Bill Janssen98d19da2007-09-10 21:51:02 +00001327 if _have_threads:
1328 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001329 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001330 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001331
Bill Janssen98d19da2007-09-10 21:51:02 +00001332 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001333
Bill Janssen98d19da2007-09-10 21:51:02 +00001334 if _have_threads:
1335 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001336
1337if __name__ == "__main__":
1338 test_main()