blob: 2cdef1668efe62c046aee84b4c98116af5e91643 [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):
Antoine Pitroub233b7d2010-08-14 17:28:36 +0000184 def setUp(self):
185 self.old_timeout = socket.getdefaulttimeout()
186 socket.setdefaulttimeout(30)
187
188 def tearDown(self):
189 socket.setdefaulttimeout(self.old_timeout)
Bill Janssen296a59d2007-09-16 22:06:00 +0000190
Antoine Pitrou3945c862010-04-28 21:11:01 +0000191 def test_connect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000192 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
193 cert_reqs=ssl.CERT_NONE)
194 s.connect(("svn.python.org", 443))
195 c = s.getpeercert()
196 if c:
Antoine Pitroudb187842010-04-27 10:32:58 +0000197 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000198 s.close()
199
200 # this should fail because we have no verification certs
201 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
202 cert_reqs=ssl.CERT_REQUIRED)
203 try:
204 s.connect(("svn.python.org", 443))
205 except ssl.SSLError:
206 pass
207 finally:
208 s.close()
209
210 # this should succeed because we specify the root cert
211 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
212 cert_reqs=ssl.CERT_REQUIRED,
213 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
214 try:
215 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000216 finally:
217 s.close()
218
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000219 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
220 def test_makefile_close(self):
221 # Issue #5238: creating a file-like object with makefile() shouldn't
222 # delay closing the underlying "real socket" (here tested with its
223 # file descriptor, hence skipping the test under Windows).
224 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
225 ss.connect(("svn.python.org", 443))
226 fd = ss.fileno()
227 f = ss.makefile()
228 f.close()
229 # The fd is still open
230 os.read(fd, 0)
231 # Closing the SSL socket should close the fd too
232 ss.close()
233 gc.collect()
234 with self.assertRaises(OSError) as e:
235 os.read(fd, 0)
236 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000237
Antoine Pitrou3945c862010-04-28 21:11:01 +0000238 def test_non_blocking_handshake(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000239 s = socket.socket(socket.AF_INET)
240 s.connect(("svn.python.org", 443))
241 s.setblocking(False)
242 s = ssl.wrap_socket(s,
243 cert_reqs=ssl.CERT_NONE,
244 do_handshake_on_connect=False)
245 count = 0
246 while True:
247 try:
248 count += 1
249 s.do_handshake()
250 break
251 except ssl.SSLError, err:
252 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
253 select.select([s], [], [])
254 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
255 select.select([], [s], [])
256 else:
257 raise
258 s.close()
259 if test_support.verbose:
260 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
261
Antoine Pitrou3945c862010-04-28 21:11:01 +0000262 def test_get_server_certificate(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000263 pem = ssl.get_server_certificate(("svn.python.org", 443))
264 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000265 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000266
267 try:
268 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
269 except ssl.SSLError:
270 #should fail
271 pass
272 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000273 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000274
275 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
276 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000277 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000278 if test_support.verbose:
279 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
280
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000281 def test_algorithms(self):
282 # Issue #8484: all algorithms should be available when verifying a
283 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000284 # SHA256 was added in OpenSSL 0.9.8
285 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
286 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000287 # NOTE: https://sha256.tbs-internet.com is another possible test host
288 remote = ("sha2.hboeck.de", 443)
289 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000290 with test_support.transient_internet("sha2.hboeck.de"):
291 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
292 cert_reqs=ssl.CERT_REQUIRED,
293 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000294 try:
295 s.connect(remote)
296 if test_support.verbose:
297 sys.stdout.write("\nCipher with %r is %r\n" %
298 (remote, s.cipher()))
299 sys.stdout.write("Certificate is:\n%s\n" %
300 pprint.pformat(s.getpeercert()))
301 finally:
302 s.close()
303
Bill Janssen296a59d2007-09-16 22:06:00 +0000304
Bill Janssen98d19da2007-09-10 21:51:02 +0000305try:
306 import threading
307except ImportError:
308 _have_threads = False
309else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000310 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000311
Bill Janssen98d19da2007-09-10 21:51:02 +0000312 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000313
Bill Janssen98d19da2007-09-10 21:51:02 +0000314 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000315
Bill Janssen98d19da2007-09-10 21:51:02 +0000316 """A mildly complicated class, because we want it to work both
317 with and without the SSL wrapper around the socket connection, so
318 that we can test the STARTTLS functionality."""
319
320 def __init__(self, server, connsock):
321 self.server = server
322 self.running = False
323 self.sock = connsock
324 self.sock.setblocking(1)
325 self.sslconn = None
326 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000327 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000328
Bill Janssen934b16d2008-06-28 22:19:33 +0000329 def show_conn_details(self):
330 if self.server.certreqs == ssl.CERT_REQUIRED:
331 cert = self.sslconn.getpeercert()
332 if test_support.verbose and self.server.chatty:
333 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
334 cert_binary = self.sslconn.getpeercert(True)
335 if test_support.verbose and self.server.chatty:
336 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
337 cipher = self.sslconn.cipher()
338 if test_support.verbose and self.server.chatty:
339 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
340
Antoine Pitrou3945c862010-04-28 21:11:01 +0000341 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000342 try:
343 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
344 certfile=self.server.certificate,
345 ssl_version=self.server.protocol,
346 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000347 cert_reqs=self.server.certreqs,
348 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000349 except ssl.SSLError:
350 # XXX Various errors can have happened here, for example
351 # a mismatching protocol version, an invalid certificate,
352 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000353 if self.server.chatty:
354 handle_error("\n server: bad connection attempt from " +
355 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000356 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000357 self.running = False
358 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000359 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000360 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000361 return True
362
363 def read(self):
364 if self.sslconn:
365 return self.sslconn.read()
366 else:
367 return self.sock.recv(1024)
368
369 def write(self, bytes):
370 if self.sslconn:
371 return self.sslconn.write(bytes)
372 else:
373 return self.sock.send(bytes)
374
375 def close(self):
376 if self.sslconn:
377 self.sslconn.close()
378 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000379 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000380
Antoine Pitrou3945c862010-04-28 21:11:01 +0000381 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000382 self.running = True
383 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000384 if isinstance(self.sock, ssl.SSLSocket):
385 self.sslconn = self.sock
386 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000387 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000388 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000389 while self.running:
390 try:
391 msg = self.read()
392 if not msg:
393 # eof, so quit this handler
394 self.running = False
395 self.close()
396 elif msg.strip() == 'over':
397 if test_support.verbose and self.server.connectionchatty:
398 sys.stdout.write(" server: client closed connection\n")
399 self.close()
400 return
401 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
402 if test_support.verbose and self.server.connectionchatty:
403 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
404 self.write("OK\n")
405 if not self.wrap_conn():
406 return
Bill Janssen39295c22008-08-12 16:31:21 +0000407 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
408 if test_support.verbose and self.server.connectionchatty:
409 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
410 self.write("OK\n")
411 self.sslconn.unwrap()
412 self.sslconn = None
413 if test_support.verbose and self.server.connectionchatty:
414 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000415 else:
416 if (test_support.verbose and
417 self.server.connectionchatty):
418 ctype = (self.sslconn and "encrypted") or "unencrypted"
419 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
420 % (repr(msg), ctype, repr(msg.lower()), ctype))
421 self.write(msg.lower())
422 except ssl.SSLError:
423 if self.server.chatty:
424 handle_error("Test server failure:\n")
425 self.close()
426 self.running = False
427 # normally, we'd just stop here, but for the test
428 # harness, we want to stop the server
429 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000430
Trent Nelsone41b0062008-04-08 23:47:30 +0000431 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000432 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000433 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000434 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000435
Bill Janssen98d19da2007-09-10 21:51:02 +0000436 if ssl_version is None:
437 ssl_version = ssl.PROTOCOL_TLSv1
438 if certreqs is None:
439 certreqs = ssl.CERT_NONE
440 self.certificate = certificate
441 self.protocol = ssl_version
442 self.certreqs = certreqs
443 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000444 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000445 self.chatty = chatty
446 self.connectionchatty = connectionchatty
447 self.starttls_server = starttls_server
448 self.sock = socket.socket()
449 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000450 if wrap_accepting_socket:
451 self.sock = ssl.wrap_socket(self.sock, server_side=True,
452 certfile=self.certificate,
453 cert_reqs = self.certreqs,
454 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000455 ssl_version = self.protocol,
456 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000457 if test_support.verbose and self.chatty:
458 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
459 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000460 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000461 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000462 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000463
Antoine Pitrou3945c862010-04-28 21:11:01 +0000464 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000465 self.flag = flag
466 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000467
Antoine Pitrou3945c862010-04-28 21:11:01 +0000468 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000469 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000470 self.sock.listen(5)
471 self.active = True
472 if self.flag:
473 # signal an event
474 self.flag.set()
475 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000476 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000477 newconn, connaddr = self.sock.accept()
478 if test_support.verbose and self.chatty:
479 sys.stdout.write(' server: new connection from '
480 + str(connaddr) + '\n')
481 handler = self.ConnectionHandler(self, newconn)
482 handler.start()
483 except socket.timeout:
484 pass
485 except KeyboardInterrupt:
486 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000487 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000488
Antoine Pitrou3945c862010-04-28 21:11:01 +0000489 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000490 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000491
Bill Janssen934b16d2008-06-28 22:19:33 +0000492 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000493
Antoine Pitrou3945c862010-04-28 21:11:01 +0000494 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000495
Antoine Pitrou3945c862010-04-28 21:11:01 +0000496 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000497
498 def __init__(self, conn, certfile):
499 asyncore.dispatcher_with_send.__init__(self, conn)
500 self.socket = ssl.wrap_socket(conn, server_side=True,
501 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000502 do_handshake_on_connect=False)
503 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000504
505 def readable(self):
506 if isinstance(self.socket, ssl.SSLSocket):
507 while self.socket.pending() > 0:
508 self.handle_read_event()
509 return True
510
Antoine Pitroufc69af12010-04-24 20:04:58 +0000511 def _do_ssl_handshake(self):
512 try:
513 self.socket.do_handshake()
514 except ssl.SSLError, err:
515 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
516 ssl.SSL_ERROR_WANT_WRITE):
517 return
518 elif err.args[0] == ssl.SSL_ERROR_EOF:
519 return self.handle_close()
520 raise
521 except socket.error, err:
522 if err.args[0] == errno.ECONNABORTED:
523 return self.handle_close()
524 else:
525 self._ssl_accepting = False
526
Bill Janssen934b16d2008-06-28 22:19:33 +0000527 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000528 if self._ssl_accepting:
529 self._do_ssl_handshake()
530 else:
531 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000532 if data and data.strip() != 'over':
533 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000534
535 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000536 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000537 if test_support.verbose:
538 sys.stdout.write(" server: closed connection %s\n" % self.socket)
539
540 def handle_error(self):
541 raise
542
543 def __init__(self, certfile):
544 self.certfile = certfile
545 asyncore.dispatcher.__init__(self)
546 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
547 self.port = test_support.bind_port(self.socket)
548 self.listen(5)
549
550 def handle_accept(self):
551 sock_obj, addr = self.accept()
552 if test_support.verbose:
553 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
554 self.ConnectionHandler(sock_obj, self.certfile)
555
556 def handle_error(self):
557 raise
558
559 def __init__(self, certfile):
560 self.flag = None
561 self.active = False
562 self.server = self.EchoServer(certfile)
563 self.port = self.server.port
564 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000565 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000566
567 def __str__(self):
568 return "<%s %s>" % (self.__class__.__name__, self.server)
569
Antoine Pitrou3945c862010-04-28 21:11:01 +0000570 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000571 self.flag = flag
572 threading.Thread.start(self)
573
Antoine Pitrou3945c862010-04-28 21:11:01 +0000574 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000575 self.active = True
576 if self.flag:
577 self.flag.set()
578 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000579 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000580
Antoine Pitrou3945c862010-04-28 21:11:01 +0000581 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000582 self.active = False
583 self.server.close()
584
585 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000586
587 class HTTPSServer(HTTPServer):
588
589 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000590 HTTPServer.__init__(self, server_address, RequestHandlerClass)
591 # we assume the certfile contains both private key and certificate
592 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000593 self.allow_reuse_address = True
594
Bill Janssen934b16d2008-06-28 22:19:33 +0000595 def __str__(self):
596 return ('<%s %s:%s>' %
597 (self.__class__.__name__,
598 self.server_name,
599 self.server_port))
600
Antoine Pitrou3945c862010-04-28 21:11:01 +0000601 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000602 # override this to wrap socket with SSL
603 sock, addr = self.socket.accept()
604 sslconn = ssl.wrap_socket(sock, server_side=True,
605 certfile=self.certfile)
606 return sslconn, addr
607
Bill Janssen296a59d2007-09-16 22:06:00 +0000608 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000609 # need to override translate_path to get a known root,
610 # instead of using os.curdir, since the test could be
611 # run from anywhere
612
613 server_version = "TestHTTPS/1.0"
614
615 root = None
616
617 def translate_path(self, path):
618 """Translate a /-separated PATH to the local filename syntax.
619
620 Components that mean special things to the local file system
621 (e.g. drive or directory names) are ignored. (XXX They should
622 probably be diagnosed.)
623
624 """
625 # abandon query parameters
626 path = urlparse.urlparse(path)[2]
627 path = os.path.normpath(urllib.unquote(path))
628 words = path.split('/')
629 words = filter(None, words)
630 path = self.root
631 for word in words:
632 drive, word = os.path.splitdrive(word)
633 head, word = os.path.split(word)
634 if word in self.root: continue
635 path = os.path.join(path, word)
636 return path
637
638 def log_message(self, format, *args):
639
640 # we override this to suppress logging unless "verbose"
641
642 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000643 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
644 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000645 self.server.server_port,
646 self.request.cipher(),
647 self.log_date_time_string(),
648 format%args))
649
650
Trent Nelsone41b0062008-04-08 23:47:30 +0000651 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000652 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000653 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
654 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000655 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
656 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000657 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000658 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000659
660 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000661 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000662
Antoine Pitrou3945c862010-04-28 21:11:01 +0000663 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000664 self.flag = flag
665 threading.Thread.start(self)
666
Antoine Pitrou3945c862010-04-28 21:11:01 +0000667 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000668 if self.flag:
669 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000670 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000671
Antoine Pitrou3945c862010-04-28 21:11:01 +0000672 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000673 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000674
675
Antoine Pitrou3945c862010-04-28 21:11:01 +0000676 def bad_cert_test(certfile):
677 """
678 Launch a server with CERT_REQUIRED, and check that trying to
679 connect to it with the given client certificate fails.
680 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000681 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000682 certreqs=ssl.CERT_REQUIRED,
683 cacerts=CERTFILE, chatty=False)
684 flag = threading.Event()
685 server.start(flag)
686 # wait for it to start
687 flag.wait()
688 # try to connect
689 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000690 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000691 s = ssl.wrap_socket(socket.socket(),
692 certfile=certfile,
693 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000694 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000695 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000696 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000697 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000698 except socket.error, x:
699 if test_support.verbose:
700 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000701 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000702 raise AssertionError("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000703 finally:
704 server.stop()
705 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000706
Antoine Pitrou3945c862010-04-28 21:11:01 +0000707 def server_params_test(certfile, protocol, certreqs, cacertsfile,
708 client_certfile, client_protocol=None, indata="FOO\n",
709 ciphers=None, chatty=True, connectionchatty=False,
710 wrap_accepting_socket=False):
711 """
712 Launch a server, connect a client to it and try various reads
713 and writes.
714 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000715 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000716 certreqs=certreqs,
717 ssl_version=protocol,
718 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000719 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000720 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000721 connectionchatty=connectionchatty,
722 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000723 flag = threading.Event()
724 server.start(flag)
725 # wait for it to start
726 flag.wait()
727 # try to connect
728 if client_protocol is None:
729 client_protocol = protocol
730 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000731 s = ssl.wrap_socket(socket.socket(),
732 certfile=client_certfile,
733 ca_certs=cacertsfile,
734 ciphers=ciphers,
735 cert_reqs=certreqs,
736 ssl_version=client_protocol)
737 s.connect((HOST, server.port))
738 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000739 if connectionchatty:
740 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000741 sys.stdout.write(
742 " client: sending %s...\n" % (repr(arg)))
743 s.write(arg)
744 outdata = s.read()
745 if connectionchatty:
746 if test_support.verbose:
747 sys.stdout.write(" client: read %s\n" % repr(outdata))
748 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000749 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000750 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
751 % (outdata[:min(len(outdata),20)], len(outdata),
752 indata[:min(len(indata),20)].lower(), len(indata)))
753 s.write("over\n")
754 if connectionchatty:
755 if test_support.verbose:
756 sys.stdout.write(" client: closing connection.\n")
757 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000758 finally:
759 server.stop()
760 server.join()
761
Antoine Pitrou3945c862010-04-28 21:11:01 +0000762 def try_protocol_combo(server_protocol,
763 client_protocol,
764 expect_success,
765 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000766 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000767 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000768 certtype = {
769 ssl.CERT_NONE: "CERT_NONE",
770 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
771 ssl.CERT_REQUIRED: "CERT_REQUIRED",
772 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000773 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000774 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000775 sys.stdout.write(formatstr %
776 (ssl.get_protocol_name(client_protocol),
777 ssl.get_protocol_name(server_protocol),
778 certtype))
779 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000780 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
781 # will send an SSLv3 hello (rather than SSLv2) starting from
782 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000783 server_params_test(CERTFILE, server_protocol, certsreqs,
784 CERTFILE, CERTFILE, client_protocol,
785 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000786 # Protocol mismatch can result in either an SSLError, or a
787 # "Connection reset by peer" error.
788 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000789 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000790 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000791 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000792 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000793 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000794 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000795 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000796 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000797 "Client protocol %s succeeded with server protocol %s!"
798 % (ssl.get_protocol_name(client_protocol),
799 ssl.get_protocol_name(server_protocol)))
800
801
Bill Janssen934b16d2008-06-28 22:19:33 +0000802 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000803
Antoine Pitrou3945c862010-04-28 21:11:01 +0000804 def test_rude_shutdown(self):
805 """A brutal shutdown of an SSL server should raise an IOError
806 in the client when attempting handshake.
807 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000808 listener_ready = threading.Event()
809 listener_gone = threading.Event()
810
Antoine Pitrou150acda2010-04-27 08:40:51 +0000811 s = socket.socket()
812 port = test_support.bind_port(s, HOST)
813
814 # `listener` runs in a thread. It sits in an accept() until
815 # the main thread connects. Then it rudely closes the socket,
816 # and sets Event `listener_gone` to let the main thread know
817 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000818 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000819 s.listen(5)
820 listener_ready.set()
821 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000822 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000823 listener_gone.set()
824
825 def connector():
826 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000827 c = socket.socket()
828 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000829 listener_gone.wait()
830 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000831 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000832 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000833 pass
834 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000835 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000836
837 t = threading.Thread(target=listener)
838 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000839 try:
840 connector()
841 finally:
842 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000843
Antoine Pitroud75efd92010-08-04 17:38:33 +0000844 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000845 def test_echo(self):
846 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000847 if test_support.verbose:
848 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000849 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
850 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
851 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000852
Antoine Pitrou3945c862010-04-28 21:11:01 +0000853 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000854 if test_support.verbose:
855 sys.stdout.write("\n")
856 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000857 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000858 certreqs=ssl.CERT_NONE,
859 ssl_version=ssl.PROTOCOL_SSLv23,
860 cacerts=CERTFILE,
861 chatty=False)
862 flag = threading.Event()
863 server.start(flag)
864 # wait for it to start
865 flag.wait()
866 # try to connect
867 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000868 s = ssl.wrap_socket(socket.socket(),
869 certfile=CERTFILE,
870 ca_certs=CERTFILE,
871 cert_reqs=ssl.CERT_REQUIRED,
872 ssl_version=ssl.PROTOCOL_SSLv23)
873 s.connect((HOST, server.port))
874 cert = s.getpeercert()
875 self.assertTrue(cert, "Can't get peer certificate.")
876 cipher = s.cipher()
877 if test_support.verbose:
878 sys.stdout.write(pprint.pformat(cert) + '\n')
879 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
880 if 'subject' not in cert:
881 self.fail("No subject field in certificate: %s." %
882 pprint.pformat(cert))
883 if ((('organizationName', 'Python Software Foundation'),)
884 not in cert['subject']):
885 self.fail(
886 "Missing or invalid 'organizationName' field in certificate subject; "
887 "should be 'Python Software Foundation'.")
888 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000889 finally:
890 server.stop()
891 server.join()
892
Antoine Pitrou3945c862010-04-28 21:11:01 +0000893 def test_empty_cert(self):
894 """Connecting with an empty cert file"""
895 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
896 "nullcert.pem"))
897 def test_malformed_cert(self):
898 """Connecting with a badly formatted certificate (syntax error)"""
899 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
900 "badcert.pem"))
901 def test_nonexisting_cert(self):
902 """Connecting with a non-existing cert file"""
903 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
904 "wrongcert.pem"))
905 def test_malformed_key(self):
906 """Connecting with a badly formatted key (syntax error)"""
907 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
908 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000909
Antoine Pitroud75efd92010-08-04 17:38:33 +0000910 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000911 def test_protocol_sslv2(self):
912 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000913 if test_support.verbose:
914 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000915 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
916 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
917 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
918 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
919 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
920 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000921
Antoine Pitroud75efd92010-08-04 17:38:33 +0000922 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000923 def test_protocol_sslv23(self):
924 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000925 if test_support.verbose:
926 sys.stdout.write("\n")
927 try:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000928 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000929 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000930 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
931 if test_support.verbose:
932 sys.stdout.write(
933 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
934 % str(x))
Antoine Pitrou3945c862010-04-28 21:11:01 +0000935 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
936 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
937 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000938
Antoine Pitrou3945c862010-04-28 21:11:01 +0000939 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
940 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
941 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000942
Antoine Pitrou3945c862010-04-28 21:11:01 +0000943 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
944 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
945 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000946
Antoine Pitroud75efd92010-08-04 17:38:33 +0000947 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000948 def test_protocol_sslv3(self):
949 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000950 if test_support.verbose:
951 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000952 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
953 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
954 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
955 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
956 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
957 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000958
Antoine Pitroud75efd92010-08-04 17:38:33 +0000959 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000960 def test_protocol_tlsv1(self):
961 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000962 if test_support.verbose:
963 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000964 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
965 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
966 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
967 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
968 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
969 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000970
Antoine Pitrou3945c862010-04-28 21:11:01 +0000971 def test_starttls(self):
972 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000973 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000974
Trent Nelsone41b0062008-04-08 23:47:30 +0000975 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000976 ssl_version=ssl.PROTOCOL_TLSv1,
977 starttls_server=True,
978 chatty=True,
979 connectionchatty=True)
980 flag = threading.Event()
981 server.start(flag)
982 # wait for it to start
983 flag.wait()
984 # try to connect
985 wrapped = False
986 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000987 s = socket.socket()
988 s.setblocking(1)
989 s.connect((HOST, server.port))
990 if test_support.verbose:
991 sys.stdout.write("\n")
992 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000993 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000994 sys.stdout.write(
995 " client: sending %s...\n" % repr(indata))
996 if wrapped:
997 conn.write(indata)
998 outdata = conn.read()
999 else:
1000 s.send(indata)
1001 outdata = s.recv(1024)
1002 if (indata == "STARTTLS" and
1003 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001004 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001005 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001006 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001007 " client: read %s from server, starting TLS...\n"
1008 % repr(outdata))
1009 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1010 wrapped = True
1011 elif (indata == "ENDTLS" and
1012 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001013 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001014 if test_support.verbose:
1015 sys.stdout.write(
1016 " client: read %s from server, ending TLS...\n"
1017 % repr(outdata))
1018 s = conn.unwrap()
1019 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001020 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001021 if test_support.verbose:
1022 sys.stdout.write(
1023 " client: read %s from server\n" % repr(outdata))
1024 if test_support.verbose:
1025 sys.stdout.write(" client: closing connection.\n")
1026 if wrapped:
1027 conn.write("over\n")
1028 else:
1029 s.send("over\n")
1030 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001031 finally:
1032 server.stop()
1033 server.join()
1034
Antoine Pitrou3945c862010-04-28 21:11:01 +00001035 def test_socketserver(self):
1036 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001037 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001038 flag = threading.Event()
1039 server.start(flag)
1040 # wait for it to start
1041 flag.wait()
1042 # try to connect
1043 try:
1044 if test_support.verbose:
1045 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001046 with open(CERTFILE, 'rb') as f:
1047 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001048 d2 = ''
1049 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001050 url = 'https://127.0.0.1:%d/%s' % (
1051 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001052 with test_support.check_py3k_warnings():
1053 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001054 dlen = f.info().getheader("content-length")
1055 if dlen and (int(dlen) > 0):
1056 d2 = f.read(int(dlen))
1057 if test_support.verbose:
1058 sys.stdout.write(
1059 " client: read %d bytes from remote server '%s'\n"
1060 % (len(d2), server))
1061 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001062 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001063 finally:
1064 server.stop()
1065 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001066
Antoine Pitrou3945c862010-04-28 21:11:01 +00001067 def test_wrapped_accept(self):
1068 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001069 if test_support.verbose:
1070 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001071 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1072 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1073 chatty=True, connectionchatty=True,
1074 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001075
Antoine Pitrou3945c862010-04-28 21:11:01 +00001076 def test_asyncore_server(self):
1077 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001078 indata = "TEST MESSAGE of mixed case\n"
1079
1080 if test_support.verbose:
1081 sys.stdout.write("\n")
1082 server = AsyncoreEchoServer(CERTFILE)
1083 flag = threading.Event()
1084 server.start(flag)
1085 # wait for it to start
1086 flag.wait()
1087 # try to connect
1088 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001089 s = ssl.wrap_socket(socket.socket())
1090 s.connect(('127.0.0.1', server.port))
1091 if test_support.verbose:
1092 sys.stdout.write(
1093 " client: sending %s...\n" % (repr(indata)))
1094 s.write(indata)
1095 outdata = s.read()
1096 if test_support.verbose:
1097 sys.stdout.write(" client: read %s\n" % repr(outdata))
1098 if outdata != indata.lower():
1099 self.fail(
1100 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1101 % (outdata[:min(len(outdata),20)], len(outdata),
1102 indata[:min(len(indata),20)].lower(), len(indata)))
1103 s.write("over\n")
1104 if test_support.verbose:
1105 sys.stdout.write(" client: closing connection.\n")
1106 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001107 finally:
1108 server.stop()
1109 # wait for server thread to end
1110 server.join()
1111
Antoine Pitrou3945c862010-04-28 21:11:01 +00001112 def test_recv_send(self):
1113 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001114 if test_support.verbose:
1115 sys.stdout.write("\n")
1116
1117 server = ThreadedEchoServer(CERTFILE,
1118 certreqs=ssl.CERT_NONE,
1119 ssl_version=ssl.PROTOCOL_TLSv1,
1120 cacerts=CERTFILE,
1121 chatty=True,
1122 connectionchatty=False)
1123 flag = threading.Event()
1124 server.start(flag)
1125 # wait for it to start
1126 flag.wait()
1127 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001128 s = ssl.wrap_socket(socket.socket(),
1129 server_side=False,
1130 certfile=CERTFILE,
1131 ca_certs=CERTFILE,
1132 cert_reqs=ssl.CERT_NONE,
1133 ssl_version=ssl.PROTOCOL_TLSv1)
1134 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001135 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001136 # helper methods for standardising recv* method signatures
1137 def _recv_into():
1138 b = bytearray("\0"*100)
1139 count = s.recv_into(b)
1140 return b[:count]
1141
1142 def _recvfrom_into():
1143 b = bytearray("\0"*100)
1144 count, addr = s.recvfrom_into(b)
1145 return b[:count]
1146
1147 # (name, method, whether to expect success, *args)
1148 send_methods = [
1149 ('send', s.send, True, []),
1150 ('sendto', s.sendto, False, ["some.address"]),
1151 ('sendall', s.sendall, True, []),
1152 ]
1153 recv_methods = [
1154 ('recv', s.recv, True, []),
1155 ('recvfrom', s.recvfrom, False, ["some.address"]),
1156 ('recv_into', _recv_into, True, []),
1157 ('recvfrom_into', _recvfrom_into, False, []),
1158 ]
1159 data_prefix = u"PREFIX_"
1160
1161 for meth_name, send_meth, expect_success, args in send_methods:
1162 indata = data_prefix + meth_name
1163 try:
1164 send_meth(indata.encode('ASCII', 'strict'), *args)
1165 outdata = s.read()
1166 outdata = outdata.decode('ASCII', 'strict')
1167 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001168 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001169 "While sending with <<%s>> bad data "
1170 "<<%r>> (%d) received; "
1171 "expected <<%r>> (%d)\n" % (
1172 meth_name, outdata[:20], len(outdata),
1173 indata[:20], len(indata)
1174 )
1175 )
1176 except ValueError as e:
1177 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001178 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001179 "Failed to send with method <<%s>>; "
1180 "expected to succeed.\n" % (meth_name,)
1181 )
1182 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001183 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001184 "Method <<%s>> failed with unexpected "
1185 "exception message: %s\n" % (
1186 meth_name, e
1187 )
1188 )
1189
1190 for meth_name, recv_meth, expect_success, args in recv_methods:
1191 indata = data_prefix + meth_name
1192 try:
1193 s.send(indata.encode('ASCII', 'strict'))
1194 outdata = recv_meth(*args)
1195 outdata = outdata.decode('ASCII', 'strict')
1196 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001197 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001198 "While receiving with <<%s>> bad data "
1199 "<<%r>> (%d) received; "
1200 "expected <<%r>> (%d)\n" % (
1201 meth_name, outdata[:20], len(outdata),
1202 indata[:20], len(indata)
1203 )
1204 )
1205 except ValueError as e:
1206 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001207 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001208 "Failed to receive with method <<%s>>; "
1209 "expected to succeed.\n" % (meth_name,)
1210 )
1211 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001212 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001213 "Method <<%s>> failed with unexpected "
1214 "exception message: %s\n" % (
1215 meth_name, e
1216 )
1217 )
1218 # consume data
1219 s.read()
1220
1221 s.write("over\n".encode("ASCII", "strict"))
1222 s.close()
1223 finally:
1224 server.stop()
1225 server.join()
1226
Antoine Pitroufc69af12010-04-24 20:04:58 +00001227 def test_handshake_timeout(self):
1228 # Issue #5103: SSL handshake must respect the socket timeout
1229 server = socket.socket(socket.AF_INET)
1230 host = "127.0.0.1"
1231 port = test_support.bind_port(server)
1232 started = threading.Event()
1233 finish = False
1234
1235 def serve():
1236 server.listen(5)
1237 started.set()
1238 conns = []
1239 while not finish:
1240 r, w, e = select.select([server], [], [], 0.1)
1241 if server in r:
1242 # Let the socket hang around rather than having
1243 # it closed by garbage collection.
1244 conns.append(server.accept()[0])
1245
1246 t = threading.Thread(target=serve)
1247 t.start()
1248 started.wait()
1249
1250 try:
1251 try:
1252 c = socket.socket(socket.AF_INET)
1253 c.settimeout(0.2)
1254 c.connect((host, port))
1255 # Will attempt handshake and time out
1256 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1257 ssl.wrap_socket, c)
1258 finally:
1259 c.close()
1260 try:
1261 c = socket.socket(socket.AF_INET)
1262 c.settimeout(0.2)
1263 c = ssl.wrap_socket(c)
1264 # Will attempt handshake and time out
1265 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1266 c.connect, (host, port))
1267 finally:
1268 c.close()
1269 finally:
1270 finish = True
1271 t.join()
1272 server.close()
1273
Bill Janssen61c001a2008-09-08 16:37:24 +00001274
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001275def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001276 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001277 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001278
Trent Nelsone41b0062008-04-08 23:47:30 +00001279 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001280 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001281 "keycert.pem")
1282 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1283 os.path.dirname(__file__) or os.curdir,
1284 "https_svn_python_org_root.pem")
1285
1286 if (not os.path.exists(CERTFILE) or
1287 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001288 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001289
1290 tests = [BasicTests]
1291
Bill Janssen296a59d2007-09-16 22:06:00 +00001292 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001293 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001294
Bill Janssen98d19da2007-09-10 21:51:02 +00001295 if _have_threads:
1296 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001297 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001298 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001299
Antoine Pitrou3945c862010-04-28 21:11:01 +00001300 try:
1301 test_support.run_unittest(*tests)
1302 finally:
1303 if _have_threads:
1304 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001305
1306if __name__ == "__main__":
1307 test_main()