blob: d6f1fce7a771b2568eae516db906d1a2e91a6365 [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):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000186 with test_support.transient_internet("svn.python.org"):
187 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
188 cert_reqs=ssl.CERT_NONE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000189 s.connect(("svn.python.org", 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000190 c = s.getpeercert()
191 if c:
192 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000193 s.close()
194
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000195 # this should fail because we have no verification certs
196 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
197 cert_reqs=ssl.CERT_REQUIRED)
198 try:
199 s.connect(("svn.python.org", 443))
200 except ssl.SSLError:
201 pass
202 finally:
203 s.close()
204
205 # this should succeed because we specify the root cert
206 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
207 cert_reqs=ssl.CERT_REQUIRED,
208 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
209 try:
210 s.connect(("svn.python.org", 443))
211 finally:
212 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +0000213
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000214 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
215 def test_makefile_close(self):
216 # Issue #5238: creating a file-like object with makefile() shouldn't
217 # delay closing the underlying "real socket" (here tested with its
218 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000219 with test_support.transient_internet("svn.python.org"):
220 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
221 ss.connect(("svn.python.org", 443))
222 fd = ss.fileno()
223 f = ss.makefile()
224 f.close()
225 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000226 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000227 # Closing the SSL socket should close the fd too
228 ss.close()
229 gc.collect()
230 with self.assertRaises(OSError) as e:
231 os.read(fd, 0)
232 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000233
Antoine Pitrou3945c862010-04-28 21:11:01 +0000234 def test_non_blocking_handshake(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000235 with test_support.transient_internet("svn.python.org"):
236 s = socket.socket(socket.AF_INET)
237 s.connect(("svn.python.org", 443))
238 s.setblocking(False)
239 s = ssl.wrap_socket(s,
240 cert_reqs=ssl.CERT_NONE,
241 do_handshake_on_connect=False)
242 count = 0
243 while True:
244 try:
245 count += 1
246 s.do_handshake()
247 break
248 except ssl.SSLError, err:
249 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
250 select.select([s], [], [])
251 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
252 select.select([], [s], [])
253 else:
254 raise
255 s.close()
256 if test_support.verbose:
257 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +0000258
Antoine Pitrou3945c862010-04-28 21:11:01 +0000259 def test_get_server_certificate(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000260 with test_support.transient_internet("svn.python.org"):
261 pem = ssl.get_server_certificate(("svn.python.org", 443))
262 if not pem:
263 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000264
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000265 try:
266 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
267 except ssl.SSLError:
268 #should fail
269 pass
270 else:
271 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000272
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000273 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
274 if not pem:
275 self.fail("No server certificate on svn.python.org:443!")
276 if test_support.verbose:
277 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000278
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000279 def test_algorithms(self):
280 # Issue #8484: all algorithms should be available when verifying a
281 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000282 # SHA256 was added in OpenSSL 0.9.8
283 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
284 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000285 # NOTE: https://sha256.tbs-internet.com is another possible test host
286 remote = ("sha2.hboeck.de", 443)
287 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000288 with test_support.transient_internet("sha2.hboeck.de"):
289 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
290 cert_reqs=ssl.CERT_REQUIRED,
291 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000292 try:
293 s.connect(remote)
294 if test_support.verbose:
295 sys.stdout.write("\nCipher with %r is %r\n" %
296 (remote, s.cipher()))
297 sys.stdout.write("Certificate is:\n%s\n" %
298 pprint.pformat(s.getpeercert()))
299 finally:
300 s.close()
301
Bill Janssen296a59d2007-09-16 22:06:00 +0000302
Bill Janssen98d19da2007-09-10 21:51:02 +0000303try:
304 import threading
305except ImportError:
306 _have_threads = False
307else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000308 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000309
Bill Janssen98d19da2007-09-10 21:51:02 +0000310 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000311
Bill Janssen98d19da2007-09-10 21:51:02 +0000312 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000313
Bill Janssen98d19da2007-09-10 21:51:02 +0000314 """A mildly complicated class, because we want it to work both
315 with and without the SSL wrapper around the socket connection, so
316 that we can test the STARTTLS functionality."""
317
318 def __init__(self, server, connsock):
319 self.server = server
320 self.running = False
321 self.sock = connsock
322 self.sock.setblocking(1)
323 self.sslconn = None
324 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000325 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000326
Bill Janssen934b16d2008-06-28 22:19:33 +0000327 def show_conn_details(self):
328 if self.server.certreqs == ssl.CERT_REQUIRED:
329 cert = self.sslconn.getpeercert()
330 if test_support.verbose and self.server.chatty:
331 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
332 cert_binary = self.sslconn.getpeercert(True)
333 if test_support.verbose and self.server.chatty:
334 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
335 cipher = self.sslconn.cipher()
336 if test_support.verbose and self.server.chatty:
337 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
338
Antoine Pitrou3945c862010-04-28 21:11:01 +0000339 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000340 try:
341 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
342 certfile=self.server.certificate,
343 ssl_version=self.server.protocol,
344 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000345 cert_reqs=self.server.certreqs,
346 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000347 except ssl.SSLError:
348 # XXX Various errors can have happened here, for example
349 # a mismatching protocol version, an invalid certificate,
350 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000351 if self.server.chatty:
352 handle_error("\n server: bad connection attempt from " +
353 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000354 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000355 self.running = False
356 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000357 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000358 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000359 return True
360
361 def read(self):
362 if self.sslconn:
363 return self.sslconn.read()
364 else:
365 return self.sock.recv(1024)
366
367 def write(self, bytes):
368 if self.sslconn:
369 return self.sslconn.write(bytes)
370 else:
371 return self.sock.send(bytes)
372
373 def close(self):
374 if self.sslconn:
375 self.sslconn.close()
376 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000377 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000378
Antoine Pitrou3945c862010-04-28 21:11:01 +0000379 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000380 self.running = True
381 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000382 if isinstance(self.sock, ssl.SSLSocket):
383 self.sslconn = self.sock
384 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000385 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000386 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000387 while self.running:
388 try:
389 msg = self.read()
390 if not msg:
391 # eof, so quit this handler
392 self.running = False
393 self.close()
394 elif msg.strip() == 'over':
395 if test_support.verbose and self.server.connectionchatty:
396 sys.stdout.write(" server: client closed connection\n")
397 self.close()
398 return
399 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
400 if test_support.verbose and self.server.connectionchatty:
401 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
402 self.write("OK\n")
403 if not self.wrap_conn():
404 return
Bill Janssen39295c22008-08-12 16:31:21 +0000405 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
406 if test_support.verbose and self.server.connectionchatty:
407 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
408 self.write("OK\n")
409 self.sslconn.unwrap()
410 self.sslconn = None
411 if test_support.verbose and self.server.connectionchatty:
412 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000413 else:
414 if (test_support.verbose and
415 self.server.connectionchatty):
416 ctype = (self.sslconn and "encrypted") or "unencrypted"
417 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
418 % (repr(msg), ctype, repr(msg.lower()), ctype))
419 self.write(msg.lower())
420 except ssl.SSLError:
421 if self.server.chatty:
422 handle_error("Test server failure:\n")
423 self.close()
424 self.running = False
425 # normally, we'd just stop here, but for the test
426 # harness, we want to stop the server
427 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000428
Trent Nelsone41b0062008-04-08 23:47:30 +0000429 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000430 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000431 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000432 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000433
Bill Janssen98d19da2007-09-10 21:51:02 +0000434 if ssl_version is None:
435 ssl_version = ssl.PROTOCOL_TLSv1
436 if certreqs is None:
437 certreqs = ssl.CERT_NONE
438 self.certificate = certificate
439 self.protocol = ssl_version
440 self.certreqs = certreqs
441 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000442 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000443 self.chatty = chatty
444 self.connectionchatty = connectionchatty
445 self.starttls_server = starttls_server
446 self.sock = socket.socket()
447 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000448 if wrap_accepting_socket:
449 self.sock = ssl.wrap_socket(self.sock, server_side=True,
450 certfile=self.certificate,
451 cert_reqs = self.certreqs,
452 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000453 ssl_version = self.protocol,
454 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000455 if test_support.verbose and self.chatty:
456 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
457 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000458 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000459 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000460 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000461
Antoine Pitrou3945c862010-04-28 21:11:01 +0000462 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000463 self.flag = flag
464 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000465
Antoine Pitrou3945c862010-04-28 21:11:01 +0000466 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000467 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000468 self.sock.listen(5)
469 self.active = True
470 if self.flag:
471 # signal an event
472 self.flag.set()
473 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000474 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000475 newconn, connaddr = self.sock.accept()
476 if test_support.verbose and self.chatty:
477 sys.stdout.write(' server: new connection from '
478 + str(connaddr) + '\n')
479 handler = self.ConnectionHandler(self, newconn)
480 handler.start()
481 except socket.timeout:
482 pass
483 except KeyboardInterrupt:
484 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000485 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000486
Antoine Pitrou3945c862010-04-28 21:11:01 +0000487 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000488 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000489
Bill Janssen934b16d2008-06-28 22:19:33 +0000490 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000491
Antoine Pitrou3945c862010-04-28 21:11:01 +0000492 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000493
Antoine Pitrou3945c862010-04-28 21:11:01 +0000494 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000495
496 def __init__(self, conn, certfile):
497 asyncore.dispatcher_with_send.__init__(self, conn)
498 self.socket = ssl.wrap_socket(conn, server_side=True,
499 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000500 do_handshake_on_connect=False)
501 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000502
503 def readable(self):
504 if isinstance(self.socket, ssl.SSLSocket):
505 while self.socket.pending() > 0:
506 self.handle_read_event()
507 return True
508
Antoine Pitroufc69af12010-04-24 20:04:58 +0000509 def _do_ssl_handshake(self):
510 try:
511 self.socket.do_handshake()
512 except ssl.SSLError, err:
513 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
514 ssl.SSL_ERROR_WANT_WRITE):
515 return
516 elif err.args[0] == ssl.SSL_ERROR_EOF:
517 return self.handle_close()
518 raise
519 except socket.error, err:
520 if err.args[0] == errno.ECONNABORTED:
521 return self.handle_close()
522 else:
523 self._ssl_accepting = False
524
Bill Janssen934b16d2008-06-28 22:19:33 +0000525 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000526 if self._ssl_accepting:
527 self._do_ssl_handshake()
528 else:
529 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000530 if data and data.strip() != 'over':
531 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000532
533 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000534 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000535 if test_support.verbose:
536 sys.stdout.write(" server: closed connection %s\n" % self.socket)
537
538 def handle_error(self):
539 raise
540
541 def __init__(self, certfile):
542 self.certfile = certfile
543 asyncore.dispatcher.__init__(self)
544 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
545 self.port = test_support.bind_port(self.socket)
546 self.listen(5)
547
548 def handle_accept(self):
549 sock_obj, addr = self.accept()
550 if test_support.verbose:
551 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
552 self.ConnectionHandler(sock_obj, self.certfile)
553
554 def handle_error(self):
555 raise
556
557 def __init__(self, certfile):
558 self.flag = None
559 self.active = False
560 self.server = self.EchoServer(certfile)
561 self.port = self.server.port
562 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000563 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000564
565 def __str__(self):
566 return "<%s %s>" % (self.__class__.__name__, self.server)
567
Antoine Pitrou3945c862010-04-28 21:11:01 +0000568 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000569 self.flag = flag
570 threading.Thread.start(self)
571
Antoine Pitrou3945c862010-04-28 21:11:01 +0000572 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000573 self.active = True
574 if self.flag:
575 self.flag.set()
576 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000577 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000578
Antoine Pitrou3945c862010-04-28 21:11:01 +0000579 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000580 self.active = False
581 self.server.close()
582
583 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000584
585 class HTTPSServer(HTTPServer):
586
587 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000588 HTTPServer.__init__(self, server_address, RequestHandlerClass)
589 # we assume the certfile contains both private key and certificate
590 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000591 self.allow_reuse_address = True
592
Bill Janssen934b16d2008-06-28 22:19:33 +0000593 def __str__(self):
594 return ('<%s %s:%s>' %
595 (self.__class__.__name__,
596 self.server_name,
597 self.server_port))
598
Antoine Pitrou3945c862010-04-28 21:11:01 +0000599 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000600 # override this to wrap socket with SSL
601 sock, addr = self.socket.accept()
602 sslconn = ssl.wrap_socket(sock, server_side=True,
603 certfile=self.certfile)
604 return sslconn, addr
605
Bill Janssen296a59d2007-09-16 22:06:00 +0000606 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000607 # need to override translate_path to get a known root,
608 # instead of using os.curdir, since the test could be
609 # run from anywhere
610
611 server_version = "TestHTTPS/1.0"
612
613 root = None
614
615 def translate_path(self, path):
616 """Translate a /-separated PATH to the local filename syntax.
617
618 Components that mean special things to the local file system
619 (e.g. drive or directory names) are ignored. (XXX They should
620 probably be diagnosed.)
621
622 """
623 # abandon query parameters
624 path = urlparse.urlparse(path)[2]
625 path = os.path.normpath(urllib.unquote(path))
626 words = path.split('/')
627 words = filter(None, words)
628 path = self.root
629 for word in words:
630 drive, word = os.path.splitdrive(word)
631 head, word = os.path.split(word)
632 if word in self.root: continue
633 path = os.path.join(path, word)
634 return path
635
636 def log_message(self, format, *args):
637
638 # we override this to suppress logging unless "verbose"
639
640 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000641 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
642 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000643 self.server.server_port,
644 self.request.cipher(),
645 self.log_date_time_string(),
646 format%args))
647
648
Trent Nelsone41b0062008-04-08 23:47:30 +0000649 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000650 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000651 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
652 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000653 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
654 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000655 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000656 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000657
658 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000659 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000660
Antoine Pitrou3945c862010-04-28 21:11:01 +0000661 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000662 self.flag = flag
663 threading.Thread.start(self)
664
Antoine Pitrou3945c862010-04-28 21:11:01 +0000665 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000666 if self.flag:
667 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000668 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000669
Antoine Pitrou3945c862010-04-28 21:11:01 +0000670 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000671 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000672
673
Antoine Pitrou3945c862010-04-28 21:11:01 +0000674 def bad_cert_test(certfile):
675 """
676 Launch a server with CERT_REQUIRED, and check that trying to
677 connect to it with the given client certificate fails.
678 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000679 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000680 certreqs=ssl.CERT_REQUIRED,
681 cacerts=CERTFILE, chatty=False)
682 flag = threading.Event()
683 server.start(flag)
684 # wait for it to start
685 flag.wait()
686 # try to connect
687 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000688 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000689 s = ssl.wrap_socket(socket.socket(),
690 certfile=certfile,
691 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000692 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000693 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000694 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000695 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000696 except socket.error, x:
697 if test_support.verbose:
698 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000699 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000700 raise AssertionError("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000701 finally:
702 server.stop()
703 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000704
Antoine Pitrou3945c862010-04-28 21:11:01 +0000705 def server_params_test(certfile, protocol, certreqs, cacertsfile,
706 client_certfile, client_protocol=None, indata="FOO\n",
707 ciphers=None, chatty=True, connectionchatty=False,
708 wrap_accepting_socket=False):
709 """
710 Launch a server, connect a client to it and try various reads
711 and writes.
712 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000713 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000714 certreqs=certreqs,
715 ssl_version=protocol,
716 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000717 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000718 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000719 connectionchatty=connectionchatty,
720 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000721 flag = threading.Event()
722 server.start(flag)
723 # wait for it to start
724 flag.wait()
725 # try to connect
726 if client_protocol is None:
727 client_protocol = protocol
728 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000729 s = ssl.wrap_socket(socket.socket(),
730 certfile=client_certfile,
731 ca_certs=cacertsfile,
732 ciphers=ciphers,
733 cert_reqs=certreqs,
734 ssl_version=client_protocol)
735 s.connect((HOST, server.port))
736 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000737 if connectionchatty:
738 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000739 sys.stdout.write(
740 " client: sending %s...\n" % (repr(arg)))
741 s.write(arg)
742 outdata = s.read()
743 if connectionchatty:
744 if test_support.verbose:
745 sys.stdout.write(" client: read %s\n" % repr(outdata))
746 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000747 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000748 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
749 % (outdata[:min(len(outdata),20)], len(outdata),
750 indata[:min(len(indata),20)].lower(), len(indata)))
751 s.write("over\n")
752 if connectionchatty:
753 if test_support.verbose:
754 sys.stdout.write(" client: closing connection.\n")
755 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000756 finally:
757 server.stop()
758 server.join()
759
Antoine Pitrou3945c862010-04-28 21:11:01 +0000760 def try_protocol_combo(server_protocol,
761 client_protocol,
762 expect_success,
763 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000764 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000765 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000766 certtype = {
767 ssl.CERT_NONE: "CERT_NONE",
768 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
769 ssl.CERT_REQUIRED: "CERT_REQUIRED",
770 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000771 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000772 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000773 sys.stdout.write(formatstr %
774 (ssl.get_protocol_name(client_protocol),
775 ssl.get_protocol_name(server_protocol),
776 certtype))
777 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000778 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
779 # will send an SSLv3 hello (rather than SSLv2) starting from
780 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000781 server_params_test(CERTFILE, server_protocol, certsreqs,
782 CERTFILE, CERTFILE, client_protocol,
783 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000784 # Protocol mismatch can result in either an SSLError, or a
785 # "Connection reset by peer" error.
786 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000787 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000788 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000789 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000790 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000791 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000792 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000793 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000794 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000795 "Client protocol %s succeeded with server protocol %s!"
796 % (ssl.get_protocol_name(client_protocol),
797 ssl.get_protocol_name(server_protocol)))
798
799
Bill Janssen934b16d2008-06-28 22:19:33 +0000800 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000801
Antoine Pitrou3945c862010-04-28 21:11:01 +0000802 def test_rude_shutdown(self):
803 """A brutal shutdown of an SSL server should raise an IOError
804 in the client when attempting handshake.
805 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000806 listener_ready = threading.Event()
807 listener_gone = threading.Event()
808
Antoine Pitrou150acda2010-04-27 08:40:51 +0000809 s = socket.socket()
810 port = test_support.bind_port(s, HOST)
811
812 # `listener` runs in a thread. It sits in an accept() until
813 # the main thread connects. Then it rudely closes the socket,
814 # and sets Event `listener_gone` to let the main thread know
815 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000816 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000817 s.listen(5)
818 listener_ready.set()
819 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000820 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000821 listener_gone.set()
822
823 def connector():
824 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000825 c = socket.socket()
826 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000827 listener_gone.wait()
828 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000829 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000830 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000831 pass
832 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000833 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000834
835 t = threading.Thread(target=listener)
836 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000837 try:
838 connector()
839 finally:
840 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000841
Antoine Pitroud75efd92010-08-04 17:38:33 +0000842 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000843 def test_echo(self):
844 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000845 if test_support.verbose:
846 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000847 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
848 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
849 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000850
Antoine Pitrou3945c862010-04-28 21:11:01 +0000851 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000852 if test_support.verbose:
853 sys.stdout.write("\n")
854 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000855 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000856 certreqs=ssl.CERT_NONE,
857 ssl_version=ssl.PROTOCOL_SSLv23,
858 cacerts=CERTFILE,
859 chatty=False)
860 flag = threading.Event()
861 server.start(flag)
862 # wait for it to start
863 flag.wait()
864 # try to connect
865 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000866 s = ssl.wrap_socket(socket.socket(),
867 certfile=CERTFILE,
868 ca_certs=CERTFILE,
869 cert_reqs=ssl.CERT_REQUIRED,
870 ssl_version=ssl.PROTOCOL_SSLv23)
871 s.connect((HOST, server.port))
872 cert = s.getpeercert()
873 self.assertTrue(cert, "Can't get peer certificate.")
874 cipher = s.cipher()
875 if test_support.verbose:
876 sys.stdout.write(pprint.pformat(cert) + '\n')
877 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
878 if 'subject' not in cert:
879 self.fail("No subject field in certificate: %s." %
880 pprint.pformat(cert))
881 if ((('organizationName', 'Python Software Foundation'),)
882 not in cert['subject']):
883 self.fail(
884 "Missing or invalid 'organizationName' field in certificate subject; "
885 "should be 'Python Software Foundation'.")
886 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000887 finally:
888 server.stop()
889 server.join()
890
Antoine Pitrou3945c862010-04-28 21:11:01 +0000891 def test_empty_cert(self):
892 """Connecting with an empty cert file"""
893 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
894 "nullcert.pem"))
895 def test_malformed_cert(self):
896 """Connecting with a badly formatted certificate (syntax error)"""
897 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
898 "badcert.pem"))
899 def test_nonexisting_cert(self):
900 """Connecting with a non-existing cert file"""
901 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
902 "wrongcert.pem"))
903 def test_malformed_key(self):
904 """Connecting with a badly formatted key (syntax error)"""
905 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
906 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000907
Antoine Pitroud75efd92010-08-04 17:38:33 +0000908 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000909 def test_protocol_sslv2(self):
910 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000911 if test_support.verbose:
912 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000913 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
914 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
915 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
916 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
917 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
918 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000919
Antoine Pitroud75efd92010-08-04 17:38:33 +0000920 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000921 def test_protocol_sslv23(self):
922 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000923 if test_support.verbose:
924 sys.stdout.write("\n")
925 try:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000926 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000927 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000928 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
929 if test_support.verbose:
930 sys.stdout.write(
931 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
932 % str(x))
Antoine Pitrou3945c862010-04-28 21:11:01 +0000933 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
934 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
935 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
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_OPTIONAL)
938 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
939 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000940
Antoine Pitrou3945c862010-04-28 21:11:01 +0000941 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
942 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
943 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000944
Antoine Pitroud75efd92010-08-04 17:38:33 +0000945 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000946 def test_protocol_sslv3(self):
947 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000948 if test_support.verbose:
949 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000950 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
951 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
952 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
953 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
954 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
955 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000956
Antoine Pitroud75efd92010-08-04 17:38:33 +0000957 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000958 def test_protocol_tlsv1(self):
959 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000960 if test_support.verbose:
961 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000962 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
963 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
964 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
965 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
966 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
967 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000968
Antoine Pitrou3945c862010-04-28 21:11:01 +0000969 def test_starttls(self):
970 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000971 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000972
Trent Nelsone41b0062008-04-08 23:47:30 +0000973 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000974 ssl_version=ssl.PROTOCOL_TLSv1,
975 starttls_server=True,
976 chatty=True,
977 connectionchatty=True)
978 flag = threading.Event()
979 server.start(flag)
980 # wait for it to start
981 flag.wait()
982 # try to connect
983 wrapped = False
984 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000985 s = socket.socket()
986 s.setblocking(1)
987 s.connect((HOST, server.port))
988 if test_support.verbose:
989 sys.stdout.write("\n")
990 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000991 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000992 sys.stdout.write(
993 " client: sending %s...\n" % repr(indata))
994 if wrapped:
995 conn.write(indata)
996 outdata = conn.read()
997 else:
998 s.send(indata)
999 outdata = s.recv(1024)
1000 if (indata == "STARTTLS" and
1001 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001002 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001003 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001004 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001005 " client: read %s from server, starting TLS...\n"
1006 % repr(outdata))
1007 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1008 wrapped = True
1009 elif (indata == "ENDTLS" and
1010 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001011 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001012 if test_support.verbose:
1013 sys.stdout.write(
1014 " client: read %s from server, ending TLS...\n"
1015 % repr(outdata))
1016 s = conn.unwrap()
1017 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001018 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001019 if test_support.verbose:
1020 sys.stdout.write(
1021 " client: read %s from server\n" % repr(outdata))
1022 if test_support.verbose:
1023 sys.stdout.write(" client: closing connection.\n")
1024 if wrapped:
1025 conn.write("over\n")
1026 else:
1027 s.send("over\n")
1028 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001029 finally:
1030 server.stop()
1031 server.join()
1032
Antoine Pitrou3945c862010-04-28 21:11:01 +00001033 def test_socketserver(self):
1034 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001035 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001036 flag = threading.Event()
1037 server.start(flag)
1038 # wait for it to start
1039 flag.wait()
1040 # try to connect
1041 try:
1042 if test_support.verbose:
1043 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001044 with open(CERTFILE, 'rb') as f:
1045 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001046 d2 = ''
1047 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001048 url = 'https://127.0.0.1:%d/%s' % (
1049 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001050 with test_support.check_py3k_warnings():
1051 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001052 dlen = f.info().getheader("content-length")
1053 if dlen and (int(dlen) > 0):
1054 d2 = f.read(int(dlen))
1055 if test_support.verbose:
1056 sys.stdout.write(
1057 " client: read %d bytes from remote server '%s'\n"
1058 % (len(d2), server))
1059 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001060 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001061 finally:
1062 server.stop()
1063 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001064
Antoine Pitrou3945c862010-04-28 21:11:01 +00001065 def test_wrapped_accept(self):
1066 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001067 if test_support.verbose:
1068 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001069 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1070 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1071 chatty=True, connectionchatty=True,
1072 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001073
Antoine Pitrou3945c862010-04-28 21:11:01 +00001074 def test_asyncore_server(self):
1075 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001076 indata = "TEST MESSAGE of mixed case\n"
1077
1078 if test_support.verbose:
1079 sys.stdout.write("\n")
1080 server = AsyncoreEchoServer(CERTFILE)
1081 flag = threading.Event()
1082 server.start(flag)
1083 # wait for it to start
1084 flag.wait()
1085 # try to connect
1086 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001087 s = ssl.wrap_socket(socket.socket())
1088 s.connect(('127.0.0.1', server.port))
1089 if test_support.verbose:
1090 sys.stdout.write(
1091 " client: sending %s...\n" % (repr(indata)))
1092 s.write(indata)
1093 outdata = s.read()
1094 if test_support.verbose:
1095 sys.stdout.write(" client: read %s\n" % repr(outdata))
1096 if outdata != indata.lower():
1097 self.fail(
1098 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1099 % (outdata[:min(len(outdata),20)], len(outdata),
1100 indata[:min(len(indata),20)].lower(), len(indata)))
1101 s.write("over\n")
1102 if test_support.verbose:
1103 sys.stdout.write(" client: closing connection.\n")
1104 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001105 finally:
1106 server.stop()
1107 # wait for server thread to end
1108 server.join()
1109
Antoine Pitrou3945c862010-04-28 21:11:01 +00001110 def test_recv_send(self):
1111 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001112 if test_support.verbose:
1113 sys.stdout.write("\n")
1114
1115 server = ThreadedEchoServer(CERTFILE,
1116 certreqs=ssl.CERT_NONE,
1117 ssl_version=ssl.PROTOCOL_TLSv1,
1118 cacerts=CERTFILE,
1119 chatty=True,
1120 connectionchatty=False)
1121 flag = threading.Event()
1122 server.start(flag)
1123 # wait for it to start
1124 flag.wait()
1125 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001126 s = ssl.wrap_socket(socket.socket(),
1127 server_side=False,
1128 certfile=CERTFILE,
1129 ca_certs=CERTFILE,
1130 cert_reqs=ssl.CERT_NONE,
1131 ssl_version=ssl.PROTOCOL_TLSv1)
1132 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001133 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001134 # helper methods for standardising recv* method signatures
1135 def _recv_into():
1136 b = bytearray("\0"*100)
1137 count = s.recv_into(b)
1138 return b[:count]
1139
1140 def _recvfrom_into():
1141 b = bytearray("\0"*100)
1142 count, addr = s.recvfrom_into(b)
1143 return b[:count]
1144
1145 # (name, method, whether to expect success, *args)
1146 send_methods = [
1147 ('send', s.send, True, []),
1148 ('sendto', s.sendto, False, ["some.address"]),
1149 ('sendall', s.sendall, True, []),
1150 ]
1151 recv_methods = [
1152 ('recv', s.recv, True, []),
1153 ('recvfrom', s.recvfrom, False, ["some.address"]),
1154 ('recv_into', _recv_into, True, []),
1155 ('recvfrom_into', _recvfrom_into, False, []),
1156 ]
1157 data_prefix = u"PREFIX_"
1158
1159 for meth_name, send_meth, expect_success, args in send_methods:
1160 indata = data_prefix + meth_name
1161 try:
1162 send_meth(indata.encode('ASCII', 'strict'), *args)
1163 outdata = s.read()
1164 outdata = outdata.decode('ASCII', 'strict')
1165 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001166 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001167 "While sending with <<%s>> bad data "
1168 "<<%r>> (%d) received; "
1169 "expected <<%r>> (%d)\n" % (
1170 meth_name, outdata[:20], len(outdata),
1171 indata[:20], len(indata)
1172 )
1173 )
1174 except ValueError as e:
1175 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001176 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001177 "Failed to send with method <<%s>>; "
1178 "expected to succeed.\n" % (meth_name,)
1179 )
1180 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001181 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001182 "Method <<%s>> failed with unexpected "
1183 "exception message: %s\n" % (
1184 meth_name, e
1185 )
1186 )
1187
1188 for meth_name, recv_meth, expect_success, args in recv_methods:
1189 indata = data_prefix + meth_name
1190 try:
1191 s.send(indata.encode('ASCII', 'strict'))
1192 outdata = recv_meth(*args)
1193 outdata = outdata.decode('ASCII', 'strict')
1194 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001195 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001196 "While receiving with <<%s>> bad data "
1197 "<<%r>> (%d) received; "
1198 "expected <<%r>> (%d)\n" % (
1199 meth_name, outdata[:20], len(outdata),
1200 indata[:20], len(indata)
1201 )
1202 )
1203 except ValueError as e:
1204 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001205 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001206 "Failed to receive with method <<%s>>; "
1207 "expected to succeed.\n" % (meth_name,)
1208 )
1209 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001210 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001211 "Method <<%s>> failed with unexpected "
1212 "exception message: %s\n" % (
1213 meth_name, e
1214 )
1215 )
1216 # consume data
1217 s.read()
1218
1219 s.write("over\n".encode("ASCII", "strict"))
1220 s.close()
1221 finally:
1222 server.stop()
1223 server.join()
1224
Antoine Pitroufc69af12010-04-24 20:04:58 +00001225 def test_handshake_timeout(self):
1226 # Issue #5103: SSL handshake must respect the socket timeout
1227 server = socket.socket(socket.AF_INET)
1228 host = "127.0.0.1"
1229 port = test_support.bind_port(server)
1230 started = threading.Event()
1231 finish = False
1232
1233 def serve():
1234 server.listen(5)
1235 started.set()
1236 conns = []
1237 while not finish:
1238 r, w, e = select.select([server], [], [], 0.1)
1239 if server in r:
1240 # Let the socket hang around rather than having
1241 # it closed by garbage collection.
1242 conns.append(server.accept()[0])
1243
1244 t = threading.Thread(target=serve)
1245 t.start()
1246 started.wait()
1247
1248 try:
1249 try:
1250 c = socket.socket(socket.AF_INET)
1251 c.settimeout(0.2)
1252 c.connect((host, port))
1253 # Will attempt handshake and time out
1254 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1255 ssl.wrap_socket, c)
1256 finally:
1257 c.close()
1258 try:
1259 c = socket.socket(socket.AF_INET)
1260 c.settimeout(0.2)
1261 c = ssl.wrap_socket(c)
1262 # Will attempt handshake and time out
1263 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1264 c.connect, (host, port))
1265 finally:
1266 c.close()
1267 finally:
1268 finish = True
1269 t.join()
1270 server.close()
1271
Bill Janssen61c001a2008-09-08 16:37:24 +00001272
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001273def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001274 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001275 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001276
Trent Nelsone41b0062008-04-08 23:47:30 +00001277 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001278 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001279 "keycert.pem")
1280 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1281 os.path.dirname(__file__) or os.curdir,
1282 "https_svn_python_org_root.pem")
1283
1284 if (not os.path.exists(CERTFILE) or
1285 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001286 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001287
Antoine Pitroude30f702010-09-14 12:54:08 +00001288 tests = [BasicTests, BasicSocketTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001289
Bill Janssen296a59d2007-09-16 22:06:00 +00001290 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001291 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001292
Bill Janssen98d19da2007-09-10 21:51:02 +00001293 if _have_threads:
1294 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001295 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001296 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001297
Antoine Pitrou3945c862010-04-28 21:11:01 +00001298 try:
1299 test_support.run_unittest(*tests)
1300 finally:
1301 if _have_threads:
1302 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001303
1304if __name__ == "__main__":
1305 test_main()