blob: e8f03d1c36f4eb7bead79bebd5cff361f741a275 [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])
650 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000651 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000652 finally:
653 server.stop()
654 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000655
Bill Janssen98d19da2007-09-10 21:51:02 +0000656 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
657 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000658 chatty=True, connectionchatty=False,
659 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000660
Trent Nelsone41b0062008-04-08 23:47:30 +0000661 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000662 certreqs=certreqs,
663 ssl_version=protocol,
664 cacerts=cacertsfile,
665 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000666 connectionchatty=connectionchatty,
667 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000668 flag = threading.Event()
669 server.start(flag)
670 # wait for it to start
671 flag.wait()
672 # try to connect
673 if client_protocol is None:
674 client_protocol = protocol
675 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000676 s = ssl.wrap_socket(socket.socket(),
677 certfile=client_certfile,
678 ca_certs=cacertsfile,
679 cert_reqs=certreqs,
680 ssl_version=client_protocol)
681 s.connect((HOST, server.port))
682 if connectionchatty:
683 if test_support.verbose:
684 sys.stdout.write(
685 " client: sending %s...\n" % (repr(indata)))
686 s.write(indata)
687 outdata = s.read()
688 if connectionchatty:
689 if test_support.verbose:
690 sys.stdout.write(" client: read %s\n" % repr(outdata))
691 if outdata != indata.lower():
692 self.fail(
693 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
694 % (outdata[:min(len(outdata),20)], len(outdata),
695 indata[:min(len(indata),20)].lower(), len(indata)))
696 s.write("over\n")
697 if connectionchatty:
698 if test_support.verbose:
699 sys.stdout.write(" client: closing connection.\n")
700 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000701 finally:
702 server.stop()
703 server.join()
704
705 def tryProtocolCombo (server_protocol,
706 client_protocol,
707 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000708 certsreqs=None):
709
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000710 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000711 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000712
713 if certsreqs == ssl.CERT_NONE:
714 certtype = "CERT_NONE"
715 elif certsreqs == ssl.CERT_OPTIONAL:
716 certtype = "CERT_OPTIONAL"
717 elif certsreqs == ssl.CERT_REQUIRED:
718 certtype = "CERT_REQUIRED"
719 if test_support.verbose:
720 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
721 sys.stdout.write(formatstr %
722 (ssl.get_protocol_name(client_protocol),
723 ssl.get_protocol_name(server_protocol),
724 certtype))
725 try:
726 serverParamsTest(CERTFILE, server_protocol, certsreqs,
727 CERTFILE, CERTFILE, client_protocol, chatty=False)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000728 # Protocol mismatch can result in either an SSLError, or a
729 # "Connection reset by peer" error.
730 except ssl.SSLError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000731 if expectedToWork:
732 raise
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000733 except socket.error as e:
734 if expectedToWork or e.errno != errno.ECONNRESET:
735 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000736 else:
737 if not expectedToWork:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000738 self.fail(
Bill Janssen98d19da2007-09-10 21:51:02 +0000739 "Client protocol %s succeeded with server protocol %s!"
740 % (ssl.get_protocol_name(client_protocol),
741 ssl.get_protocol_name(server_protocol)))
742
743
Bill Janssen934b16d2008-06-28 22:19:33 +0000744 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000745
746 def testRudeShutdown(self):
747
748 listener_ready = threading.Event()
749 listener_gone = threading.Event()
750
Antoine Pitrou6535b312010-04-27 08:43:11 +0000751 s = socket.socket()
752 port = test_support.bind_port(s, HOST)
753
754 # `listener` runs in a thread. It sits in an accept() until
755 # the main thread connects. Then it rudely closes the socket,
756 # and sets Event `listener_gone` to let the main thread know
757 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000758 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000759 s.listen(5)
760 listener_ready.set()
761 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000762 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000763 listener_gone.set()
764
765 def connector():
766 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000767 c = socket.socket()
768 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000769 listener_gone.wait()
770 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000771 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000772 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000773 pass
774 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000775 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000776
777 t = threading.Thread(target=listener)
778 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000779 try:
780 connector()
781 finally:
782 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000783
784 def testEcho (self):
785
786 if test_support.verbose:
787 sys.stdout.write("\n")
788 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
789 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
790 chatty=True, connectionchatty=True)
791
792 def testReadCert(self):
793
794 if test_support.verbose:
795 sys.stdout.write("\n")
796 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000797 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000798 certreqs=ssl.CERT_NONE,
799 ssl_version=ssl.PROTOCOL_SSLv23,
800 cacerts=CERTFILE,
801 chatty=False)
802 flag = threading.Event()
803 server.start(flag)
804 # wait for it to start
805 flag.wait()
806 # try to connect
807 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000808 s = ssl.wrap_socket(socket.socket(),
809 certfile=CERTFILE,
810 ca_certs=CERTFILE,
811 cert_reqs=ssl.CERT_REQUIRED,
812 ssl_version=ssl.PROTOCOL_SSLv23)
813 s.connect((HOST, server.port))
814 cert = s.getpeercert()
815 self.assertTrue(cert, "Can't get peer certificate.")
816 cipher = s.cipher()
817 if test_support.verbose:
818 sys.stdout.write(pprint.pformat(cert) + '\n')
819 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
820 if 'subject' not in cert:
821 self.fail("No subject field in certificate: %s." %
822 pprint.pformat(cert))
823 if ((('organizationName', 'Python Software Foundation'),)
824 not in cert['subject']):
825 self.fail(
826 "Missing or invalid 'organizationName' field in certificate subject; "
827 "should be 'Python Software Foundation'.")
828 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000829 finally:
830 server.stop()
831 server.join()
832
833 def testNULLcert(self):
834 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
835 "nullcert.pem"))
836 def testMalformedCert(self):
837 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
838 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000839 def testWrongCert(self):
840 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
841 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000842 def testMalformedKey(self):
843 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
844 "badkey.pem"))
845
846 def testProtocolSSL2(self):
847 if test_support.verbose:
848 sys.stdout.write("\n")
849 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
850 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
851 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
852 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
853 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
854 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
855
856 def testProtocolSSL23(self):
857 if test_support.verbose:
858 sys.stdout.write("\n")
859 try:
860 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000861 except (SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000862 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
863 if test_support.verbose:
864 sys.stdout.write(
865 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
866 % str(x))
867 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
868 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
869 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
870
871 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
872 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
873 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
874
875 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
876 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
877 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
878
879 def testProtocolSSL3(self):
880 if test_support.verbose:
881 sys.stdout.write("\n")
882 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
883 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
884 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
885 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
886 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
887 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
888
889 def testProtocolTLS1(self):
890 if test_support.verbose:
891 sys.stdout.write("\n")
892 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
893 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
894 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
895 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
896 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
897 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
898
899 def testSTARTTLS (self):
900
Bill Janssen39295c22008-08-12 16:31:21 +0000901 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000902
Trent Nelsone41b0062008-04-08 23:47:30 +0000903 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000904 ssl_version=ssl.PROTOCOL_TLSv1,
905 starttls_server=True,
906 chatty=True,
907 connectionchatty=True)
908 flag = threading.Event()
909 server.start(flag)
910 # wait for it to start
911 flag.wait()
912 # try to connect
913 wrapped = False
914 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000915 s = socket.socket()
916 s.setblocking(1)
917 s.connect((HOST, server.port))
918 if test_support.verbose:
919 sys.stdout.write("\n")
920 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000921 if test_support.verbose:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000922 sys.stdout.write(
923 " client: sending %s...\n" % repr(indata))
924 if wrapped:
925 conn.write(indata)
926 outdata = conn.read()
927 else:
928 s.send(indata)
929 outdata = s.recv(1024)
930 if (indata == "STARTTLS" and
931 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000932 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000933 sys.stdout.write(
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000934 " client: read %s from server, starting TLS...\n"
935 % repr(outdata))
936 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
937 wrapped = True
938 elif (indata == "ENDTLS" and
939 outdata.strip().lower().startswith("ok")):
940 if test_support.verbose:
941 sys.stdout.write(
942 " client: read %s from server, ending TLS...\n"
943 % repr(outdata))
944 s = conn.unwrap()
945 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000946 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000947 if test_support.verbose:
948 sys.stdout.write(
949 " client: read %s from server\n" % repr(outdata))
950 if test_support.verbose:
951 sys.stdout.write(" client: closing connection.\n")
952 if wrapped:
953 conn.write("over\n")
954 else:
955 s.send("over\n")
956 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000957 finally:
958 server.stop()
959 server.join()
960
Bill Janssen934b16d2008-06-28 22:19:33 +0000961 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000962
Bill Janssen934b16d2008-06-28 22:19:33 +0000963 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000964 flag = threading.Event()
965 server.start(flag)
966 # wait for it to start
967 flag.wait()
968 # try to connect
969 try:
970 if test_support.verbose:
971 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +0000972 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000973 d2 = ''
974 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +0000975 url = 'https://127.0.0.1:%d/%s' % (
976 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +0000977 f = urllib.urlopen(url)
978 dlen = f.info().getheader("content-length")
979 if dlen and (int(dlen) > 0):
980 d2 = f.read(int(dlen))
981 if test_support.verbose:
982 sys.stdout.write(
983 " client: read %d bytes from remote server '%s'\n"
984 % (len(d2), server))
985 f.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000986 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000987 finally:
988 server.stop()
989 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +0000990
Bill Janssen934b16d2008-06-28 22:19:33 +0000991 def testWrappedAccept (self):
992
993 if test_support.verbose:
994 sys.stdout.write("\n")
995 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
996 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
997 chatty=True, connectionchatty=True,
998 wrap_accepting_socket=True)
999
1000
1001 def testAsyncoreServer (self):
1002
1003 indata = "TEST MESSAGE of mixed case\n"
1004
1005 if test_support.verbose:
1006 sys.stdout.write("\n")
1007 server = AsyncoreEchoServer(CERTFILE)
1008 flag = threading.Event()
1009 server.start(flag)
1010 # wait for it to start
1011 flag.wait()
1012 # try to connect
1013 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001014 s = ssl.wrap_socket(socket.socket())
1015 s.connect(('127.0.0.1', server.port))
1016 if test_support.verbose:
1017 sys.stdout.write(
1018 " client: sending %s...\n" % (repr(indata)))
1019 s.write(indata)
1020 outdata = s.read()
1021 if test_support.verbose:
1022 sys.stdout.write(" client: read %s\n" % repr(outdata))
1023 if outdata != indata.lower():
1024 self.fail(
1025 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1026 % (outdata[:min(len(outdata),20)], len(outdata),
1027 indata[:min(len(indata),20)].lower(), len(indata)))
1028 s.write("over\n")
1029 if test_support.verbose:
1030 sys.stdout.write(" client: closing connection.\n")
1031 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001032 finally:
1033 server.stop()
1034 # wait for server thread to end
1035 server.join()
1036
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001037
Bill Janssen61c001a2008-09-08 16:37:24 +00001038 def testAllRecvAndSendMethods(self):
1039
1040 if test_support.verbose:
1041 sys.stdout.write("\n")
1042
1043 server = ThreadedEchoServer(CERTFILE,
1044 certreqs=ssl.CERT_NONE,
1045 ssl_version=ssl.PROTOCOL_TLSv1,
1046 cacerts=CERTFILE,
1047 chatty=True,
1048 connectionchatty=False)
1049 flag = threading.Event()
1050 server.start(flag)
1051 # wait for it to start
1052 flag.wait()
1053 # try to connect
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001054 s = ssl.wrap_socket(socket.socket(),
1055 server_side=False,
1056 certfile=CERTFILE,
1057 ca_certs=CERTFILE,
1058 cert_reqs=ssl.CERT_NONE,
1059 ssl_version=ssl.PROTOCOL_TLSv1)
1060 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001061 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001062 # helper methods for standardising recv* method signatures
1063 def _recv_into():
1064 b = bytearray("\0"*100)
1065 count = s.recv_into(b)
1066 return b[:count]
1067
1068 def _recvfrom_into():
1069 b = bytearray("\0"*100)
1070 count, addr = s.recvfrom_into(b)
1071 return b[:count]
1072
1073 # (name, method, whether to expect success, *args)
1074 send_methods = [
1075 ('send', s.send, True, []),
1076 ('sendto', s.sendto, False, ["some.address"]),
1077 ('sendall', s.sendall, True, []),
1078 ]
1079 recv_methods = [
1080 ('recv', s.recv, True, []),
1081 ('recvfrom', s.recvfrom, False, ["some.address"]),
1082 ('recv_into', _recv_into, True, []),
1083 ('recvfrom_into', _recvfrom_into, False, []),
1084 ]
1085 data_prefix = u"PREFIX_"
1086
1087 for meth_name, send_meth, expect_success, args in send_methods:
1088 indata = data_prefix + meth_name
1089 try:
1090 send_meth(indata.encode('ASCII', 'strict'), *args)
1091 outdata = s.read()
1092 outdata = outdata.decode('ASCII', 'strict')
1093 if outdata != indata.lower():
1094 raise support.TestFailed(
1095 "While sending with <<%s>> bad data "
1096 "<<%r>> (%d) received; "
1097 "expected <<%r>> (%d)\n" % (
1098 meth_name, outdata[:20], len(outdata),
1099 indata[:20], len(indata)
1100 )
1101 )
1102 except ValueError as e:
1103 if expect_success:
1104 raise support.TestFailed(
1105 "Failed to send with method <<%s>>; "
1106 "expected to succeed.\n" % (meth_name,)
1107 )
1108 if not str(e).startswith(meth_name):
1109 raise support.TestFailed(
1110 "Method <<%s>> failed with unexpected "
1111 "exception message: %s\n" % (
1112 meth_name, e
1113 )
1114 )
1115
1116 for meth_name, recv_meth, expect_success, args in recv_methods:
1117 indata = data_prefix + meth_name
1118 try:
1119 s.send(indata.encode('ASCII', 'strict'))
1120 outdata = recv_meth(*args)
1121 outdata = outdata.decode('ASCII', 'strict')
1122 if outdata != indata.lower():
1123 raise support.TestFailed(
1124 "While receiving with <<%s>> bad data "
1125 "<<%r>> (%d) received; "
1126 "expected <<%r>> (%d)\n" % (
1127 meth_name, outdata[:20], len(outdata),
1128 indata[:20], len(indata)
1129 )
1130 )
1131 except ValueError as e:
1132 if expect_success:
1133 raise support.TestFailed(
1134 "Failed to receive with method <<%s>>; "
1135 "expected to succeed.\n" % (meth_name,)
1136 )
1137 if not str(e).startswith(meth_name):
1138 raise support.TestFailed(
1139 "Method <<%s>> failed with unexpected "
1140 "exception message: %s\n" % (
1141 meth_name, e
1142 )
1143 )
1144 # consume data
1145 s.read()
1146
1147 s.write("over\n".encode("ASCII", "strict"))
1148 s.close()
1149 finally:
1150 server.stop()
1151 server.join()
1152
Antoine Pitrouc689d962010-04-24 20:13:37 +00001153 def test_handshake_timeout(self):
1154 # Issue #5103: SSL handshake must respect the socket timeout
1155 server = socket.socket(socket.AF_INET)
1156 host = "127.0.0.1"
1157 port = test_support.bind_port(server)
1158 started = threading.Event()
1159 finish = False
1160
1161 def serve():
1162 server.listen(5)
1163 started.set()
1164 conns = []
1165 while not finish:
1166 r, w, e = select.select([server], [], [], 0.1)
1167 if server in r:
1168 # Let the socket hang around rather than having
1169 # it closed by garbage collection.
1170 conns.append(server.accept()[0])
1171
1172 t = threading.Thread(target=serve)
1173 t.start()
1174 started.wait()
1175
1176 try:
1177 try:
1178 c = socket.socket(socket.AF_INET)
1179 c.settimeout(0.2)
1180 c.connect((host, port))
1181 # Will attempt handshake and time out
1182 try:
1183 ssl.wrap_socket(c)
1184 except ssl.SSLError, e:
1185 self.assertTrue("timed out" in str(e), str(e))
1186 else:
1187 self.fail("SSLError wasn't raised")
1188 finally:
1189 c.close()
1190 try:
1191 c = socket.socket(socket.AF_INET)
1192 c.settimeout(0.2)
1193 c = ssl.wrap_socket(c)
1194 # Will attempt handshake and time out
1195 try:
1196 c.connect((host, port))
1197 except ssl.SSLError, e:
1198 self.assertTrue("timed out" in str(e), str(e))
1199 else:
1200 self.fail("SSLError wasn't raised")
1201 finally:
1202 c.close()
1203 finally:
1204 finish = True
1205 t.join()
1206 server.close()
1207
Bill Janssen61c001a2008-09-08 16:37:24 +00001208
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001209def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001210 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001211 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001212
Trent Nelsone41b0062008-04-08 23:47:30 +00001213 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001214 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001215 "keycert.pem")
1216 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1217 os.path.dirname(__file__) or os.curdir,
1218 "https_svn_python_org_root.pem")
1219
1220 if (not os.path.exists(CERTFILE) or
1221 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001222 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001223
1224 tests = [BasicTests]
1225
Bill Janssen296a59d2007-09-16 22:06:00 +00001226 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001227 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001228
Bill Janssen98d19da2007-09-10 21:51:02 +00001229 if _have_threads:
1230 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001231 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001232 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001233
Bill Janssen98d19da2007-09-10 21:51:02 +00001234 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001235
Bill Janssen98d19da2007-09-10 21:51:02 +00001236 if _have_threads:
1237 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001238
1239if __name__ == "__main__":
1240 test_main()