blob: cc04f4c54c694f987e08eae46737dfb6c1d6b8d2 [file] [log] [blame]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
5from test import test_support
Bill Janssen934b16d2008-06-28 22:19:33 +00006import asyncore
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00007import socket
Bill Janssen934b16d2008-06-28 22:19:33 +00008import select
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00009import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000010import subprocess
11import time
Antoine Pitroud4030da2010-04-23 23:35:01 +000012import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import os
Antoine Pitroud4030da2010-04-23 23:35:01 +000014import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000016import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000017import shutil
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000018import traceback
Antoine Pitrou3df58d12010-04-23 23:07:37 +000019import weakref
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000020
Bill Janssen296a59d2007-09-16 22:06:00 +000021from BaseHTTPServer import HTTPServer
22from SimpleHTTPServer import SimpleHTTPRequestHandler
23
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000024# Optionally test SSL support, if we have it in the tested platform
25skip_expected = False
26try:
27 import ssl
28except ImportError:
29 skip_expected = True
30
Trent Nelsone41b0062008-04-08 23:47:30 +000031HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000032CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000033SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000034
Neal Norwitz3e533c22007-08-27 01:03:18 +000035def handle_error(prefix):
36 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000037 if test_support.verbose:
38 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000039
Antoine Pitrou77a1c362010-04-27 09:54:14 +000040
41class BasicTests(unittest.TestCase):
42
Bill Jansseneb257ac2008-09-29 18:56:38 +000043 def testSimpleSSLwrap(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +000044 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000045 try:
46 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
47 except IOError, e:
48 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
49 pass
50 else:
51 raise
52 try:
53 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
54 except IOError, e:
55 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
56 pass
57 else:
58 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000059
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000060 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000061 if not test_support.is_resource_enabled('network'):
62 return
Bill Janssen296a59d2007-09-16 22:06:00 +000063 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
64 cert_reqs=ssl.CERT_NONE)
65 s.connect(("svn.python.org", 443))
66 c = s.getpeercert()
67 if c:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +000068 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +000069 s.close()
70
71 # this should fail because we have no verification certs
72 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
73 cert_reqs=ssl.CERT_REQUIRED)
74 try:
75 s.connect(("svn.python.org", 443))
76 except ssl.SSLError:
77 pass
78 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000079 s.close()
80
Bill Janssen98d19da2007-09-10 21:51:02 +000081 def testCrucialConstants(self):
82 ssl.PROTOCOL_SSLv2
83 ssl.PROTOCOL_SSLv23
84 ssl.PROTOCOL_SSLv3
85 ssl.PROTOCOL_TLSv1
86 ssl.CERT_NONE
87 ssl.CERT_OPTIONAL
88 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000089
Bill Janssen98d19da2007-09-10 21:51:02 +000090 def testRAND(self):
91 v = ssl.RAND_status()
92 if test_support.verbose:
93 sys.stdout.write("\n RAND_status is %d (%s)\n"
94 % (v, (v and "sufficient randomness") or
95 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000096 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000097 ssl.RAND_egd(1)
98 except TypeError:
99 pass
Guido van Rossume4729332007-08-26 19:35:09 +0000100 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 print "didn't raise TypeError"
102 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000103
Bill Janssen98d19da2007-09-10 21:51:02 +0000104 def testParseCert(self):
105 # note that this uses an 'unofficial' function in _ssl.c,
106 # provided solely for this test, to exercise the certificate
107 # parsing code
108 p = ssl._ssl._test_decode_cert(CERTFILE, False)
109 if test_support.verbose:
110 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000111
Bill Janssen296a59d2007-09-16 22:06:00 +0000112 def testDERtoPEM(self):
113
114 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
115 d1 = ssl.PEM_cert_to_DER_cert(pem)
116 p2 = ssl.DER_cert_to_PEM_cert(d1)
117 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000118 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000119
Antoine Pitrou3df58d12010-04-23 23:07:37 +0000120 def test_refcycle(self):
121 # Issue #7943: an SSL object doesn't create reference cycles with
122 # itself.
123 s = socket.socket(socket.AF_INET)
124 ss = ssl.wrap_socket(s)
125 wr = weakref.ref(ss)
126 del ss
127 self.assertEqual(wr(), None)
128
Antoine Pitroud4030da2010-04-23 23:35:01 +0000129
Bill Janssen934b16d2008-06-28 22:19:33 +0000130class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000131
132 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000133 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
134 cert_reqs=ssl.CERT_NONE)
135 s.connect(("svn.python.org", 443))
136 c = s.getpeercert()
137 if c:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000138 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000139 s.close()
140
141 # this should fail because we have no verification certs
142 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
143 cert_reqs=ssl.CERT_REQUIRED)
144 try:
145 s.connect(("svn.python.org", 443))
146 except ssl.SSLError:
147 pass
148 finally:
149 s.close()
150
151 # this should succeed because we specify the root cert
152 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
153 cert_reqs=ssl.CERT_REQUIRED,
154 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
155 try:
156 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000157 finally:
158 s.close()
159
Antoine Pitrou0753d942010-04-24 11:09:52 +0000160 def test_makefile_close(self):
161 # Issue #5238: creating a file-like object with makefile() shouldn't
162 # delay closing the underlying "real socket" (here tested with its
163 # file descriptor, hence skipping the test under Windows).
164 if os.name == "nt":
165 if test_support.verbose:
166 print "Skipped: can't use a socket as a file under Windows"
167 return
168 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
169 ss.connect(("svn.python.org", 443))
170 fd = ss.fileno()
171 f = ss.makefile()
172 f.close()
173 # The fd is still open
174 os.read(fd, 0)
175 # Closing the SSL socket should close the fd too
176 ss.close()
177 gc.collect()
178 try:
179 os.read(fd, 0)
180 except OSError, e:
181 self.assertEqual(e.errno, errno.EBADF)
182 else:
183 self.fail("OSError wasn't raised")
Bill Janssen934b16d2008-06-28 22:19:33 +0000184
185 def testNonBlockingHandshake(self):
186 s = socket.socket(socket.AF_INET)
187 s.connect(("svn.python.org", 443))
188 s.setblocking(False)
189 s = ssl.wrap_socket(s,
190 cert_reqs=ssl.CERT_NONE,
191 do_handshake_on_connect=False)
192 count = 0
193 while True:
194 try:
195 count += 1
196 s.do_handshake()
197 break
198 except ssl.SSLError, err:
199 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
200 select.select([s], [], [])
201 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
202 select.select([], [s], [])
203 else:
204 raise
205 s.close()
206 if test_support.verbose:
207 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
208
Bill Janssen296a59d2007-09-16 22:06:00 +0000209 def testFetchServerCert(self):
210
211 pem = ssl.get_server_certificate(("svn.python.org", 443))
212 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000213 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000214
215 try:
216 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
217 except ssl.SSLError:
218 #should fail
219 pass
220 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000221 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000222
223 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
224 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000225 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000226 if test_support.verbose:
227 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
228
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000229 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000230 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000231 if test_support.verbose:
232 sys.stdout.write("test_algorithms disabled, "
233 "as it fails on some old OpenSSL versions")
234 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000235 # Issue #8484: all algorithms should be available when verifying a
236 # certificate.
237 # NOTE: https://sha256.tbs-internet.com is another possible test host
238 remote = ("sha2.hboeck.de", 443)
239 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
240 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
241 cert_reqs=ssl.CERT_REQUIRED,
242 ca_certs=sha256_cert,)
243 with test_support.transient_internet():
244 try:
245 s.connect(remote)
246 if test_support.verbose:
247 sys.stdout.write("\nCipher with %r is %r\n" %
248 (remote, s.cipher()))
249 sys.stdout.write("Certificate is:\n%s\n" %
250 pprint.pformat(s.getpeercert()))
251 finally:
252 s.close()
253
Bill Janssen296a59d2007-09-16 22:06:00 +0000254
Bill Janssen98d19da2007-09-10 21:51:02 +0000255try:
256 import threading
257except ImportError:
258 _have_threads = False
259else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000260
Bill Janssen98d19da2007-09-10 21:51:02 +0000261 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000262
Bill Janssen98d19da2007-09-10 21:51:02 +0000263 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000264
Bill Janssen98d19da2007-09-10 21:51:02 +0000265 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000266
Bill Janssen98d19da2007-09-10 21:51:02 +0000267 """A mildly complicated class, because we want it to work both
268 with and without the SSL wrapper around the socket connection, so
269 that we can test the STARTTLS functionality."""
270
271 def __init__(self, server, connsock):
272 self.server = server
273 self.running = False
274 self.sock = connsock
275 self.sock.setblocking(1)
276 self.sslconn = None
277 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000278 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000279
Bill Janssen934b16d2008-06-28 22:19:33 +0000280 def show_conn_details(self):
281 if self.server.certreqs == ssl.CERT_REQUIRED:
282 cert = self.sslconn.getpeercert()
283 if test_support.verbose and self.server.chatty:
284 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
285 cert_binary = self.sslconn.getpeercert(True)
286 if test_support.verbose and self.server.chatty:
287 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
288 cipher = self.sslconn.cipher()
289 if test_support.verbose and self.server.chatty:
290 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
291
Bill Janssen98d19da2007-09-10 21:51:02 +0000292 def wrap_conn (self):
293 try:
294 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
295 certfile=self.server.certificate,
296 ssl_version=self.server.protocol,
297 ca_certs=self.server.cacerts,
298 cert_reqs=self.server.certreqs)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000299 except ssl.SSLError:
300 # XXX Various errors can have happened here, for example
301 # a mismatching protocol version, an invalid certificate,
302 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000303 if self.server.chatty:
304 handle_error("\n server: bad connection attempt from " +
305 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000306 self.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000307 self.running = False
308 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000309 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000310 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000311 return True
312
313 def read(self):
314 if self.sslconn:
315 return self.sslconn.read()
316 else:
317 return self.sock.recv(1024)
318
319 def write(self, bytes):
320 if self.sslconn:
321 return self.sslconn.write(bytes)
322 else:
323 return self.sock.send(bytes)
324
325 def close(self):
326 if self.sslconn:
327 self.sslconn.close()
328 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000329 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000330
331 def run (self):
332 self.running = True
333 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000334 if isinstance(self.sock, ssl.SSLSocket):
335 self.sslconn = self.sock
336 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000337 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000338 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000339 while self.running:
340 try:
341 msg = self.read()
342 if not msg:
343 # eof, so quit this handler
344 self.running = False
345 self.close()
346 elif msg.strip() == 'over':
347 if test_support.verbose and self.server.connectionchatty:
348 sys.stdout.write(" server: client closed connection\n")
349 self.close()
350 return
351 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
352 if test_support.verbose and self.server.connectionchatty:
353 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
354 self.write("OK\n")
355 if not self.wrap_conn():
356 return
Bill Janssen39295c22008-08-12 16:31:21 +0000357 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
358 if test_support.verbose and self.server.connectionchatty:
359 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
360 self.write("OK\n")
361 self.sslconn.unwrap()
362 self.sslconn = None
363 if test_support.verbose and self.server.connectionchatty:
364 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000365 else:
366 if (test_support.verbose and
367 self.server.connectionchatty):
368 ctype = (self.sslconn and "encrypted") or "unencrypted"
369 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
370 % (repr(msg), ctype, repr(msg.lower()), ctype))
371 self.write(msg.lower())
372 except ssl.SSLError:
373 if self.server.chatty:
374 handle_error("Test server failure:\n")
375 self.close()
376 self.running = False
377 # normally, we'd just stop here, but for the test
378 # harness, we want to stop the server
379 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000380
Trent Nelsone41b0062008-04-08 23:47:30 +0000381 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000382 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000383 chatty=True, connectionchatty=False, starttls_server=False,
384 wrap_accepting_socket=False):
385
Bill Janssen98d19da2007-09-10 21:51:02 +0000386 if ssl_version is None:
387 ssl_version = ssl.PROTOCOL_TLSv1
388 if certreqs is None:
389 certreqs = ssl.CERT_NONE
390 self.certificate = certificate
391 self.protocol = ssl_version
392 self.certreqs = certreqs
393 self.cacerts = cacerts
Bill Janssen98d19da2007-09-10 21:51:02 +0000394 self.chatty = chatty
395 self.connectionchatty = connectionchatty
396 self.starttls_server = starttls_server
397 self.sock = socket.socket()
398 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000399 if wrap_accepting_socket:
400 self.sock = ssl.wrap_socket(self.sock, server_side=True,
401 certfile=self.certificate,
402 cert_reqs = self.certreqs,
403 ca_certs = self.cacerts,
404 ssl_version = self.protocol)
405 if test_support.verbose and self.chatty:
406 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
407 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000408 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000409 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000410 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000411
412 def start (self, flag=None):
413 self.flag = flag
414 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000415
416 def run (self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000417 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000418 self.sock.listen(5)
419 self.active = True
420 if self.flag:
421 # signal an event
422 self.flag.set()
423 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000424 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000425 newconn, connaddr = self.sock.accept()
426 if test_support.verbose and self.chatty:
427 sys.stdout.write(' server: new connection from '
428 + str(connaddr) + '\n')
429 handler = self.ConnectionHandler(self, newconn)
430 handler.start()
431 except socket.timeout:
432 pass
433 except KeyboardInterrupt:
434 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000435 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000436
Bill Janssen98d19da2007-09-10 21:51:02 +0000437 def stop (self):
438 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000439
Bill Janssen934b16d2008-06-28 22:19:33 +0000440 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000441
Bill Janssen934b16d2008-06-28 22:19:33 +0000442 class EchoServer (asyncore.dispatcher):
443
444 class ConnectionHandler (asyncore.dispatcher_with_send):
445
446 def __init__(self, conn, certfile):
447 asyncore.dispatcher_with_send.__init__(self, conn)
448 self.socket = ssl.wrap_socket(conn, server_side=True,
449 certfile=certfile,
Antoine Pitrouc689d962010-04-24 20:13:37 +0000450 do_handshake_on_connect=False)
451 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000452
453 def readable(self):
454 if isinstance(self.socket, ssl.SSLSocket):
455 while self.socket.pending() > 0:
456 self.handle_read_event()
457 return True
458
Antoine Pitrouc689d962010-04-24 20:13:37 +0000459 def _do_ssl_handshake(self):
460 try:
461 self.socket.do_handshake()
462 except ssl.SSLError, err:
463 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
464 ssl.SSL_ERROR_WANT_WRITE):
465 return
466 elif err.args[0] == ssl.SSL_ERROR_EOF:
467 return self.handle_close()
468 raise
469 except socket.error, err:
470 if err.args[0] == errno.ECONNABORTED:
471 return self.handle_close()
472 else:
473 self._ssl_accepting = False
474
Bill Janssen934b16d2008-06-28 22:19:33 +0000475 def handle_read(self):
Antoine Pitrouc689d962010-04-24 20:13:37 +0000476 if self._ssl_accepting:
477 self._do_ssl_handshake()
478 else:
479 data = self.recv(1024)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000480 if data and data.strip() != 'over':
481 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000482
483 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000484 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000485 if test_support.verbose:
486 sys.stdout.write(" server: closed connection %s\n" % self.socket)
487
488 def handle_error(self):
489 raise
490
491 def __init__(self, certfile):
492 self.certfile = certfile
493 asyncore.dispatcher.__init__(self)
494 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
495 self.port = test_support.bind_port(self.socket)
496 self.listen(5)
497
498 def handle_accept(self):
499 sock_obj, addr = self.accept()
500 if test_support.verbose:
501 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
502 self.ConnectionHandler(sock_obj, self.certfile)
503
504 def handle_error(self):
505 raise
506
507 def __init__(self, certfile):
508 self.flag = None
509 self.active = False
510 self.server = self.EchoServer(certfile)
511 self.port = self.server.port
512 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000513 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000514
515 def __str__(self):
516 return "<%s %s>" % (self.__class__.__name__, self.server)
517
518 def start (self, flag=None):
519 self.flag = flag
520 threading.Thread.start(self)
521
522 def run (self):
523 self.active = True
524 if self.flag:
525 self.flag.set()
526 while self.active:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000527 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000528
529 def stop (self):
530 self.active = False
531 self.server.close()
532
533 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000534
535 class HTTPSServer(HTTPServer):
536
537 def __init__(self, server_address, RequestHandlerClass, certfile):
538
539 HTTPServer.__init__(self, server_address, RequestHandlerClass)
540 # we assume the certfile contains both private key and certificate
541 self.certfile = certfile
542 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000543 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000544 self.allow_reuse_address = True
545
Bill Janssen934b16d2008-06-28 22:19:33 +0000546 def __str__(self):
547 return ('<%s %s:%s>' %
548 (self.__class__.__name__,
549 self.server_name,
550 self.server_port))
551
Bill Janssen296a59d2007-09-16 22:06:00 +0000552 def get_request (self):
553 # override this to wrap socket with SSL
554 sock, addr = self.socket.accept()
555 sslconn = ssl.wrap_socket(sock, server_side=True,
556 certfile=self.certfile)
557 return sslconn, addr
558
Bill Janssen296a59d2007-09-16 22:06:00 +0000559 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
560
561 # need to override translate_path to get a known root,
562 # instead of using os.curdir, since the test could be
563 # run from anywhere
564
565 server_version = "TestHTTPS/1.0"
566
567 root = None
568
569 def translate_path(self, path):
570 """Translate a /-separated PATH to the local filename syntax.
571
572 Components that mean special things to the local file system
573 (e.g. drive or directory names) are ignored. (XXX They should
574 probably be diagnosed.)
575
576 """
577 # abandon query parameters
578 path = urlparse.urlparse(path)[2]
579 path = os.path.normpath(urllib.unquote(path))
580 words = path.split('/')
581 words = filter(None, words)
582 path = self.root
583 for word in words:
584 drive, word = os.path.splitdrive(word)
585 head, word = os.path.split(word)
586 if word in self.root: continue
587 path = os.path.join(path, word)
588 return path
589
590 def log_message(self, format, *args):
591
592 # we override this to suppress logging unless "verbose"
593
594 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000595 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
596 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000597 self.server.server_port,
598 self.request.cipher(),
599 self.log_date_time_string(),
600 format%args))
601
602
Trent Nelsone41b0062008-04-08 23:47:30 +0000603 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000604 self.flag = None
605 self.active = False
606 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
607 self.server = self.HTTPSServer(
Antoine Pitrou6535b312010-04-27 08:43:11 +0000608 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
609 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000610 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000611 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000612
613 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000614 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000615
616 def start (self, flag=None):
617 self.flag = flag
618 threading.Thread.start(self)
619
620 def run (self):
621 self.active = True
622 if self.flag:
623 self.flag.set()
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000624 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000625 self.active = False
626
627 def stop (self):
628 self.active = False
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000629 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000630
631
Bill Janssen98d19da2007-09-10 21:51:02 +0000632 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000633 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000634 certreqs=ssl.CERT_REQUIRED,
635 cacerts=CERTFILE, chatty=False)
636 flag = threading.Event()
637 server.start(flag)
638 # wait for it to start
639 flag.wait()
640 # try to connect
641 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000642 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000643 s = ssl.wrap_socket(socket.socket(),
644 certfile=certfile,
645 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000646 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000647 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000648 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000649 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000650 except socket.error, x:
651 if test_support.verbose:
652 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000653 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000654 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000655 finally:
656 server.stop()
657 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000658
Bill Janssen98d19da2007-09-10 21:51:02 +0000659 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
660 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000661 chatty=True, connectionchatty=False,
662 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000663
Trent Nelsone41b0062008-04-08 23:47:30 +0000664 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000665 certreqs=certreqs,
666 ssl_version=protocol,
667 cacerts=cacertsfile,
668 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000669 connectionchatty=connectionchatty,
670 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000671 flag = threading.Event()
672 server.start(flag)
673 # wait for it to start
674 flag.wait()
675 # try to connect
676 if client_protocol is None:
677 client_protocol = protocol
678 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000679 s = ssl.wrap_socket(socket.socket(),
680 certfile=client_certfile,
681 ca_certs=cacertsfile,
682 cert_reqs=certreqs,
683 ssl_version=client_protocol)
684 s.connect((HOST, server.port))
685 if connectionchatty:
686 if test_support.verbose:
687 sys.stdout.write(
688 " client: sending %s...\n" % (repr(indata)))
689 s.write(indata)
690 outdata = s.read()
691 if connectionchatty:
692 if test_support.verbose:
693 sys.stdout.write(" client: read %s\n" % repr(outdata))
694 if outdata != indata.lower():
695 self.fail(
696 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
697 % (outdata[:min(len(outdata),20)], len(outdata),
698 indata[:min(len(indata),20)].lower(), len(indata)))
699 s.write("over\n")
700 if connectionchatty:
701 if test_support.verbose:
702 sys.stdout.write(" client: closing connection.\n")
703 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000704 finally:
705 server.stop()
706 server.join()
707
708 def tryProtocolCombo (server_protocol,
709 client_protocol,
710 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000711 certsreqs=None):
712
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000713 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000714 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000715
716 if certsreqs == ssl.CERT_NONE:
717 certtype = "CERT_NONE"
718 elif certsreqs == ssl.CERT_OPTIONAL:
719 certtype = "CERT_OPTIONAL"
720 elif certsreqs == ssl.CERT_REQUIRED:
721 certtype = "CERT_REQUIRED"
722 if test_support.verbose:
723 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
724 sys.stdout.write(formatstr %
725 (ssl.get_protocol_name(client_protocol),
726 ssl.get_protocol_name(server_protocol),
727 certtype))
728 try:
729 serverParamsTest(CERTFILE, server_protocol, certsreqs,
730 CERTFILE, CERTFILE, client_protocol, chatty=False)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000731 # Protocol mismatch can result in either an SSLError, or a
732 # "Connection reset by peer" error.
733 except ssl.SSLError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000734 if expectedToWork:
735 raise
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000736 except socket.error as e:
737 if expectedToWork or e.errno != errno.ECONNRESET:
738 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000739 else:
740 if not expectedToWork:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000741 self.fail(
Bill Janssen98d19da2007-09-10 21:51:02 +0000742 "Client protocol %s succeeded with server protocol %s!"
743 % (ssl.get_protocol_name(client_protocol),
744 ssl.get_protocol_name(server_protocol)))
745
746
Bill Janssen934b16d2008-06-28 22:19:33 +0000747 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000748
749 def testRudeShutdown(self):
750
751 listener_ready = threading.Event()
752 listener_gone = threading.Event()
753
Antoine Pitrou6535b312010-04-27 08:43:11 +0000754 s = socket.socket()
755 port = test_support.bind_port(s, HOST)
756
757 # `listener` runs in a thread. It sits in an accept() until
758 # the main thread connects. Then it rudely closes the socket,
759 # and sets Event `listener_gone` to let the main thread know
760 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000761 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000762 s.listen(5)
763 listener_ready.set()
764 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000765 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000766 listener_gone.set()
767
768 def connector():
769 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000770 c = socket.socket()
771 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000772 listener_gone.wait()
773 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000774 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000775 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000776 pass
777 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000778 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000779
780 t = threading.Thread(target=listener)
781 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000782 try:
783 connector()
784 finally:
785 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000786
787 def testEcho (self):
788
789 if test_support.verbose:
790 sys.stdout.write("\n")
791 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
792 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
793 chatty=True, connectionchatty=True)
794
795 def testReadCert(self):
796
797 if test_support.verbose:
798 sys.stdout.write("\n")
799 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000800 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000801 certreqs=ssl.CERT_NONE,
802 ssl_version=ssl.PROTOCOL_SSLv23,
803 cacerts=CERTFILE,
804 chatty=False)
805 flag = threading.Event()
806 server.start(flag)
807 # wait for it to start
808 flag.wait()
809 # try to connect
810 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000811 s = ssl.wrap_socket(socket.socket(),
812 certfile=CERTFILE,
813 ca_certs=CERTFILE,
814 cert_reqs=ssl.CERT_REQUIRED,
815 ssl_version=ssl.PROTOCOL_SSLv23)
816 s.connect((HOST, server.port))
817 cert = s.getpeercert()
818 self.assertTrue(cert, "Can't get peer certificate.")
819 cipher = s.cipher()
820 if test_support.verbose:
821 sys.stdout.write(pprint.pformat(cert) + '\n')
822 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
823 if 'subject' not in cert:
824 self.fail("No subject field in certificate: %s." %
825 pprint.pformat(cert))
826 if ((('organizationName', 'Python Software Foundation'),)
827 not in cert['subject']):
828 self.fail(
829 "Missing or invalid 'organizationName' field in certificate subject; "
830 "should be 'Python Software Foundation'.")
831 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000832 finally:
833 server.stop()
834 server.join()
835
836 def testNULLcert(self):
837 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
838 "nullcert.pem"))
839 def testMalformedCert(self):
840 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
841 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000842 def testWrongCert(self):
843 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
844 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000845 def testMalformedKey(self):
846 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
847 "badkey.pem"))
848
849 def testProtocolSSL2(self):
850 if test_support.verbose:
851 sys.stdout.write("\n")
852 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
853 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
854 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
855 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
856 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
857 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
858
859 def testProtocolSSL23(self):
860 if test_support.verbose:
861 sys.stdout.write("\n")
862 try:
863 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000864 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000865 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
866 if test_support.verbose:
867 sys.stdout.write(
868 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
869 % str(x))
870 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
871 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
872 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
873
874 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
875 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
876 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
877
878 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
879 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
880 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
881
882 def testProtocolSSL3(self):
883 if test_support.verbose:
884 sys.stdout.write("\n")
885 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
886 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
887 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
888 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
889 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
890 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
891
892 def testProtocolTLS1(self):
893 if test_support.verbose:
894 sys.stdout.write("\n")
895 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
896 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
897 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
898 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
899 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
900 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
901
902 def testSTARTTLS (self):
903
Bill Janssen39295c22008-08-12 16:31:21 +0000904 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000905
Trent Nelsone41b0062008-04-08 23:47:30 +0000906 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000907 ssl_version=ssl.PROTOCOL_TLSv1,
908 starttls_server=True,
909 chatty=True,
910 connectionchatty=True)
911 flag = threading.Event()
912 server.start(flag)
913 # wait for it to start
914 flag.wait()
915 # try to connect
916 wrapped = False
917 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000918 s = socket.socket()
919 s.setblocking(1)
920 s.connect((HOST, server.port))
921 if test_support.verbose:
922 sys.stdout.write("\n")
923 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000924 if test_support.verbose:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000925 sys.stdout.write(
926 " client: sending %s...\n" % repr(indata))
927 if wrapped:
928 conn.write(indata)
929 outdata = conn.read()
930 else:
931 s.send(indata)
932 outdata = s.recv(1024)
933 if (indata == "STARTTLS" and
934 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000935 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000936 sys.stdout.write(
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000937 " client: read %s from server, starting TLS...\n"
938 % repr(outdata))
939 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
940 wrapped = True
941 elif (indata == "ENDTLS" and
942 outdata.strip().lower().startswith("ok")):
943 if test_support.verbose:
944 sys.stdout.write(
945 " client: read %s from server, ending TLS...\n"
946 % repr(outdata))
947 s = conn.unwrap()
948 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000949 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000950 if test_support.verbose:
951 sys.stdout.write(
952 " client: read %s from server\n" % repr(outdata))
953 if test_support.verbose:
954 sys.stdout.write(" client: closing connection.\n")
955 if wrapped:
956 conn.write("over\n")
957 else:
958 s.send("over\n")
959 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000960 finally:
961 server.stop()
962 server.join()
963
Bill Janssen934b16d2008-06-28 22:19:33 +0000964 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000965
Bill Janssen934b16d2008-06-28 22:19:33 +0000966 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000967 flag = threading.Event()
968 server.start(flag)
969 # wait for it to start
970 flag.wait()
971 # try to connect
972 try:
973 if test_support.verbose:
974 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +0000975 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000976 d2 = ''
977 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +0000978 url = 'https://127.0.0.1:%d/%s' % (
979 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +0000980 f = urllib.urlopen(url)
981 dlen = f.info().getheader("content-length")
982 if dlen and (int(dlen) > 0):
983 d2 = f.read(int(dlen))
984 if test_support.verbose:
985 sys.stdout.write(
986 " client: read %d bytes from remote server '%s'\n"
987 % (len(d2), server))
988 f.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000989 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000990 finally:
991 server.stop()
992 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +0000993
Bill Janssen934b16d2008-06-28 22:19:33 +0000994 def testWrappedAccept (self):
995
996 if test_support.verbose:
997 sys.stdout.write("\n")
998 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
999 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1000 chatty=True, connectionchatty=True,
1001 wrap_accepting_socket=True)
1002
1003
1004 def testAsyncoreServer (self):
1005
1006 indata = "TEST MESSAGE of mixed case\n"
1007
1008 if test_support.verbose:
1009 sys.stdout.write("\n")
1010 server = AsyncoreEchoServer(CERTFILE)
1011 flag = threading.Event()
1012 server.start(flag)
1013 # wait for it to start
1014 flag.wait()
1015 # try to connect
1016 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001017 s = ssl.wrap_socket(socket.socket())
1018 s.connect(('127.0.0.1', server.port))
1019 if test_support.verbose:
1020 sys.stdout.write(
1021 " client: sending %s...\n" % (repr(indata)))
1022 s.write(indata)
1023 outdata = s.read()
1024 if test_support.verbose:
1025 sys.stdout.write(" client: read %s\n" % repr(outdata))
1026 if outdata != indata.lower():
1027 self.fail(
1028 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1029 % (outdata[:min(len(outdata),20)], len(outdata),
1030 indata[:min(len(indata),20)].lower(), len(indata)))
1031 s.write("over\n")
1032 if test_support.verbose:
1033 sys.stdout.write(" client: closing connection.\n")
1034 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001035 finally:
1036 server.stop()
1037 # wait for server thread to end
1038 server.join()
1039
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001040
Bill Janssen61c001a2008-09-08 16:37:24 +00001041 def testAllRecvAndSendMethods(self):
1042
1043 if test_support.verbose:
1044 sys.stdout.write("\n")
1045
1046 server = ThreadedEchoServer(CERTFILE,
1047 certreqs=ssl.CERT_NONE,
1048 ssl_version=ssl.PROTOCOL_TLSv1,
1049 cacerts=CERTFILE,
1050 chatty=True,
1051 connectionchatty=False)
1052 flag = threading.Event()
1053 server.start(flag)
1054 # wait for it to start
1055 flag.wait()
1056 # try to connect
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001057 s = ssl.wrap_socket(socket.socket(),
1058 server_side=False,
1059 certfile=CERTFILE,
1060 ca_certs=CERTFILE,
1061 cert_reqs=ssl.CERT_NONE,
1062 ssl_version=ssl.PROTOCOL_TLSv1)
1063 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001064 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001065 # helper methods for standardising recv* method signatures
1066 def _recv_into():
1067 b = bytearray("\0"*100)
1068 count = s.recv_into(b)
1069 return b[:count]
1070
1071 def _recvfrom_into():
1072 b = bytearray("\0"*100)
1073 count, addr = s.recvfrom_into(b)
1074 return b[:count]
1075
1076 # (name, method, whether to expect success, *args)
1077 send_methods = [
1078 ('send', s.send, True, []),
1079 ('sendto', s.sendto, False, ["some.address"]),
1080 ('sendall', s.sendall, True, []),
1081 ]
1082 recv_methods = [
1083 ('recv', s.recv, True, []),
1084 ('recvfrom', s.recvfrom, False, ["some.address"]),
1085 ('recv_into', _recv_into, True, []),
1086 ('recvfrom_into', _recvfrom_into, False, []),
1087 ]
1088 data_prefix = u"PREFIX_"
1089
1090 for meth_name, send_meth, expect_success, args in send_methods:
1091 indata = data_prefix + meth_name
1092 try:
1093 send_meth(indata.encode('ASCII', 'strict'), *args)
1094 outdata = s.read()
1095 outdata = outdata.decode('ASCII', 'strict')
1096 if outdata != indata.lower():
1097 raise support.TestFailed(
1098 "While sending with <<%s>> bad data "
1099 "<<%r>> (%d) received; "
1100 "expected <<%r>> (%d)\n" % (
1101 meth_name, outdata[:20], len(outdata),
1102 indata[:20], len(indata)
1103 )
1104 )
1105 except ValueError as e:
1106 if expect_success:
1107 raise support.TestFailed(
1108 "Failed to send with method <<%s>>; "
1109 "expected to succeed.\n" % (meth_name,)
1110 )
1111 if not str(e).startswith(meth_name):
1112 raise support.TestFailed(
1113 "Method <<%s>> failed with unexpected "
1114 "exception message: %s\n" % (
1115 meth_name, e
1116 )
1117 )
1118
1119 for meth_name, recv_meth, expect_success, args in recv_methods:
1120 indata = data_prefix + meth_name
1121 try:
1122 s.send(indata.encode('ASCII', 'strict'))
1123 outdata = recv_meth(*args)
1124 outdata = outdata.decode('ASCII', 'strict')
1125 if outdata != indata.lower():
1126 raise support.TestFailed(
1127 "While receiving with <<%s>> bad data "
1128 "<<%r>> (%d) received; "
1129 "expected <<%r>> (%d)\n" % (
1130 meth_name, outdata[:20], len(outdata),
1131 indata[:20], len(indata)
1132 )
1133 )
1134 except ValueError as e:
1135 if expect_success:
1136 raise support.TestFailed(
1137 "Failed to receive with method <<%s>>; "
1138 "expected to succeed.\n" % (meth_name,)
1139 )
1140 if not str(e).startswith(meth_name):
1141 raise support.TestFailed(
1142 "Method <<%s>> failed with unexpected "
1143 "exception message: %s\n" % (
1144 meth_name, e
1145 )
1146 )
1147 # consume data
1148 s.read()
1149
1150 s.write("over\n".encode("ASCII", "strict"))
1151 s.close()
1152 finally:
1153 server.stop()
1154 server.join()
1155
Antoine Pitrouc689d962010-04-24 20:13:37 +00001156 def test_handshake_timeout(self):
1157 # Issue #5103: SSL handshake must respect the socket timeout
1158 server = socket.socket(socket.AF_INET)
1159 host = "127.0.0.1"
1160 port = test_support.bind_port(server)
1161 started = threading.Event()
1162 finish = False
1163
1164 def serve():
1165 server.listen(5)
1166 started.set()
1167 conns = []
1168 while not finish:
1169 r, w, e = select.select([server], [], [], 0.1)
1170 if server in r:
1171 # Let the socket hang around rather than having
1172 # it closed by garbage collection.
1173 conns.append(server.accept()[0])
1174
1175 t = threading.Thread(target=serve)
1176 t.start()
1177 started.wait()
1178
1179 try:
1180 try:
1181 c = socket.socket(socket.AF_INET)
1182 c.settimeout(0.2)
1183 c.connect((host, port))
1184 # Will attempt handshake and time out
1185 try:
1186 ssl.wrap_socket(c)
1187 except ssl.SSLError, e:
1188 self.assertTrue("timed out" in str(e), str(e))
1189 else:
1190 self.fail("SSLError wasn't raised")
1191 finally:
1192 c.close()
1193 try:
1194 c = socket.socket(socket.AF_INET)
1195 c.settimeout(0.2)
1196 c = ssl.wrap_socket(c)
1197 # Will attempt handshake and time out
1198 try:
1199 c.connect((host, port))
1200 except ssl.SSLError, e:
1201 self.assertTrue("timed out" in str(e), str(e))
1202 else:
1203 self.fail("SSLError wasn't raised")
1204 finally:
1205 c.close()
1206 finally:
1207 finish = True
1208 t.join()
1209 server.close()
1210
Bill Janssen61c001a2008-09-08 16:37:24 +00001211
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001212def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001213 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001214 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001215
Trent Nelsone41b0062008-04-08 23:47:30 +00001216 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001217 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001218 "keycert.pem")
1219 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1220 os.path.dirname(__file__) or os.curdir,
1221 "https_svn_python_org_root.pem")
1222
1223 if (not os.path.exists(CERTFILE) or
1224 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001225 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001226
1227 tests = [BasicTests]
1228
Bill Janssen296a59d2007-09-16 22:06:00 +00001229 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001230 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001231
Bill Janssen98d19da2007-09-10 21:51:02 +00001232 if _have_threads:
1233 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001234 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001235 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001236
Bill Janssen98d19da2007-09-10 21:51:02 +00001237 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001238
Bill Janssen98d19da2007-09-10 21:51:02 +00001239 if _have_threads:
1240 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001241
1242if __name__ == "__main__":
1243 test_main()