blob: c1e53ec1a67cbeed6f5d0194aa5bad464e3e9f7b [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
Antoine Pitroud2867642010-04-28 21:12:43 +000043 def test_sslwrap_simple(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
Antoine Pitroud2867642010-04-28 21:12:43 +000060 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000061 ssl.PROTOCOL_SSLv2
62 ssl.PROTOCOL_SSLv23
63 ssl.PROTOCOL_SSLv3
64 ssl.PROTOCOL_TLSv1
65 ssl.CERT_NONE
66 ssl.CERT_OPTIONAL
67 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000068
Antoine Pitroud2867642010-04-28 21:12:43 +000069 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000070 v = ssl.RAND_status()
71 if test_support.verbose:
72 sys.stdout.write("\n RAND_status is %d (%s)\n"
73 % (v, (v and "sufficient randomness") or
74 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000075 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000076 ssl.RAND_egd(1)
77 except TypeError:
78 pass
Guido van Rossume4729332007-08-26 19:35:09 +000079 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000080 print "didn't raise TypeError"
81 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000082
Antoine Pitroud2867642010-04-28 21:12:43 +000083 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000084 # note that this uses an 'unofficial' function in _ssl.c,
85 # provided solely for this test, to exercise the certificate
86 # parsing code
87 p = ssl._ssl._test_decode_cert(CERTFILE, False)
88 if test_support.verbose:
89 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000090
Antoine Pitroud2867642010-04-28 21:12:43 +000091 def test_DER_to_PEM(self):
92 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
93 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +000094 d1 = ssl.PEM_cert_to_DER_cert(pem)
95 p2 = ssl.DER_cert_to_PEM_cert(d1)
96 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +000097 self.assertEqual(d1, d2)
Antoine Pitrou12cb1292010-04-27 22:05:18 +000098 if not p2.startswith(ssl.PEM_HEADER + '\n'):
99 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
100 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
101 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000102
Antoine Pitrou3df58d12010-04-23 23:07:37 +0000103 def test_refcycle(self):
104 # Issue #7943: an SSL object doesn't create reference cycles with
105 # itself.
106 s = socket.socket(socket.AF_INET)
107 ss = ssl.wrap_socket(s)
108 wr = weakref.ref(ss)
109 del ss
110 self.assertEqual(wr(), None)
111
Antoine Pitroud4030da2010-04-23 23:35:01 +0000112
Bill Janssen934b16d2008-06-28 22:19:33 +0000113class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000114
Antoine Pitroud2867642010-04-28 21:12:43 +0000115 def test_connect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000116 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
117 cert_reqs=ssl.CERT_NONE)
118 s.connect(("svn.python.org", 443))
119 c = s.getpeercert()
120 if c:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000121 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000122 s.close()
123
124 # this should fail because we have no verification certs
125 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
126 cert_reqs=ssl.CERT_REQUIRED)
127 try:
128 s.connect(("svn.python.org", 443))
129 except ssl.SSLError:
130 pass
131 finally:
132 s.close()
133
134 # this should succeed because we specify the root cert
135 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
136 cert_reqs=ssl.CERT_REQUIRED,
137 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
138 try:
139 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000140 finally:
141 s.close()
142
Antoine Pitrou0753d942010-04-24 11:09:52 +0000143 def test_makefile_close(self):
144 # Issue #5238: creating a file-like object with makefile() shouldn't
145 # delay closing the underlying "real socket" (here tested with its
146 # file descriptor, hence skipping the test under Windows).
147 if os.name == "nt":
148 if test_support.verbose:
149 print "Skipped: can't use a socket as a file under Windows"
150 return
151 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
152 ss.connect(("svn.python.org", 443))
153 fd = ss.fileno()
154 f = ss.makefile()
155 f.close()
156 # The fd is still open
157 os.read(fd, 0)
158 # Closing the SSL socket should close the fd too
159 ss.close()
160 gc.collect()
161 try:
162 os.read(fd, 0)
163 except OSError, e:
164 self.assertEqual(e.errno, errno.EBADF)
165 else:
166 self.fail("OSError wasn't raised")
Bill Janssen934b16d2008-06-28 22:19:33 +0000167
Antoine Pitroud2867642010-04-28 21:12:43 +0000168 def test_non_blocking_handshake(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000169 s = socket.socket(socket.AF_INET)
170 s.connect(("svn.python.org", 443))
171 s.setblocking(False)
172 s = ssl.wrap_socket(s,
173 cert_reqs=ssl.CERT_NONE,
174 do_handshake_on_connect=False)
175 count = 0
176 while True:
177 try:
178 count += 1
179 s.do_handshake()
180 break
181 except ssl.SSLError, err:
182 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
183 select.select([s], [], [])
184 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
185 select.select([], [s], [])
186 else:
187 raise
188 s.close()
189 if test_support.verbose:
190 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
191
Antoine Pitroud2867642010-04-28 21:12:43 +0000192 def test_get_server_certificate(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000193 pem = ssl.get_server_certificate(("svn.python.org", 443))
194 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000195 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000196
197 try:
198 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
199 except ssl.SSLError:
200 #should fail
201 pass
202 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000203 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000204
205 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
206 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000207 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000208 if test_support.verbose:
209 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
210
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000211 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000212 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000213 if test_support.verbose:
214 sys.stdout.write("test_algorithms disabled, "
215 "as it fails on some old OpenSSL versions")
216 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000217 # Issue #8484: all algorithms should be available when verifying a
218 # certificate.
219 # NOTE: https://sha256.tbs-internet.com is another possible test host
220 remote = ("sha2.hboeck.de", 443)
221 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
222 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
223 cert_reqs=ssl.CERT_REQUIRED,
224 ca_certs=sha256_cert,)
225 with test_support.transient_internet():
226 try:
227 s.connect(remote)
228 if test_support.verbose:
229 sys.stdout.write("\nCipher with %r is %r\n" %
230 (remote, s.cipher()))
231 sys.stdout.write("Certificate is:\n%s\n" %
232 pprint.pformat(s.getpeercert()))
233 finally:
234 s.close()
235
Bill Janssen296a59d2007-09-16 22:06:00 +0000236
Bill Janssen98d19da2007-09-10 21:51:02 +0000237try:
238 import threading
239except ImportError:
240 _have_threads = False
241else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000242 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000243
Bill Janssen98d19da2007-09-10 21:51:02 +0000244 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000245
Bill Janssen98d19da2007-09-10 21:51:02 +0000246 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000247
Bill Janssen98d19da2007-09-10 21:51:02 +0000248 """A mildly complicated class, because we want it to work both
249 with and without the SSL wrapper around the socket connection, so
250 that we can test the STARTTLS functionality."""
251
252 def __init__(self, server, connsock):
253 self.server = server
254 self.running = False
255 self.sock = connsock
256 self.sock.setblocking(1)
257 self.sslconn = None
258 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000259 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000260
Bill Janssen934b16d2008-06-28 22:19:33 +0000261 def show_conn_details(self):
262 if self.server.certreqs == ssl.CERT_REQUIRED:
263 cert = self.sslconn.getpeercert()
264 if test_support.verbose and self.server.chatty:
265 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
266 cert_binary = self.sslconn.getpeercert(True)
267 if test_support.verbose and self.server.chatty:
268 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
269 cipher = self.sslconn.cipher()
270 if test_support.verbose and self.server.chatty:
271 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
272
Antoine Pitroud2867642010-04-28 21:12:43 +0000273 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000274 try:
275 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
276 certfile=self.server.certificate,
277 ssl_version=self.server.protocol,
278 ca_certs=self.server.cacerts,
279 cert_reqs=self.server.certreqs)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000280 except ssl.SSLError:
281 # XXX Various errors can have happened here, for example
282 # a mismatching protocol version, an invalid certificate,
283 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000284 if self.server.chatty:
285 handle_error("\n server: bad connection attempt from " +
286 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000287 self.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000288 self.running = False
289 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000290 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000291 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000292 return True
293
294 def read(self):
295 if self.sslconn:
296 return self.sslconn.read()
297 else:
298 return self.sock.recv(1024)
299
300 def write(self, bytes):
301 if self.sslconn:
302 return self.sslconn.write(bytes)
303 else:
304 return self.sock.send(bytes)
305
306 def close(self):
307 if self.sslconn:
308 self.sslconn.close()
309 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000310 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000311
Antoine Pitroud2867642010-04-28 21:12:43 +0000312 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000313 self.running = True
314 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000315 if isinstance(self.sock, ssl.SSLSocket):
316 self.sslconn = self.sock
317 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000318 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000319 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000320 while self.running:
321 try:
322 msg = self.read()
323 if not msg:
324 # eof, so quit this handler
325 self.running = False
326 self.close()
327 elif msg.strip() == 'over':
328 if test_support.verbose and self.server.connectionchatty:
329 sys.stdout.write(" server: client closed connection\n")
330 self.close()
331 return
332 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
333 if test_support.verbose and self.server.connectionchatty:
334 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
335 self.write("OK\n")
336 if not self.wrap_conn():
337 return
Bill Janssen39295c22008-08-12 16:31:21 +0000338 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
339 if test_support.verbose and self.server.connectionchatty:
340 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
341 self.write("OK\n")
342 self.sslconn.unwrap()
343 self.sslconn = None
344 if test_support.verbose and self.server.connectionchatty:
345 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000346 else:
347 if (test_support.verbose and
348 self.server.connectionchatty):
349 ctype = (self.sslconn and "encrypted") or "unencrypted"
350 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
351 % (repr(msg), ctype, repr(msg.lower()), ctype))
352 self.write(msg.lower())
353 except ssl.SSLError:
354 if self.server.chatty:
355 handle_error("Test server failure:\n")
356 self.close()
357 self.running = False
358 # normally, we'd just stop here, but for the test
359 # harness, we want to stop the server
360 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000361
Trent Nelsone41b0062008-04-08 23:47:30 +0000362 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000363 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000364 chatty=True, connectionchatty=False, starttls_server=False,
365 wrap_accepting_socket=False):
366
Bill Janssen98d19da2007-09-10 21:51:02 +0000367 if ssl_version is None:
368 ssl_version = ssl.PROTOCOL_TLSv1
369 if certreqs is None:
370 certreqs = ssl.CERT_NONE
371 self.certificate = certificate
372 self.protocol = ssl_version
373 self.certreqs = certreqs
374 self.cacerts = cacerts
Bill Janssen98d19da2007-09-10 21:51:02 +0000375 self.chatty = chatty
376 self.connectionchatty = connectionchatty
377 self.starttls_server = starttls_server
378 self.sock = socket.socket()
379 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000380 if wrap_accepting_socket:
381 self.sock = ssl.wrap_socket(self.sock, server_side=True,
382 certfile=self.certificate,
383 cert_reqs = self.certreqs,
384 ca_certs = self.cacerts,
385 ssl_version = self.protocol)
386 if test_support.verbose and self.chatty:
387 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
388 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000389 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000390 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000391 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000392
Antoine Pitroud2867642010-04-28 21:12:43 +0000393 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000394 self.flag = flag
395 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000396
Antoine Pitroud2867642010-04-28 21:12:43 +0000397 def run(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000398 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000399 self.sock.listen(5)
400 self.active = True
401 if self.flag:
402 # signal an event
403 self.flag.set()
404 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000405 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000406 newconn, connaddr = self.sock.accept()
407 if test_support.verbose and self.chatty:
408 sys.stdout.write(' server: new connection from '
409 + str(connaddr) + '\n')
410 handler = self.ConnectionHandler(self, newconn)
411 handler.start()
412 except socket.timeout:
413 pass
414 except KeyboardInterrupt:
415 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000416 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000417
Antoine Pitroud2867642010-04-28 21:12:43 +0000418 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000419 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000420
Bill Janssen934b16d2008-06-28 22:19:33 +0000421 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000422
Antoine Pitroud2867642010-04-28 21:12:43 +0000423 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000424
Antoine Pitroud2867642010-04-28 21:12:43 +0000425 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000426
427 def __init__(self, conn, certfile):
428 asyncore.dispatcher_with_send.__init__(self, conn)
429 self.socket = ssl.wrap_socket(conn, server_side=True,
430 certfile=certfile,
Antoine Pitrouc689d962010-04-24 20:13:37 +0000431 do_handshake_on_connect=False)
432 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000433
434 def readable(self):
435 if isinstance(self.socket, ssl.SSLSocket):
436 while self.socket.pending() > 0:
437 self.handle_read_event()
438 return True
439
Antoine Pitrouc689d962010-04-24 20:13:37 +0000440 def _do_ssl_handshake(self):
441 try:
442 self.socket.do_handshake()
443 except ssl.SSLError, err:
444 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
445 ssl.SSL_ERROR_WANT_WRITE):
446 return
447 elif err.args[0] == ssl.SSL_ERROR_EOF:
448 return self.handle_close()
449 raise
450 except socket.error, err:
451 if err.args[0] == errno.ECONNABORTED:
452 return self.handle_close()
453 else:
454 self._ssl_accepting = False
455
Bill Janssen934b16d2008-06-28 22:19:33 +0000456 def handle_read(self):
Antoine Pitrouc689d962010-04-24 20:13:37 +0000457 if self._ssl_accepting:
458 self._do_ssl_handshake()
459 else:
460 data = self.recv(1024)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000461 if data and data.strip() != 'over':
462 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000463
464 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000465 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000466 if test_support.verbose:
467 sys.stdout.write(" server: closed connection %s\n" % self.socket)
468
469 def handle_error(self):
470 raise
471
472 def __init__(self, certfile):
473 self.certfile = certfile
474 asyncore.dispatcher.__init__(self)
475 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
476 self.port = test_support.bind_port(self.socket)
477 self.listen(5)
478
479 def handle_accept(self):
480 sock_obj, addr = self.accept()
481 if test_support.verbose:
482 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
483 self.ConnectionHandler(sock_obj, self.certfile)
484
485 def handle_error(self):
486 raise
487
488 def __init__(self, certfile):
489 self.flag = None
490 self.active = False
491 self.server = self.EchoServer(certfile)
492 self.port = self.server.port
493 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000494 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000495
496 def __str__(self):
497 return "<%s %s>" % (self.__class__.__name__, self.server)
498
Antoine Pitroud2867642010-04-28 21:12:43 +0000499 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000500 self.flag = flag
501 threading.Thread.start(self)
502
Antoine Pitroud2867642010-04-28 21:12:43 +0000503 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000504 self.active = True
505 if self.flag:
506 self.flag.set()
507 while self.active:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000508 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000509
Antoine Pitroud2867642010-04-28 21:12:43 +0000510 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000511 self.active = False
512 self.server.close()
513
514 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000515
516 class HTTPSServer(HTTPServer):
517
518 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000519 HTTPServer.__init__(self, server_address, RequestHandlerClass)
520 # we assume the certfile contains both private key and certificate
521 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000522 self.allow_reuse_address = True
523
Bill Janssen934b16d2008-06-28 22:19:33 +0000524 def __str__(self):
525 return ('<%s %s:%s>' %
526 (self.__class__.__name__,
527 self.server_name,
528 self.server_port))
529
Antoine Pitroud2867642010-04-28 21:12:43 +0000530 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000531 # override this to wrap socket with SSL
532 sock, addr = self.socket.accept()
533 sslconn = ssl.wrap_socket(sock, server_side=True,
534 certfile=self.certfile)
535 return sslconn, addr
536
Bill Janssen296a59d2007-09-16 22:06:00 +0000537 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000538 # need to override translate_path to get a known root,
539 # instead of using os.curdir, since the test could be
540 # run from anywhere
541
542 server_version = "TestHTTPS/1.0"
543
544 root = None
545
546 def translate_path(self, path):
547 """Translate a /-separated PATH to the local filename syntax.
548
549 Components that mean special things to the local file system
550 (e.g. drive or directory names) are ignored. (XXX They should
551 probably be diagnosed.)
552
553 """
554 # abandon query parameters
555 path = urlparse.urlparse(path)[2]
556 path = os.path.normpath(urllib.unquote(path))
557 words = path.split('/')
558 words = filter(None, words)
559 path = self.root
560 for word in words:
561 drive, word = os.path.splitdrive(word)
562 head, word = os.path.split(word)
563 if word in self.root: continue
564 path = os.path.join(path, word)
565 return path
566
567 def log_message(self, format, *args):
568
569 # we override this to suppress logging unless "verbose"
570
571 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000572 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
573 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000574 self.server.server_port,
575 self.request.cipher(),
576 self.log_date_time_string(),
577 format%args))
578
579
Trent Nelsone41b0062008-04-08 23:47:30 +0000580 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000581 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000582 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
583 self.server = self.HTTPSServer(
Antoine Pitrou6535b312010-04-27 08:43:11 +0000584 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
585 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000586 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000587 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000588
589 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000590 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000591
Antoine Pitroud2867642010-04-28 21:12:43 +0000592 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000593 self.flag = flag
594 threading.Thread.start(self)
595
Antoine Pitroud2867642010-04-28 21:12:43 +0000596 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000597 if self.flag:
598 self.flag.set()
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000599 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000600
Antoine Pitroud2867642010-04-28 21:12:43 +0000601 def stop(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000602 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000603
604
Antoine Pitroud2867642010-04-28 21:12:43 +0000605 def bad_cert_test(certfile):
606 """
607 Launch a server with CERT_REQUIRED, and check that trying to
608 connect to it with the given client certificate fails.
609 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000610 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000611 certreqs=ssl.CERT_REQUIRED,
612 cacerts=CERTFILE, chatty=False)
613 flag = threading.Event()
614 server.start(flag)
615 # wait for it to start
616 flag.wait()
617 # try to connect
618 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000619 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000620 s = ssl.wrap_socket(socket.socket(),
621 certfile=certfile,
622 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000623 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000624 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000625 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000626 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000627 except socket.error, x:
628 if test_support.verbose:
629 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000630 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000631 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000632 finally:
633 server.stop()
634 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000635
Antoine Pitroud2867642010-04-28 21:12:43 +0000636 def server_params_test(certfile, protocol, certreqs, cacertsfile,
637 client_certfile, client_protocol=None, indata="FOO\n",
638 chatty=True, connectionchatty=False,
639 wrap_accepting_socket=False):
640 """
641 Launch a server, connect a client to it and try various reads
642 and writes.
643 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000644 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000645 certreqs=certreqs,
646 ssl_version=protocol,
647 cacerts=cacertsfile,
648 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000649 connectionchatty=connectionchatty,
650 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000651 flag = threading.Event()
652 server.start(flag)
653 # wait for it to start
654 flag.wait()
655 # try to connect
656 if client_protocol is None:
657 client_protocol = protocol
658 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000659 s = ssl.wrap_socket(socket.socket(),
660 certfile=client_certfile,
661 ca_certs=cacertsfile,
662 cert_reqs=certreqs,
663 ssl_version=client_protocol)
664 s.connect((HOST, server.port))
665 if connectionchatty:
666 if test_support.verbose:
667 sys.stdout.write(
668 " client: sending %s...\n" % (repr(indata)))
669 s.write(indata)
670 outdata = s.read()
671 if connectionchatty:
672 if test_support.verbose:
673 sys.stdout.write(" client: read %s\n" % repr(outdata))
674 if outdata != indata.lower():
675 self.fail(
676 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
677 % (outdata[:min(len(outdata),20)], len(outdata),
678 indata[:min(len(indata),20)].lower(), len(indata)))
679 s.write("over\n")
680 if connectionchatty:
681 if test_support.verbose:
682 sys.stdout.write(" client: closing connection.\n")
683 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000684 finally:
685 server.stop()
686 server.join()
687
Antoine Pitroud2867642010-04-28 21:12:43 +0000688 def try_protocol_combo(server_protocol,
689 client_protocol,
690 expect_success,
691 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000692 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000693 certsreqs = ssl.CERT_NONE
Antoine Pitroud2867642010-04-28 21:12:43 +0000694 certtype = {
695 ssl.CERT_NONE: "CERT_NONE",
696 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
697 ssl.CERT_REQUIRED: "CERT_REQUIRED",
698 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000699 if test_support.verbose:
Antoine Pitroud2867642010-04-28 21:12:43 +0000700 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000701 sys.stdout.write(formatstr %
702 (ssl.get_protocol_name(client_protocol),
703 ssl.get_protocol_name(server_protocol),
704 certtype))
705 try:
Antoine Pitroud2867642010-04-28 21:12:43 +0000706 server_params_test(CERTFILE, server_protocol, certsreqs,
707 CERTFILE, CERTFILE, client_protocol,
708 chatty=False)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000709 # Protocol mismatch can result in either an SSLError, or a
710 # "Connection reset by peer" error.
711 except ssl.SSLError:
Antoine Pitroud2867642010-04-28 21:12:43 +0000712 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000713 raise
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000714 except socket.error as e:
Antoine Pitroud2867642010-04-28 21:12:43 +0000715 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000716 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000717 else:
Antoine Pitroud2867642010-04-28 21:12:43 +0000718 if not expect_success:
Antoine Pitrou12226692010-05-06 13:49:10 +0000719 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000720 "Client protocol %s succeeded with server protocol %s!"
721 % (ssl.get_protocol_name(client_protocol),
722 ssl.get_protocol_name(server_protocol)))
723
724
Bill Janssen934b16d2008-06-28 22:19:33 +0000725 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000726
Antoine Pitroud2867642010-04-28 21:12:43 +0000727 def test_rude_shutdown(self):
728 """A brutal shutdown of an SSL server should raise an IOError
729 in the client when attempting handshake.
730 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000731 listener_ready = threading.Event()
732 listener_gone = threading.Event()
733
Antoine Pitrou6535b312010-04-27 08:43:11 +0000734 s = socket.socket()
735 port = test_support.bind_port(s, HOST)
736
737 # `listener` runs in a thread. It sits in an accept() until
738 # the main thread connects. Then it rudely closes the socket,
739 # and sets Event `listener_gone` to let the main thread know
740 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000741 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000742 s.listen(5)
743 listener_ready.set()
744 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000745 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000746 listener_gone.set()
747
748 def connector():
749 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000750 c = socket.socket()
751 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000752 listener_gone.wait()
753 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000754 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000755 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000756 pass
757 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000758 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000759
760 t = threading.Thread(target=listener)
761 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000762 try:
763 connector()
764 finally:
765 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000766
Antoine Pitroud2867642010-04-28 21:12:43 +0000767 def test_echo(self):
768 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000769 if test_support.verbose:
770 sys.stdout.write("\n")
Antoine Pitroud2867642010-04-28 21:12:43 +0000771 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
772 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
773 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000774
Antoine Pitroud2867642010-04-28 21:12:43 +0000775 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000776 if test_support.verbose:
777 sys.stdout.write("\n")
778 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000779 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000780 certreqs=ssl.CERT_NONE,
781 ssl_version=ssl.PROTOCOL_SSLv23,
782 cacerts=CERTFILE,
783 chatty=False)
784 flag = threading.Event()
785 server.start(flag)
786 # wait for it to start
787 flag.wait()
788 # try to connect
789 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000790 s = ssl.wrap_socket(socket.socket(),
791 certfile=CERTFILE,
792 ca_certs=CERTFILE,
793 cert_reqs=ssl.CERT_REQUIRED,
794 ssl_version=ssl.PROTOCOL_SSLv23)
795 s.connect((HOST, server.port))
796 cert = s.getpeercert()
797 self.assertTrue(cert, "Can't get peer certificate.")
798 cipher = s.cipher()
799 if test_support.verbose:
800 sys.stdout.write(pprint.pformat(cert) + '\n')
801 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
802 if 'subject' not in cert:
803 self.fail("No subject field in certificate: %s." %
804 pprint.pformat(cert))
805 if ((('organizationName', 'Python Software Foundation'),)
806 not in cert['subject']):
807 self.fail(
808 "Missing or invalid 'organizationName' field in certificate subject; "
809 "should be 'Python Software Foundation'.")
810 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000811 finally:
812 server.stop()
813 server.join()
814
Antoine Pitroud2867642010-04-28 21:12:43 +0000815 def test_empty_cert(self):
816 """Connecting with an empty cert file"""
817 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
818 "nullcert.pem"))
819 def test_malformed_cert(self):
820 """Connecting with a badly formatted certificate (syntax error)"""
821 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
822 "badcert.pem"))
823 def test_nonexisting_cert(self):
824 """Connecting with a non-existing cert file"""
825 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
826 "wrongcert.pem"))
827 def test_malformed_key(self):
828 """Connecting with a badly formatted key (syntax error)"""
829 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
830 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000831
Antoine Pitroud2867642010-04-28 21:12:43 +0000832 def test_protocol_sslv2(self):
833 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000834 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000835 sys.stdout.write("\ntest_protocol_sslv2 disabled, "
836 "as it fails on OpenSSL 1.0.0+")
837 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000838 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
839 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
840 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
841 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
842 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
843 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000844
Antoine Pitroud2867642010-04-28 21:12:43 +0000845 def test_protocol_sslv23(self):
846 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000847 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000848 sys.stdout.write("\ntest_protocol_sslv23 disabled, "
849 "as it fails on OpenSSL 1.0.0+")
850 return
Bill Janssen98d19da2007-09-10 21:51:02 +0000851 try:
Antoine Pitroud2867642010-04-28 21:12:43 +0000852 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000853 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000854 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
855 if test_support.verbose:
856 sys.stdout.write(
857 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
858 % str(x))
Antoine Pitroud2867642010-04-28 21:12:43 +0000859 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
860 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
861 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000862
Antoine Pitroud2867642010-04-28 21:12:43 +0000863 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
864 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
865 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000866
Antoine Pitroud2867642010-04-28 21:12:43 +0000867 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
868 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
869 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000870
Antoine Pitroud2867642010-04-28 21:12:43 +0000871 def test_protocol_sslv3(self):
872 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000873 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000874 sys.stdout.write("\ntest_protocol_sslv3 disabled, "
875 "as it fails on OpenSSL 1.0.0+")
876 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000877 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
878 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
879 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
880 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
881 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
882 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000883
Antoine Pitroud2867642010-04-28 21:12:43 +0000884 def test_protocol_tlsv1(self):
885 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000886 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000887 sys.stdout.write("\ntest_protocol_tlsv1 disabled, "
888 "as it fails on OpenSSL 1.0.0+")
889 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000890 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
891 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
892 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
893 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
894 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
895 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000896
Antoine Pitroud2867642010-04-28 21:12:43 +0000897 def test_starttls(self):
898 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000899 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000900
Trent Nelsone41b0062008-04-08 23:47:30 +0000901 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000902 ssl_version=ssl.PROTOCOL_TLSv1,
903 starttls_server=True,
904 chatty=True,
905 connectionchatty=True)
906 flag = threading.Event()
907 server.start(flag)
908 # wait for it to start
909 flag.wait()
910 # try to connect
911 wrapped = False
912 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000913 s = socket.socket()
914 s.setblocking(1)
915 s.connect((HOST, server.port))
916 if test_support.verbose:
917 sys.stdout.write("\n")
918 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000919 if test_support.verbose:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000920 sys.stdout.write(
921 " client: sending %s...\n" % repr(indata))
922 if wrapped:
923 conn.write(indata)
924 outdata = conn.read()
925 else:
926 s.send(indata)
927 outdata = s.recv(1024)
928 if (indata == "STARTTLS" and
929 outdata.strip().lower().startswith("ok")):
Antoine Pitroud2867642010-04-28 21:12:43 +0000930 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +0000931 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000932 sys.stdout.write(
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000933 " client: read %s from server, starting TLS...\n"
934 % repr(outdata))
935 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
936 wrapped = True
937 elif (indata == "ENDTLS" and
938 outdata.strip().lower().startswith("ok")):
Antoine Pitroud2867642010-04-28 21:12:43 +0000939 # ENDTLS ok, switch back to clear text
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000940 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
Antoine Pitroud2867642010-04-28 21:12:43 +0000961 def test_socketserver(self):
962 """Using a SocketServer to create and manage SSL connections."""
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')
Antoine Pitroud2867642010-04-28 21:12:43 +0000972 with open(CERTFILE, 'rb') as f:
973 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000974 d2 = ''
975 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +0000976 url = 'https://127.0.0.1:%d/%s' % (
977 server.port, os.path.split(CERTFILE)[1])
Ezio Melottia65e2af2010-08-02 19:56:05 +0000978 with test_support._check_py3k_warnings():
979 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +0000980 dlen = f.info().getheader("content-length")
981 if dlen and (int(dlen) > 0):
982 d2 = f.read(int(dlen))
983 if test_support.verbose:
984 sys.stdout.write(
985 " client: read %d bytes from remote server '%s'\n"
986 % (len(d2), server))
987 f.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000988 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000989 finally:
990 server.stop()
991 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +0000992
Antoine Pitroud2867642010-04-28 21:12:43 +0000993 def test_wrapped_accept(self):
994 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +0000995 if test_support.verbose:
996 sys.stdout.write("\n")
Antoine Pitroud2867642010-04-28 21:12:43 +0000997 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
998 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
999 chatty=True, connectionchatty=True,
1000 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001001
Antoine Pitroud2867642010-04-28 21:12:43 +00001002 def test_asyncore_server(self):
1003 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001004 indata = "TEST MESSAGE of mixed case\n"
1005
1006 if test_support.verbose:
1007 sys.stdout.write("\n")
1008 server = AsyncoreEchoServer(CERTFILE)
1009 flag = threading.Event()
1010 server.start(flag)
1011 # wait for it to start
1012 flag.wait()
1013 # try to connect
1014 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001015 s = ssl.wrap_socket(socket.socket())
1016 s.connect(('127.0.0.1', server.port))
1017 if test_support.verbose:
1018 sys.stdout.write(
1019 " client: sending %s...\n" % (repr(indata)))
1020 s.write(indata)
1021 outdata = s.read()
1022 if test_support.verbose:
1023 sys.stdout.write(" client: read %s\n" % repr(outdata))
1024 if outdata != indata.lower():
1025 self.fail(
1026 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1027 % (outdata[:min(len(outdata),20)], len(outdata),
1028 indata[:min(len(indata),20)].lower(), len(indata)))
1029 s.write("over\n")
1030 if test_support.verbose:
1031 sys.stdout.write(" client: closing connection.\n")
1032 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001033 finally:
1034 server.stop()
1035 # wait for server thread to end
1036 server.join()
1037
Antoine Pitroud2867642010-04-28 21:12:43 +00001038 def test_recv_send(self):
1039 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001040 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
Antoine Pitroud2867642010-04-28 21:12:43 +00001234 try:
1235 test_support.run_unittest(*tests)
1236 finally:
1237 if _have_threads:
1238 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001239
1240if __name__ == "__main__":
1241 test_main()