blob: c95b93c9072ccbf24bbd1186c1869eb8fd03bcef [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.
63 import _ssl
64 @functools.wraps(func)
65 def f(*args, **kwargs):
66 try:
67 s = socket.socket(socket.AF_INET)
68 _ssl.sslwrap(s._sock, 0, None, None,
69 ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None)
70 except ssl.SSLError as e:
71 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
72 platform.linux_distribution() == ('debian', 'squeeze/sid', '')
73 and 'Invalid SSL protocol variant specified' in str(e)):
74 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
75 return func(*args, **kwargs)
76 return f
77
78
79class BasicSocketTests(unittest.TestCase):
80
Antoine Pitrou3945c862010-04-28 21:11:01 +000081 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000082 ssl.PROTOCOL_SSLv2
83 ssl.PROTOCOL_SSLv23
84 ssl.PROTOCOL_SSLv3
85 ssl.PROTOCOL_TLSv1
86 ssl.CERT_NONE
87 ssl.CERT_OPTIONAL
88 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000089
Antoine Pitrou3945c862010-04-28 21:11:01 +000090 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000091 v = ssl.RAND_status()
92 if test_support.verbose:
93 sys.stdout.write("\n RAND_status is %d (%s)\n"
94 % (v, (v and "sufficient randomness") or
95 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000096 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000097 ssl.RAND_egd(1)
98 except TypeError:
99 pass
Guido van Rossume4729332007-08-26 19:35:09 +0000100 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 print "didn't raise TypeError"
102 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000103
Antoine Pitrou3945c862010-04-28 21:11:01 +0000104 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000105 # note that this uses an 'unofficial' function in _ssl.c,
106 # provided solely for this test, to exercise the certificate
107 # parsing code
108 p = ssl._ssl._test_decode_cert(CERTFILE, False)
109 if test_support.verbose:
110 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000111
Antoine Pitrou3945c862010-04-28 21:11:01 +0000112 def test_DER_to_PEM(self):
113 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
114 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000115 d1 = ssl.PEM_cert_to_DER_cert(pem)
116 p2 = ssl.DER_cert_to_PEM_cert(d1)
117 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000118 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000119 if not p2.startswith(ssl.PEM_HEADER + '\n'):
120 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
121 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
122 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000123
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000124 def test_openssl_version(self):
125 n = ssl.OPENSSL_VERSION_NUMBER
126 t = ssl.OPENSSL_VERSION_INFO
127 s = ssl.OPENSSL_VERSION
128 self.assertIsInstance(n, (int, long))
129 self.assertIsInstance(t, tuple)
130 self.assertIsInstance(s, str)
131 # Some sanity checks follow
132 # >= 0.9
133 self.assertGreaterEqual(n, 0x900000)
134 # < 2.0
135 self.assertLess(n, 0x20000000)
136 major, minor, fix, patch, status = t
137 self.assertGreaterEqual(major, 0)
138 self.assertLess(major, 2)
139 self.assertGreaterEqual(minor, 0)
140 self.assertLess(minor, 256)
141 self.assertGreaterEqual(fix, 0)
142 self.assertLess(fix, 256)
143 self.assertGreaterEqual(patch, 0)
144 self.assertLessEqual(patch, 26)
145 self.assertGreaterEqual(status, 0)
146 self.assertLessEqual(status, 15)
147 # Version string as returned by OpenSSL, the format might change
148 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
149 (s, t))
150
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000151 def test_ciphers(self):
152 if not test_support.is_resource_enabled('network'):
153 return
154 remote = ("svn.python.org", 443)
155 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
156 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
157 s.connect(remote)
158 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
159 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
160 s.connect(remote)
161 # Error checking occurs when connecting, because the SSL context
162 # isn't created before.
163 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
164 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
165 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
166 s.connect(remote)
167
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000168 @test_support.cpython_only
169 def test_refcycle(self):
170 # Issue #7943: an SSL object doesn't create reference cycles with
171 # itself.
172 s = socket.socket(socket.AF_INET)
173 ss = ssl.wrap_socket(s)
174 wr = weakref.ref(ss)
175 del ss
176 self.assertEqual(wr(), None)
177
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000178
Bill Janssen934b16d2008-06-28 22:19:33 +0000179class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000180
Antoine Pitrou3945c862010-04-28 21:11:01 +0000181 def test_connect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000182 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
183 cert_reqs=ssl.CERT_NONE)
184 s.connect(("svn.python.org", 443))
185 c = s.getpeercert()
186 if c:
Antoine Pitroudb187842010-04-27 10:32:58 +0000187 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000188 s.close()
189
190 # this should fail because we have no verification certs
191 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
192 cert_reqs=ssl.CERT_REQUIRED)
193 try:
194 s.connect(("svn.python.org", 443))
195 except ssl.SSLError:
196 pass
197 finally:
198 s.close()
199
200 # this should succeed because we specify the root cert
201 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
202 cert_reqs=ssl.CERT_REQUIRED,
203 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
204 try:
205 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000206 finally:
207 s.close()
208
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000209 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
210 def test_makefile_close(self):
211 # Issue #5238: creating a file-like object with makefile() shouldn't
212 # delay closing the underlying "real socket" (here tested with its
213 # file descriptor, hence skipping the test under Windows).
214 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
215 ss.connect(("svn.python.org", 443))
216 fd = ss.fileno()
217 f = ss.makefile()
218 f.close()
219 # The fd is still open
220 os.read(fd, 0)
221 # Closing the SSL socket should close the fd too
222 ss.close()
223 gc.collect()
224 with self.assertRaises(OSError) as e:
225 os.read(fd, 0)
226 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000227
Antoine Pitrou3945c862010-04-28 21:11:01 +0000228 def test_non_blocking_handshake(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000229 s = socket.socket(socket.AF_INET)
230 s.connect(("svn.python.org", 443))
231 s.setblocking(False)
232 s = ssl.wrap_socket(s,
233 cert_reqs=ssl.CERT_NONE,
234 do_handshake_on_connect=False)
235 count = 0
236 while True:
237 try:
238 count += 1
239 s.do_handshake()
240 break
241 except ssl.SSLError, err:
242 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
243 select.select([s], [], [])
244 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
245 select.select([], [s], [])
246 else:
247 raise
248 s.close()
249 if test_support.verbose:
250 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
251
Antoine Pitrou3945c862010-04-28 21:11:01 +0000252 def test_get_server_certificate(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000253 pem = ssl.get_server_certificate(("svn.python.org", 443))
254 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000255 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000256
257 try:
258 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
259 except ssl.SSLError:
260 #should fail
261 pass
262 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000263 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000264
265 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
266 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000267 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000268 if test_support.verbose:
269 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
270
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000271 def test_algorithms(self):
272 # Issue #8484: all algorithms should be available when verifying a
273 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000274 # SHA256 was added in OpenSSL 0.9.8
275 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
276 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000277 # NOTE: https://sha256.tbs-internet.com is another possible test host
278 remote = ("sha2.hboeck.de", 443)
279 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
280 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
281 cert_reqs=ssl.CERT_REQUIRED,
282 ca_certs=sha256_cert,)
283 with test_support.transient_internet():
284 try:
285 s.connect(remote)
286 if test_support.verbose:
287 sys.stdout.write("\nCipher with %r is %r\n" %
288 (remote, s.cipher()))
289 sys.stdout.write("Certificate is:\n%s\n" %
290 pprint.pformat(s.getpeercert()))
291 finally:
292 s.close()
293
Bill Janssen296a59d2007-09-16 22:06:00 +0000294
Bill Janssen98d19da2007-09-10 21:51:02 +0000295try:
296 import threading
297except ImportError:
298 _have_threads = False
299else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000300 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000301
Bill Janssen98d19da2007-09-10 21:51:02 +0000302 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000303
Bill Janssen98d19da2007-09-10 21:51:02 +0000304 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000305
Bill Janssen98d19da2007-09-10 21:51:02 +0000306 """A mildly complicated class, because we want it to work both
307 with and without the SSL wrapper around the socket connection, so
308 that we can test the STARTTLS functionality."""
309
310 def __init__(self, server, connsock):
311 self.server = server
312 self.running = False
313 self.sock = connsock
314 self.sock.setblocking(1)
315 self.sslconn = None
316 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000317 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000318
Bill Janssen934b16d2008-06-28 22:19:33 +0000319 def show_conn_details(self):
320 if self.server.certreqs == ssl.CERT_REQUIRED:
321 cert = self.sslconn.getpeercert()
322 if test_support.verbose and self.server.chatty:
323 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
324 cert_binary = self.sslconn.getpeercert(True)
325 if test_support.verbose and self.server.chatty:
326 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
327 cipher = self.sslconn.cipher()
328 if test_support.verbose and self.server.chatty:
329 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
330
Antoine Pitrou3945c862010-04-28 21:11:01 +0000331 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000332 try:
333 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
334 certfile=self.server.certificate,
335 ssl_version=self.server.protocol,
336 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000337 cert_reqs=self.server.certreqs,
338 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000339 except ssl.SSLError:
340 # XXX Various errors can have happened here, for example
341 # a mismatching protocol version, an invalid certificate,
342 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000343 if self.server.chatty:
344 handle_error("\n server: bad connection attempt from " +
345 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000346 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000347 self.running = False
348 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000349 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000350 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000351 return True
352
353 def read(self):
354 if self.sslconn:
355 return self.sslconn.read()
356 else:
357 return self.sock.recv(1024)
358
359 def write(self, bytes):
360 if self.sslconn:
361 return self.sslconn.write(bytes)
362 else:
363 return self.sock.send(bytes)
364
365 def close(self):
366 if self.sslconn:
367 self.sslconn.close()
368 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000369 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000370
Antoine Pitrou3945c862010-04-28 21:11:01 +0000371 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000372 self.running = True
373 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000374 if isinstance(self.sock, ssl.SSLSocket):
375 self.sslconn = self.sock
376 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000377 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000378 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000379 while self.running:
380 try:
381 msg = self.read()
382 if not msg:
383 # eof, so quit this handler
384 self.running = False
385 self.close()
386 elif msg.strip() == 'over':
387 if test_support.verbose and self.server.connectionchatty:
388 sys.stdout.write(" server: client closed connection\n")
389 self.close()
390 return
391 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
392 if test_support.verbose and self.server.connectionchatty:
393 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
394 self.write("OK\n")
395 if not self.wrap_conn():
396 return
Bill Janssen39295c22008-08-12 16:31:21 +0000397 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
398 if test_support.verbose and self.server.connectionchatty:
399 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
400 self.write("OK\n")
401 self.sslconn.unwrap()
402 self.sslconn = None
403 if test_support.verbose and self.server.connectionchatty:
404 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000405 else:
406 if (test_support.verbose and
407 self.server.connectionchatty):
408 ctype = (self.sslconn and "encrypted") or "unencrypted"
409 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
410 % (repr(msg), ctype, repr(msg.lower()), ctype))
411 self.write(msg.lower())
412 except ssl.SSLError:
413 if self.server.chatty:
414 handle_error("Test server failure:\n")
415 self.close()
416 self.running = False
417 # normally, we'd just stop here, but for the test
418 # harness, we want to stop the server
419 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000420
Trent Nelsone41b0062008-04-08 23:47:30 +0000421 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000422 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000423 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000424 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000425
Bill Janssen98d19da2007-09-10 21:51:02 +0000426 if ssl_version is None:
427 ssl_version = ssl.PROTOCOL_TLSv1
428 if certreqs is None:
429 certreqs = ssl.CERT_NONE
430 self.certificate = certificate
431 self.protocol = ssl_version
432 self.certreqs = certreqs
433 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000434 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000435 self.chatty = chatty
436 self.connectionchatty = connectionchatty
437 self.starttls_server = starttls_server
438 self.sock = socket.socket()
439 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000440 if wrap_accepting_socket:
441 self.sock = ssl.wrap_socket(self.sock, server_side=True,
442 certfile=self.certificate,
443 cert_reqs = self.certreqs,
444 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000445 ssl_version = self.protocol,
446 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000447 if test_support.verbose and self.chatty:
448 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
449 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000450 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000451 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000452 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000453
Antoine Pitrou3945c862010-04-28 21:11:01 +0000454 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000455 self.flag = flag
456 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000457
Antoine Pitrou3945c862010-04-28 21:11:01 +0000458 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000459 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000460 self.sock.listen(5)
461 self.active = True
462 if self.flag:
463 # signal an event
464 self.flag.set()
465 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000466 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000467 newconn, connaddr = self.sock.accept()
468 if test_support.verbose and self.chatty:
469 sys.stdout.write(' server: new connection from '
470 + str(connaddr) + '\n')
471 handler = self.ConnectionHandler(self, newconn)
472 handler.start()
473 except socket.timeout:
474 pass
475 except KeyboardInterrupt:
476 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000477 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000478
Antoine Pitrou3945c862010-04-28 21:11:01 +0000479 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000480 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000481
Bill Janssen934b16d2008-06-28 22:19:33 +0000482 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000483
Antoine Pitrou3945c862010-04-28 21:11:01 +0000484 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000485
Antoine Pitrou3945c862010-04-28 21:11:01 +0000486 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000487
488 def __init__(self, conn, certfile):
489 asyncore.dispatcher_with_send.__init__(self, conn)
490 self.socket = ssl.wrap_socket(conn, server_side=True,
491 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000492 do_handshake_on_connect=False)
493 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000494
495 def readable(self):
496 if isinstance(self.socket, ssl.SSLSocket):
497 while self.socket.pending() > 0:
498 self.handle_read_event()
499 return True
500
Antoine Pitroufc69af12010-04-24 20:04:58 +0000501 def _do_ssl_handshake(self):
502 try:
503 self.socket.do_handshake()
504 except ssl.SSLError, err:
505 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
506 ssl.SSL_ERROR_WANT_WRITE):
507 return
508 elif err.args[0] == ssl.SSL_ERROR_EOF:
509 return self.handle_close()
510 raise
511 except socket.error, err:
512 if err.args[0] == errno.ECONNABORTED:
513 return self.handle_close()
514 else:
515 self._ssl_accepting = False
516
Bill Janssen934b16d2008-06-28 22:19:33 +0000517 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000518 if self._ssl_accepting:
519 self._do_ssl_handshake()
520 else:
521 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000522 if data and data.strip() != 'over':
523 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000524
525 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000526 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000527 if test_support.verbose:
528 sys.stdout.write(" server: closed connection %s\n" % self.socket)
529
530 def handle_error(self):
531 raise
532
533 def __init__(self, certfile):
534 self.certfile = certfile
535 asyncore.dispatcher.__init__(self)
536 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
537 self.port = test_support.bind_port(self.socket)
538 self.listen(5)
539
540 def handle_accept(self):
541 sock_obj, addr = self.accept()
542 if test_support.verbose:
543 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
544 self.ConnectionHandler(sock_obj, self.certfile)
545
546 def handle_error(self):
547 raise
548
549 def __init__(self, certfile):
550 self.flag = None
551 self.active = False
552 self.server = self.EchoServer(certfile)
553 self.port = self.server.port
554 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000555 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000556
557 def __str__(self):
558 return "<%s %s>" % (self.__class__.__name__, self.server)
559
Antoine Pitrou3945c862010-04-28 21:11:01 +0000560 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000561 self.flag = flag
562 threading.Thread.start(self)
563
Antoine Pitrou3945c862010-04-28 21:11:01 +0000564 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000565 self.active = True
566 if self.flag:
567 self.flag.set()
568 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000569 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000570
Antoine Pitrou3945c862010-04-28 21:11:01 +0000571 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000572 self.active = False
573 self.server.close()
574
575 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000576
577 class HTTPSServer(HTTPServer):
578
579 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000580 HTTPServer.__init__(self, server_address, RequestHandlerClass)
581 # we assume the certfile contains both private key and certificate
582 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000583 self.allow_reuse_address = True
584
Bill Janssen934b16d2008-06-28 22:19:33 +0000585 def __str__(self):
586 return ('<%s %s:%s>' %
587 (self.__class__.__name__,
588 self.server_name,
589 self.server_port))
590
Antoine Pitrou3945c862010-04-28 21:11:01 +0000591 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000592 # override this to wrap socket with SSL
593 sock, addr = self.socket.accept()
594 sslconn = ssl.wrap_socket(sock, server_side=True,
595 certfile=self.certfile)
596 return sslconn, addr
597
Bill Janssen296a59d2007-09-16 22:06:00 +0000598 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000599 # need to override translate_path to get a known root,
600 # instead of using os.curdir, since the test could be
601 # run from anywhere
602
603 server_version = "TestHTTPS/1.0"
604
605 root = None
606
607 def translate_path(self, path):
608 """Translate a /-separated PATH to the local filename syntax.
609
610 Components that mean special things to the local file system
611 (e.g. drive or directory names) are ignored. (XXX They should
612 probably be diagnosed.)
613
614 """
615 # abandon query parameters
616 path = urlparse.urlparse(path)[2]
617 path = os.path.normpath(urllib.unquote(path))
618 words = path.split('/')
619 words = filter(None, words)
620 path = self.root
621 for word in words:
622 drive, word = os.path.splitdrive(word)
623 head, word = os.path.split(word)
624 if word in self.root: continue
625 path = os.path.join(path, word)
626 return path
627
628 def log_message(self, format, *args):
629
630 # we override this to suppress logging unless "verbose"
631
632 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000633 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
634 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000635 self.server.server_port,
636 self.request.cipher(),
637 self.log_date_time_string(),
638 format%args))
639
640
Trent Nelsone41b0062008-04-08 23:47:30 +0000641 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000642 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000643 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
644 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000645 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
646 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000647 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000648 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000649
650 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000651 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000652
Antoine Pitrou3945c862010-04-28 21:11:01 +0000653 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000654 self.flag = flag
655 threading.Thread.start(self)
656
Antoine Pitrou3945c862010-04-28 21:11:01 +0000657 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000658 if self.flag:
659 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000660 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000661
Antoine Pitrou3945c862010-04-28 21:11:01 +0000662 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000663 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000664
665
Antoine Pitrou3945c862010-04-28 21:11:01 +0000666 def bad_cert_test(certfile):
667 """
668 Launch a server with CERT_REQUIRED, and check that trying to
669 connect to it with the given client certificate fails.
670 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000671 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000672 certreqs=ssl.CERT_REQUIRED,
673 cacerts=CERTFILE, chatty=False)
674 flag = threading.Event()
675 server.start(flag)
676 # wait for it to start
677 flag.wait()
678 # try to connect
679 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000680 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000681 s = ssl.wrap_socket(socket.socket(),
682 certfile=certfile,
683 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000684 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000685 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000686 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000687 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000688 except socket.error, x:
689 if test_support.verbose:
690 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000691 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000692 raise AssertionError("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000693 finally:
694 server.stop()
695 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000696
Antoine Pitrou3945c862010-04-28 21:11:01 +0000697 def server_params_test(certfile, protocol, certreqs, cacertsfile,
698 client_certfile, client_protocol=None, indata="FOO\n",
699 ciphers=None, chatty=True, connectionchatty=False,
700 wrap_accepting_socket=False):
701 """
702 Launch a server, connect a client to it and try various reads
703 and writes.
704 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000705 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000706 certreqs=certreqs,
707 ssl_version=protocol,
708 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000709 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000710 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000711 connectionchatty=connectionchatty,
712 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000713 flag = threading.Event()
714 server.start(flag)
715 # wait for it to start
716 flag.wait()
717 # try to connect
718 if client_protocol is None:
719 client_protocol = protocol
720 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000721 s = ssl.wrap_socket(socket.socket(),
722 certfile=client_certfile,
723 ca_certs=cacertsfile,
724 ciphers=ciphers,
725 cert_reqs=certreqs,
726 ssl_version=client_protocol)
727 s.connect((HOST, server.port))
728 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000729 if connectionchatty:
730 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000731 sys.stdout.write(
732 " client: sending %s...\n" % (repr(arg)))
733 s.write(arg)
734 outdata = s.read()
735 if connectionchatty:
736 if test_support.verbose:
737 sys.stdout.write(" client: read %s\n" % repr(outdata))
738 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000739 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000740 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
741 % (outdata[:min(len(outdata),20)], len(outdata),
742 indata[:min(len(indata),20)].lower(), len(indata)))
743 s.write("over\n")
744 if connectionchatty:
745 if test_support.verbose:
746 sys.stdout.write(" client: closing connection.\n")
747 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000748 finally:
749 server.stop()
750 server.join()
751
Antoine Pitrou3945c862010-04-28 21:11:01 +0000752 def try_protocol_combo(server_protocol,
753 client_protocol,
754 expect_success,
755 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000756 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000757 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000758 certtype = {
759 ssl.CERT_NONE: "CERT_NONE",
760 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
761 ssl.CERT_REQUIRED: "CERT_REQUIRED",
762 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000763 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000764 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000765 sys.stdout.write(formatstr %
766 (ssl.get_protocol_name(client_protocol),
767 ssl.get_protocol_name(server_protocol),
768 certtype))
769 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000770 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
771 # will send an SSLv3 hello (rather than SSLv2) starting from
772 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000773 server_params_test(CERTFILE, server_protocol, certsreqs,
774 CERTFILE, CERTFILE, client_protocol,
775 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000776 # Protocol mismatch can result in either an SSLError, or a
777 # "Connection reset by peer" error.
778 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000779 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000780 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000781 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000782 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000783 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000784 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000785 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000786 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000787 "Client protocol %s succeeded with server protocol %s!"
788 % (ssl.get_protocol_name(client_protocol),
789 ssl.get_protocol_name(server_protocol)))
790
791
Bill Janssen934b16d2008-06-28 22:19:33 +0000792 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000793
Antoine Pitrou3945c862010-04-28 21:11:01 +0000794 def test_rude_shutdown(self):
795 """A brutal shutdown of an SSL server should raise an IOError
796 in the client when attempting handshake.
797 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000798 listener_ready = threading.Event()
799 listener_gone = threading.Event()
800
Antoine Pitrou150acda2010-04-27 08:40:51 +0000801 s = socket.socket()
802 port = test_support.bind_port(s, HOST)
803
804 # `listener` runs in a thread. It sits in an accept() until
805 # the main thread connects. Then it rudely closes the socket,
806 # and sets Event `listener_gone` to let the main thread know
807 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000808 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000809 s.listen(5)
810 listener_ready.set()
811 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000812 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000813 listener_gone.set()
814
815 def connector():
816 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000817 c = socket.socket()
818 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000819 listener_gone.wait()
820 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000821 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000822 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000823 pass
824 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000825 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000826
827 t = threading.Thread(target=listener)
828 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000829 try:
830 connector()
831 finally:
832 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000833
Antoine Pitroud75efd92010-08-04 17:38:33 +0000834 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000835 def test_echo(self):
836 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000837 if test_support.verbose:
838 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000839 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
840 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
841 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000842
Antoine Pitrou3945c862010-04-28 21:11:01 +0000843 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000844 if test_support.verbose:
845 sys.stdout.write("\n")
846 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000847 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000848 certreqs=ssl.CERT_NONE,
849 ssl_version=ssl.PROTOCOL_SSLv23,
850 cacerts=CERTFILE,
851 chatty=False)
852 flag = threading.Event()
853 server.start(flag)
854 # wait for it to start
855 flag.wait()
856 # try to connect
857 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000858 s = ssl.wrap_socket(socket.socket(),
859 certfile=CERTFILE,
860 ca_certs=CERTFILE,
861 cert_reqs=ssl.CERT_REQUIRED,
862 ssl_version=ssl.PROTOCOL_SSLv23)
863 s.connect((HOST, server.port))
864 cert = s.getpeercert()
865 self.assertTrue(cert, "Can't get peer certificate.")
866 cipher = s.cipher()
867 if test_support.verbose:
868 sys.stdout.write(pprint.pformat(cert) + '\n')
869 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
870 if 'subject' not in cert:
871 self.fail("No subject field in certificate: %s." %
872 pprint.pformat(cert))
873 if ((('organizationName', 'Python Software Foundation'),)
874 not in cert['subject']):
875 self.fail(
876 "Missing or invalid 'organizationName' field in certificate subject; "
877 "should be 'Python Software Foundation'.")
878 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000879 finally:
880 server.stop()
881 server.join()
882
Antoine Pitrou3945c862010-04-28 21:11:01 +0000883 def test_empty_cert(self):
884 """Connecting with an empty cert file"""
885 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
886 "nullcert.pem"))
887 def test_malformed_cert(self):
888 """Connecting with a badly formatted certificate (syntax error)"""
889 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
890 "badcert.pem"))
891 def test_nonexisting_cert(self):
892 """Connecting with a non-existing cert file"""
893 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
894 "wrongcert.pem"))
895 def test_malformed_key(self):
896 """Connecting with a badly formatted key (syntax error)"""
897 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
898 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000899
Antoine Pitroud75efd92010-08-04 17:38:33 +0000900 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000901 def test_protocol_sslv2(self):
902 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000903 if test_support.verbose:
904 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000905 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
906 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
907 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
908 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
909 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
910 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000911
Antoine Pitroud75efd92010-08-04 17:38:33 +0000912 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000913 def test_protocol_sslv23(self):
914 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000915 if test_support.verbose:
916 sys.stdout.write("\n")
917 try:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000918 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000919 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000920 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
921 if test_support.verbose:
922 sys.stdout.write(
923 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
924 % str(x))
Antoine Pitrou3945c862010-04-28 21:11:01 +0000925 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
926 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
927 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000928
Antoine Pitrou3945c862010-04-28 21:11:01 +0000929 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
930 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
931 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000932
Antoine Pitrou3945c862010-04-28 21:11:01 +0000933 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
934 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
935 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000936
Antoine Pitroud75efd92010-08-04 17:38:33 +0000937 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000938 def test_protocol_sslv3(self):
939 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000940 if test_support.verbose:
941 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000942 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
943 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
944 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
945 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
946 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
947 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000948
Antoine Pitroud75efd92010-08-04 17:38:33 +0000949 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000950 def test_protocol_tlsv1(self):
951 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000952 if test_support.verbose:
953 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000954 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
955 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
956 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
957 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
958 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
959 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000960
Antoine Pitrou3945c862010-04-28 21:11:01 +0000961 def test_starttls(self):
962 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000963 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000964
Trent Nelsone41b0062008-04-08 23:47:30 +0000965 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000966 ssl_version=ssl.PROTOCOL_TLSv1,
967 starttls_server=True,
968 chatty=True,
969 connectionchatty=True)
970 flag = threading.Event()
971 server.start(flag)
972 # wait for it to start
973 flag.wait()
974 # try to connect
975 wrapped = False
976 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000977 s = socket.socket()
978 s.setblocking(1)
979 s.connect((HOST, server.port))
980 if test_support.verbose:
981 sys.stdout.write("\n")
982 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000983 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000984 sys.stdout.write(
985 " client: sending %s...\n" % repr(indata))
986 if wrapped:
987 conn.write(indata)
988 outdata = conn.read()
989 else:
990 s.send(indata)
991 outdata = s.recv(1024)
992 if (indata == "STARTTLS" and
993 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +0000994 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +0000995 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000996 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +0000997 " client: read %s from server, starting TLS...\n"
998 % repr(outdata))
999 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1000 wrapped = True
1001 elif (indata == "ENDTLS" and
1002 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001003 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001004 if test_support.verbose:
1005 sys.stdout.write(
1006 " client: read %s from server, ending TLS...\n"
1007 % repr(outdata))
1008 s = conn.unwrap()
1009 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001010 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001011 if test_support.verbose:
1012 sys.stdout.write(
1013 " client: read %s from server\n" % repr(outdata))
1014 if test_support.verbose:
1015 sys.stdout.write(" client: closing connection.\n")
1016 if wrapped:
1017 conn.write("over\n")
1018 else:
1019 s.send("over\n")
1020 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001021 finally:
1022 server.stop()
1023 server.join()
1024
Antoine Pitrou3945c862010-04-28 21:11:01 +00001025 def test_socketserver(self):
1026 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001027 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001028 flag = threading.Event()
1029 server.start(flag)
1030 # wait for it to start
1031 flag.wait()
1032 # try to connect
1033 try:
1034 if test_support.verbose:
1035 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001036 with open(CERTFILE, 'rb') as f:
1037 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001038 d2 = ''
1039 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001040 url = 'https://127.0.0.1:%d/%s' % (
1041 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001042 with test_support.check_py3k_warnings():
1043 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001044 dlen = f.info().getheader("content-length")
1045 if dlen and (int(dlen) > 0):
1046 d2 = f.read(int(dlen))
1047 if test_support.verbose:
1048 sys.stdout.write(
1049 " client: read %d bytes from remote server '%s'\n"
1050 % (len(d2), server))
1051 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001052 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001053 finally:
1054 server.stop()
1055 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001056
Antoine Pitrou3945c862010-04-28 21:11:01 +00001057 def test_wrapped_accept(self):
1058 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001059 if test_support.verbose:
1060 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001061 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1062 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1063 chatty=True, connectionchatty=True,
1064 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001065
Antoine Pitrou3945c862010-04-28 21:11:01 +00001066 def test_asyncore_server(self):
1067 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001068 indata = "TEST MESSAGE of mixed case\n"
1069
1070 if test_support.verbose:
1071 sys.stdout.write("\n")
1072 server = AsyncoreEchoServer(CERTFILE)
1073 flag = threading.Event()
1074 server.start(flag)
1075 # wait for it to start
1076 flag.wait()
1077 # try to connect
1078 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001079 s = ssl.wrap_socket(socket.socket())
1080 s.connect(('127.0.0.1', server.port))
1081 if test_support.verbose:
1082 sys.stdout.write(
1083 " client: sending %s...\n" % (repr(indata)))
1084 s.write(indata)
1085 outdata = s.read()
1086 if test_support.verbose:
1087 sys.stdout.write(" client: read %s\n" % repr(outdata))
1088 if outdata != indata.lower():
1089 self.fail(
1090 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1091 % (outdata[:min(len(outdata),20)], len(outdata),
1092 indata[:min(len(indata),20)].lower(), len(indata)))
1093 s.write("over\n")
1094 if test_support.verbose:
1095 sys.stdout.write(" client: closing connection.\n")
1096 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001097 finally:
1098 server.stop()
1099 # wait for server thread to end
1100 server.join()
1101
Antoine Pitrou3945c862010-04-28 21:11:01 +00001102 def test_recv_send(self):
1103 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001104 if test_support.verbose:
1105 sys.stdout.write("\n")
1106
1107 server = ThreadedEchoServer(CERTFILE,
1108 certreqs=ssl.CERT_NONE,
1109 ssl_version=ssl.PROTOCOL_TLSv1,
1110 cacerts=CERTFILE,
1111 chatty=True,
1112 connectionchatty=False)
1113 flag = threading.Event()
1114 server.start(flag)
1115 # wait for it to start
1116 flag.wait()
1117 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001118 s = ssl.wrap_socket(socket.socket(),
1119 server_side=False,
1120 certfile=CERTFILE,
1121 ca_certs=CERTFILE,
1122 cert_reqs=ssl.CERT_NONE,
1123 ssl_version=ssl.PROTOCOL_TLSv1)
1124 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001125 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001126 # helper methods for standardising recv* method signatures
1127 def _recv_into():
1128 b = bytearray("\0"*100)
1129 count = s.recv_into(b)
1130 return b[:count]
1131
1132 def _recvfrom_into():
1133 b = bytearray("\0"*100)
1134 count, addr = s.recvfrom_into(b)
1135 return b[:count]
1136
1137 # (name, method, whether to expect success, *args)
1138 send_methods = [
1139 ('send', s.send, True, []),
1140 ('sendto', s.sendto, False, ["some.address"]),
1141 ('sendall', s.sendall, True, []),
1142 ]
1143 recv_methods = [
1144 ('recv', s.recv, True, []),
1145 ('recvfrom', s.recvfrom, False, ["some.address"]),
1146 ('recv_into', _recv_into, True, []),
1147 ('recvfrom_into', _recvfrom_into, False, []),
1148 ]
1149 data_prefix = u"PREFIX_"
1150
1151 for meth_name, send_meth, expect_success, args in send_methods:
1152 indata = data_prefix + meth_name
1153 try:
1154 send_meth(indata.encode('ASCII', 'strict'), *args)
1155 outdata = s.read()
1156 outdata = outdata.decode('ASCII', 'strict')
1157 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001158 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001159 "While sending with <<%s>> bad data "
1160 "<<%r>> (%d) received; "
1161 "expected <<%r>> (%d)\n" % (
1162 meth_name, outdata[:20], len(outdata),
1163 indata[:20], len(indata)
1164 )
1165 )
1166 except ValueError as e:
1167 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001168 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001169 "Failed to send with method <<%s>>; "
1170 "expected to succeed.\n" % (meth_name,)
1171 )
1172 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001173 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001174 "Method <<%s>> failed with unexpected "
1175 "exception message: %s\n" % (
1176 meth_name, e
1177 )
1178 )
1179
1180 for meth_name, recv_meth, expect_success, args in recv_methods:
1181 indata = data_prefix + meth_name
1182 try:
1183 s.send(indata.encode('ASCII', 'strict'))
1184 outdata = recv_meth(*args)
1185 outdata = outdata.decode('ASCII', 'strict')
1186 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001187 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001188 "While receiving with <<%s>> bad data "
1189 "<<%r>> (%d) received; "
1190 "expected <<%r>> (%d)\n" % (
1191 meth_name, outdata[:20], len(outdata),
1192 indata[:20], len(indata)
1193 )
1194 )
1195 except ValueError as e:
1196 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001197 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001198 "Failed to receive with method <<%s>>; "
1199 "expected to succeed.\n" % (meth_name,)
1200 )
1201 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001202 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001203 "Method <<%s>> failed with unexpected "
1204 "exception message: %s\n" % (
1205 meth_name, e
1206 )
1207 )
1208 # consume data
1209 s.read()
1210
1211 s.write("over\n".encode("ASCII", "strict"))
1212 s.close()
1213 finally:
1214 server.stop()
1215 server.join()
1216
Antoine Pitroufc69af12010-04-24 20:04:58 +00001217 def test_handshake_timeout(self):
1218 # Issue #5103: SSL handshake must respect the socket timeout
1219 server = socket.socket(socket.AF_INET)
1220 host = "127.0.0.1"
1221 port = test_support.bind_port(server)
1222 started = threading.Event()
1223 finish = False
1224
1225 def serve():
1226 server.listen(5)
1227 started.set()
1228 conns = []
1229 while not finish:
1230 r, w, e = select.select([server], [], [], 0.1)
1231 if server in r:
1232 # Let the socket hang around rather than having
1233 # it closed by garbage collection.
1234 conns.append(server.accept()[0])
1235
1236 t = threading.Thread(target=serve)
1237 t.start()
1238 started.wait()
1239
1240 try:
1241 try:
1242 c = socket.socket(socket.AF_INET)
1243 c.settimeout(0.2)
1244 c.connect((host, port))
1245 # Will attempt handshake and time out
1246 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1247 ssl.wrap_socket, c)
1248 finally:
1249 c.close()
1250 try:
1251 c = socket.socket(socket.AF_INET)
1252 c.settimeout(0.2)
1253 c = ssl.wrap_socket(c)
1254 # Will attempt handshake and time out
1255 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1256 c.connect, (host, port))
1257 finally:
1258 c.close()
1259 finally:
1260 finish = True
1261 t.join()
1262 server.close()
1263
Bill Janssen61c001a2008-09-08 16:37:24 +00001264
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001265def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001266 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001267 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001268
Trent Nelsone41b0062008-04-08 23:47:30 +00001269 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001270 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001271 "keycert.pem")
1272 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1273 os.path.dirname(__file__) or os.curdir,
1274 "https_svn_python_org_root.pem")
1275
1276 if (not os.path.exists(CERTFILE) or
1277 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001278 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001279
1280 tests = [BasicTests]
1281
Bill Janssen296a59d2007-09-16 22:06:00 +00001282 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001283 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001284
Bill Janssen98d19da2007-09-10 21:51:02 +00001285 if _have_threads:
1286 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001287 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001288 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001289
Antoine Pitrou3945c862010-04-28 21:11:01 +00001290 try:
1291 test_support.run_unittest(*tests)
1292 finally:
1293 if _have_threads:
1294 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001295
1296if __name__ == "__main__":
1297 test_main()