blob: 091234c5809c20cf559d5ec574a4640c04f8caed [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 Pitrou2d9cb9c2010-04-17 17:40:45 +0000156 def test_ciphers(self):
157 if not support.is_resource_enabled('network'):
158 return
159 remote = ("svn.python.org", 443)
160 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
161 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
162 s.connect(remote)
163 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
164 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
165 s.connect(remote)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000166 # Error checking can happen at instantiation or when connecting
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000167 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000168 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou30474062010-05-16 23:46:26 +0000169 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000170 s.connect(remote)
171
Antoine Pitrou9d543662010-04-23 23:10:32 +0000172 @support.cpython_only
173 def test_refcycle(self):
174 # Issue #7943: an SSL object doesn't create reference cycles with
175 # itself.
176 s = socket.socket(socket.AF_INET)
177 ss = ssl.wrap_socket(s)
178 wr = weakref.ref(ss)
179 del ss
180 self.assertEqual(wr(), None)
181
Antoine Pitrou40f08742010-04-24 22:04:40 +0000182 def test_timeout(self):
183 # Issue #8524: when creating an SSL socket, the timeout of the
184 # original socket should be retained.
185 for timeout in (None, 0.0, 5.0):
186 s = socket.socket(socket.AF_INET)
187 s.settimeout(timeout)
188 ss = ssl.wrap_socket(s)
189 self.assertEqual(timeout, ss.gettimeout())
190
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000191
Antoine Pitrou152efa22010-05-16 18:19:27 +0000192class ContextTests(unittest.TestCase):
193
Antoine Pitrou23df4832010-08-04 17:14:06 +0000194 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000195 def test_constructor(self):
196 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
197 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
198 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
199 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
200 self.assertRaises(TypeError, ssl.SSLContext)
201 self.assertRaises(ValueError, ssl.SSLContext, -1)
202 self.assertRaises(ValueError, ssl.SSLContext, 42)
203
Antoine Pitrou23df4832010-08-04 17:14:06 +0000204 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000205 def test_protocol(self):
206 for proto in PROTOCOLS:
207 ctx = ssl.SSLContext(proto)
208 self.assertEqual(ctx.protocol, proto)
209
210 def test_ciphers(self):
211 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
212 ctx.set_ciphers("ALL")
213 ctx.set_ciphers("DEFAULT")
214 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000215 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000216
Antoine Pitrou23df4832010-08-04 17:14:06 +0000217 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000218 def test_options(self):
219 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
220 # OP_ALL is the default value
221 self.assertEqual(ssl.OP_ALL, ctx.options)
222 ctx.options |= ssl.OP_NO_SSLv2
223 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
224 ctx.options)
225 ctx.options |= ssl.OP_NO_SSLv3
226 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
227 ctx.options)
228 if can_clear_options():
229 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
230 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
231 ctx.options)
232 ctx.options = 0
233 self.assertEqual(0, ctx.options)
234 else:
235 with self.assertRaises(ValueError):
236 ctx.options = 0
237
Antoine Pitrou152efa22010-05-16 18:19:27 +0000238 def test_verify(self):
239 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
240 # Default value
241 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
242 ctx.verify_mode = ssl.CERT_OPTIONAL
243 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
244 ctx.verify_mode = ssl.CERT_REQUIRED
245 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
246 ctx.verify_mode = ssl.CERT_NONE
247 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
248 with self.assertRaises(TypeError):
249 ctx.verify_mode = None
250 with self.assertRaises(ValueError):
251 ctx.verify_mode = 42
252
253 def test_load_cert_chain(self):
254 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
255 # Combined key and cert in a single file
256 ctx.load_cert_chain(CERTFILE)
257 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
258 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
259 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
260 ctx.load_cert_chain(WRONGCERT)
261 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
262 ctx.load_cert_chain(BADCERT)
263 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
264 ctx.load_cert_chain(EMPTYCERT)
265 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000266 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000267 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
268 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
269 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
270 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
271 ctx.load_cert_chain(ONLYCERT)
272 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
273 ctx.load_cert_chain(ONLYKEY)
274 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
275 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
276 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000277 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000278 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
279 ctx.load_cert_chain(CERTFILE, ONLYKEY)
280
281 def test_load_verify_locations(self):
282 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
283 ctx.load_verify_locations(CERTFILE)
284 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
285 ctx.load_verify_locations(BYTES_CERTFILE)
286 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
287 self.assertRaises(TypeError, ctx.load_verify_locations)
288 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
289 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
290 ctx.load_verify_locations(WRONGCERT)
291 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
292 ctx.load_verify_locations(BADCERT)
293 ctx.load_verify_locations(CERTFILE, CAPATH)
294 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
295
296
Bill Janssen6e027db2007-11-15 22:23:56 +0000297class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000298
Antoine Pitrou480a1242010-04-28 21:37:09 +0000299 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000300 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
301 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000302 try:
303 s.connect(("svn.python.org", 443))
304 self.assertEqual({}, s.getpeercert())
305 finally:
306 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000307
308 # this should fail because we have no verification certs
309 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
310 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000311 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
312 s.connect, ("svn.python.org", 443))
313 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000314
315 # this should succeed because we specify the root cert
316 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
317 cert_reqs=ssl.CERT_REQUIRED,
318 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
319 try:
320 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000321 self.assertTrue(s.getpeercert())
322 finally:
323 s.close()
324
325 def test_connect_with_context(self):
326 # Same as test_connect, but with a separately created context
327 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
328 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
329 s.connect(("svn.python.org", 443))
330 try:
331 self.assertEqual({}, s.getpeercert())
332 finally:
333 s.close()
334 # This should fail because we have no verification certs
335 ctx.verify_mode = ssl.CERT_REQUIRED
336 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
337 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
338 s.connect, ("svn.python.org", 443))
339 s.close()
340 # This should succeed because we specify the root cert
341 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
342 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
343 s.connect(("svn.python.org", 443))
344 try:
345 cert = s.getpeercert()
346 self.assertTrue(cert)
347 finally:
348 s.close()
349
350 def test_connect_capath(self):
351 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000352 # NOTE: the subject hashing algorithm has been changed between
353 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
354 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000355 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000356 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
357 ctx.verify_mode = ssl.CERT_REQUIRED
358 ctx.load_verify_locations(capath=CAPATH)
359 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
360 s.connect(("svn.python.org", 443))
361 try:
362 cert = s.getpeercert()
363 self.assertTrue(cert)
364 finally:
365 s.close()
366 # Same with a bytes `capath` argument
367 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
368 ctx.verify_mode = ssl.CERT_REQUIRED
369 ctx.load_verify_locations(capath=BYTES_CAPATH)
370 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
371 s.connect(("svn.python.org", 443))
372 try:
373 cert = s.getpeercert()
374 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000375 finally:
376 s.close()
377
Antoine Pitroue3220242010-04-24 11:13:53 +0000378 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
379 def test_makefile_close(self):
380 # Issue #5238: creating a file-like object with makefile() shouldn't
381 # delay closing the underlying "real socket" (here tested with its
382 # file descriptor, hence skipping the test under Windows).
383 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
384 ss.connect(("svn.python.org", 443))
385 fd = ss.fileno()
386 f = ss.makefile()
387 f.close()
388 # The fd is still open
389 os.read(fd, 0)
390 # Closing the SSL socket should close the fd too
391 ss.close()
392 gc.collect()
393 with self.assertRaises(OSError) as e:
394 os.read(fd, 0)
395 self.assertEqual(e.exception.errno, errno.EBADF)
396
Antoine Pitrou480a1242010-04-28 21:37:09 +0000397 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000398 s = socket.socket(socket.AF_INET)
399 s.connect(("svn.python.org", 443))
400 s.setblocking(False)
401 s = ssl.wrap_socket(s,
402 cert_reqs=ssl.CERT_NONE,
403 do_handshake_on_connect=False)
404 count = 0
405 while True:
406 try:
407 count += 1
408 s.do_handshake()
409 break
410 except ssl.SSLError as err:
411 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
412 select.select([s], [], [])
413 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
414 select.select([], [s], [])
415 else:
416 raise
417 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000418 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000419 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000420
Antoine Pitrou480a1242010-04-28 21:37:09 +0000421 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000422 pem = ssl.get_server_certificate(("svn.python.org", 443))
423 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000424 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000425
426 return
427
428 try:
429 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
430 except ssl.SSLError as x:
431 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000432 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000433 sys.stdout.write("%s\n" % x)
434 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000435 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000436
437 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
438 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000439 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000440 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000441 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
442
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000443 def test_algorithms(self):
444 # Issue #8484: all algorithms should be available when verifying a
445 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000446 # SHA256 was added in OpenSSL 0.9.8
447 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
448 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000449 # NOTE: https://sha256.tbs-internet.com is another possible test host
450 remote = ("sha2.hboeck.de", 443)
451 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
452 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
453 cert_reqs=ssl.CERT_REQUIRED,
454 ca_certs=sha256_cert,)
455 with support.transient_internet():
456 try:
457 s.connect(remote)
458 if support.verbose:
459 sys.stdout.write("\nCipher with %r is %r\n" %
460 (remote, s.cipher()))
461 sys.stdout.write("Certificate is:\n%s\n" %
462 pprint.pformat(s.getpeercert()))
463 finally:
464 s.close()
465
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000466
467try:
468 import threading
469except ImportError:
470 _have_threads = False
471else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000472 _have_threads = True
473
474 class ThreadedEchoServer(threading.Thread):
475
476 class ConnectionHandler(threading.Thread):
477
478 """A mildly complicated class, because we want it to work both
479 with and without the SSL wrapper around the socket connection, so
480 that we can test the STARTTLS functionality."""
481
Bill Janssen6e027db2007-11-15 22:23:56 +0000482 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000483 self.server = server
484 self.running = False
485 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000486 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000487 self.sock.setblocking(1)
488 self.sslconn = None
489 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000490 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000491
Antoine Pitrou480a1242010-04-28 21:37:09 +0000492 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000494 self.sslconn = self.server.context.wrap_socket(
495 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000496 except ssl.SSLError:
497 # XXX Various errors can have happened here, for example
498 # a mismatching protocol version, an invalid certificate,
499 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000500 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000501 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000502 self.running = False
503 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000504 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000506 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000507 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000508 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000509 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000510 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
511 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000512 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000513 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
514 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000515 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000516 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
517 return True
518
519 def read(self):
520 if self.sslconn:
521 return self.sslconn.read()
522 else:
523 return self.sock.recv(1024)
524
525 def write(self, bytes):
526 if self.sslconn:
527 return self.sslconn.write(bytes)
528 else:
529 return self.sock.send(bytes)
530
531 def close(self):
532 if self.sslconn:
533 self.sslconn.close()
534 else:
535 self.sock.close()
536
Antoine Pitrou480a1242010-04-28 21:37:09 +0000537 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000538 self.running = True
539 if not self.server.starttls_server:
540 if not self.wrap_conn():
541 return
542 while self.running:
543 try:
544 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000545 stripped = msg.strip()
546 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000547 # eof, so quit this handler
548 self.running = False
549 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000550 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000551 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000552 sys.stdout.write(" server: client closed connection\n")
553 self.close()
554 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000555 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000556 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000557 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000558 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000559 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000560 if not self.wrap_conn():
561 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000562 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000563 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000564 if support.verbose and self.server.connectionchatty:
565 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000566 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000567 self.sock = self.sslconn.unwrap()
568 self.sslconn = None
569 if support.verbose and self.server.connectionchatty:
570 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000571 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000572 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000573 self.server.connectionchatty):
574 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000575 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
576 % (msg, ctype, msg.lower(), ctype))
577 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000578 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000579 if self.server.chatty:
580 handle_error("Test server failure:\n")
581 self.close()
582 self.running = False
583 # normally, we'd just stop here, but for the test
584 # harness, we want to stop the server
585 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000586
Antoine Pitroub5218772010-05-21 09:56:06 +0000587 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000588 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000589 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000590 ciphers=None, context=None):
591 if context:
592 self.context = context
593 else:
594 self.context = ssl.SSLContext(ssl_version
595 if ssl_version is not None
596 else ssl.PROTOCOL_TLSv1)
597 self.context.verify_mode = (certreqs if certreqs is not None
598 else ssl.CERT_NONE)
599 if cacerts:
600 self.context.load_verify_locations(cacerts)
601 if certificate:
602 self.context.load_cert_chain(certificate)
603 if ciphers:
604 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000605 self.chatty = chatty
606 self.connectionchatty = connectionchatty
607 self.starttls_server = starttls_server
608 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000609 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000610 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000611 self.active = False
612 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000613 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000614
Antoine Pitrou480a1242010-04-28 21:37:09 +0000615 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000616 self.flag = flag
617 threading.Thread.start(self)
618
Antoine Pitrou480a1242010-04-28 21:37:09 +0000619 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000620 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000621 self.sock.listen(5)
622 self.active = True
623 if self.flag:
624 # signal an event
625 self.flag.set()
626 while self.active:
627 try:
628 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000629 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000630 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000631 + repr(connaddr) + '\n')
632 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000633 handler.start()
634 except socket.timeout:
635 pass
636 except KeyboardInterrupt:
637 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000638 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639
Antoine Pitrou480a1242010-04-28 21:37:09 +0000640 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000641 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000642
Bill Janssen54cc54c2007-12-14 22:08:56 +0000643 class OurHTTPSServer(threading.Thread):
644
645 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000646
647 class HTTPSServer(HTTPServer):
648
649 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 HTTPServer.__init__(self, server_address, RequestHandlerClass)
651 # we assume the certfile contains both private key and certificate
652 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000653 self.allow_reuse_address = True
654
Bill Janssen6e027db2007-11-15 22:23:56 +0000655 def __str__(self):
656 return ('<%s %s:%s>' %
657 (self.__class__.__name__,
658 self.server_name,
659 self.server_port))
660
Antoine Pitrou480a1242010-04-28 21:37:09 +0000661 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 # override this to wrap socket with SSL
663 sock, addr = self.socket.accept()
664 sslconn = ssl.wrap_socket(sock, server_side=True,
665 certfile=self.certfile)
666 return sslconn, addr
667
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000668 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000669 # need to override translate_path to get a known root,
670 # instead of using os.curdir, since the test could be
671 # run from anywhere
672
673 server_version = "TestHTTPS/1.0"
674
675 root = None
676
677 def translate_path(self, path):
678 """Translate a /-separated PATH to the local filename syntax.
679
680 Components that mean special things to the local file system
681 (e.g. drive or directory names) are ignored. (XXX They should
682 probably be diagnosed.)
683
684 """
685 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000686 path = urllib.parse.urlparse(path)[2]
687 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000688 words = path.split('/')
689 words = filter(None, words)
690 path = self.root
691 for word in words:
692 drive, word = os.path.splitdrive(word)
693 head, word = os.path.split(word)
694 if word in self.root: continue
695 path = os.path.join(path, word)
696 return path
697
698 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000699 # we override this to suppress logging unless "verbose"
700
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000701 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000702 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
703 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000704 self.server.server_port,
705 self.request.cipher(),
706 self.log_date_time_string(),
707 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000708
709
Trent Nelson78520002008-04-10 20:54:35 +0000710 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000711 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000712 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
713 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000714 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
715 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000716 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000717 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000718
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000719 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000720 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000721
Antoine Pitrou480a1242010-04-28 21:37:09 +0000722 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000723 self.flag = flag
724 threading.Thread.start(self)
725
Antoine Pitrou480a1242010-04-28 21:37:09 +0000726 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000727 if self.flag:
728 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000729 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000730
Antoine Pitrou480a1242010-04-28 21:37:09 +0000731 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000732 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000733
734
Bill Janssen54cc54c2007-12-14 22:08:56 +0000735 class AsyncoreEchoServer(threading.Thread):
736
737 # this one's based on asyncore.dispatcher
738
739 class EchoServer (asyncore.dispatcher):
740
741 class ConnectionHandler (asyncore.dispatcher_with_send):
742
743 def __init__(self, conn, certfile):
744 self.socket = ssl.wrap_socket(conn, server_side=True,
745 certfile=certfile,
746 do_handshake_on_connect=False)
747 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000748 self._ssl_accepting = True
749 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000750
751 def readable(self):
752 if isinstance(self.socket, ssl.SSLSocket):
753 while self.socket.pending() > 0:
754 self.handle_read_event()
755 return True
756
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000757 def _do_ssl_handshake(self):
758 try:
759 self.socket.do_handshake()
760 except ssl.SSLError as err:
761 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
762 ssl.SSL_ERROR_WANT_WRITE):
763 return
764 elif err.args[0] == ssl.SSL_ERROR_EOF:
765 return self.handle_close()
766 raise
767 except socket.error as err:
768 if err.args[0] == errno.ECONNABORTED:
769 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000770 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000771 self._ssl_accepting = False
772
773 def handle_read(self):
774 if self._ssl_accepting:
775 self._do_ssl_handshake()
776 else:
777 data = self.recv(1024)
778 if support.verbose:
779 sys.stdout.write(" server: read %s from client\n" % repr(data))
780 if not data:
781 self.close()
782 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000783 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000784
785 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000786 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000787 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000788 sys.stdout.write(" server: closed connection %s\n" % self.socket)
789
790 def handle_error(self):
791 raise
792
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000793 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000794 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000795 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
796 self.port = support.bind_port(sock, '')
797 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000798 self.listen(5)
799
800 def handle_accept(self):
801 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000802 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000803 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
804 self.ConnectionHandler(sock_obj, self.certfile)
805
806 def handle_error(self):
807 raise
808
Trent Nelson78520002008-04-10 20:54:35 +0000809 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000810 self.flag = None
811 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000812 self.server = self.EchoServer(certfile)
813 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000814 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000815 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000816
817 def __str__(self):
818 return "<%s %s>" % (self.__class__.__name__, self.server)
819
820 def start (self, flag=None):
821 self.flag = flag
822 threading.Thread.start(self)
823
Antoine Pitrou480a1242010-04-28 21:37:09 +0000824 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000825 self.active = True
826 if self.flag:
827 self.flag.set()
828 while self.active:
829 try:
830 asyncore.loop(1)
831 except:
832 pass
833
Antoine Pitrou480a1242010-04-28 21:37:09 +0000834 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000835 self.active = False
836 self.server.close()
837
Antoine Pitrou480a1242010-04-28 21:37:09 +0000838 def bad_cert_test(certfile):
839 """
840 Launch a server with CERT_REQUIRED, and check that trying to
841 connect to it with the given client certificate fails.
842 """
Trent Nelson78520002008-04-10 20:54:35 +0000843 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000844 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000845 cacerts=CERTFILE, chatty=False,
846 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000847 flag = threading.Event()
848 server.start(flag)
849 # wait for it to start
850 flag.wait()
851 # try to connect
852 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000853 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000854 s = ssl.wrap_socket(socket.socket(),
855 certfile=certfile,
856 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000857 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000858 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000859 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000860 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000861 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000862 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000863 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000864 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000865 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 finally:
867 server.stop()
868 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000869
Antoine Pitroub5218772010-05-21 09:56:06 +0000870 def server_params_test(client_context, server_context, indata=b"FOO\n",
871 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000872 """
873 Launch a server, connect a client to it and try various reads
874 and writes.
875 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000876 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000877 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000878 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879 flag = threading.Event()
880 server.start(flag)
881 # wait for it to start
882 flag.wait()
883 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000884 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000885 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000886 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000887 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000888 if connectionchatty:
889 if support.verbose:
890 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000891 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000892 s.write(arg)
893 outdata = s.read()
894 if connectionchatty:
895 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000896 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000897 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000898 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000899 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
900 % (outdata[:20], len(outdata),
901 indata[:20].lower(), len(indata)))
902 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000903 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000904 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000905 sys.stdout.write(" client: closing connection.\n")
906 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 finally:
908 server.stop()
909 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000910
Antoine Pitroub5218772010-05-21 09:56:06 +0000911 def try_protocol_combo(server_protocol, client_protocol, expect_success,
912 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000913 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000914 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000915 certtype = {
916 ssl.CERT_NONE: "CERT_NONE",
917 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
918 ssl.CERT_REQUIRED: "CERT_REQUIRED",
919 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000920 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000921 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 sys.stdout.write(formatstr %
923 (ssl.get_protocol_name(client_protocol),
924 ssl.get_protocol_name(server_protocol),
925 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000926 client_context = ssl.SSLContext(client_protocol)
927 client_context.options = ssl.OP_ALL | client_options
928 server_context = ssl.SSLContext(server_protocol)
929 server_context.options = ssl.OP_ALL | server_options
930 for ctx in (client_context, server_context):
931 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000932 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
933 # will send an SSLv3 hello (rather than SSLv2) starting from
934 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000935 ctx.set_ciphers("ALL")
936 ctx.load_cert_chain(CERTFILE)
937 ctx.load_verify_locations(CERTFILE)
938 try:
939 server_params_test(client_context, server_context,
940 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000941 # Protocol mismatch can result in either an SSLError, or a
942 # "Connection reset by peer" error.
943 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000944 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000945 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000946 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000947 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000948 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000950 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000951 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000952 "Client protocol %s succeeded with server protocol %s!"
953 % (ssl.get_protocol_name(client_protocol),
954 ssl.get_protocol_name(server_protocol)))
955
956
Bill Janssen6e027db2007-11-15 22:23:56 +0000957 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000958
Antoine Pitrou23df4832010-08-04 17:14:06 +0000959 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000960 def test_echo(self):
961 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000962 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000964 for protocol in PROTOCOLS:
965 context = ssl.SSLContext(protocol)
966 context.load_cert_chain(CERTFILE)
967 server_params_test(context, context,
968 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000969
Antoine Pitrou480a1242010-04-28 21:37:09 +0000970 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000971 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000972 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000973 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
974 context.verify_mode = ssl.CERT_REQUIRED
975 context.load_verify_locations(CERTFILE)
976 context.load_cert_chain(CERTFILE)
977 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 flag = threading.Event()
979 server.start(flag)
980 # wait for it to start
981 flag.wait()
982 # try to connect
983 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000984 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000985 s.connect((HOST, server.port))
986 cert = s.getpeercert()
987 self.assertTrue(cert, "Can't get peer certificate.")
988 cipher = s.cipher()
989 if support.verbose:
990 sys.stdout.write(pprint.pformat(cert) + '\n')
991 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
992 if 'subject' not in cert:
993 self.fail("No subject field in certificate: %s." %
994 pprint.pformat(cert))
995 if ((('organizationName', 'Python Software Foundation'),)
996 not in cert['subject']):
997 self.fail(
998 "Missing or invalid 'organizationName' field in certificate subject; "
999 "should be 'Python Software Foundation'.")
1000 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001 finally:
1002 server.stop()
1003 server.join()
1004
Antoine Pitrou480a1242010-04-28 21:37:09 +00001005 def test_empty_cert(self):
1006 """Connecting with an empty cert file"""
1007 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1008 "nullcert.pem"))
1009 def test_malformed_cert(self):
1010 """Connecting with a badly formatted certificate (syntax error)"""
1011 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1012 "badcert.pem"))
1013 def test_nonexisting_cert(self):
1014 """Connecting with a non-existing cert file"""
1015 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1016 "wrongcert.pem"))
1017 def test_malformed_key(self):
1018 """Connecting with a badly formatted key (syntax error)"""
1019 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1020 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001021
Antoine Pitrou480a1242010-04-28 21:37:09 +00001022 def test_rude_shutdown(self):
1023 """A brutal shutdown of an SSL server should raise an IOError
1024 in the client when attempting handshake.
1025 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001026 listener_ready = threading.Event()
1027 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001028
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001029 s = socket.socket()
1030 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001031
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001032 # `listener` runs in a thread. It sits in an accept() until
1033 # the main thread connects. Then it rudely closes the socket,
1034 # and sets Event `listener_gone` to let the main thread know
1035 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001036 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001037 s.listen(5)
1038 listener_ready.set()
1039 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001040 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001041 listener_gone.set()
1042
1043 def connector():
1044 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001045 c = socket.socket()
1046 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001047 listener_gone.wait()
1048 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001049 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001050 except IOError:
1051 pass
1052 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001053 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001054
1055 t = threading.Thread(target=listener)
1056 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001057 try:
1058 connector()
1059 finally:
1060 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001061
Antoine Pitrou23df4832010-08-04 17:14:06 +00001062 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001063 def test_protocol_sslv2(self):
1064 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001065 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1068 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1069 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1070 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1071 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1072 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001073 # SSLv23 client with specific SSL options
1074 if no_sslv2_implies_sslv3_hello():
1075 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1076 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1077 client_options=ssl.OP_NO_SSLv2)
1078 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1079 client_options=ssl.OP_NO_SSLv3)
1080 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1081 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001082
Antoine Pitrou23df4832010-08-04 17:14:06 +00001083 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001084 def test_protocol_sslv23(self):
1085 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001086 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001087 sys.stdout.write("\n")
1088 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001089 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001090 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001091 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001092 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093 sys.stdout.write(
1094 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1095 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001096 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1097 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1098 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001099
Antoine Pitrou480a1242010-04-28 21:37:09 +00001100 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1101 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1102 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001103
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1105 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1106 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107
Antoine Pitroub5218772010-05-21 09:56:06 +00001108 # Server with specific SSL options
1109 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1110 server_options=ssl.OP_NO_SSLv3)
1111 # Will choose TLSv1
1112 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1113 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1114 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1115 server_options=ssl.OP_NO_TLSv1)
1116
1117
Antoine Pitrou23df4832010-08-04 17:14:06 +00001118 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001119 def test_protocol_sslv3(self):
1120 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001121 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001122 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001123 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1124 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1125 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1126 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1127 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1128 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001129 if no_sslv2_implies_sslv3_hello():
1130 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1131 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1132 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001133
Antoine Pitrou23df4832010-08-04 17:14:06 +00001134 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001135 def test_protocol_tlsv1(self):
1136 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001137 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001138 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1140 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1141 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1142 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1143 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1144 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001145
Antoine Pitrou480a1242010-04-28 21:37:09 +00001146 def test_starttls(self):
1147 """Switching from clear text to encrypted and back again."""
1148 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 +00001149
Trent Nelson78520002008-04-10 20:54:35 +00001150 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001151 ssl_version=ssl.PROTOCOL_TLSv1,
1152 starttls_server=True,
1153 chatty=True,
1154 connectionchatty=True)
1155 flag = threading.Event()
1156 server.start(flag)
1157 # wait for it to start
1158 flag.wait()
1159 # try to connect
1160 wrapped = False
1161 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001162 s = socket.socket()
1163 s.setblocking(1)
1164 s.connect((HOST, server.port))
1165 if support.verbose:
1166 sys.stdout.write("\n")
1167 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001168 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001169 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001170 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001171 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001172 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001173 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001175 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001176 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001177 msg = outdata.strip().lower()
1178 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1179 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001180 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001181 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 " client: read %r from server, starting TLS...\n"
1183 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001184 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1185 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001186 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1187 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001188 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001189 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001190 " client: read %r from server, ending TLS...\n"
1191 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001192 s = conn.unwrap()
1193 wrapped = False
1194 else:
1195 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001196 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001197 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001198 if support.verbose:
1199 sys.stdout.write(" client: closing connection.\n")
1200 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001201 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001202 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001204 if wrapped:
1205 conn.close()
1206 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001207 s.close()
1208 finally:
1209 server.stop()
1210 server.join()
1211
Antoine Pitrou480a1242010-04-28 21:37:09 +00001212 def test_socketserver(self):
1213 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001214 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001215 flag = threading.Event()
1216 server.start(flag)
1217 # wait for it to start
1218 flag.wait()
1219 # try to connect
1220 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001221 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001222 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001223 with open(CERTFILE, 'rb') as f:
1224 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001225 d2 = ''
1226 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001227 url = 'https://%s:%d/%s' % (
1228 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001229 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001230 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 if dlen and (int(dlen) > 0):
1232 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001233 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234 sys.stdout.write(
1235 " client: read %d bytes from remote server '%s'\n"
1236 % (len(d2), server))
1237 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001238 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001239 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001240 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001241 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001242 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001243 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001244 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001245 server.join()
1246
Antoine Pitrou480a1242010-04-28 21:37:09 +00001247 def test_asyncore_server(self):
1248 """Check the example asyncore integration."""
1249 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001250
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001251 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001252 sys.stdout.write("\n")
1253
Antoine Pitrou480a1242010-04-28 21:37:09 +00001254 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001255 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001256 flag = threading.Event()
1257 server.start(flag)
1258 # wait for it to start
1259 flag.wait()
1260 # try to connect
1261 try:
1262 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001263 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001264 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001265 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001266 " client: sending %r...\n" % indata)
1267 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001268 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001269 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001270 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001271 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001272 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001273 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1274 % (outdata[:20], len(outdata),
1275 indata[:20].lower(), len(indata)))
1276 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001277 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001278 sys.stdout.write(" client: closing connection.\n")
1279 s.close()
1280 finally:
1281 server.stop()
1282 server.join()
1283
Antoine Pitrou480a1242010-04-28 21:37:09 +00001284 def test_recv_send(self):
1285 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001286 if support.verbose:
1287 sys.stdout.write("\n")
1288
1289 server = ThreadedEchoServer(CERTFILE,
1290 certreqs=ssl.CERT_NONE,
1291 ssl_version=ssl.PROTOCOL_TLSv1,
1292 cacerts=CERTFILE,
1293 chatty=True,
1294 connectionchatty=False)
1295 flag = threading.Event()
1296 server.start(flag)
1297 # wait for it to start
1298 flag.wait()
1299 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001300 s = ssl.wrap_socket(socket.socket(),
1301 server_side=False,
1302 certfile=CERTFILE,
1303 ca_certs=CERTFILE,
1304 cert_reqs=ssl.CERT_NONE,
1305 ssl_version=ssl.PROTOCOL_TLSv1)
1306 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001307 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001308 # helper methods for standardising recv* method signatures
1309 def _recv_into():
1310 b = bytearray(b"\0"*100)
1311 count = s.recv_into(b)
1312 return b[:count]
1313
1314 def _recvfrom_into():
1315 b = bytearray(b"\0"*100)
1316 count, addr = s.recvfrom_into(b)
1317 return b[:count]
1318
1319 # (name, method, whether to expect success, *args)
1320 send_methods = [
1321 ('send', s.send, True, []),
1322 ('sendto', s.sendto, False, ["some.address"]),
1323 ('sendall', s.sendall, True, []),
1324 ]
1325 recv_methods = [
1326 ('recv', s.recv, True, []),
1327 ('recvfrom', s.recvfrom, False, ["some.address"]),
1328 ('recv_into', _recv_into, True, []),
1329 ('recvfrom_into', _recvfrom_into, False, []),
1330 ]
1331 data_prefix = "PREFIX_"
1332
1333 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001334 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001335 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001336 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001337 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001338 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001339 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001340 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 "<<{outdata:r}>> ({nout:d}) received; "
1342 "expected <<{indata:r}>> ({nin:d})\n".format(
1343 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001344 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001345 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001346 )
1347 )
1348 except ValueError as e:
1349 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001350 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001351 "Failed to send with method <<{name:s}>>; "
1352 "expected to succeed.\n".format(name=meth_name)
1353 )
1354 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001355 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001356 "Method <<{name:s}>> failed with unexpected "
1357 "exception message: {exp:s}\n".format(
1358 name=meth_name, exp=e
1359 )
1360 )
1361
1362 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001363 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001364 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001365 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001366 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001367 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001368 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001369 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001370 "<<{outdata:r}>> ({nout:d}) received; "
1371 "expected <<{indata:r}>> ({nin:d})\n".format(
1372 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001373 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001374 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001375 )
1376 )
1377 except ValueError as e:
1378 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001379 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001380 "Failed to receive with method <<{name:s}>>; "
1381 "expected to succeed.\n".format(name=meth_name)
1382 )
1383 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001384 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001385 "Method <<{name:s}>> failed with unexpected "
1386 "exception message: {exp:s}\n".format(
1387 name=meth_name, exp=e
1388 )
1389 )
1390 # consume data
1391 s.read()
1392
Antoine Pitrou480a1242010-04-28 21:37:09 +00001393 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001394 s.close()
1395 finally:
1396 server.stop()
1397 server.join()
1398
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001399 def test_handshake_timeout(self):
1400 # Issue #5103: SSL handshake must respect the socket timeout
1401 server = socket.socket(socket.AF_INET)
1402 host = "127.0.0.1"
1403 port = support.bind_port(server)
1404 started = threading.Event()
1405 finish = False
1406
1407 def serve():
1408 server.listen(5)
1409 started.set()
1410 conns = []
1411 while not finish:
1412 r, w, e = select.select([server], [], [], 0.1)
1413 if server in r:
1414 # Let the socket hang around rather than having
1415 # it closed by garbage collection.
1416 conns.append(server.accept()[0])
1417
1418 t = threading.Thread(target=serve)
1419 t.start()
1420 started.wait()
1421
1422 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001423 try:
1424 c = socket.socket(socket.AF_INET)
1425 c.settimeout(0.2)
1426 c.connect((host, port))
1427 # Will attempt handshake and time out
1428 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1429 ssl.wrap_socket, c)
1430 finally:
1431 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001432 try:
1433 c = socket.socket(socket.AF_INET)
1434 c = ssl.wrap_socket(c)
1435 c.settimeout(0.2)
1436 # Will attempt handshake and time out
1437 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1438 c.connect, (host, port))
1439 finally:
1440 c.close()
1441 finally:
1442 finish = True
1443 t.join()
1444 server.close()
1445
Bill Janssen58afe4c2008-09-08 16:45:19 +00001446
Thomas Woutersed03b412007-08-28 21:37:11 +00001447def test_main(verbose=False):
1448 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001449 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001450
Antoine Pitrou15cee622010-08-04 16:45:21 +00001451 if support.verbose:
1452 plats = {
1453 'Linux': platform.linux_distribution,
1454 'Mac': platform.mac_ver,
1455 'Windows': platform.win32_ver,
1456 }
1457 for name, func in plats.items():
1458 plat = func()
1459 if plat and plat[0]:
1460 plat = '%s %r' % (name, plat)
1461 break
1462 else:
1463 plat = repr(platform.platform())
1464 print("test_ssl: testing with %r %r" %
1465 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1466 print(" under %s" % plat)
1467
Antoine Pitrou152efa22010-05-16 18:19:27 +00001468 for filename in [
1469 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1470 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1471 BADCERT, BADKEY, EMPTYCERT]:
1472 if not os.path.exists(filename):
1473 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001474
Antoine Pitrou152efa22010-05-16 18:19:27 +00001475 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001476
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001477 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001478 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001479
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001480 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001481 thread_info = support.threading_setup()
1482 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001483 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001484
Antoine Pitrou480a1242010-04-28 21:37:09 +00001485 try:
1486 support.run_unittest(*tests)
1487 finally:
1488 if _have_threads:
1489 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001490
1491if __name__ == "__main__":
1492 test_main()