blob: b485605d420a0abcefbd8e4e49d7fbd137c5778f [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Jeremy Hylton1afc1692008-06-18 20:49:58 +000014import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +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
Antoine Pitrou27ba6382010-05-16 20:35:03 +000029else:
30 PROTOCOLS = [
31 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
32 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
33 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000034
Benjamin Petersonee8712c2008-05-20 21:35:26 +000035HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
37data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038
39CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
54
Thomas Woutersed03b412007-08-28 21:37:11 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056def handle_error(prefix):
57 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000059 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitroub5218772010-05-21 09:56:06 +000061def can_clear_options():
62 # 0.9.8m or higher
63 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
64
65def no_sslv2_implies_sslv3_hello():
66 # 0.9.7h or higher
67 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
68
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou23df4832010-08-04 17:14:06 +000070# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
71def skip_if_broken_ubuntu_ssl(func):
72 @functools.wraps(func)
73 def f(*args, **kwargs):
74 try:
75 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
76 except ssl.SSLError:
77 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
78 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
79 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
80 return func(*args, **kwargs)
81 return f
82
83
Antoine Pitrou152efa22010-05-16 18:19:27 +000084class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Antoine Pitrou480a1242010-04-28 21:37:09 +000086 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 ssl.PROTOCOL_SSLv2
88 ssl.PROTOCOL_SSLv23
89 ssl.PROTOCOL_SSLv3
90 ssl.PROTOCOL_TLSv1
91 ssl.CERT_NONE
92 ssl.CERT_OPTIONAL
93 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000097 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 sys.stdout.write("\n RAND_status is %d (%s)\n"
99 % (v, (v and "sufficient randomness") or
100 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000101 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102 ssl.RAND_egd(1)
103 except TypeError:
104 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000105 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 print("didn't raise TypeError")
107 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000108
Antoine Pitrou480a1242010-04-28 21:37:09 +0000109 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000110 # note that this uses an 'unofficial' function in _ssl.c,
111 # provided solely for this test, to exercise the certificate
112 # parsing code
113 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000116
Antoine Pitrou480a1242010-04-28 21:37:09 +0000117 def test_DER_to_PEM(self):
118 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
119 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 d1 = ssl.PEM_cert_to_DER_cert(pem)
121 p2 = ssl.DER_cert_to_PEM_cert(d1)
122 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000123 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000124 if not p2.startswith(ssl.PEM_HEADER + '\n'):
125 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
126 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
127 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000129 def test_openssl_version(self):
130 n = ssl.OPENSSL_VERSION_NUMBER
131 t = ssl.OPENSSL_VERSION_INFO
132 s = ssl.OPENSSL_VERSION
133 self.assertIsInstance(n, int)
134 self.assertIsInstance(t, tuple)
135 self.assertIsInstance(s, str)
136 # Some sanity checks follow
137 # >= 0.9
138 self.assertGreaterEqual(n, 0x900000)
139 # < 2.0
140 self.assertLess(n, 0x20000000)
141 major, minor, fix, patch, status = t
142 self.assertGreaterEqual(major, 0)
143 self.assertLess(major, 2)
144 self.assertGreaterEqual(minor, 0)
145 self.assertLess(minor, 256)
146 self.assertGreaterEqual(fix, 0)
147 self.assertLess(fix, 256)
148 self.assertGreaterEqual(patch, 0)
149 self.assertLessEqual(patch, 26)
150 self.assertGreaterEqual(status, 0)
151 self.assertLessEqual(status, 15)
152 # Version string as returned by OpenSSL, the format might change
153 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
154 (s, t))
155
Antoine Pitrou9d543662010-04-23 23:10:32 +0000156 @support.cpython_only
157 def test_refcycle(self):
158 # Issue #7943: an SSL object doesn't create reference cycles with
159 # itself.
160 s = socket.socket(socket.AF_INET)
161 ss = ssl.wrap_socket(s)
162 wr = weakref.ref(ss)
163 del ss
164 self.assertEqual(wr(), None)
165
Antoine Pitrou40f08742010-04-24 22:04:40 +0000166 def test_timeout(self):
167 # Issue #8524: when creating an SSL socket, the timeout of the
168 # original socket should be retained.
169 for timeout in (None, 0.0, 5.0):
170 s = socket.socket(socket.AF_INET)
171 s.settimeout(timeout)
172 ss = ssl.wrap_socket(s)
173 self.assertEqual(timeout, ss.gettimeout())
174
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000175 def test_errors(self):
176 sock = socket.socket()
177 with self.assertRaisesRegexp(ValueError, "certfile must be specified"):
178 ssl.wrap_socket(sock, server_side=True)
179 ssl.wrap_socket(sock, server_side=True, certfile="")
180 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
181 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
182 s.connect, (HOST, 8080))
183 with self.assertRaisesRegexp(IOError, "No such file"):
184 ssl.wrap_socket(sock, certfile=WRONGCERT)
185 ssl.wrap_socket(sock, keyfile=WRONGCERT)
186 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
187
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000188
Antoine Pitrou152efa22010-05-16 18:19:27 +0000189class ContextTests(unittest.TestCase):
190
Antoine Pitrou23df4832010-08-04 17:14:06 +0000191 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000192 def test_constructor(self):
193 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
194 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
195 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
196 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
197 self.assertRaises(TypeError, ssl.SSLContext)
198 self.assertRaises(ValueError, ssl.SSLContext, -1)
199 self.assertRaises(ValueError, ssl.SSLContext, 42)
200
Antoine Pitrou23df4832010-08-04 17:14:06 +0000201 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000202 def test_protocol(self):
203 for proto in PROTOCOLS:
204 ctx = ssl.SSLContext(proto)
205 self.assertEqual(ctx.protocol, proto)
206
207 def test_ciphers(self):
208 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
209 ctx.set_ciphers("ALL")
210 ctx.set_ciphers("DEFAULT")
211 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000212 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000213
Antoine Pitrou23df4832010-08-04 17:14:06 +0000214 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000215 def test_options(self):
216 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
217 # OP_ALL is the default value
218 self.assertEqual(ssl.OP_ALL, ctx.options)
219 ctx.options |= ssl.OP_NO_SSLv2
220 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
221 ctx.options)
222 ctx.options |= ssl.OP_NO_SSLv3
223 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
224 ctx.options)
225 if can_clear_options():
226 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
227 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
228 ctx.options)
229 ctx.options = 0
230 self.assertEqual(0, ctx.options)
231 else:
232 with self.assertRaises(ValueError):
233 ctx.options = 0
234
Antoine Pitrou152efa22010-05-16 18:19:27 +0000235 def test_verify(self):
236 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
237 # Default value
238 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
239 ctx.verify_mode = ssl.CERT_OPTIONAL
240 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
241 ctx.verify_mode = ssl.CERT_REQUIRED
242 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
243 ctx.verify_mode = ssl.CERT_NONE
244 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
245 with self.assertRaises(TypeError):
246 ctx.verify_mode = None
247 with self.assertRaises(ValueError):
248 ctx.verify_mode = 42
249
250 def test_load_cert_chain(self):
251 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
252 # Combined key and cert in a single file
253 ctx.load_cert_chain(CERTFILE)
254 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
255 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000256 with self.assertRaisesRegexp(IOError, "No such file"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000257 ctx.load_cert_chain(WRONGCERT)
258 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
259 ctx.load_cert_chain(BADCERT)
260 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
261 ctx.load_cert_chain(EMPTYCERT)
262 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000263 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000264 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
265 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
266 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
267 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
268 ctx.load_cert_chain(ONLYCERT)
269 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
270 ctx.load_cert_chain(ONLYKEY)
271 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
272 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
273 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000274 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000275 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
276 ctx.load_cert_chain(CERTFILE, ONLYKEY)
277
278 def test_load_verify_locations(self):
279 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
280 ctx.load_verify_locations(CERTFILE)
281 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
282 ctx.load_verify_locations(BYTES_CERTFILE)
283 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
284 self.assertRaises(TypeError, ctx.load_verify_locations)
285 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000286 with self.assertRaisesRegexp(IOError, "No such file"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000287 ctx.load_verify_locations(WRONGCERT)
288 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
289 ctx.load_verify_locations(BADCERT)
290 ctx.load_verify_locations(CERTFILE, CAPATH)
291 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
292
293
Bill Janssen6e027db2007-11-15 22:23:56 +0000294class NetworkedTests(unittest.TestCase):
Antoine Pitroud151e272010-08-14 16:32:10 +0000295 def setUp(self):
296 self.old_timeout = socket.getdefaulttimeout()
297 socket.setdefaulttimeout(30)
298
299 def tearDown(self):
300 socket.setdefaulttimeout(self.old_timeout)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000301
Antoine Pitrou480a1242010-04-28 21:37:09 +0000302 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000303 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
304 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000305 try:
306 s.connect(("svn.python.org", 443))
307 self.assertEqual({}, s.getpeercert())
308 finally:
309 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000310
311 # this should fail because we have no verification certs
312 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
313 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000314 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
315 s.connect, ("svn.python.org", 443))
316 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000317
318 # this should succeed because we specify the root cert
319 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
320 cert_reqs=ssl.CERT_REQUIRED,
321 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
322 try:
323 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000324 self.assertTrue(s.getpeercert())
325 finally:
326 s.close()
327
328 def test_connect_with_context(self):
329 # Same as test_connect, but with a separately created context
330 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
331 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
332 s.connect(("svn.python.org", 443))
333 try:
334 self.assertEqual({}, s.getpeercert())
335 finally:
336 s.close()
337 # This should fail because we have no verification certs
338 ctx.verify_mode = ssl.CERT_REQUIRED
339 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
340 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
341 s.connect, ("svn.python.org", 443))
342 s.close()
343 # This should succeed because we specify the root cert
344 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
345 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
346 s.connect(("svn.python.org", 443))
347 try:
348 cert = s.getpeercert()
349 self.assertTrue(cert)
350 finally:
351 s.close()
352
353 def test_connect_capath(self):
354 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000355 # NOTE: the subject hashing algorithm has been changed between
356 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
357 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000358 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000359 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
360 ctx.verify_mode = ssl.CERT_REQUIRED
361 ctx.load_verify_locations(capath=CAPATH)
362 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
363 s.connect(("svn.python.org", 443))
364 try:
365 cert = s.getpeercert()
366 self.assertTrue(cert)
367 finally:
368 s.close()
369 # Same with a bytes `capath` argument
370 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
371 ctx.verify_mode = ssl.CERT_REQUIRED
372 ctx.load_verify_locations(capath=BYTES_CAPATH)
373 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
374 s.connect(("svn.python.org", 443))
375 try:
376 cert = s.getpeercert()
377 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000378 finally:
379 s.close()
380
Antoine Pitroue3220242010-04-24 11:13:53 +0000381 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
382 def test_makefile_close(self):
383 # Issue #5238: creating a file-like object with makefile() shouldn't
384 # delay closing the underlying "real socket" (here tested with its
385 # file descriptor, hence skipping the test under Windows).
386 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
387 ss.connect(("svn.python.org", 443))
388 fd = ss.fileno()
389 f = ss.makefile()
390 f.close()
391 # The fd is still open
392 os.read(fd, 0)
393 # Closing the SSL socket should close the fd too
394 ss.close()
395 gc.collect()
396 with self.assertRaises(OSError) as e:
397 os.read(fd, 0)
398 self.assertEqual(e.exception.errno, errno.EBADF)
399
Antoine Pitrou480a1242010-04-28 21:37:09 +0000400 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000401 s = socket.socket(socket.AF_INET)
402 s.connect(("svn.python.org", 443))
403 s.setblocking(False)
404 s = ssl.wrap_socket(s,
405 cert_reqs=ssl.CERT_NONE,
406 do_handshake_on_connect=False)
407 count = 0
408 while True:
409 try:
410 count += 1
411 s.do_handshake()
412 break
413 except ssl.SSLError as err:
414 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
415 select.select([s], [], [])
416 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
417 select.select([], [s], [])
418 else:
419 raise
420 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000421 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000422 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000423
Antoine Pitrou480a1242010-04-28 21:37:09 +0000424 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000425 pem = ssl.get_server_certificate(("svn.python.org", 443))
426 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000427 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000428
Bill Janssen54cc54c2007-12-14 22:08:56 +0000429 try:
430 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
431 except ssl.SSLError as x:
432 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000433 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000434 sys.stdout.write("%s\n" % x)
435 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000436 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000437
438 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
439 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000440 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000441 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000442 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
443
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000444 def test_ciphers(self):
445 remote = ("svn.python.org", 443)
446 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
447 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
448 s.connect(remote)
449 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
450 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
451 s.connect(remote)
452 # Error checking can happen at instantiation or when connecting
453 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
454 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
455 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
456 s.connect(remote)
457
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000458 def test_algorithms(self):
459 # Issue #8484: all algorithms should be available when verifying a
460 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000461 # SHA256 was added in OpenSSL 0.9.8
462 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
463 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000464 # NOTE: https://sha256.tbs-internet.com is another possible test host
465 remote = ("sha2.hboeck.de", 443)
466 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
467 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
468 cert_reqs=ssl.CERT_REQUIRED,
469 ca_certs=sha256_cert,)
470 with support.transient_internet():
471 try:
472 s.connect(remote)
473 if support.verbose:
474 sys.stdout.write("\nCipher with %r is %r\n" %
475 (remote, s.cipher()))
476 sys.stdout.write("Certificate is:\n%s\n" %
477 pprint.pformat(s.getpeercert()))
478 finally:
479 s.close()
480
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000481
482try:
483 import threading
484except ImportError:
485 _have_threads = False
486else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000487 _have_threads = True
488
489 class ThreadedEchoServer(threading.Thread):
490
491 class ConnectionHandler(threading.Thread):
492
493 """A mildly complicated class, because we want it to work both
494 with and without the SSL wrapper around the socket connection, so
495 that we can test the STARTTLS functionality."""
496
Bill Janssen6e027db2007-11-15 22:23:56 +0000497 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000498 self.server = server
499 self.running = False
500 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000501 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000502 self.sock.setblocking(1)
503 self.sslconn = None
504 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000505 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000506
Antoine Pitrou480a1242010-04-28 21:37:09 +0000507 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000508 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000509 self.sslconn = self.server.context.wrap_socket(
510 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000511 except ssl.SSLError:
512 # XXX Various errors can have happened here, for example
513 # a mismatching protocol version, an invalid certificate,
514 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000515 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000516 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000517 self.running = False
518 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000519 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000520 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000521 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000522 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000523 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000524 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000525 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
526 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000527 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
529 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000530 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000531 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
532 return True
533
534 def read(self):
535 if self.sslconn:
536 return self.sslconn.read()
537 else:
538 return self.sock.recv(1024)
539
540 def write(self, bytes):
541 if self.sslconn:
542 return self.sslconn.write(bytes)
543 else:
544 return self.sock.send(bytes)
545
546 def close(self):
547 if self.sslconn:
548 self.sslconn.close()
549 else:
550 self.sock.close()
551
Antoine Pitrou480a1242010-04-28 21:37:09 +0000552 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000553 self.running = True
554 if not self.server.starttls_server:
555 if not self.wrap_conn():
556 return
557 while self.running:
558 try:
559 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000560 stripped = msg.strip()
561 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000562 # eof, so quit this handler
563 self.running = False
564 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000565 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000566 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000567 sys.stdout.write(" server: client closed connection\n")
568 self.close()
569 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000570 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000571 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000572 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000573 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000574 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000575 if not self.wrap_conn():
576 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000577 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000578 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000579 if support.verbose and self.server.connectionchatty:
580 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000581 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000582 self.sock = self.sslconn.unwrap()
583 self.sslconn = None
584 if support.verbose and self.server.connectionchatty:
585 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000586 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000587 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000588 self.server.connectionchatty):
589 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000590 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
591 % (msg, ctype, msg.lower(), ctype))
592 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000593 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000594 if self.server.chatty:
595 handle_error("Test server failure:\n")
596 self.close()
597 self.running = False
598 # normally, we'd just stop here, but for the test
599 # harness, we want to stop the server
600 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000601
Antoine Pitroub5218772010-05-21 09:56:06 +0000602 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000603 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000604 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000605 ciphers=None, context=None):
606 if context:
607 self.context = context
608 else:
609 self.context = ssl.SSLContext(ssl_version
610 if ssl_version is not None
611 else ssl.PROTOCOL_TLSv1)
612 self.context.verify_mode = (certreqs if certreqs is not None
613 else ssl.CERT_NONE)
614 if cacerts:
615 self.context.load_verify_locations(cacerts)
616 if certificate:
617 self.context.load_cert_chain(certificate)
618 if ciphers:
619 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000620 self.chatty = chatty
621 self.connectionchatty = connectionchatty
622 self.starttls_server = starttls_server
623 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000624 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000625 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000626 self.active = False
627 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000628 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000629
Antoine Pitrou480a1242010-04-28 21:37:09 +0000630 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000631 self.flag = flag
632 threading.Thread.start(self)
633
Antoine Pitrou480a1242010-04-28 21:37:09 +0000634 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000635 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000636 self.sock.listen(5)
637 self.active = True
638 if self.flag:
639 # signal an event
640 self.flag.set()
641 while self.active:
642 try:
643 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000644 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000646 + repr(connaddr) + '\n')
647 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000648 handler.start()
649 except socket.timeout:
650 pass
651 except KeyboardInterrupt:
652 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000653 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000654
Antoine Pitrou480a1242010-04-28 21:37:09 +0000655 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000656 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657
Bill Janssen54cc54c2007-12-14 22:08:56 +0000658 class OurHTTPSServer(threading.Thread):
659
660 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000661
662 class HTTPSServer(HTTPServer):
663
664 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665 HTTPServer.__init__(self, server_address, RequestHandlerClass)
666 # we assume the certfile contains both private key and certificate
667 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000668 self.allow_reuse_address = True
669
Bill Janssen6e027db2007-11-15 22:23:56 +0000670 def __str__(self):
671 return ('<%s %s:%s>' %
672 (self.__class__.__name__,
673 self.server_name,
674 self.server_port))
675
Antoine Pitrou480a1242010-04-28 21:37:09 +0000676 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000677 # override this to wrap socket with SSL
678 sock, addr = self.socket.accept()
679 sslconn = ssl.wrap_socket(sock, server_side=True,
680 certfile=self.certfile)
681 return sslconn, addr
682
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000683 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000684 # need to override translate_path to get a known root,
685 # instead of using os.curdir, since the test could be
686 # run from anywhere
687
688 server_version = "TestHTTPS/1.0"
689
690 root = None
691
692 def translate_path(self, path):
693 """Translate a /-separated PATH to the local filename syntax.
694
695 Components that mean special things to the local file system
696 (e.g. drive or directory names) are ignored. (XXX They should
697 probably be diagnosed.)
698
699 """
700 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000701 path = urllib.parse.urlparse(path)[2]
702 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000703 words = path.split('/')
704 words = filter(None, words)
705 path = self.root
706 for word in words:
707 drive, word = os.path.splitdrive(word)
708 head, word = os.path.split(word)
709 if word in self.root: continue
710 path = os.path.join(path, word)
711 return path
712
713 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000714 # we override this to suppress logging unless "verbose"
715
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000716 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000717 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
718 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000719 self.server.server_port,
720 self.request.cipher(),
721 self.log_date_time_string(),
722 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000723
724
Trent Nelson78520002008-04-10 20:54:35 +0000725 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000726 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000727 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
728 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000729 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
730 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000731 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000732 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000733
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000734 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000735 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000736
Antoine Pitrou480a1242010-04-28 21:37:09 +0000737 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000738 self.flag = flag
739 threading.Thread.start(self)
740
Antoine Pitrou480a1242010-04-28 21:37:09 +0000741 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000742 if self.flag:
743 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000744 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000745
Antoine Pitrou480a1242010-04-28 21:37:09 +0000746 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000747 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000748
749
Bill Janssen54cc54c2007-12-14 22:08:56 +0000750 class AsyncoreEchoServer(threading.Thread):
751
752 # this one's based on asyncore.dispatcher
753
754 class EchoServer (asyncore.dispatcher):
755
756 class ConnectionHandler (asyncore.dispatcher_with_send):
757
758 def __init__(self, conn, certfile):
759 self.socket = ssl.wrap_socket(conn, server_side=True,
760 certfile=certfile,
761 do_handshake_on_connect=False)
762 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000763 self._ssl_accepting = True
764 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000765
766 def readable(self):
767 if isinstance(self.socket, ssl.SSLSocket):
768 while self.socket.pending() > 0:
769 self.handle_read_event()
770 return True
771
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000772 def _do_ssl_handshake(self):
773 try:
774 self.socket.do_handshake()
775 except ssl.SSLError as err:
776 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
777 ssl.SSL_ERROR_WANT_WRITE):
778 return
779 elif err.args[0] == ssl.SSL_ERROR_EOF:
780 return self.handle_close()
781 raise
782 except socket.error as err:
783 if err.args[0] == errno.ECONNABORTED:
784 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000785 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000786 self._ssl_accepting = False
787
788 def handle_read(self):
789 if self._ssl_accepting:
790 self._do_ssl_handshake()
791 else:
792 data = self.recv(1024)
793 if support.verbose:
794 sys.stdout.write(" server: read %s from client\n" % repr(data))
795 if not data:
796 self.close()
797 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000798 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000799
800 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000801 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000802 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000803 sys.stdout.write(" server: closed connection %s\n" % self.socket)
804
805 def handle_error(self):
806 raise
807
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000808 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000809 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000810 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
811 self.port = support.bind_port(sock, '')
812 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000813 self.listen(5)
814
815 def handle_accept(self):
816 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000817 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000818 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
819 self.ConnectionHandler(sock_obj, self.certfile)
820
821 def handle_error(self):
822 raise
823
Trent Nelson78520002008-04-10 20:54:35 +0000824 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000825 self.flag = None
826 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000827 self.server = self.EchoServer(certfile)
828 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000829 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000830 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000831
832 def __str__(self):
833 return "<%s %s>" % (self.__class__.__name__, self.server)
834
835 def start (self, flag=None):
836 self.flag = flag
837 threading.Thread.start(self)
838
Antoine Pitrou480a1242010-04-28 21:37:09 +0000839 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000840 self.active = True
841 if self.flag:
842 self.flag.set()
843 while self.active:
844 try:
845 asyncore.loop(1)
846 except:
847 pass
848
Antoine Pitrou480a1242010-04-28 21:37:09 +0000849 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000850 self.active = False
851 self.server.close()
852
Antoine Pitrou480a1242010-04-28 21:37:09 +0000853 def bad_cert_test(certfile):
854 """
855 Launch a server with CERT_REQUIRED, and check that trying to
856 connect to it with the given client certificate fails.
857 """
Trent Nelson78520002008-04-10 20:54:35 +0000858 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000859 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000860 cacerts=CERTFILE, chatty=False,
861 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862 flag = threading.Event()
863 server.start(flag)
864 # wait for it to start
865 flag.wait()
866 # try to connect
867 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000868 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000869 s = ssl.wrap_socket(socket.socket(),
870 certfile=certfile,
871 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000872 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000874 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000875 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000876 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000877 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000878 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000879 except IOError as x:
880 if support.verbose:
881 sys.stdout.write("\nsocket.error is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000882 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000883 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000884 finally:
885 server.stop()
886 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000887
Antoine Pitroub5218772010-05-21 09:56:06 +0000888 def server_params_test(client_context, server_context, indata=b"FOO\n",
889 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000890 """
891 Launch a server, connect a client to it and try various reads
892 and writes.
893 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000894 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000896 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000897 flag = threading.Event()
898 server.start(flag)
899 # wait for it to start
900 flag.wait()
901 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000902 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000903 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000904 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000905 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000906 if connectionchatty:
907 if support.verbose:
908 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000909 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000910 s.write(arg)
911 outdata = s.read()
912 if connectionchatty:
913 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000914 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000915 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000916 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000917 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
918 % (outdata[:20], len(outdata),
919 indata[:20].lower(), len(indata)))
920 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000921 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000922 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000923 sys.stdout.write(" client: closing connection.\n")
924 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 finally:
926 server.stop()
927 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000928
Antoine Pitroub5218772010-05-21 09:56:06 +0000929 def try_protocol_combo(server_protocol, client_protocol, expect_success,
930 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000931 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000932 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000933 certtype = {
934 ssl.CERT_NONE: "CERT_NONE",
935 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
936 ssl.CERT_REQUIRED: "CERT_REQUIRED",
937 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000938 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000939 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000940 sys.stdout.write(formatstr %
941 (ssl.get_protocol_name(client_protocol),
942 ssl.get_protocol_name(server_protocol),
943 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000944 client_context = ssl.SSLContext(client_protocol)
945 client_context.options = ssl.OP_ALL | client_options
946 server_context = ssl.SSLContext(server_protocol)
947 server_context.options = ssl.OP_ALL | server_options
948 for ctx in (client_context, server_context):
949 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000950 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
951 # will send an SSLv3 hello (rather than SSLv2) starting from
952 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000953 ctx.set_ciphers("ALL")
954 ctx.load_cert_chain(CERTFILE)
955 ctx.load_verify_locations(CERTFILE)
956 try:
957 server_params_test(client_context, server_context,
958 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000959 # Protocol mismatch can result in either an SSLError, or a
960 # "Connection reset by peer" error.
961 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000962 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000964 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000965 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000966 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000967 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000968 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000969 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 "Client protocol %s succeeded with server protocol %s!"
971 % (ssl.get_protocol_name(client_protocol),
972 ssl.get_protocol_name(server_protocol)))
973
974
Bill Janssen6e027db2007-11-15 22:23:56 +0000975 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000976
Antoine Pitrou23df4832010-08-04 17:14:06 +0000977 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000978 def test_echo(self):
979 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000980 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000982 for protocol in PROTOCOLS:
983 context = ssl.SSLContext(protocol)
984 context.load_cert_chain(CERTFILE)
985 server_params_test(context, context,
986 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000987
Antoine Pitrou480a1242010-04-28 21:37:09 +0000988 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000989 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000991 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
992 context.verify_mode = ssl.CERT_REQUIRED
993 context.load_verify_locations(CERTFILE)
994 context.load_cert_chain(CERTFILE)
995 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000996 flag = threading.Event()
997 server.start(flag)
998 # wait for it to start
999 flag.wait()
1000 # try to connect
1001 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001002 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001003 s.connect((HOST, server.port))
1004 cert = s.getpeercert()
1005 self.assertTrue(cert, "Can't get peer certificate.")
1006 cipher = s.cipher()
1007 if support.verbose:
1008 sys.stdout.write(pprint.pformat(cert) + '\n')
1009 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1010 if 'subject' not in cert:
1011 self.fail("No subject field in certificate: %s." %
1012 pprint.pformat(cert))
1013 if ((('organizationName', 'Python Software Foundation'),)
1014 not in cert['subject']):
1015 self.fail(
1016 "Missing or invalid 'organizationName' field in certificate subject; "
1017 "should be 'Python Software Foundation'.")
1018 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001019 finally:
1020 server.stop()
1021 server.join()
1022
Antoine Pitrou480a1242010-04-28 21:37:09 +00001023 def test_empty_cert(self):
1024 """Connecting with an empty cert file"""
1025 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1026 "nullcert.pem"))
1027 def test_malformed_cert(self):
1028 """Connecting with a badly formatted certificate (syntax error)"""
1029 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1030 "badcert.pem"))
1031 def test_nonexisting_cert(self):
1032 """Connecting with a non-existing cert file"""
1033 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1034 "wrongcert.pem"))
1035 def test_malformed_key(self):
1036 """Connecting with a badly formatted key (syntax error)"""
1037 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1038 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001039
Antoine Pitrou480a1242010-04-28 21:37:09 +00001040 def test_rude_shutdown(self):
1041 """A brutal shutdown of an SSL server should raise an IOError
1042 in the client when attempting handshake.
1043 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001044 listener_ready = threading.Event()
1045 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001046
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001047 s = socket.socket()
1048 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001049
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001050 # `listener` runs in a thread. It sits in an accept() until
1051 # the main thread connects. Then it rudely closes the socket,
1052 # and sets Event `listener_gone` to let the main thread know
1053 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001054 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001055 s.listen(5)
1056 listener_ready.set()
1057 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001058 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001059 listener_gone.set()
1060
1061 def connector():
1062 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001063 c = socket.socket()
1064 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001065 listener_gone.wait()
1066 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001067 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001068 except IOError:
1069 pass
1070 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001071 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001072
1073 t = threading.Thread(target=listener)
1074 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001075 try:
1076 connector()
1077 finally:
1078 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001079
Antoine Pitrou23df4832010-08-04 17:14:06 +00001080 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001081 def test_protocol_sslv2(self):
1082 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001083 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001084 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001085 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1086 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1087 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1088 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1089 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1090 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001091 # SSLv23 client with specific SSL options
1092 if no_sslv2_implies_sslv3_hello():
1093 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1094 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1095 client_options=ssl.OP_NO_SSLv2)
1096 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1097 client_options=ssl.OP_NO_SSLv3)
1098 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1099 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001100
Antoine Pitrou23df4832010-08-04 17:14:06 +00001101 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001102 def test_protocol_sslv23(self):
1103 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001104 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001105 sys.stdout.write("\n")
1106 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001107 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001108 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001110 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001111 sys.stdout.write(
1112 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1113 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001114 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1115 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1116 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001117
Antoine Pitrou480a1242010-04-28 21:37:09 +00001118 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1119 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1120 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001121
Antoine Pitrou480a1242010-04-28 21:37:09 +00001122 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1123 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1124 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125
Antoine Pitroub5218772010-05-21 09:56:06 +00001126 # Server with specific SSL options
1127 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1128 server_options=ssl.OP_NO_SSLv3)
1129 # Will choose TLSv1
1130 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1131 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1132 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1133 server_options=ssl.OP_NO_TLSv1)
1134
1135
Antoine Pitrou23df4832010-08-04 17:14:06 +00001136 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001137 def test_protocol_sslv3(self):
1138 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001139 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1142 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1143 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1144 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1145 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1146 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001147 if no_sslv2_implies_sslv3_hello():
1148 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1149 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1150 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001151
Antoine Pitrou23df4832010-08-04 17:14:06 +00001152 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001153 def test_protocol_tlsv1(self):
1154 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001155 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001157 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1158 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1159 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1160 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1161 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1162 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163
Antoine Pitrou480a1242010-04-28 21:37:09 +00001164 def test_starttls(self):
1165 """Switching from clear text to encrypted and back again."""
1166 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167
Trent Nelson78520002008-04-10 20:54:35 +00001168 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001169 ssl_version=ssl.PROTOCOL_TLSv1,
1170 starttls_server=True,
1171 chatty=True,
1172 connectionchatty=True)
1173 flag = threading.Event()
1174 server.start(flag)
1175 # wait for it to start
1176 flag.wait()
1177 # try to connect
1178 wrapped = False
1179 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001180 s = socket.socket()
1181 s.setblocking(1)
1182 s.connect((HOST, server.port))
1183 if support.verbose:
1184 sys.stdout.write("\n")
1185 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001186 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001187 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001188 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001189 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001190 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001191 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001192 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001193 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001194 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001195 msg = outdata.strip().lower()
1196 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1197 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001198 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001199 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001200 " client: read %r from server, starting TLS...\n"
1201 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001202 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1203 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001204 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1205 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001206 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001207 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001208 " client: read %r from server, ending TLS...\n"
1209 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001210 s = conn.unwrap()
1211 wrapped = False
1212 else:
1213 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001214 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001215 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001216 if support.verbose:
1217 sys.stdout.write(" client: closing connection.\n")
1218 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001219 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001220 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001221 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001222 if wrapped:
1223 conn.close()
1224 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001225 s.close()
1226 finally:
1227 server.stop()
1228 server.join()
1229
Antoine Pitrou480a1242010-04-28 21:37:09 +00001230 def test_socketserver(self):
1231 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001232 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001233 flag = threading.Event()
1234 server.start(flag)
1235 # wait for it to start
1236 flag.wait()
1237 # try to connect
1238 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001239 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001240 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001241 with open(CERTFILE, 'rb') as f:
1242 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 d2 = ''
1244 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001245 url = 'https://%s:%d/%s' % (
1246 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001247 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001248 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001249 if dlen and (int(dlen) > 0):
1250 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001251 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001252 sys.stdout.write(
1253 " client: read %d bytes from remote server '%s'\n"
1254 % (len(d2), server))
1255 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001256 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001257 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001258 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001259 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001260 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001261 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001262 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001263 server.join()
1264
Antoine Pitrou480a1242010-04-28 21:37:09 +00001265 def test_asyncore_server(self):
1266 """Check the example asyncore integration."""
1267 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001268
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001269 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001270 sys.stdout.write("\n")
1271
Antoine Pitrou480a1242010-04-28 21:37:09 +00001272 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001273 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001274 flag = threading.Event()
1275 server.start(flag)
1276 # wait for it to start
1277 flag.wait()
1278 # try to connect
1279 try:
1280 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001281 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001282 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001283 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001284 " client: sending %r...\n" % indata)
1285 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001286 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001287 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001288 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001289 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001290 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001291 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1292 % (outdata[:20], len(outdata),
1293 indata[:20].lower(), len(indata)))
1294 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001295 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001296 sys.stdout.write(" client: closing connection.\n")
1297 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001298 if support.verbose:
1299 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001300 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001301 if support.verbose:
1302 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001303 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001304 if support.verbose:
1305 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001306 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001307 if support.verbose:
1308 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001309
Antoine Pitrou480a1242010-04-28 21:37:09 +00001310 def test_recv_send(self):
1311 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001312 if support.verbose:
1313 sys.stdout.write("\n")
1314
1315 server = ThreadedEchoServer(CERTFILE,
1316 certreqs=ssl.CERT_NONE,
1317 ssl_version=ssl.PROTOCOL_TLSv1,
1318 cacerts=CERTFILE,
1319 chatty=True,
1320 connectionchatty=False)
1321 flag = threading.Event()
1322 server.start(flag)
1323 # wait for it to start
1324 flag.wait()
1325 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001326 s = ssl.wrap_socket(socket.socket(),
1327 server_side=False,
1328 certfile=CERTFILE,
1329 ca_certs=CERTFILE,
1330 cert_reqs=ssl.CERT_NONE,
1331 ssl_version=ssl.PROTOCOL_TLSv1)
1332 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001333 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001334 # helper methods for standardising recv* method signatures
1335 def _recv_into():
1336 b = bytearray(b"\0"*100)
1337 count = s.recv_into(b)
1338 return b[:count]
1339
1340 def _recvfrom_into():
1341 b = bytearray(b"\0"*100)
1342 count, addr = s.recvfrom_into(b)
1343 return b[:count]
1344
1345 # (name, method, whether to expect success, *args)
1346 send_methods = [
1347 ('send', s.send, True, []),
1348 ('sendto', s.sendto, False, ["some.address"]),
1349 ('sendall', s.sendall, True, []),
1350 ]
1351 recv_methods = [
1352 ('recv', s.recv, True, []),
1353 ('recvfrom', s.recvfrom, False, ["some.address"]),
1354 ('recv_into', _recv_into, True, []),
1355 ('recvfrom_into', _recvfrom_into, False, []),
1356 ]
1357 data_prefix = "PREFIX_"
1358
1359 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001360 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001361 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001362 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001363 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001364 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001365 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001366 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001367 "<<{outdata:r}>> ({nout:d}) received; "
1368 "expected <<{indata:r}>> ({nin:d})\n".format(
1369 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001370 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001371 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001372 )
1373 )
1374 except ValueError as e:
1375 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001376 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001377 "Failed to send with method <<{name:s}>>; "
1378 "expected to succeed.\n".format(name=meth_name)
1379 )
1380 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001381 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001382 "Method <<{name:s}>> failed with unexpected "
1383 "exception message: {exp:s}\n".format(
1384 name=meth_name, exp=e
1385 )
1386 )
1387
1388 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001390 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001392 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001393 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001394 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001395 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 "<<{outdata:r}>> ({nout:d}) received; "
1397 "expected <<{indata:r}>> ({nin:d})\n".format(
1398 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001399 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001401 )
1402 )
1403 except ValueError as e:
1404 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001405 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001406 "Failed to receive with method <<{name:s}>>; "
1407 "expected to succeed.\n".format(name=meth_name)
1408 )
1409 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001410 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001411 "Method <<{name:s}>> failed with unexpected "
1412 "exception message: {exp:s}\n".format(
1413 name=meth_name, exp=e
1414 )
1415 )
1416 # consume data
1417 s.read()
1418
Antoine Pitrou480a1242010-04-28 21:37:09 +00001419 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001420 s.close()
1421 finally:
1422 server.stop()
1423 server.join()
1424
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001425 def test_handshake_timeout(self):
1426 # Issue #5103: SSL handshake must respect the socket timeout
1427 server = socket.socket(socket.AF_INET)
1428 host = "127.0.0.1"
1429 port = support.bind_port(server)
1430 started = threading.Event()
1431 finish = False
1432
1433 def serve():
1434 server.listen(5)
1435 started.set()
1436 conns = []
1437 while not finish:
1438 r, w, e = select.select([server], [], [], 0.1)
1439 if server in r:
1440 # Let the socket hang around rather than having
1441 # it closed by garbage collection.
1442 conns.append(server.accept()[0])
1443
1444 t = threading.Thread(target=serve)
1445 t.start()
1446 started.wait()
1447
1448 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001449 try:
1450 c = socket.socket(socket.AF_INET)
1451 c.settimeout(0.2)
1452 c.connect((host, port))
1453 # Will attempt handshake and time out
1454 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1455 ssl.wrap_socket, c)
1456 finally:
1457 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001458 try:
1459 c = socket.socket(socket.AF_INET)
1460 c = ssl.wrap_socket(c)
1461 c.settimeout(0.2)
1462 # Will attempt handshake and time out
1463 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1464 c.connect, (host, port))
1465 finally:
1466 c.close()
1467 finally:
1468 finish = True
1469 t.join()
1470 server.close()
1471
Bill Janssen58afe4c2008-09-08 16:45:19 +00001472
Thomas Woutersed03b412007-08-28 21:37:11 +00001473def test_main(verbose=False):
1474 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001475 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001476
Antoine Pitrou15cee622010-08-04 16:45:21 +00001477 if support.verbose:
1478 plats = {
1479 'Linux': platform.linux_distribution,
1480 'Mac': platform.mac_ver,
1481 'Windows': platform.win32_ver,
1482 }
1483 for name, func in plats.items():
1484 plat = func()
1485 if plat and plat[0]:
1486 plat = '%s %r' % (name, plat)
1487 break
1488 else:
1489 plat = repr(platform.platform())
1490 print("test_ssl: testing with %r %r" %
1491 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1492 print(" under %s" % plat)
1493
Antoine Pitrou152efa22010-05-16 18:19:27 +00001494 for filename in [
1495 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1496 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1497 BADCERT, BADKEY, EMPTYCERT]:
1498 if not os.path.exists(filename):
1499 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001500
Antoine Pitrou152efa22010-05-16 18:19:27 +00001501 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001502
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001503 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001504 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001505
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001506 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001507 thread_info = support.threading_setup()
1508 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001509 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001510
Antoine Pitrou480a1242010-04-28 21:37:09 +00001511 try:
1512 support.run_unittest(*tests)
1513 finally:
1514 if _have_threads:
1515 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001516
1517if __name__ == "__main__":
1518 test_main()