blob: a7bcf9434c72e25ca871f80ffd7504a8614a02bb [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 time
Antoine Pitroub558f172010-04-23 23:25:45 +000010import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000011import os
Antoine Pitroub558f172010-04-23 23:25:45 +000012import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000014import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import traceback
Antoine Pitroudfb299b2010-04-23 22:54:59 +000016import weakref
Antoine Pitroud75efd92010-08-04 17:38:33 +000017import functools
18import platform
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000019
Bill Janssen296a59d2007-09-16 22:06:00 +000020from BaseHTTPServer import HTTPServer
21from SimpleHTTPServer import SimpleHTTPRequestHandler
22
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
29
Trent Nelsone41b0062008-04-08 23:47:30 +000030HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000031CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000032SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000033
Neal Norwitz3e533c22007-08-27 01:03:18 +000034def handle_error(prefix):
35 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000036 if test_support.verbose:
37 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000038
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000039
40class BasicTests(unittest.TestCase):
41
Antoine Pitrou3945c862010-04-28 21:11:01 +000042 def test_sslwrap_simple(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000043 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000044 try:
45 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
46 except IOError, e:
47 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
48 pass
49 else:
50 raise
51 try:
52 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
53 except IOError, e:
54 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
55 pass
56 else:
57 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000058
Antoine Pitroud75efd92010-08-04 17:38:33 +000059# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
60def skip_if_broken_ubuntu_ssl(func):
61 # We need to access the lower-level wrapper in order to create an
62 # implicit SSL context without trying to connect or listen.
Antoine Pitrou969fbe32010-08-05 01:30:23 +000063 try:
64 import _ssl
65 except ImportError:
66 # The returned function won't get executed, just ignore the error
67 pass
Antoine Pitroud75efd92010-08-04 17:38:33 +000068 @functools.wraps(func)
69 def f(*args, **kwargs):
70 try:
71 s = socket.socket(socket.AF_INET)
72 _ssl.sslwrap(s._sock, 0, None, None,
73 ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None)
74 except ssl.SSLError as e:
75 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
76 platform.linux_distribution() == ('debian', 'squeeze/sid', '')
77 and 'Invalid SSL protocol variant specified' in str(e)):
78 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
79 return func(*args, **kwargs)
80 return f
81
82
83class BasicSocketTests(unittest.TestCase):
84
Antoine Pitrou3945c862010-04-28 21:11:01 +000085 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000086 ssl.PROTOCOL_SSLv2
87 ssl.PROTOCOL_SSLv23
88 ssl.PROTOCOL_SSLv3
89 ssl.PROTOCOL_TLSv1
90 ssl.CERT_NONE
91 ssl.CERT_OPTIONAL
92 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000093
Antoine Pitrou3945c862010-04-28 21:11:01 +000094 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000095 v = ssl.RAND_status()
96 if test_support.verbose:
97 sys.stdout.write("\n RAND_status is %d (%s)\n"
98 % (v, (v and "sufficient randomness") or
99 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +0000100 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 ssl.RAND_egd(1)
102 except TypeError:
103 pass
Guido van Rossume4729332007-08-26 19:35:09 +0000104 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000105 print "didn't raise TypeError"
106 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000107
Antoine Pitrou3945c862010-04-28 21:11:01 +0000108 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000109 # note that this uses an 'unofficial' function in _ssl.c,
110 # provided solely for this test, to exercise the certificate
111 # parsing code
112 p = ssl._ssl._test_decode_cert(CERTFILE, False)
113 if test_support.verbose:
114 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000115
Antoine Pitrou3945c862010-04-28 21:11:01 +0000116 def test_DER_to_PEM(self):
117 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
118 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000119 d1 = ssl.PEM_cert_to_DER_cert(pem)
120 p2 = ssl.DER_cert_to_PEM_cert(d1)
121 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000122 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000123 if not p2.startswith(ssl.PEM_HEADER + '\n'):
124 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
125 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
126 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000127
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000128 def test_openssl_version(self):
129 n = ssl.OPENSSL_VERSION_NUMBER
130 t = ssl.OPENSSL_VERSION_INFO
131 s = ssl.OPENSSL_VERSION
132 self.assertIsInstance(n, (int, long))
133 self.assertIsInstance(t, tuple)
134 self.assertIsInstance(s, str)
135 # Some sanity checks follow
136 # >= 0.9
137 self.assertGreaterEqual(n, 0x900000)
138 # < 2.0
139 self.assertLess(n, 0x20000000)
140 major, minor, fix, patch, status = t
141 self.assertGreaterEqual(major, 0)
142 self.assertLess(major, 2)
143 self.assertGreaterEqual(minor, 0)
144 self.assertLess(minor, 256)
145 self.assertGreaterEqual(fix, 0)
146 self.assertLess(fix, 256)
147 self.assertGreaterEqual(patch, 0)
148 self.assertLessEqual(patch, 26)
149 self.assertGreaterEqual(status, 0)
150 self.assertLessEqual(status, 15)
151 # Version string as returned by OpenSSL, the format might change
152 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
153 (s, t))
154
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000155 def test_ciphers(self):
156 if not test_support.is_resource_enabled('network'):
157 return
158 remote = ("svn.python.org", 443)
159 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
160 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
161 s.connect(remote)
162 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
163 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
164 s.connect(remote)
165 # Error checking occurs when connecting, because the SSL context
166 # isn't created before.
167 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
168 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
169 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
170 s.connect(remote)
171
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000172 @test_support.cpython_only
173 def test_refcycle(self):
174 # Issue #7943: an SSL object doesn't create reference cycles with
175 # itself.
176 s = socket.socket(socket.AF_INET)
177 ss = ssl.wrap_socket(s)
178 wr = weakref.ref(ss)
179 del ss
180 self.assertEqual(wr(), None)
181
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000182
Bill Janssen934b16d2008-06-28 22:19:33 +0000183class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000184
Antoine Pitrou3945c862010-04-28 21:11:01 +0000185 def test_connect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000186 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
187 cert_reqs=ssl.CERT_NONE)
188 s.connect(("svn.python.org", 443))
189 c = s.getpeercert()
190 if c:
Antoine Pitroudb187842010-04-27 10:32:58 +0000191 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000192 s.close()
193
194 # this should fail because we have no verification certs
195 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
196 cert_reqs=ssl.CERT_REQUIRED)
197 try:
198 s.connect(("svn.python.org", 443))
199 except ssl.SSLError:
200 pass
201 finally:
202 s.close()
203
204 # this should succeed because we specify the root cert
205 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
206 cert_reqs=ssl.CERT_REQUIRED,
207 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
208 try:
209 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000210 finally:
211 s.close()
212
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000213 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
214 def test_makefile_close(self):
215 # Issue #5238: creating a file-like object with makefile() shouldn't
216 # delay closing the underlying "real socket" (here tested with its
217 # file descriptor, hence skipping the test under Windows).
218 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
219 ss.connect(("svn.python.org", 443))
220 fd = ss.fileno()
221 f = ss.makefile()
222 f.close()
223 # The fd is still open
224 os.read(fd, 0)
225 # Closing the SSL socket should close the fd too
226 ss.close()
227 gc.collect()
228 with self.assertRaises(OSError) as e:
229 os.read(fd, 0)
230 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000231
Antoine Pitrou3945c862010-04-28 21:11:01 +0000232 def test_non_blocking_handshake(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000233 s = socket.socket(socket.AF_INET)
234 s.connect(("svn.python.org", 443))
235 s.setblocking(False)
236 s = ssl.wrap_socket(s,
237 cert_reqs=ssl.CERT_NONE,
238 do_handshake_on_connect=False)
239 count = 0
240 while True:
241 try:
242 count += 1
243 s.do_handshake()
244 break
245 except ssl.SSLError, err:
246 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
247 select.select([s], [], [])
248 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
249 select.select([], [s], [])
250 else:
251 raise
252 s.close()
253 if test_support.verbose:
254 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
255
Antoine Pitrou3945c862010-04-28 21:11:01 +0000256 def test_get_server_certificate(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000257 pem = ssl.get_server_certificate(("svn.python.org", 443))
258 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000259 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000260
261 try:
262 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
263 except ssl.SSLError:
264 #should fail
265 pass
266 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000267 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000268
269 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
270 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000271 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000272 if test_support.verbose:
273 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
274
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000275 def test_algorithms(self):
276 # Issue #8484: all algorithms should be available when verifying a
277 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000278 # SHA256 was added in OpenSSL 0.9.8
279 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
280 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000281 # NOTE: https://sha256.tbs-internet.com is another possible test host
282 remote = ("sha2.hboeck.de", 443)
283 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
284 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
285 cert_reqs=ssl.CERT_REQUIRED,
286 ca_certs=sha256_cert,)
287 with test_support.transient_internet():
288 try:
289 s.connect(remote)
290 if test_support.verbose:
291 sys.stdout.write("\nCipher with %r is %r\n" %
292 (remote, s.cipher()))
293 sys.stdout.write("Certificate is:\n%s\n" %
294 pprint.pformat(s.getpeercert()))
295 finally:
296 s.close()
297
Bill Janssen296a59d2007-09-16 22:06:00 +0000298
Bill Janssen98d19da2007-09-10 21:51:02 +0000299try:
300 import threading
301except ImportError:
302 _have_threads = False
303else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000304 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000305
Bill Janssen98d19da2007-09-10 21:51:02 +0000306 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000307
Bill Janssen98d19da2007-09-10 21:51:02 +0000308 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000309
Bill Janssen98d19da2007-09-10 21:51:02 +0000310 """A mildly complicated class, because we want it to work both
311 with and without the SSL wrapper around the socket connection, so
312 that we can test the STARTTLS functionality."""
313
314 def __init__(self, server, connsock):
315 self.server = server
316 self.running = False
317 self.sock = connsock
318 self.sock.setblocking(1)
319 self.sslconn = None
320 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000321 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000322
Bill Janssen934b16d2008-06-28 22:19:33 +0000323 def show_conn_details(self):
324 if self.server.certreqs == ssl.CERT_REQUIRED:
325 cert = self.sslconn.getpeercert()
326 if test_support.verbose and self.server.chatty:
327 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
328 cert_binary = self.sslconn.getpeercert(True)
329 if test_support.verbose and self.server.chatty:
330 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
331 cipher = self.sslconn.cipher()
332 if test_support.verbose and self.server.chatty:
333 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
334
Antoine Pitrou3945c862010-04-28 21:11:01 +0000335 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000336 try:
337 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
338 certfile=self.server.certificate,
339 ssl_version=self.server.protocol,
340 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000341 cert_reqs=self.server.certreqs,
342 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000343 except ssl.SSLError:
344 # XXX Various errors can have happened here, for example
345 # a mismatching protocol version, an invalid certificate,
346 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000347 if self.server.chatty:
348 handle_error("\n server: bad connection attempt from " +
349 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000350 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000351 self.running = False
352 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000353 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000354 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000355 return True
356
357 def read(self):
358 if self.sslconn:
359 return self.sslconn.read()
360 else:
361 return self.sock.recv(1024)
362
363 def write(self, bytes):
364 if self.sslconn:
365 return self.sslconn.write(bytes)
366 else:
367 return self.sock.send(bytes)
368
369 def close(self):
370 if self.sslconn:
371 self.sslconn.close()
372 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000373 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000374
Antoine Pitrou3945c862010-04-28 21:11:01 +0000375 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000376 self.running = True
377 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000378 if isinstance(self.sock, ssl.SSLSocket):
379 self.sslconn = self.sock
380 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000381 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000382 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000383 while self.running:
384 try:
385 msg = self.read()
386 if not msg:
387 # eof, so quit this handler
388 self.running = False
389 self.close()
390 elif msg.strip() == 'over':
391 if test_support.verbose and self.server.connectionchatty:
392 sys.stdout.write(" server: client closed connection\n")
393 self.close()
394 return
395 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
396 if test_support.verbose and self.server.connectionchatty:
397 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
398 self.write("OK\n")
399 if not self.wrap_conn():
400 return
Bill Janssen39295c22008-08-12 16:31:21 +0000401 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
402 if test_support.verbose and self.server.connectionchatty:
403 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
404 self.write("OK\n")
405 self.sslconn.unwrap()
406 self.sslconn = None
407 if test_support.verbose and self.server.connectionchatty:
408 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000409 else:
410 if (test_support.verbose and
411 self.server.connectionchatty):
412 ctype = (self.sslconn and "encrypted") or "unencrypted"
413 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
414 % (repr(msg), ctype, repr(msg.lower()), ctype))
415 self.write(msg.lower())
416 except ssl.SSLError:
417 if self.server.chatty:
418 handle_error("Test server failure:\n")
419 self.close()
420 self.running = False
421 # normally, we'd just stop here, but for the test
422 # harness, we want to stop the server
423 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000424
Trent Nelsone41b0062008-04-08 23:47:30 +0000425 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000426 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000427 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000428 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000429
Bill Janssen98d19da2007-09-10 21:51:02 +0000430 if ssl_version is None:
431 ssl_version = ssl.PROTOCOL_TLSv1
432 if certreqs is None:
433 certreqs = ssl.CERT_NONE
434 self.certificate = certificate
435 self.protocol = ssl_version
436 self.certreqs = certreqs
437 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000438 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000439 self.chatty = chatty
440 self.connectionchatty = connectionchatty
441 self.starttls_server = starttls_server
442 self.sock = socket.socket()
443 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000444 if wrap_accepting_socket:
445 self.sock = ssl.wrap_socket(self.sock, server_side=True,
446 certfile=self.certificate,
447 cert_reqs = self.certreqs,
448 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000449 ssl_version = self.protocol,
450 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000451 if test_support.verbose and self.chatty:
452 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
453 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000454 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000455 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000456 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000457
Antoine Pitrou3945c862010-04-28 21:11:01 +0000458 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000459 self.flag = flag
460 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000461
Antoine Pitrou3945c862010-04-28 21:11:01 +0000462 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000463 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000464 self.sock.listen(5)
465 self.active = True
466 if self.flag:
467 # signal an event
468 self.flag.set()
469 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000470 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000471 newconn, connaddr = self.sock.accept()
472 if test_support.verbose and self.chatty:
473 sys.stdout.write(' server: new connection from '
474 + str(connaddr) + '\n')
475 handler = self.ConnectionHandler(self, newconn)
476 handler.start()
477 except socket.timeout:
478 pass
479 except KeyboardInterrupt:
480 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000481 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000482
Antoine Pitrou3945c862010-04-28 21:11:01 +0000483 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000484 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000485
Bill Janssen934b16d2008-06-28 22:19:33 +0000486 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000487
Antoine Pitrou3945c862010-04-28 21:11:01 +0000488 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000489
Antoine Pitrou3945c862010-04-28 21:11:01 +0000490 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000491
492 def __init__(self, conn, certfile):
493 asyncore.dispatcher_with_send.__init__(self, conn)
494 self.socket = ssl.wrap_socket(conn, server_side=True,
495 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000496 do_handshake_on_connect=False)
497 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000498
499 def readable(self):
500 if isinstance(self.socket, ssl.SSLSocket):
501 while self.socket.pending() > 0:
502 self.handle_read_event()
503 return True
504
Antoine Pitroufc69af12010-04-24 20:04:58 +0000505 def _do_ssl_handshake(self):
506 try:
507 self.socket.do_handshake()
508 except ssl.SSLError, err:
509 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
510 ssl.SSL_ERROR_WANT_WRITE):
511 return
512 elif err.args[0] == ssl.SSL_ERROR_EOF:
513 return self.handle_close()
514 raise
515 except socket.error, err:
516 if err.args[0] == errno.ECONNABORTED:
517 return self.handle_close()
518 else:
519 self._ssl_accepting = False
520
Bill Janssen934b16d2008-06-28 22:19:33 +0000521 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000522 if self._ssl_accepting:
523 self._do_ssl_handshake()
524 else:
525 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000526 if data and data.strip() != 'over':
527 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000528
529 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000530 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000531 if test_support.verbose:
532 sys.stdout.write(" server: closed connection %s\n" % self.socket)
533
534 def handle_error(self):
535 raise
536
537 def __init__(self, certfile):
538 self.certfile = certfile
539 asyncore.dispatcher.__init__(self)
540 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
541 self.port = test_support.bind_port(self.socket)
542 self.listen(5)
543
544 def handle_accept(self):
545 sock_obj, addr = self.accept()
546 if test_support.verbose:
547 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
548 self.ConnectionHandler(sock_obj, self.certfile)
549
550 def handle_error(self):
551 raise
552
553 def __init__(self, certfile):
554 self.flag = None
555 self.active = False
556 self.server = self.EchoServer(certfile)
557 self.port = self.server.port
558 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000559 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000560
561 def __str__(self):
562 return "<%s %s>" % (self.__class__.__name__, self.server)
563
Antoine Pitrou3945c862010-04-28 21:11:01 +0000564 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000565 self.flag = flag
566 threading.Thread.start(self)
567
Antoine Pitrou3945c862010-04-28 21:11:01 +0000568 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000569 self.active = True
570 if self.flag:
571 self.flag.set()
572 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000573 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000574
Antoine Pitrou3945c862010-04-28 21:11:01 +0000575 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000576 self.active = False
577 self.server.close()
578
579 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000580
581 class HTTPSServer(HTTPServer):
582
583 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000584 HTTPServer.__init__(self, server_address, RequestHandlerClass)
585 # we assume the certfile contains both private key and certificate
586 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000587 self.allow_reuse_address = True
588
Bill Janssen934b16d2008-06-28 22:19:33 +0000589 def __str__(self):
590 return ('<%s %s:%s>' %
591 (self.__class__.__name__,
592 self.server_name,
593 self.server_port))
594
Antoine Pitrou3945c862010-04-28 21:11:01 +0000595 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000596 # override this to wrap socket with SSL
597 sock, addr = self.socket.accept()
598 sslconn = ssl.wrap_socket(sock, server_side=True,
599 certfile=self.certfile)
600 return sslconn, addr
601
Bill Janssen296a59d2007-09-16 22:06:00 +0000602 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000603 # need to override translate_path to get a known root,
604 # instead of using os.curdir, since the test could be
605 # run from anywhere
606
607 server_version = "TestHTTPS/1.0"
608
609 root = None
610
611 def translate_path(self, path):
612 """Translate a /-separated PATH to the local filename syntax.
613
614 Components that mean special things to the local file system
615 (e.g. drive or directory names) are ignored. (XXX They should
616 probably be diagnosed.)
617
618 """
619 # abandon query parameters
620 path = urlparse.urlparse(path)[2]
621 path = os.path.normpath(urllib.unquote(path))
622 words = path.split('/')
623 words = filter(None, words)
624 path = self.root
625 for word in words:
626 drive, word = os.path.splitdrive(word)
627 head, word = os.path.split(word)
628 if word in self.root: continue
629 path = os.path.join(path, word)
630 return path
631
632 def log_message(self, format, *args):
633
634 # we override this to suppress logging unless "verbose"
635
636 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000637 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
638 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000639 self.server.server_port,
640 self.request.cipher(),
641 self.log_date_time_string(),
642 format%args))
643
644
Trent Nelsone41b0062008-04-08 23:47:30 +0000645 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000646 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000647 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
648 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000649 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
650 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000651 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000652 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000653
654 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000655 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000656
Antoine Pitrou3945c862010-04-28 21:11:01 +0000657 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000658 self.flag = flag
659 threading.Thread.start(self)
660
Antoine Pitrou3945c862010-04-28 21:11:01 +0000661 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000662 if self.flag:
663 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000664 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000665
Antoine Pitrou3945c862010-04-28 21:11:01 +0000666 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000667 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000668
669
Antoine Pitrou3945c862010-04-28 21:11:01 +0000670 def bad_cert_test(certfile):
671 """
672 Launch a server with CERT_REQUIRED, and check that trying to
673 connect to it with the given client certificate fails.
674 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000675 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000676 certreqs=ssl.CERT_REQUIRED,
677 cacerts=CERTFILE, chatty=False)
678 flag = threading.Event()
679 server.start(flag)
680 # wait for it to start
681 flag.wait()
682 # try to connect
683 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000684 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000685 s = ssl.wrap_socket(socket.socket(),
686 certfile=certfile,
687 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000688 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000689 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000690 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000691 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000692 except socket.error, x:
693 if test_support.verbose:
694 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000695 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000696 raise AssertionError("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000697 finally:
698 server.stop()
699 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000700
Antoine Pitrou3945c862010-04-28 21:11:01 +0000701 def server_params_test(certfile, protocol, certreqs, cacertsfile,
702 client_certfile, client_protocol=None, indata="FOO\n",
703 ciphers=None, chatty=True, connectionchatty=False,
704 wrap_accepting_socket=False):
705 """
706 Launch a server, connect a client to it and try various reads
707 and writes.
708 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000709 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000710 certreqs=certreqs,
711 ssl_version=protocol,
712 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000713 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000714 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000715 connectionchatty=connectionchatty,
716 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000717 flag = threading.Event()
718 server.start(flag)
719 # wait for it to start
720 flag.wait()
721 # try to connect
722 if client_protocol is None:
723 client_protocol = protocol
724 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000725 s = ssl.wrap_socket(socket.socket(),
726 certfile=client_certfile,
727 ca_certs=cacertsfile,
728 ciphers=ciphers,
729 cert_reqs=certreqs,
730 ssl_version=client_protocol)
731 s.connect((HOST, server.port))
732 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000733 if connectionchatty:
734 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000735 sys.stdout.write(
736 " client: sending %s...\n" % (repr(arg)))
737 s.write(arg)
738 outdata = s.read()
739 if connectionchatty:
740 if test_support.verbose:
741 sys.stdout.write(" client: read %s\n" % repr(outdata))
742 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000743 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000744 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
745 % (outdata[:min(len(outdata),20)], len(outdata),
746 indata[:min(len(indata),20)].lower(), len(indata)))
747 s.write("over\n")
748 if connectionchatty:
749 if test_support.verbose:
750 sys.stdout.write(" client: closing connection.\n")
751 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000752 finally:
753 server.stop()
754 server.join()
755
Antoine Pitrou3945c862010-04-28 21:11:01 +0000756 def try_protocol_combo(server_protocol,
757 client_protocol,
758 expect_success,
759 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000760 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000761 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000762 certtype = {
763 ssl.CERT_NONE: "CERT_NONE",
764 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
765 ssl.CERT_REQUIRED: "CERT_REQUIRED",
766 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000767 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000768 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000769 sys.stdout.write(formatstr %
770 (ssl.get_protocol_name(client_protocol),
771 ssl.get_protocol_name(server_protocol),
772 certtype))
773 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000774 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
775 # will send an SSLv3 hello (rather than SSLv2) starting from
776 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000777 server_params_test(CERTFILE, server_protocol, certsreqs,
778 CERTFILE, CERTFILE, client_protocol,
779 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000780 # Protocol mismatch can result in either an SSLError, or a
781 # "Connection reset by peer" error.
782 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000783 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000784 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000785 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000786 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000787 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000788 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000789 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000790 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000791 "Client protocol %s succeeded with server protocol %s!"
792 % (ssl.get_protocol_name(client_protocol),
793 ssl.get_protocol_name(server_protocol)))
794
795
Bill Janssen934b16d2008-06-28 22:19:33 +0000796 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000797
Antoine Pitrou3945c862010-04-28 21:11:01 +0000798 def test_rude_shutdown(self):
799 """A brutal shutdown of an SSL server should raise an IOError
800 in the client when attempting handshake.
801 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000802 listener_ready = threading.Event()
803 listener_gone = threading.Event()
804
Antoine Pitrou150acda2010-04-27 08:40:51 +0000805 s = socket.socket()
806 port = test_support.bind_port(s, HOST)
807
808 # `listener` runs in a thread. It sits in an accept() until
809 # the main thread connects. Then it rudely closes the socket,
810 # and sets Event `listener_gone` to let the main thread know
811 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000812 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000813 s.listen(5)
814 listener_ready.set()
815 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000816 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000817 listener_gone.set()
818
819 def connector():
820 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000821 c = socket.socket()
822 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000823 listener_gone.wait()
824 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000825 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000826 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000827 pass
828 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000829 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000830
831 t = threading.Thread(target=listener)
832 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000833 try:
834 connector()
835 finally:
836 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000837
Antoine Pitroud75efd92010-08-04 17:38:33 +0000838 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000839 def test_echo(self):
840 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000841 if test_support.verbose:
842 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000843 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
844 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
845 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000846
Antoine Pitrou3945c862010-04-28 21:11:01 +0000847 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000848 if test_support.verbose:
849 sys.stdout.write("\n")
850 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000851 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000852 certreqs=ssl.CERT_NONE,
853 ssl_version=ssl.PROTOCOL_SSLv23,
854 cacerts=CERTFILE,
855 chatty=False)
856 flag = threading.Event()
857 server.start(flag)
858 # wait for it to start
859 flag.wait()
860 # try to connect
861 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000862 s = ssl.wrap_socket(socket.socket(),
863 certfile=CERTFILE,
864 ca_certs=CERTFILE,
865 cert_reqs=ssl.CERT_REQUIRED,
866 ssl_version=ssl.PROTOCOL_SSLv23)
867 s.connect((HOST, server.port))
868 cert = s.getpeercert()
869 self.assertTrue(cert, "Can't get peer certificate.")
870 cipher = s.cipher()
871 if test_support.verbose:
872 sys.stdout.write(pprint.pformat(cert) + '\n')
873 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
874 if 'subject' not in cert:
875 self.fail("No subject field in certificate: %s." %
876 pprint.pformat(cert))
877 if ((('organizationName', 'Python Software Foundation'),)
878 not in cert['subject']):
879 self.fail(
880 "Missing or invalid 'organizationName' field in certificate subject; "
881 "should be 'Python Software Foundation'.")
882 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000883 finally:
884 server.stop()
885 server.join()
886
Antoine Pitrou3945c862010-04-28 21:11:01 +0000887 def test_empty_cert(self):
888 """Connecting with an empty cert file"""
889 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
890 "nullcert.pem"))
891 def test_malformed_cert(self):
892 """Connecting with a badly formatted certificate (syntax error)"""
893 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
894 "badcert.pem"))
895 def test_nonexisting_cert(self):
896 """Connecting with a non-existing cert file"""
897 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
898 "wrongcert.pem"))
899 def test_malformed_key(self):
900 """Connecting with a badly formatted key (syntax error)"""
901 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
902 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000903
Antoine Pitroud75efd92010-08-04 17:38:33 +0000904 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000905 def test_protocol_sslv2(self):
906 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000907 if test_support.verbose:
908 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000909 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
910 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
911 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
912 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
913 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
914 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000915
Antoine Pitroud75efd92010-08-04 17:38:33 +0000916 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000917 def test_protocol_sslv23(self):
918 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000919 if test_support.verbose:
920 sys.stdout.write("\n")
921 try:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000922 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000923 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000924 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
925 if test_support.verbose:
926 sys.stdout.write(
927 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
928 % str(x))
Antoine Pitrou3945c862010-04-28 21:11:01 +0000929 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
930 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
931 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000932
Antoine Pitrou3945c862010-04-28 21:11:01 +0000933 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
934 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
935 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000936
Antoine Pitrou3945c862010-04-28 21:11:01 +0000937 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
938 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
939 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000940
Antoine Pitroud75efd92010-08-04 17:38:33 +0000941 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000942 def test_protocol_sslv3(self):
943 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000944 if test_support.verbose:
945 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000946 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
947 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
948 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
949 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
950 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
951 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000952
Antoine Pitroud75efd92010-08-04 17:38:33 +0000953 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000954 def test_protocol_tlsv1(self):
955 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000956 if test_support.verbose:
957 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000958 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
959 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
960 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
961 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
962 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
963 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000964
Antoine Pitrou3945c862010-04-28 21:11:01 +0000965 def test_starttls(self):
966 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000967 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000968
Trent Nelsone41b0062008-04-08 23:47:30 +0000969 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000970 ssl_version=ssl.PROTOCOL_TLSv1,
971 starttls_server=True,
972 chatty=True,
973 connectionchatty=True)
974 flag = threading.Event()
975 server.start(flag)
976 # wait for it to start
977 flag.wait()
978 # try to connect
979 wrapped = False
980 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000981 s = socket.socket()
982 s.setblocking(1)
983 s.connect((HOST, server.port))
984 if test_support.verbose:
985 sys.stdout.write("\n")
986 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000987 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000988 sys.stdout.write(
989 " client: sending %s...\n" % repr(indata))
990 if wrapped:
991 conn.write(indata)
992 outdata = conn.read()
993 else:
994 s.send(indata)
995 outdata = s.recv(1024)
996 if (indata == "STARTTLS" and
997 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +0000998 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +0000999 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001000 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001001 " client: read %s from server, starting TLS...\n"
1002 % repr(outdata))
1003 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1004 wrapped = True
1005 elif (indata == "ENDTLS" and
1006 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001007 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001008 if test_support.verbose:
1009 sys.stdout.write(
1010 " client: read %s from server, ending TLS...\n"
1011 % repr(outdata))
1012 s = conn.unwrap()
1013 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001014 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001015 if test_support.verbose:
1016 sys.stdout.write(
1017 " client: read %s from server\n" % repr(outdata))
1018 if test_support.verbose:
1019 sys.stdout.write(" client: closing connection.\n")
1020 if wrapped:
1021 conn.write("over\n")
1022 else:
1023 s.send("over\n")
1024 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001025 finally:
1026 server.stop()
1027 server.join()
1028
Antoine Pitrou3945c862010-04-28 21:11:01 +00001029 def test_socketserver(self):
1030 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001031 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001032 flag = threading.Event()
1033 server.start(flag)
1034 # wait for it to start
1035 flag.wait()
1036 # try to connect
1037 try:
1038 if test_support.verbose:
1039 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001040 with open(CERTFILE, 'rb') as f:
1041 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001042 d2 = ''
1043 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001044 url = 'https://127.0.0.1:%d/%s' % (
1045 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001046 with test_support.check_py3k_warnings():
1047 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001048 dlen = f.info().getheader("content-length")
1049 if dlen and (int(dlen) > 0):
1050 d2 = f.read(int(dlen))
1051 if test_support.verbose:
1052 sys.stdout.write(
1053 " client: read %d bytes from remote server '%s'\n"
1054 % (len(d2), server))
1055 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001056 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001057 finally:
1058 server.stop()
1059 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001060
Antoine Pitrou3945c862010-04-28 21:11:01 +00001061 def test_wrapped_accept(self):
1062 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001063 if test_support.verbose:
1064 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001065 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1066 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1067 chatty=True, connectionchatty=True,
1068 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001069
Antoine Pitrou3945c862010-04-28 21:11:01 +00001070 def test_asyncore_server(self):
1071 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001072 indata = "TEST MESSAGE of mixed case\n"
1073
1074 if test_support.verbose:
1075 sys.stdout.write("\n")
1076 server = AsyncoreEchoServer(CERTFILE)
1077 flag = threading.Event()
1078 server.start(flag)
1079 # wait for it to start
1080 flag.wait()
1081 # try to connect
1082 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001083 s = ssl.wrap_socket(socket.socket())
1084 s.connect(('127.0.0.1', server.port))
1085 if test_support.verbose:
1086 sys.stdout.write(
1087 " client: sending %s...\n" % (repr(indata)))
1088 s.write(indata)
1089 outdata = s.read()
1090 if test_support.verbose:
1091 sys.stdout.write(" client: read %s\n" % repr(outdata))
1092 if outdata != indata.lower():
1093 self.fail(
1094 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1095 % (outdata[:min(len(outdata),20)], len(outdata),
1096 indata[:min(len(indata),20)].lower(), len(indata)))
1097 s.write("over\n")
1098 if test_support.verbose:
1099 sys.stdout.write(" client: closing connection.\n")
1100 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001101 finally:
1102 server.stop()
1103 # wait for server thread to end
1104 server.join()
1105
Antoine Pitrou3945c862010-04-28 21:11:01 +00001106 def test_recv_send(self):
1107 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001108 if test_support.verbose:
1109 sys.stdout.write("\n")
1110
1111 server = ThreadedEchoServer(CERTFILE,
1112 certreqs=ssl.CERT_NONE,
1113 ssl_version=ssl.PROTOCOL_TLSv1,
1114 cacerts=CERTFILE,
1115 chatty=True,
1116 connectionchatty=False)
1117 flag = threading.Event()
1118 server.start(flag)
1119 # wait for it to start
1120 flag.wait()
1121 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001122 s = ssl.wrap_socket(socket.socket(),
1123 server_side=False,
1124 certfile=CERTFILE,
1125 ca_certs=CERTFILE,
1126 cert_reqs=ssl.CERT_NONE,
1127 ssl_version=ssl.PROTOCOL_TLSv1)
1128 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001129 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001130 # helper methods for standardising recv* method signatures
1131 def _recv_into():
1132 b = bytearray("\0"*100)
1133 count = s.recv_into(b)
1134 return b[:count]
1135
1136 def _recvfrom_into():
1137 b = bytearray("\0"*100)
1138 count, addr = s.recvfrom_into(b)
1139 return b[:count]
1140
1141 # (name, method, whether to expect success, *args)
1142 send_methods = [
1143 ('send', s.send, True, []),
1144 ('sendto', s.sendto, False, ["some.address"]),
1145 ('sendall', s.sendall, True, []),
1146 ]
1147 recv_methods = [
1148 ('recv', s.recv, True, []),
1149 ('recvfrom', s.recvfrom, False, ["some.address"]),
1150 ('recv_into', _recv_into, True, []),
1151 ('recvfrom_into', _recvfrom_into, False, []),
1152 ]
1153 data_prefix = u"PREFIX_"
1154
1155 for meth_name, send_meth, expect_success, args in send_methods:
1156 indata = data_prefix + meth_name
1157 try:
1158 send_meth(indata.encode('ASCII', 'strict'), *args)
1159 outdata = s.read()
1160 outdata = outdata.decode('ASCII', 'strict')
1161 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001162 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001163 "While sending with <<%s>> bad data "
1164 "<<%r>> (%d) received; "
1165 "expected <<%r>> (%d)\n" % (
1166 meth_name, outdata[:20], len(outdata),
1167 indata[:20], len(indata)
1168 )
1169 )
1170 except ValueError as e:
1171 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001172 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001173 "Failed to send with method <<%s>>; "
1174 "expected to succeed.\n" % (meth_name,)
1175 )
1176 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001177 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001178 "Method <<%s>> failed with unexpected "
1179 "exception message: %s\n" % (
1180 meth_name, e
1181 )
1182 )
1183
1184 for meth_name, recv_meth, expect_success, args in recv_methods:
1185 indata = data_prefix + meth_name
1186 try:
1187 s.send(indata.encode('ASCII', 'strict'))
1188 outdata = recv_meth(*args)
1189 outdata = outdata.decode('ASCII', 'strict')
1190 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001191 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001192 "While receiving with <<%s>> bad data "
1193 "<<%r>> (%d) received; "
1194 "expected <<%r>> (%d)\n" % (
1195 meth_name, outdata[:20], len(outdata),
1196 indata[:20], len(indata)
1197 )
1198 )
1199 except ValueError as e:
1200 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001201 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001202 "Failed to receive with method <<%s>>; "
1203 "expected to succeed.\n" % (meth_name,)
1204 )
1205 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001206 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001207 "Method <<%s>> failed with unexpected "
1208 "exception message: %s\n" % (
1209 meth_name, e
1210 )
1211 )
1212 # consume data
1213 s.read()
1214
1215 s.write("over\n".encode("ASCII", "strict"))
1216 s.close()
1217 finally:
1218 server.stop()
1219 server.join()
1220
Antoine Pitroufc69af12010-04-24 20:04:58 +00001221 def test_handshake_timeout(self):
1222 # Issue #5103: SSL handshake must respect the socket timeout
1223 server = socket.socket(socket.AF_INET)
1224 host = "127.0.0.1"
1225 port = test_support.bind_port(server)
1226 started = threading.Event()
1227 finish = False
1228
1229 def serve():
1230 server.listen(5)
1231 started.set()
1232 conns = []
1233 while not finish:
1234 r, w, e = select.select([server], [], [], 0.1)
1235 if server in r:
1236 # Let the socket hang around rather than having
1237 # it closed by garbage collection.
1238 conns.append(server.accept()[0])
1239
1240 t = threading.Thread(target=serve)
1241 t.start()
1242 started.wait()
1243
1244 try:
1245 try:
1246 c = socket.socket(socket.AF_INET)
1247 c.settimeout(0.2)
1248 c.connect((host, port))
1249 # Will attempt handshake and time out
1250 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1251 ssl.wrap_socket, c)
1252 finally:
1253 c.close()
1254 try:
1255 c = socket.socket(socket.AF_INET)
1256 c.settimeout(0.2)
1257 c = ssl.wrap_socket(c)
1258 # Will attempt handshake and time out
1259 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1260 c.connect, (host, port))
1261 finally:
1262 c.close()
1263 finally:
1264 finish = True
1265 t.join()
1266 server.close()
1267
Bill Janssen61c001a2008-09-08 16:37:24 +00001268
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001269def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001270 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001271 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001272
Trent Nelsone41b0062008-04-08 23:47:30 +00001273 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001274 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001275 "keycert.pem")
1276 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1277 os.path.dirname(__file__) or os.curdir,
1278 "https_svn_python_org_root.pem")
1279
1280 if (not os.path.exists(CERTFILE) or
1281 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001282 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001283
1284 tests = [BasicTests]
1285
Bill Janssen296a59d2007-09-16 22:06:00 +00001286 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001287 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001288
Bill Janssen98d19da2007-09-10 21:51:02 +00001289 if _have_threads:
1290 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001291 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001292 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001293
Antoine Pitrou3945c862010-04-28 21:11:01 +00001294 try:
1295 test_support.run_unittest(*tests)
1296 finally:
1297 if _have_threads:
1298 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001299
1300if __name__ == "__main__":
1301 test_main()