blob: 9c79af9e2adc14948305751eaa5a0085ebc25ca0 [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]
Trent Nelsone41b0062008-04-08 23:47:30 +0000662 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000663 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000664 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
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()
Trent Nelsone41b0062008-04-08 23:47:30 +0000810 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000811
812 # `listener` runs in a thread. It opens a socket listening on
813 # PORT, and sits in an accept() until the main thread connects.
814 # Then it rudely closes the socket, and sets Event `listener_gone`
815 # to let the main thread know the socket is gone.
816 def listener():
817 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000818 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000819 s.listen(5)
820 listener_ready.set()
821 s.accept()
822 s = None # reclaim the socket object, which also closes it
823 listener_gone.set()
824
825 def connector():
826 listener_ready.wait()
827 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000828 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000829 listener_gone.wait()
830 try:
831 ssl_sock = ssl.wrap_socket(s)
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()
840 connector()
841 t.join()
842
843 def testEcho (self):
844
845 if test_support.verbose:
846 sys.stdout.write("\n")
847 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
848 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
849 chatty=True, connectionchatty=True)
850
851 def testReadCert(self):
852
853 if test_support.verbose:
854 sys.stdout.write("\n")
855 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000856 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000857 certreqs=ssl.CERT_NONE,
858 ssl_version=ssl.PROTOCOL_SSLv23,
859 cacerts=CERTFILE,
860 chatty=False)
861 flag = threading.Event()
862 server.start(flag)
863 # wait for it to start
864 flag.wait()
865 # try to connect
866 try:
867 try:
868 s = ssl.wrap_socket(socket.socket(),
869 certfile=CERTFILE,
870 ca_certs=CERTFILE,
871 cert_reqs=ssl.CERT_REQUIRED,
872 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000873 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000874 except ssl.SSLError, x:
875 raise test_support.TestFailed(
876 "Unexpected SSL error: " + str(x))
877 except Exception, x:
878 raise test_support.TestFailed(
879 "Unexpected exception: " + str(x))
880 else:
881 if not s:
882 raise test_support.TestFailed(
883 "Can't SSL-handshake with test server")
884 cert = s.getpeercert()
885 if not cert:
886 raise test_support.TestFailed(
887 "Can't get peer certificate.")
888 cipher = s.cipher()
889 if test_support.verbose:
890 sys.stdout.write(pprint.pformat(cert) + '\n')
891 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
892 if not cert.has_key('subject'):
893 raise test_support.TestFailed(
894 "No subject field in certificate: %s." %
895 pprint.pformat(cert))
896 if ((('organizationName', 'Python Software Foundation'),)
897 not in cert['subject']):
898 raise test_support.TestFailed(
899 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000900 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000901 s.close()
902 finally:
903 server.stop()
904 server.join()
905
906 def testNULLcert(self):
907 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
908 "nullcert.pem"))
909 def testMalformedCert(self):
910 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
911 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000912 def testWrongCert(self):
913 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
914 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000915 def testMalformedKey(self):
916 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
917 "badkey.pem"))
918
919 def testProtocolSSL2(self):
920 if test_support.verbose:
921 sys.stdout.write("\n")
922 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
923 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
924 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
925 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
926 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
927 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
928
929 def testProtocolSSL23(self):
930 if test_support.verbose:
931 sys.stdout.write("\n")
932 try:
933 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
934 except test_support.TestFailed, x:
935 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
936 if test_support.verbose:
937 sys.stdout.write(
938 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
939 % str(x))
940 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
941 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
942 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
943
944 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
945 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
946 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
947
948 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
949 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
950 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
951
952 def testProtocolSSL3(self):
953 if test_support.verbose:
954 sys.stdout.write("\n")
955 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
956 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
957 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
958 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
959 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
960 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
961
962 def testProtocolTLS1(self):
963 if test_support.verbose:
964 sys.stdout.write("\n")
965 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
966 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
967 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
968 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
969 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
970 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
971
972 def testSTARTTLS (self):
973
Bill Janssen39295c22008-08-12 16:31:21 +0000974 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000975
Trent Nelsone41b0062008-04-08 23:47:30 +0000976 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000977 ssl_version=ssl.PROTOCOL_TLSv1,
978 starttls_server=True,
979 chatty=True,
980 connectionchatty=True)
981 flag = threading.Event()
982 server.start(flag)
983 # wait for it to start
984 flag.wait()
985 # try to connect
986 wrapped = False
987 try:
988 try:
989 s = socket.socket()
990 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000991 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000992 except Exception, x:
993 raise test_support.TestFailed("Unexpected exception: " + str(x))
994 else:
995 if test_support.verbose:
996 sys.stdout.write("\n")
997 for indata in msgs:
998 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000999 sys.stdout.write(
1000 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001001 if wrapped:
1002 conn.write(indata)
1003 outdata = conn.read()
1004 else:
1005 s.send(indata)
1006 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001007 if (indata == "STARTTLS" and
1008 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001009 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001010 sys.stdout.write(
1011 " client: read %s from server, starting TLS...\n"
1012 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001013 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001014 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001015 elif (indata == "ENDTLS" and
1016 outdata.strip().lower().startswith("ok")):
1017 if test_support.verbose:
1018 sys.stdout.write(
1019 " client: read %s from server, ending TLS...\n"
1020 % repr(outdata))
1021 s = conn.unwrap()
1022 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001023 else:
1024 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001025 sys.stdout.write(
1026 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001027 if test_support.verbose:
1028 sys.stdout.write(" client: closing connection.\n")
1029 if wrapped:
1030 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001031 else:
1032 s.send("over\n")
1033 s.close()
1034 finally:
1035 server.stop()
1036 server.join()
1037
Bill Janssen934b16d2008-06-28 22:19:33 +00001038 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001039
Bill Janssen934b16d2008-06-28 22:19:33 +00001040 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001041 flag = threading.Event()
1042 server.start(flag)
1043 # wait for it to start
1044 flag.wait()
1045 # try to connect
1046 try:
1047 if test_support.verbose:
1048 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001049 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001050 d2 = ''
1051 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001052 url = 'https://127.0.0.1:%d/%s' % (
1053 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +00001054 f = urllib.urlopen(url)
1055 dlen = f.info().getheader("content-length")
1056 if dlen and (int(dlen) > 0):
1057 d2 = f.read(int(dlen))
1058 if test_support.verbose:
1059 sys.stdout.write(
1060 " client: read %d bytes from remote server '%s'\n"
1061 % (len(d2), server))
1062 f.close()
1063 except:
1064 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1065 if test_support.verbose:
1066 sys.stdout.write('\n' + msg)
1067 raise test_support.TestFailed(msg)
1068 else:
1069 if not (d1 == d2):
1070 raise test_support.TestFailed(
1071 "Couldn't fetch data from HTTPS server")
1072 finally:
1073 server.stop()
1074 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001075
Bill Janssen934b16d2008-06-28 22:19:33 +00001076 def testWrappedAccept (self):
1077
1078 if test_support.verbose:
1079 sys.stdout.write("\n")
1080 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1081 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1082 chatty=True, connectionchatty=True,
1083 wrap_accepting_socket=True)
1084
1085
1086 def testAsyncoreServer (self):
1087
1088 indata = "TEST MESSAGE of mixed case\n"
1089
1090 if test_support.verbose:
1091 sys.stdout.write("\n")
1092 server = AsyncoreEchoServer(CERTFILE)
1093 flag = threading.Event()
1094 server.start(flag)
1095 # wait for it to start
1096 flag.wait()
1097 # try to connect
1098 try:
1099 try:
1100 s = ssl.wrap_socket(socket.socket())
1101 s.connect(('127.0.0.1', server.port))
1102 except ssl.SSLError, x:
1103 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1104 except Exception, x:
1105 raise test_support.TestFailed("Unexpected exception: " + str(x))
1106 else:
1107 if test_support.verbose:
1108 sys.stdout.write(
1109 " client: sending %s...\n" % (repr(indata)))
1110 s.write(indata)
1111 outdata = s.read()
1112 if test_support.verbose:
1113 sys.stdout.write(" client: read %s\n" % repr(outdata))
1114 if outdata != indata.lower():
1115 raise test_support.TestFailed(
1116 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1117 % (outdata[:min(len(outdata),20)], len(outdata),
1118 indata[:min(len(indata),20)].lower(), len(indata)))
1119 s.write("over\n")
1120 if test_support.verbose:
1121 sys.stdout.write(" client: closing connection.\n")
1122 s.close()
1123 finally:
1124 server.stop()
1125 # wait for server thread to end
1126 server.join()
1127
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001128
Bill Janssen61c001a2008-09-08 16:37:24 +00001129 def testAllRecvAndSendMethods(self):
1130
1131 if test_support.verbose:
1132 sys.stdout.write("\n")
1133
1134 server = ThreadedEchoServer(CERTFILE,
1135 certreqs=ssl.CERT_NONE,
1136 ssl_version=ssl.PROTOCOL_TLSv1,
1137 cacerts=CERTFILE,
1138 chatty=True,
1139 connectionchatty=False)
1140 flag = threading.Event()
1141 server.start(flag)
1142 # wait for it to start
1143 flag.wait()
1144 # try to connect
1145 try:
1146 s = ssl.wrap_socket(socket.socket(),
1147 server_side=False,
1148 certfile=CERTFILE,
1149 ca_certs=CERTFILE,
1150 cert_reqs=ssl.CERT_NONE,
1151 ssl_version=ssl.PROTOCOL_TLSv1)
1152 s.connect((HOST, server.port))
1153 except ssl.SSLError as x:
1154 raise support.TestFailed("Unexpected SSL error: " + str(x))
1155 except Exception as x:
1156 raise support.TestFailed("Unexpected exception: " + str(x))
1157 else:
1158 # helper methods for standardising recv* method signatures
1159 def _recv_into():
1160 b = bytearray("\0"*100)
1161 count = s.recv_into(b)
1162 return b[:count]
1163
1164 def _recvfrom_into():
1165 b = bytearray("\0"*100)
1166 count, addr = s.recvfrom_into(b)
1167 return b[:count]
1168
1169 # (name, method, whether to expect success, *args)
1170 send_methods = [
1171 ('send', s.send, True, []),
1172 ('sendto', s.sendto, False, ["some.address"]),
1173 ('sendall', s.sendall, True, []),
1174 ]
1175 recv_methods = [
1176 ('recv', s.recv, True, []),
1177 ('recvfrom', s.recvfrom, False, ["some.address"]),
1178 ('recv_into', _recv_into, True, []),
1179 ('recvfrom_into', _recvfrom_into, False, []),
1180 ]
1181 data_prefix = u"PREFIX_"
1182
1183 for meth_name, send_meth, expect_success, args in send_methods:
1184 indata = data_prefix + meth_name
1185 try:
1186 send_meth(indata.encode('ASCII', 'strict'), *args)
1187 outdata = s.read()
1188 outdata = outdata.decode('ASCII', 'strict')
1189 if outdata != indata.lower():
1190 raise support.TestFailed(
1191 "While sending with <<%s>> bad data "
1192 "<<%r>> (%d) received; "
1193 "expected <<%r>> (%d)\n" % (
1194 meth_name, outdata[:20], len(outdata),
1195 indata[:20], len(indata)
1196 )
1197 )
1198 except ValueError as e:
1199 if expect_success:
1200 raise support.TestFailed(
1201 "Failed to send with method <<%s>>; "
1202 "expected to succeed.\n" % (meth_name,)
1203 )
1204 if not str(e).startswith(meth_name):
1205 raise support.TestFailed(
1206 "Method <<%s>> failed with unexpected "
1207 "exception message: %s\n" % (
1208 meth_name, e
1209 )
1210 )
1211
1212 for meth_name, recv_meth, expect_success, args in recv_methods:
1213 indata = data_prefix + meth_name
1214 try:
1215 s.send(indata.encode('ASCII', 'strict'))
1216 outdata = recv_meth(*args)
1217 outdata = outdata.decode('ASCII', 'strict')
1218 if outdata != indata.lower():
1219 raise support.TestFailed(
1220 "While receiving with <<%s>> bad data "
1221 "<<%r>> (%d) received; "
1222 "expected <<%r>> (%d)\n" % (
1223 meth_name, outdata[:20], len(outdata),
1224 indata[:20], len(indata)
1225 )
1226 )
1227 except ValueError as e:
1228 if expect_success:
1229 raise support.TestFailed(
1230 "Failed to receive with method <<%s>>; "
1231 "expected to succeed.\n" % (meth_name,)
1232 )
1233 if not str(e).startswith(meth_name):
1234 raise support.TestFailed(
1235 "Method <<%s>> failed with unexpected "
1236 "exception message: %s\n" % (
1237 meth_name, e
1238 )
1239 )
1240 # consume data
1241 s.read()
1242
1243 s.write("over\n".encode("ASCII", "strict"))
1244 s.close()
1245 finally:
1246 server.stop()
1247 server.join()
1248
Antoine Pitrouc689d962010-04-24 20:13:37 +00001249 def test_handshake_timeout(self):
1250 # Issue #5103: SSL handshake must respect the socket timeout
1251 server = socket.socket(socket.AF_INET)
1252 host = "127.0.0.1"
1253 port = test_support.bind_port(server)
1254 started = threading.Event()
1255 finish = False
1256
1257 def serve():
1258 server.listen(5)
1259 started.set()
1260 conns = []
1261 while not finish:
1262 r, w, e = select.select([server], [], [], 0.1)
1263 if server in r:
1264 # Let the socket hang around rather than having
1265 # it closed by garbage collection.
1266 conns.append(server.accept()[0])
1267
1268 t = threading.Thread(target=serve)
1269 t.start()
1270 started.wait()
1271
1272 try:
1273 try:
1274 c = socket.socket(socket.AF_INET)
1275 c.settimeout(0.2)
1276 c.connect((host, port))
1277 # Will attempt handshake and time out
1278 try:
1279 ssl.wrap_socket(c)
1280 except ssl.SSLError, e:
1281 self.assertTrue("timed out" in str(e), str(e))
1282 else:
1283 self.fail("SSLError wasn't raised")
1284 finally:
1285 c.close()
1286 try:
1287 c = socket.socket(socket.AF_INET)
1288 c.settimeout(0.2)
1289 c = ssl.wrap_socket(c)
1290 # Will attempt handshake and time out
1291 try:
1292 c.connect((host, port))
1293 except ssl.SSLError, e:
1294 self.assertTrue("timed out" in str(e), str(e))
1295 else:
1296 self.fail("SSLError wasn't raised")
1297 finally:
1298 c.close()
1299 finally:
1300 finish = True
1301 t.join()
1302 server.close()
1303
Bill Janssen61c001a2008-09-08 16:37:24 +00001304
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001305def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001306 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001307 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001308
Trent Nelsone41b0062008-04-08 23:47:30 +00001309 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001310 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001311 "keycert.pem")
1312 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1313 os.path.dirname(__file__) or os.curdir,
1314 "https_svn_python_org_root.pem")
1315
1316 if (not os.path.exists(CERTFILE) or
1317 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001318 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001319
Bill Janssen934b16d2008-06-28 22:19:33 +00001320 TESTPORT = test_support.find_unused_port()
1321 if not TESTPORT:
1322 raise test_support.TestFailed("Can't find open port to test servers on!")
1323
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001324 tests = [BasicTests]
1325
Bill Janssen296a59d2007-09-16 22:06:00 +00001326 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001327 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001328
Bill Janssen98d19da2007-09-10 21:51:02 +00001329 if _have_threads:
1330 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001331 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001332 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001333
Bill Janssen98d19da2007-09-10 21:51:02 +00001334 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001335
Bill Janssen98d19da2007-09-10 21:51:02 +00001336 if _have_threads:
1337 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001338
1339if __name__ == "__main__":
1340 test_main()