blob: 71ba9e1bcbd0eac386e32f49fc262231a2bbc7bf [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
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000175
Antoine Pitrou152efa22010-05-16 18:19:27 +0000176class ContextTests(unittest.TestCase):
177
Antoine Pitrou23df4832010-08-04 17:14:06 +0000178 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000179 def test_constructor(self):
180 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
181 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
182 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
183 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
184 self.assertRaises(TypeError, ssl.SSLContext)
185 self.assertRaises(ValueError, ssl.SSLContext, -1)
186 self.assertRaises(ValueError, ssl.SSLContext, 42)
187
Antoine Pitrou23df4832010-08-04 17:14:06 +0000188 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000189 def test_protocol(self):
190 for proto in PROTOCOLS:
191 ctx = ssl.SSLContext(proto)
192 self.assertEqual(ctx.protocol, proto)
193
194 def test_ciphers(self):
195 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
196 ctx.set_ciphers("ALL")
197 ctx.set_ciphers("DEFAULT")
198 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000199 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000200
Antoine Pitrou23df4832010-08-04 17:14:06 +0000201 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000202 def test_options(self):
203 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
204 # OP_ALL is the default value
205 self.assertEqual(ssl.OP_ALL, ctx.options)
206 ctx.options |= ssl.OP_NO_SSLv2
207 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
208 ctx.options)
209 ctx.options |= ssl.OP_NO_SSLv3
210 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
211 ctx.options)
212 if can_clear_options():
213 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
214 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
215 ctx.options)
216 ctx.options = 0
217 self.assertEqual(0, ctx.options)
218 else:
219 with self.assertRaises(ValueError):
220 ctx.options = 0
221
Antoine Pitrou152efa22010-05-16 18:19:27 +0000222 def test_verify(self):
223 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
224 # Default value
225 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
226 ctx.verify_mode = ssl.CERT_OPTIONAL
227 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
228 ctx.verify_mode = ssl.CERT_REQUIRED
229 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
230 ctx.verify_mode = ssl.CERT_NONE
231 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
232 with self.assertRaises(TypeError):
233 ctx.verify_mode = None
234 with self.assertRaises(ValueError):
235 ctx.verify_mode = 42
236
237 def test_load_cert_chain(self):
238 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
239 # Combined key and cert in a single file
240 ctx.load_cert_chain(CERTFILE)
241 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
242 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
243 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
244 ctx.load_cert_chain(WRONGCERT)
245 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
246 ctx.load_cert_chain(BADCERT)
247 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
248 ctx.load_cert_chain(EMPTYCERT)
249 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000250 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000251 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
252 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
253 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
254 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
255 ctx.load_cert_chain(ONLYCERT)
256 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
257 ctx.load_cert_chain(ONLYKEY)
258 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
259 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
260 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000261 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000262 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
263 ctx.load_cert_chain(CERTFILE, ONLYKEY)
264
265 def test_load_verify_locations(self):
266 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
267 ctx.load_verify_locations(CERTFILE)
268 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
269 ctx.load_verify_locations(BYTES_CERTFILE)
270 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
271 self.assertRaises(TypeError, ctx.load_verify_locations)
272 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
273 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
274 ctx.load_verify_locations(WRONGCERT)
275 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
276 ctx.load_verify_locations(BADCERT)
277 ctx.load_verify_locations(CERTFILE, CAPATH)
278 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
279
280
Bill Janssen6e027db2007-11-15 22:23:56 +0000281class NetworkedTests(unittest.TestCase):
Antoine Pitroud151e272010-08-14 16:32:10 +0000282 def setUp(self):
283 self.old_timeout = socket.getdefaulttimeout()
284 socket.setdefaulttimeout(30)
285
286 def tearDown(self):
287 socket.setdefaulttimeout(self.old_timeout)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000288
Antoine Pitrou480a1242010-04-28 21:37:09 +0000289 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000290 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
291 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000292 try:
293 s.connect(("svn.python.org", 443))
294 self.assertEqual({}, s.getpeercert())
295 finally:
296 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000297
298 # this should fail because we have no verification certs
299 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
300 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000301 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
302 s.connect, ("svn.python.org", 443))
303 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000304
305 # this should succeed because we specify the root cert
306 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
307 cert_reqs=ssl.CERT_REQUIRED,
308 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
309 try:
310 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000311 self.assertTrue(s.getpeercert())
312 finally:
313 s.close()
314
315 def test_connect_with_context(self):
316 # Same as test_connect, but with a separately created context
317 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
318 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
319 s.connect(("svn.python.org", 443))
320 try:
321 self.assertEqual({}, s.getpeercert())
322 finally:
323 s.close()
324 # This should fail because we have no verification certs
325 ctx.verify_mode = ssl.CERT_REQUIRED
326 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
327 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
328 s.connect, ("svn.python.org", 443))
329 s.close()
330 # This should succeed because we specify the root cert
331 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
332 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
333 s.connect(("svn.python.org", 443))
334 try:
335 cert = s.getpeercert()
336 self.assertTrue(cert)
337 finally:
338 s.close()
339
340 def test_connect_capath(self):
341 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000342 # NOTE: the subject hashing algorithm has been changed between
343 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
344 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000345 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000346 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
347 ctx.verify_mode = ssl.CERT_REQUIRED
348 ctx.load_verify_locations(capath=CAPATH)
349 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
350 s.connect(("svn.python.org", 443))
351 try:
352 cert = s.getpeercert()
353 self.assertTrue(cert)
354 finally:
355 s.close()
356 # Same with a bytes `capath` argument
357 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
358 ctx.verify_mode = ssl.CERT_REQUIRED
359 ctx.load_verify_locations(capath=BYTES_CAPATH)
360 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
361 s.connect(("svn.python.org", 443))
362 try:
363 cert = s.getpeercert()
364 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000365 finally:
366 s.close()
367
Antoine Pitroue3220242010-04-24 11:13:53 +0000368 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
369 def test_makefile_close(self):
370 # Issue #5238: creating a file-like object with makefile() shouldn't
371 # delay closing the underlying "real socket" (here tested with its
372 # file descriptor, hence skipping the test under Windows).
373 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
374 ss.connect(("svn.python.org", 443))
375 fd = ss.fileno()
376 f = ss.makefile()
377 f.close()
378 # The fd is still open
379 os.read(fd, 0)
380 # Closing the SSL socket should close the fd too
381 ss.close()
382 gc.collect()
383 with self.assertRaises(OSError) as e:
384 os.read(fd, 0)
385 self.assertEqual(e.exception.errno, errno.EBADF)
386
Antoine Pitrou480a1242010-04-28 21:37:09 +0000387 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000388 s = socket.socket(socket.AF_INET)
389 s.connect(("svn.python.org", 443))
390 s.setblocking(False)
391 s = ssl.wrap_socket(s,
392 cert_reqs=ssl.CERT_NONE,
393 do_handshake_on_connect=False)
394 count = 0
395 while True:
396 try:
397 count += 1
398 s.do_handshake()
399 break
400 except ssl.SSLError as err:
401 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
402 select.select([s], [], [])
403 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
404 select.select([], [s], [])
405 else:
406 raise
407 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000408 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000409 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000410
Antoine Pitrou480a1242010-04-28 21:37:09 +0000411 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000412 pem = ssl.get_server_certificate(("svn.python.org", 443))
413 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000414 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000415
Bill Janssen54cc54c2007-12-14 22:08:56 +0000416 try:
417 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
418 except ssl.SSLError as x:
419 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000420 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000421 sys.stdout.write("%s\n" % x)
422 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000423 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000424
425 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
426 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000427 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000428 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000429 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
430
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000431 def test_ciphers(self):
432 remote = ("svn.python.org", 443)
433 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
434 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
435 s.connect(remote)
436 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
437 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
438 s.connect(remote)
439 # Error checking can happen at instantiation or when connecting
440 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
441 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
442 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
443 s.connect(remote)
444
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000445 def test_algorithms(self):
446 # Issue #8484: all algorithms should be available when verifying a
447 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000448 # SHA256 was added in OpenSSL 0.9.8
449 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
450 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000451 # NOTE: https://sha256.tbs-internet.com is another possible test host
452 remote = ("sha2.hboeck.de", 443)
453 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
454 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
455 cert_reqs=ssl.CERT_REQUIRED,
456 ca_certs=sha256_cert,)
457 with support.transient_internet():
458 try:
459 s.connect(remote)
460 if support.verbose:
461 sys.stdout.write("\nCipher with %r is %r\n" %
462 (remote, s.cipher()))
463 sys.stdout.write("Certificate is:\n%s\n" %
464 pprint.pformat(s.getpeercert()))
465 finally:
466 s.close()
467
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000468
469try:
470 import threading
471except ImportError:
472 _have_threads = False
473else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000474 _have_threads = True
475
476 class ThreadedEchoServer(threading.Thread):
477
478 class ConnectionHandler(threading.Thread):
479
480 """A mildly complicated class, because we want it to work both
481 with and without the SSL wrapper around the socket connection, so
482 that we can test the STARTTLS functionality."""
483
Bill Janssen6e027db2007-11-15 22:23:56 +0000484 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000485 self.server = server
486 self.running = False
487 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000488 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000489 self.sock.setblocking(1)
490 self.sslconn = None
491 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000492 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493
Antoine Pitrou480a1242010-04-28 21:37:09 +0000494 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000495 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000496 self.sslconn = self.server.context.wrap_socket(
497 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000498 except ssl.SSLError:
499 # XXX Various errors can have happened here, for example
500 # a mismatching protocol version, an invalid certificate,
501 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000502 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000503 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000504 self.running = False
505 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000506 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000507 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000508 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000509 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000510 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000511 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
513 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000514 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000515 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
516 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000517 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000518 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
519 return True
520
521 def read(self):
522 if self.sslconn:
523 return self.sslconn.read()
524 else:
525 return self.sock.recv(1024)
526
527 def write(self, bytes):
528 if self.sslconn:
529 return self.sslconn.write(bytes)
530 else:
531 return self.sock.send(bytes)
532
533 def close(self):
534 if self.sslconn:
535 self.sslconn.close()
536 else:
537 self.sock.close()
538
Antoine Pitrou480a1242010-04-28 21:37:09 +0000539 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000540 self.running = True
541 if not self.server.starttls_server:
542 if not self.wrap_conn():
543 return
544 while self.running:
545 try:
546 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000547 stripped = msg.strip()
548 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000549 # eof, so quit this handler
550 self.running = False
551 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000552 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000553 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000554 sys.stdout.write(" server: client closed connection\n")
555 self.close()
556 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000557 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000558 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000559 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000560 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000561 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000562 if not self.wrap_conn():
563 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000564 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000565 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000566 if support.verbose and self.server.connectionchatty:
567 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000568 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000569 self.sock = self.sslconn.unwrap()
570 self.sslconn = None
571 if support.verbose and self.server.connectionchatty:
572 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000573 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000574 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000575 self.server.connectionchatty):
576 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000577 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
578 % (msg, ctype, msg.lower(), ctype))
579 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000580 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000581 if self.server.chatty:
582 handle_error("Test server failure:\n")
583 self.close()
584 self.running = False
585 # normally, we'd just stop here, but for the test
586 # harness, we want to stop the server
587 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000588
Antoine Pitroub5218772010-05-21 09:56:06 +0000589 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000590 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000591 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000592 ciphers=None, context=None):
593 if context:
594 self.context = context
595 else:
596 self.context = ssl.SSLContext(ssl_version
597 if ssl_version is not None
598 else ssl.PROTOCOL_TLSv1)
599 self.context.verify_mode = (certreqs if certreqs is not None
600 else ssl.CERT_NONE)
601 if cacerts:
602 self.context.load_verify_locations(cacerts)
603 if certificate:
604 self.context.load_cert_chain(certificate)
605 if ciphers:
606 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000607 self.chatty = chatty
608 self.connectionchatty = connectionchatty
609 self.starttls_server = starttls_server
610 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000611 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000612 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000613 self.active = False
614 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000615 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000616
Antoine Pitrou480a1242010-04-28 21:37:09 +0000617 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000618 self.flag = flag
619 threading.Thread.start(self)
620
Antoine Pitrou480a1242010-04-28 21:37:09 +0000621 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000622 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000623 self.sock.listen(5)
624 self.active = True
625 if self.flag:
626 # signal an event
627 self.flag.set()
628 while self.active:
629 try:
630 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000631 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000632 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000633 + repr(connaddr) + '\n')
634 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000635 handler.start()
636 except socket.timeout:
637 pass
638 except KeyboardInterrupt:
639 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000640 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000641
Antoine Pitrou480a1242010-04-28 21:37:09 +0000642 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000643 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000644
Bill Janssen54cc54c2007-12-14 22:08:56 +0000645 class OurHTTPSServer(threading.Thread):
646
647 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000648
649 class HTTPSServer(HTTPServer):
650
651 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000652 HTTPServer.__init__(self, server_address, RequestHandlerClass)
653 # we assume the certfile contains both private key and certificate
654 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000655 self.allow_reuse_address = True
656
Bill Janssen6e027db2007-11-15 22:23:56 +0000657 def __str__(self):
658 return ('<%s %s:%s>' %
659 (self.__class__.__name__,
660 self.server_name,
661 self.server_port))
662
Antoine Pitrou480a1242010-04-28 21:37:09 +0000663 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000664 # override this to wrap socket with SSL
665 sock, addr = self.socket.accept()
666 sslconn = ssl.wrap_socket(sock, server_side=True,
667 certfile=self.certfile)
668 return sslconn, addr
669
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000670 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000671 # need to override translate_path to get a known root,
672 # instead of using os.curdir, since the test could be
673 # run from anywhere
674
675 server_version = "TestHTTPS/1.0"
676
677 root = None
678
679 def translate_path(self, path):
680 """Translate a /-separated PATH to the local filename syntax.
681
682 Components that mean special things to the local file system
683 (e.g. drive or directory names) are ignored. (XXX They should
684 probably be diagnosed.)
685
686 """
687 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000688 path = urllib.parse.urlparse(path)[2]
689 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000690 words = path.split('/')
691 words = filter(None, words)
692 path = self.root
693 for word in words:
694 drive, word = os.path.splitdrive(word)
695 head, word = os.path.split(word)
696 if word in self.root: continue
697 path = os.path.join(path, word)
698 return path
699
700 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000701 # we override this to suppress logging unless "verbose"
702
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000703 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000704 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
705 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000706 self.server.server_port,
707 self.request.cipher(),
708 self.log_date_time_string(),
709 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000710
711
Trent Nelson78520002008-04-10 20:54:35 +0000712 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000713 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000714 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
715 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000716 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
717 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000718 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000719 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000720
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000721 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000722 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000723
Antoine Pitrou480a1242010-04-28 21:37:09 +0000724 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000725 self.flag = flag
726 threading.Thread.start(self)
727
Antoine Pitrou480a1242010-04-28 21:37:09 +0000728 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000729 if self.flag:
730 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000731 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000732
Antoine Pitrou480a1242010-04-28 21:37:09 +0000733 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000734 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000735
736
Bill Janssen54cc54c2007-12-14 22:08:56 +0000737 class AsyncoreEchoServer(threading.Thread):
738
739 # this one's based on asyncore.dispatcher
740
741 class EchoServer (asyncore.dispatcher):
742
743 class ConnectionHandler (asyncore.dispatcher_with_send):
744
745 def __init__(self, conn, certfile):
746 self.socket = ssl.wrap_socket(conn, server_side=True,
747 certfile=certfile,
748 do_handshake_on_connect=False)
749 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000750 self._ssl_accepting = True
751 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000752
753 def readable(self):
754 if isinstance(self.socket, ssl.SSLSocket):
755 while self.socket.pending() > 0:
756 self.handle_read_event()
757 return True
758
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000759 def _do_ssl_handshake(self):
760 try:
761 self.socket.do_handshake()
762 except ssl.SSLError as err:
763 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
764 ssl.SSL_ERROR_WANT_WRITE):
765 return
766 elif err.args[0] == ssl.SSL_ERROR_EOF:
767 return self.handle_close()
768 raise
769 except socket.error as err:
770 if err.args[0] == errno.ECONNABORTED:
771 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000772 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000773 self._ssl_accepting = False
774
775 def handle_read(self):
776 if self._ssl_accepting:
777 self._do_ssl_handshake()
778 else:
779 data = self.recv(1024)
780 if support.verbose:
781 sys.stdout.write(" server: read %s from client\n" % repr(data))
782 if not data:
783 self.close()
784 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000785 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000786
787 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000788 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000789 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000790 sys.stdout.write(" server: closed connection %s\n" % self.socket)
791
792 def handle_error(self):
793 raise
794
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000795 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000796 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000797 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
798 self.port = support.bind_port(sock, '')
799 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000800 self.listen(5)
801
802 def handle_accept(self):
803 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000804 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000805 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
806 self.ConnectionHandler(sock_obj, self.certfile)
807
808 def handle_error(self):
809 raise
810
Trent Nelson78520002008-04-10 20:54:35 +0000811 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000812 self.flag = None
813 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000814 self.server = self.EchoServer(certfile)
815 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000816 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000817 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000818
819 def __str__(self):
820 return "<%s %s>" % (self.__class__.__name__, self.server)
821
822 def start (self, flag=None):
823 self.flag = flag
824 threading.Thread.start(self)
825
Antoine Pitrou480a1242010-04-28 21:37:09 +0000826 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000827 self.active = True
828 if self.flag:
829 self.flag.set()
830 while self.active:
831 try:
832 asyncore.loop(1)
833 except:
834 pass
835
Antoine Pitrou480a1242010-04-28 21:37:09 +0000836 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000837 self.active = False
838 self.server.close()
839
Antoine Pitrou480a1242010-04-28 21:37:09 +0000840 def bad_cert_test(certfile):
841 """
842 Launch a server with CERT_REQUIRED, and check that trying to
843 connect to it with the given client certificate fails.
844 """
Trent Nelson78520002008-04-10 20:54:35 +0000845 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000847 cacerts=CERTFILE, chatty=False,
848 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000849 flag = threading.Event()
850 server.start(flag)
851 # wait for it to start
852 flag.wait()
853 # try to connect
854 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000855 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856 s = ssl.wrap_socket(socket.socket(),
857 certfile=certfile,
858 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000859 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000861 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000862 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000863 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000864 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000865 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000867 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868 finally:
869 server.stop()
870 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000871
Antoine Pitroub5218772010-05-21 09:56:06 +0000872 def server_params_test(client_context, server_context, indata=b"FOO\n",
873 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000874 """
875 Launch a server, connect a client to it and try various reads
876 and writes.
877 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000878 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000880 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 flag = threading.Event()
882 server.start(flag)
883 # wait for it to start
884 flag.wait()
885 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000887 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000888 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000889 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000890 if connectionchatty:
891 if support.verbose:
892 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000893 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000894 s.write(arg)
895 outdata = s.read()
896 if connectionchatty:
897 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000898 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000899 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000900 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000901 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
902 % (outdata[:20], len(outdata),
903 indata[:20].lower(), len(indata)))
904 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000905 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000906 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000907 sys.stdout.write(" client: closing connection.\n")
908 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 finally:
910 server.stop()
911 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000912
Antoine Pitroub5218772010-05-21 09:56:06 +0000913 def try_protocol_combo(server_protocol, client_protocol, expect_success,
914 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000915 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000916 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000917 certtype = {
918 ssl.CERT_NONE: "CERT_NONE",
919 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
920 ssl.CERT_REQUIRED: "CERT_REQUIRED",
921 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000922 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000923 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924 sys.stdout.write(formatstr %
925 (ssl.get_protocol_name(client_protocol),
926 ssl.get_protocol_name(server_protocol),
927 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000928 client_context = ssl.SSLContext(client_protocol)
929 client_context.options = ssl.OP_ALL | client_options
930 server_context = ssl.SSLContext(server_protocol)
931 server_context.options = ssl.OP_ALL | server_options
932 for ctx in (client_context, server_context):
933 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000934 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
935 # will send an SSLv3 hello (rather than SSLv2) starting from
936 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000937 ctx.set_ciphers("ALL")
938 ctx.load_cert_chain(CERTFILE)
939 ctx.load_verify_locations(CERTFILE)
940 try:
941 server_params_test(client_context, server_context,
942 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000943 # Protocol mismatch can result in either an SSLError, or a
944 # "Connection reset by peer" error.
945 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000946 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000948 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000949 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000950 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000952 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000953 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000954 "Client protocol %s succeeded with server protocol %s!"
955 % (ssl.get_protocol_name(client_protocol),
956 ssl.get_protocol_name(server_protocol)))
957
958
Bill Janssen6e027db2007-11-15 22:23:56 +0000959 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960
Antoine Pitrou23df4832010-08-04 17:14:06 +0000961 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000962 def test_echo(self):
963 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000964 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000965 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000966 for protocol in PROTOCOLS:
967 context = ssl.SSLContext(protocol)
968 context.load_cert_chain(CERTFILE)
969 server_params_test(context, context,
970 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000971
Antoine Pitrou480a1242010-04-28 21:37:09 +0000972 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000973 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000974 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000975 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
976 context.verify_mode = ssl.CERT_REQUIRED
977 context.load_verify_locations(CERTFILE)
978 context.load_cert_chain(CERTFILE)
979 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980 flag = threading.Event()
981 server.start(flag)
982 # wait for it to start
983 flag.wait()
984 # try to connect
985 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000986 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000987 s.connect((HOST, server.port))
988 cert = s.getpeercert()
989 self.assertTrue(cert, "Can't get peer certificate.")
990 cipher = s.cipher()
991 if support.verbose:
992 sys.stdout.write(pprint.pformat(cert) + '\n')
993 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
994 if 'subject' not in cert:
995 self.fail("No subject field in certificate: %s." %
996 pprint.pformat(cert))
997 if ((('organizationName', 'Python Software Foundation'),)
998 not in cert['subject']):
999 self.fail(
1000 "Missing or invalid 'organizationName' field in certificate subject; "
1001 "should be 'Python Software Foundation'.")
1002 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 finally:
1004 server.stop()
1005 server.join()
1006
Antoine Pitrou480a1242010-04-28 21:37:09 +00001007 def test_empty_cert(self):
1008 """Connecting with an empty cert file"""
1009 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1010 "nullcert.pem"))
1011 def test_malformed_cert(self):
1012 """Connecting with a badly formatted certificate (syntax error)"""
1013 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1014 "badcert.pem"))
1015 def test_nonexisting_cert(self):
1016 """Connecting with a non-existing cert file"""
1017 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1018 "wrongcert.pem"))
1019 def test_malformed_key(self):
1020 """Connecting with a badly formatted key (syntax error)"""
1021 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1022 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001023
Antoine Pitrou480a1242010-04-28 21:37:09 +00001024 def test_rude_shutdown(self):
1025 """A brutal shutdown of an SSL server should raise an IOError
1026 in the client when attempting handshake.
1027 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001028 listener_ready = threading.Event()
1029 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001030
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001031 s = socket.socket()
1032 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001033
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001034 # `listener` runs in a thread. It sits in an accept() until
1035 # the main thread connects. Then it rudely closes the socket,
1036 # and sets Event `listener_gone` to let the main thread know
1037 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001038 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001039 s.listen(5)
1040 listener_ready.set()
1041 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001042 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001043 listener_gone.set()
1044
1045 def connector():
1046 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001047 c = socket.socket()
1048 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001049 listener_gone.wait()
1050 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001051 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001052 except IOError:
1053 pass
1054 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001055 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001056
1057 t = threading.Thread(target=listener)
1058 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001059 try:
1060 connector()
1061 finally:
1062 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001063
Antoine Pitrou23df4832010-08-04 17:14:06 +00001064 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001065 def test_protocol_sslv2(self):
1066 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001067 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001068 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001069 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1070 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1071 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1072 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1073 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1074 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001075 # SSLv23 client with specific SSL options
1076 if no_sslv2_implies_sslv3_hello():
1077 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1078 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1079 client_options=ssl.OP_NO_SSLv2)
1080 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1081 client_options=ssl.OP_NO_SSLv3)
1082 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1083 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001084
Antoine Pitrou23df4832010-08-04 17:14:06 +00001085 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001086 def test_protocol_sslv23(self):
1087 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001088 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001089 sys.stdout.write("\n")
1090 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001092 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001094 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001095 sys.stdout.write(
1096 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1097 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001098 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1099 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1100 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001101
Antoine Pitrou480a1242010-04-28 21:37:09 +00001102 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1103 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1104 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001105
Antoine Pitrou480a1242010-04-28 21:37:09 +00001106 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1107 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1108 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109
Antoine Pitroub5218772010-05-21 09:56:06 +00001110 # Server with specific SSL options
1111 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1112 server_options=ssl.OP_NO_SSLv3)
1113 # Will choose TLSv1
1114 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1115 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1116 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1117 server_options=ssl.OP_NO_TLSv1)
1118
1119
Antoine Pitrou23df4832010-08-04 17:14:06 +00001120 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001121 def test_protocol_sslv3(self):
1122 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001123 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001124 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001125 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1126 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1127 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1128 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1129 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1130 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001131 if no_sslv2_implies_sslv3_hello():
1132 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1133 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1134 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001135
Antoine Pitrou23df4832010-08-04 17:14:06 +00001136 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001137 def test_protocol_tlsv1(self):
1138 """Connecting to a TLSv1 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_TLSv1, ssl.PROTOCOL_TLSv1, True)
1142 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1143 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1144 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1145 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1146 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147
Antoine Pitrou480a1242010-04-28 21:37:09 +00001148 def test_starttls(self):
1149 """Switching from clear text to encrypted and back again."""
1150 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 +00001151
Trent Nelson78520002008-04-10 20:54:35 +00001152 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001153 ssl_version=ssl.PROTOCOL_TLSv1,
1154 starttls_server=True,
1155 chatty=True,
1156 connectionchatty=True)
1157 flag = threading.Event()
1158 server.start(flag)
1159 # wait for it to start
1160 flag.wait()
1161 # try to connect
1162 wrapped = False
1163 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001164 s = socket.socket()
1165 s.setblocking(1)
1166 s.connect((HOST, server.port))
1167 if support.verbose:
1168 sys.stdout.write("\n")
1169 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001170 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001171 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001172 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001173 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001175 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001176 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001177 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001178 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001179 msg = outdata.strip().lower()
1180 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1181 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001182 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001183 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001184 " client: read %r from server, starting TLS...\n"
1185 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001186 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1187 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001188 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1189 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001190 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001191 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001192 " client: read %r from server, ending TLS...\n"
1193 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001194 s = conn.unwrap()
1195 wrapped = False
1196 else:
1197 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001198 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001199 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001200 if support.verbose:
1201 sys.stdout.write(" client: closing connection.\n")
1202 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001204 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001206 if wrapped:
1207 conn.close()
1208 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001209 s.close()
1210 finally:
1211 server.stop()
1212 server.join()
1213
Antoine Pitrou480a1242010-04-28 21:37:09 +00001214 def test_socketserver(self):
1215 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001216 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001217 flag = threading.Event()
1218 server.start(flag)
1219 # wait for it to start
1220 flag.wait()
1221 # try to connect
1222 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001223 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001224 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001225 with open(CERTFILE, 'rb') as f:
1226 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001227 d2 = ''
1228 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001229 url = 'https://%s:%d/%s' % (
1230 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001231 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001232 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001233 if dlen and (int(dlen) > 0):
1234 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001235 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001236 sys.stdout.write(
1237 " client: read %d bytes from remote server '%s'\n"
1238 % (len(d2), server))
1239 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001240 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001242 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001243 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001244 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001245 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001246 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001247 server.join()
1248
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 def test_asyncore_server(self):
1250 """Check the example asyncore integration."""
1251 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001252
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001253 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001254 sys.stdout.write("\n")
1255
Antoine Pitrou480a1242010-04-28 21:37:09 +00001256 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001257 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001258 flag = threading.Event()
1259 server.start(flag)
1260 # wait for it to start
1261 flag.wait()
1262 # try to connect
1263 try:
1264 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001265 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001266 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001267 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001268 " client: sending %r...\n" % indata)
1269 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001270 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001271 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001272 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001273 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001274 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001275 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1276 % (outdata[:20], len(outdata),
1277 indata[:20].lower(), len(indata)))
1278 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001279 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001280 sys.stdout.write(" client: closing connection.\n")
1281 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001282 if support.verbose:
1283 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001284 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001285 if support.verbose:
1286 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001287 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001288 if support.verbose:
1289 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001290 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001291 if support.verbose:
1292 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001293
Antoine Pitrou480a1242010-04-28 21:37:09 +00001294 def test_recv_send(self):
1295 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001296 if support.verbose:
1297 sys.stdout.write("\n")
1298
1299 server = ThreadedEchoServer(CERTFILE,
1300 certreqs=ssl.CERT_NONE,
1301 ssl_version=ssl.PROTOCOL_TLSv1,
1302 cacerts=CERTFILE,
1303 chatty=True,
1304 connectionchatty=False)
1305 flag = threading.Event()
1306 server.start(flag)
1307 # wait for it to start
1308 flag.wait()
1309 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001310 s = ssl.wrap_socket(socket.socket(),
1311 server_side=False,
1312 certfile=CERTFILE,
1313 ca_certs=CERTFILE,
1314 cert_reqs=ssl.CERT_NONE,
1315 ssl_version=ssl.PROTOCOL_TLSv1)
1316 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001317 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001318 # helper methods for standardising recv* method signatures
1319 def _recv_into():
1320 b = bytearray(b"\0"*100)
1321 count = s.recv_into(b)
1322 return b[:count]
1323
1324 def _recvfrom_into():
1325 b = bytearray(b"\0"*100)
1326 count, addr = s.recvfrom_into(b)
1327 return b[:count]
1328
1329 # (name, method, whether to expect success, *args)
1330 send_methods = [
1331 ('send', s.send, True, []),
1332 ('sendto', s.sendto, False, ["some.address"]),
1333 ('sendall', s.sendall, True, []),
1334 ]
1335 recv_methods = [
1336 ('recv', s.recv, True, []),
1337 ('recvfrom', s.recvfrom, False, ["some.address"]),
1338 ('recv_into', _recv_into, True, []),
1339 ('recvfrom_into', _recvfrom_into, False, []),
1340 ]
1341 data_prefix = "PREFIX_"
1342
1343 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001344 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001345 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001346 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001347 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001348 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001349 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001350 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001351 "<<{outdata:r}>> ({nout:d}) received; "
1352 "expected <<{indata:r}>> ({nin:d})\n".format(
1353 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001354 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001355 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001356 )
1357 )
1358 except ValueError as e:
1359 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001360 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001361 "Failed to send with method <<{name:s}>>; "
1362 "expected to succeed.\n".format(name=meth_name)
1363 )
1364 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001365 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001366 "Method <<{name:s}>> failed with unexpected "
1367 "exception message: {exp:s}\n".format(
1368 name=meth_name, exp=e
1369 )
1370 )
1371
1372 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001373 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001374 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001375 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001376 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001377 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001378 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 "<<{outdata:r}>> ({nout:d}) received; "
1381 "expected <<{indata:r}>> ({nin:d})\n".format(
1382 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001383 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001384 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001385 )
1386 )
1387 except ValueError as e:
1388 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001389 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001390 "Failed to receive with method <<{name:s}>>; "
1391 "expected to succeed.\n".format(name=meth_name)
1392 )
1393 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001394 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001395 "Method <<{name:s}>> failed with unexpected "
1396 "exception message: {exp:s}\n".format(
1397 name=meth_name, exp=e
1398 )
1399 )
1400 # consume data
1401 s.read()
1402
Antoine Pitrou480a1242010-04-28 21:37:09 +00001403 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001404 s.close()
1405 finally:
1406 server.stop()
1407 server.join()
1408
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001409 def test_handshake_timeout(self):
1410 # Issue #5103: SSL handshake must respect the socket timeout
1411 server = socket.socket(socket.AF_INET)
1412 host = "127.0.0.1"
1413 port = support.bind_port(server)
1414 started = threading.Event()
1415 finish = False
1416
1417 def serve():
1418 server.listen(5)
1419 started.set()
1420 conns = []
1421 while not finish:
1422 r, w, e = select.select([server], [], [], 0.1)
1423 if server in r:
1424 # Let the socket hang around rather than having
1425 # it closed by garbage collection.
1426 conns.append(server.accept()[0])
1427
1428 t = threading.Thread(target=serve)
1429 t.start()
1430 started.wait()
1431
1432 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001433 try:
1434 c = socket.socket(socket.AF_INET)
1435 c.settimeout(0.2)
1436 c.connect((host, port))
1437 # Will attempt handshake and time out
1438 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1439 ssl.wrap_socket, c)
1440 finally:
1441 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001442 try:
1443 c = socket.socket(socket.AF_INET)
1444 c = ssl.wrap_socket(c)
1445 c.settimeout(0.2)
1446 # Will attempt handshake and time out
1447 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1448 c.connect, (host, port))
1449 finally:
1450 c.close()
1451 finally:
1452 finish = True
1453 t.join()
1454 server.close()
1455
Bill Janssen58afe4c2008-09-08 16:45:19 +00001456
Thomas Woutersed03b412007-08-28 21:37:11 +00001457def test_main(verbose=False):
1458 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001459 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001460
Antoine Pitrou15cee622010-08-04 16:45:21 +00001461 if support.verbose:
1462 plats = {
1463 'Linux': platform.linux_distribution,
1464 'Mac': platform.mac_ver,
1465 'Windows': platform.win32_ver,
1466 }
1467 for name, func in plats.items():
1468 plat = func()
1469 if plat and plat[0]:
1470 plat = '%s %r' % (name, plat)
1471 break
1472 else:
1473 plat = repr(platform.platform())
1474 print("test_ssl: testing with %r %r" %
1475 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1476 print(" under %s" % plat)
1477
Antoine Pitrou152efa22010-05-16 18:19:27 +00001478 for filename in [
1479 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1480 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1481 BADCERT, BADKEY, EMPTYCERT]:
1482 if not os.path.exists(filename):
1483 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001484
Antoine Pitrou152efa22010-05-16 18:19:27 +00001485 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001486
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001487 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001488 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001489
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001490 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001491 thread_info = support.threading_setup()
1492 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001493 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001494
Antoine Pitrou480a1242010-04-28 21:37:09 +00001495 try:
1496 support.run_unittest(*tests)
1497 finally:
1498 if _have_threads:
1499 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001500
1501if __name__ == "__main__":
1502 test_main()