blob: 9ee4db17caac5ee2835fe761b22279c3b31ea884 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Jeremy Hylton1afc1692008-06-18 20:49:58 +000014import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000029else:
30 PROTOCOLS = [
31 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
32 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
33 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000034
Benjamin Petersonee8712c2008-05-20 21:35:26 +000035HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
37data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038
39CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
54
Thomas Woutersed03b412007-08-28 21:37:11 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056def handle_error(prefix):
57 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000059 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitroub5218772010-05-21 09:56:06 +000061def can_clear_options():
62 # 0.9.8m or higher
63 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
64
65def no_sslv2_implies_sslv3_hello():
66 # 0.9.7h or higher
67 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
68
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou23df4832010-08-04 17:14:06 +000070# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
71def skip_if_broken_ubuntu_ssl(func):
72 @functools.wraps(func)
73 def f(*args, **kwargs):
74 try:
75 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
76 except ssl.SSLError:
77 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
78 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
79 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
80 return func(*args, **kwargs)
81 return f
82
83
Antoine Pitrou152efa22010-05-16 18:19:27 +000084class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Antoine Pitrou480a1242010-04-28 21:37:09 +000086 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 ssl.PROTOCOL_SSLv2
88 ssl.PROTOCOL_SSLv23
89 ssl.PROTOCOL_SSLv3
90 ssl.PROTOCOL_TLSv1
91 ssl.CERT_NONE
92 ssl.CERT_OPTIONAL
93 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000097 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 sys.stdout.write("\n RAND_status is %d (%s)\n"
99 % (v, (v and "sufficient randomness") or
100 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000101 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102 ssl.RAND_egd(1)
103 except TypeError:
104 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000105 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 print("didn't raise TypeError")
107 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000108
Antoine Pitrou480a1242010-04-28 21:37:09 +0000109 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000110 # note that this uses an 'unofficial' function in _ssl.c,
111 # provided solely for this test, to exercise the certificate
112 # parsing code
113 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000116
Antoine Pitrou480a1242010-04-28 21:37:09 +0000117 def test_DER_to_PEM(self):
118 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
119 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 d1 = ssl.PEM_cert_to_DER_cert(pem)
121 p2 = ssl.DER_cert_to_PEM_cert(d1)
122 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000123 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000124 if not p2.startswith(ssl.PEM_HEADER + '\n'):
125 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
126 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
127 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000129 def test_openssl_version(self):
130 n = ssl.OPENSSL_VERSION_NUMBER
131 t = ssl.OPENSSL_VERSION_INFO
132 s = ssl.OPENSSL_VERSION
133 self.assertIsInstance(n, int)
134 self.assertIsInstance(t, tuple)
135 self.assertIsInstance(s, str)
136 # Some sanity checks follow
137 # >= 0.9
138 self.assertGreaterEqual(n, 0x900000)
139 # < 2.0
140 self.assertLess(n, 0x20000000)
141 major, minor, fix, patch, status = t
142 self.assertGreaterEqual(major, 0)
143 self.assertLess(major, 2)
144 self.assertGreaterEqual(minor, 0)
145 self.assertLess(minor, 256)
146 self.assertGreaterEqual(fix, 0)
147 self.assertLess(fix, 256)
148 self.assertGreaterEqual(patch, 0)
149 self.assertLessEqual(patch, 26)
150 self.assertGreaterEqual(status, 0)
151 self.assertLessEqual(status, 15)
152 # Version string as returned by OpenSSL, the format might change
153 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
154 (s, t))
155
Antoine Pitrou9d543662010-04-23 23:10:32 +0000156 @support.cpython_only
157 def test_refcycle(self):
158 # Issue #7943: an SSL object doesn't create reference cycles with
159 # itself.
160 s = socket.socket(socket.AF_INET)
161 ss = ssl.wrap_socket(s)
162 wr = weakref.ref(ss)
163 del ss
164 self.assertEqual(wr(), None)
165
Antoine Pitrou40f08742010-04-24 22:04:40 +0000166 def test_timeout(self):
167 # Issue #8524: when creating an SSL socket, the timeout of the
168 # original socket should be retained.
169 for timeout in (None, 0.0, 5.0):
170 s = socket.socket(socket.AF_INET)
171 s.settimeout(timeout)
172 ss = ssl.wrap_socket(s)
173 self.assertEqual(timeout, ss.gettimeout())
174
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000175 def test_errors(self):
176 sock = socket.socket()
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000177 self.assertRaisesRegexp(ValueError,
178 "certfile must be specified",
179 ssl.wrap_socket, sock, keyfile=CERTFILE)
180 self.assertRaisesRegexp(ValueError,
181 "certfile must be specified for server-side operations",
182 ssl.wrap_socket, sock, server_side=True)
183 self.assertRaisesRegexp(ValueError,
184 "certfile must be specified for server-side operations",
185 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000186 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
187 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
188 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000189 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000190 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000191 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000192 with self.assertRaises(IOError) as cm:
193 ssl.wrap_socket(socket.socket(), certfile=CERTFILE, keyfile=WRONGCERT)
194 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000195 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000196 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000197 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000198
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000199
Antoine Pitrou152efa22010-05-16 18:19:27 +0000200class ContextTests(unittest.TestCase):
201
Antoine Pitrou23df4832010-08-04 17:14:06 +0000202 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000203 def test_constructor(self):
204 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
205 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
206 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
207 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
208 self.assertRaises(TypeError, ssl.SSLContext)
209 self.assertRaises(ValueError, ssl.SSLContext, -1)
210 self.assertRaises(ValueError, ssl.SSLContext, 42)
211
Antoine Pitrou23df4832010-08-04 17:14:06 +0000212 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000213 def test_protocol(self):
214 for proto in PROTOCOLS:
215 ctx = ssl.SSLContext(proto)
216 self.assertEqual(ctx.protocol, proto)
217
218 def test_ciphers(self):
219 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
220 ctx.set_ciphers("ALL")
221 ctx.set_ciphers("DEFAULT")
222 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000223 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000224
Antoine Pitrou23df4832010-08-04 17:14:06 +0000225 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000226 def test_options(self):
227 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
228 # OP_ALL is the default value
229 self.assertEqual(ssl.OP_ALL, ctx.options)
230 ctx.options |= ssl.OP_NO_SSLv2
231 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
232 ctx.options)
233 ctx.options |= ssl.OP_NO_SSLv3
234 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
235 ctx.options)
236 if can_clear_options():
237 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
238 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
239 ctx.options)
240 ctx.options = 0
241 self.assertEqual(0, ctx.options)
242 else:
243 with self.assertRaises(ValueError):
244 ctx.options = 0
245
Antoine Pitrou152efa22010-05-16 18:19:27 +0000246 def test_verify(self):
247 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
248 # Default value
249 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
250 ctx.verify_mode = ssl.CERT_OPTIONAL
251 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
252 ctx.verify_mode = ssl.CERT_REQUIRED
253 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
254 ctx.verify_mode = ssl.CERT_NONE
255 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
256 with self.assertRaises(TypeError):
257 ctx.verify_mode = None
258 with self.assertRaises(ValueError):
259 ctx.verify_mode = 42
260
261 def test_load_cert_chain(self):
262 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
263 # Combined key and cert in a single file
264 ctx.load_cert_chain(CERTFILE)
265 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
266 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000267 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000268 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000269 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000270 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
271 ctx.load_cert_chain(BADCERT)
272 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
273 ctx.load_cert_chain(EMPTYCERT)
274 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000275 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000276 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
277 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
278 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
279 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
280 ctx.load_cert_chain(ONLYCERT)
281 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
282 ctx.load_cert_chain(ONLYKEY)
283 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
284 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
285 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000286 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000287 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
288 ctx.load_cert_chain(CERTFILE, ONLYKEY)
289
290 def test_load_verify_locations(self):
291 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
292 ctx.load_verify_locations(CERTFILE)
293 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
294 ctx.load_verify_locations(BYTES_CERTFILE)
295 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
296 self.assertRaises(TypeError, ctx.load_verify_locations)
297 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000298 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000299 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000300 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000301 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
302 ctx.load_verify_locations(BADCERT)
303 ctx.load_verify_locations(CERTFILE, CAPATH)
304 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
305
306
Bill Janssen6e027db2007-11-15 22:23:56 +0000307class NetworkedTests(unittest.TestCase):
Antoine Pitroud151e272010-08-14 16:32:10 +0000308 def setUp(self):
309 self.old_timeout = socket.getdefaulttimeout()
310 socket.setdefaulttimeout(30)
311
312 def tearDown(self):
313 socket.setdefaulttimeout(self.old_timeout)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000314
Antoine Pitrou480a1242010-04-28 21:37:09 +0000315 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000316 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
317 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000318 try:
319 s.connect(("svn.python.org", 443))
320 self.assertEqual({}, s.getpeercert())
321 finally:
322 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000323
324 # this should fail because we have no verification certs
325 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
326 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000327 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
328 s.connect, ("svn.python.org", 443))
329 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000330
331 # this should succeed because we specify the root cert
332 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
333 cert_reqs=ssl.CERT_REQUIRED,
334 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
335 try:
336 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000337 self.assertTrue(s.getpeercert())
338 finally:
339 s.close()
340
341 def test_connect_with_context(self):
342 # Same as test_connect, but with a separately created context
343 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
344 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
345 s.connect(("svn.python.org", 443))
346 try:
347 self.assertEqual({}, s.getpeercert())
348 finally:
349 s.close()
350 # This should fail because we have no verification certs
351 ctx.verify_mode = ssl.CERT_REQUIRED
352 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
353 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
354 s.connect, ("svn.python.org", 443))
355 s.close()
356 # This should succeed because we specify the root cert
357 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
358 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
359 s.connect(("svn.python.org", 443))
360 try:
361 cert = s.getpeercert()
362 self.assertTrue(cert)
363 finally:
364 s.close()
365
366 def test_connect_capath(self):
367 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000368 # NOTE: the subject hashing algorithm has been changed between
369 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
370 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000371 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000372 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
373 ctx.verify_mode = ssl.CERT_REQUIRED
374 ctx.load_verify_locations(capath=CAPATH)
375 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
376 s.connect(("svn.python.org", 443))
377 try:
378 cert = s.getpeercert()
379 self.assertTrue(cert)
380 finally:
381 s.close()
382 # Same with a bytes `capath` argument
383 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
384 ctx.verify_mode = ssl.CERT_REQUIRED
385 ctx.load_verify_locations(capath=BYTES_CAPATH)
386 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
387 s.connect(("svn.python.org", 443))
388 try:
389 cert = s.getpeercert()
390 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000391 finally:
392 s.close()
393
Antoine Pitroue3220242010-04-24 11:13:53 +0000394 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
395 def test_makefile_close(self):
396 # Issue #5238: creating a file-like object with makefile() shouldn't
397 # delay closing the underlying "real socket" (here tested with its
398 # file descriptor, hence skipping the test under Windows).
399 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
400 ss.connect(("svn.python.org", 443))
401 fd = ss.fileno()
402 f = ss.makefile()
403 f.close()
404 # The fd is still open
405 os.read(fd, 0)
406 # Closing the SSL socket should close the fd too
407 ss.close()
408 gc.collect()
409 with self.assertRaises(OSError) as e:
410 os.read(fd, 0)
411 self.assertEqual(e.exception.errno, errno.EBADF)
412
Antoine Pitrou480a1242010-04-28 21:37:09 +0000413 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000414 s = socket.socket(socket.AF_INET)
415 s.connect(("svn.python.org", 443))
416 s.setblocking(False)
417 s = ssl.wrap_socket(s,
418 cert_reqs=ssl.CERT_NONE,
419 do_handshake_on_connect=False)
420 count = 0
421 while True:
422 try:
423 count += 1
424 s.do_handshake()
425 break
426 except ssl.SSLError as err:
427 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
428 select.select([s], [], [])
429 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
430 select.select([], [s], [])
431 else:
432 raise
433 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000434 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000435 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000436
Antoine Pitrou480a1242010-04-28 21:37:09 +0000437 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000438 pem = ssl.get_server_certificate(("svn.python.org", 443))
439 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000440 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000441
Bill Janssen54cc54c2007-12-14 22:08:56 +0000442 try:
443 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
444 except ssl.SSLError as x:
445 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000446 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000447 sys.stdout.write("%s\n" % x)
448 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000449 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000450
451 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
452 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000453 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000454 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000455 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
456
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000457 def test_ciphers(self):
458 remote = ("svn.python.org", 443)
459 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
460 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
461 s.connect(remote)
462 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
463 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
464 s.connect(remote)
465 # Error checking can happen at instantiation or when connecting
466 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
467 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
468 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
469 s.connect(remote)
470
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000471 def test_algorithms(self):
472 # Issue #8484: all algorithms should be available when verifying a
473 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000474 # SHA256 was added in OpenSSL 0.9.8
475 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
476 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000477 # NOTE: https://sha256.tbs-internet.com is another possible test host
478 remote = ("sha2.hboeck.de", 443)
479 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000480 with support.transient_internet("sha2.hboeck.de"):
481 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
482 cert_reqs=ssl.CERT_REQUIRED,
483 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000484 try:
485 s.connect(remote)
486 if support.verbose:
487 sys.stdout.write("\nCipher with %r is %r\n" %
488 (remote, s.cipher()))
489 sys.stdout.write("Certificate is:\n%s\n" %
490 pprint.pformat(s.getpeercert()))
491 finally:
492 s.close()
493
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000494
495try:
496 import threading
497except ImportError:
498 _have_threads = False
499else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000500 _have_threads = True
501
502 class ThreadedEchoServer(threading.Thread):
503
504 class ConnectionHandler(threading.Thread):
505
506 """A mildly complicated class, because we want it to work both
507 with and without the SSL wrapper around the socket connection, so
508 that we can test the STARTTLS functionality."""
509
Bill Janssen6e027db2007-11-15 22:23:56 +0000510 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000511 self.server = server
512 self.running = False
513 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000514 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000515 self.sock.setblocking(1)
516 self.sslconn = None
517 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000518 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000519
Antoine Pitrou480a1242010-04-28 21:37:09 +0000520 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000521 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000522 self.sslconn = self.server.context.wrap_socket(
523 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000524 except ssl.SSLError:
525 # XXX Various errors can have happened here, for example
526 # a mismatching protocol version, an invalid certificate,
527 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000529 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000530 self.running = False
531 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000532 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000533 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000534 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000535 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000536 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000537 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000538 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
539 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000540 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000541 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
542 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000543 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000544 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
545 return True
546
547 def read(self):
548 if self.sslconn:
549 return self.sslconn.read()
550 else:
551 return self.sock.recv(1024)
552
553 def write(self, bytes):
554 if self.sslconn:
555 return self.sslconn.write(bytes)
556 else:
557 return self.sock.send(bytes)
558
559 def close(self):
560 if self.sslconn:
561 self.sslconn.close()
562 else:
563 self.sock.close()
564
Antoine Pitrou480a1242010-04-28 21:37:09 +0000565 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000566 self.running = True
567 if not self.server.starttls_server:
568 if not self.wrap_conn():
569 return
570 while self.running:
571 try:
572 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000573 stripped = msg.strip()
574 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000575 # eof, so quit this handler
576 self.running = False
577 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000578 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000579 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000580 sys.stdout.write(" server: client closed connection\n")
581 self.close()
582 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000583 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000584 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000585 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000586 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000587 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000588 if not self.wrap_conn():
589 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000590 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000591 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000592 if support.verbose and self.server.connectionchatty:
593 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000594 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000595 self.sock = self.sslconn.unwrap()
596 self.sslconn = None
597 if support.verbose and self.server.connectionchatty:
598 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000599 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000600 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000601 self.server.connectionchatty):
602 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000603 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
604 % (msg, ctype, msg.lower(), ctype))
605 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000606 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000607 if self.server.chatty:
608 handle_error("Test server failure:\n")
609 self.close()
610 self.running = False
611 # normally, we'd just stop here, but for the test
612 # harness, we want to stop the server
613 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000614
Antoine Pitroub5218772010-05-21 09:56:06 +0000615 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000616 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000617 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000618 ciphers=None, context=None):
619 if context:
620 self.context = context
621 else:
622 self.context = ssl.SSLContext(ssl_version
623 if ssl_version is not None
624 else ssl.PROTOCOL_TLSv1)
625 self.context.verify_mode = (certreqs if certreqs is not None
626 else ssl.CERT_NONE)
627 if cacerts:
628 self.context.load_verify_locations(cacerts)
629 if certificate:
630 self.context.load_cert_chain(certificate)
631 if ciphers:
632 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000633 self.chatty = chatty
634 self.connectionchatty = connectionchatty
635 self.starttls_server = starttls_server
636 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000637 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000638 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 self.active = False
640 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000641 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000642
Antoine Pitrou480a1242010-04-28 21:37:09 +0000643 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000644 self.flag = flag
645 threading.Thread.start(self)
646
Antoine Pitrou480a1242010-04-28 21:37:09 +0000647 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000648 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000649 self.sock.listen(5)
650 self.active = True
651 if self.flag:
652 # signal an event
653 self.flag.set()
654 while self.active:
655 try:
656 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000657 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000658 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000659 + repr(connaddr) + '\n')
660 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000661 handler.start()
662 except socket.timeout:
663 pass
664 except KeyboardInterrupt:
665 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000666 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000667
Antoine Pitrou480a1242010-04-28 21:37:09 +0000668 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000669 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000670
Bill Janssen54cc54c2007-12-14 22:08:56 +0000671 class OurHTTPSServer(threading.Thread):
672
673 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000674
675 class HTTPSServer(HTTPServer):
676
677 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000678 HTTPServer.__init__(self, server_address, RequestHandlerClass)
679 # we assume the certfile contains both private key and certificate
680 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000681 self.allow_reuse_address = True
682
Bill Janssen6e027db2007-11-15 22:23:56 +0000683 def __str__(self):
684 return ('<%s %s:%s>' %
685 (self.__class__.__name__,
686 self.server_name,
687 self.server_port))
688
Antoine Pitrou480a1242010-04-28 21:37:09 +0000689 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000690 # override this to wrap socket with SSL
691 sock, addr = self.socket.accept()
692 sslconn = ssl.wrap_socket(sock, server_side=True,
693 certfile=self.certfile)
694 return sslconn, addr
695
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000696 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000697 # need to override translate_path to get a known root,
698 # instead of using os.curdir, since the test could be
699 # run from anywhere
700
701 server_version = "TestHTTPS/1.0"
702
703 root = None
704
705 def translate_path(self, path):
706 """Translate a /-separated PATH to the local filename syntax.
707
708 Components that mean special things to the local file system
709 (e.g. drive or directory names) are ignored. (XXX They should
710 probably be diagnosed.)
711
712 """
713 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000714 path = urllib.parse.urlparse(path)[2]
715 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000716 words = path.split('/')
717 words = filter(None, words)
718 path = self.root
719 for word in words:
720 drive, word = os.path.splitdrive(word)
721 head, word = os.path.split(word)
722 if word in self.root: continue
723 path = os.path.join(path, word)
724 return path
725
726 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000727 # we override this to suppress logging unless "verbose"
728
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000729 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000730 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
731 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000732 self.server.server_port,
733 self.request.cipher(),
734 self.log_date_time_string(),
735 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000736
737
Trent Nelson78520002008-04-10 20:54:35 +0000738 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000740 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
741 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000742 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
743 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000744 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000745 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000746
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000747 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000748 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000749
Antoine Pitrou480a1242010-04-28 21:37:09 +0000750 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000751 self.flag = flag
752 threading.Thread.start(self)
753
Antoine Pitrou480a1242010-04-28 21:37:09 +0000754 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000755 if self.flag:
756 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000757 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000758
Antoine Pitrou480a1242010-04-28 21:37:09 +0000759 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000760 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000761
762
Bill Janssen54cc54c2007-12-14 22:08:56 +0000763 class AsyncoreEchoServer(threading.Thread):
764
765 # this one's based on asyncore.dispatcher
766
767 class EchoServer (asyncore.dispatcher):
768
769 class ConnectionHandler (asyncore.dispatcher_with_send):
770
771 def __init__(self, conn, certfile):
772 self.socket = ssl.wrap_socket(conn, server_side=True,
773 certfile=certfile,
774 do_handshake_on_connect=False)
775 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000776 self._ssl_accepting = True
777 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000778
779 def readable(self):
780 if isinstance(self.socket, ssl.SSLSocket):
781 while self.socket.pending() > 0:
782 self.handle_read_event()
783 return True
784
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000785 def _do_ssl_handshake(self):
786 try:
787 self.socket.do_handshake()
788 except ssl.SSLError as err:
789 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
790 ssl.SSL_ERROR_WANT_WRITE):
791 return
792 elif err.args[0] == ssl.SSL_ERROR_EOF:
793 return self.handle_close()
794 raise
795 except socket.error as err:
796 if err.args[0] == errno.ECONNABORTED:
797 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000798 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000799 self._ssl_accepting = False
800
801 def handle_read(self):
802 if self._ssl_accepting:
803 self._do_ssl_handshake()
804 else:
805 data = self.recv(1024)
806 if support.verbose:
807 sys.stdout.write(" server: read %s from client\n" % repr(data))
808 if not data:
809 self.close()
810 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000811 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000812
813 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000814 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000815 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000816 sys.stdout.write(" server: closed connection %s\n" % self.socket)
817
818 def handle_error(self):
819 raise
820
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000821 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000822 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000823 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
824 self.port = support.bind_port(sock, '')
825 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000826 self.listen(5)
827
828 def handle_accept(self):
829 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000830 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000831 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
832 self.ConnectionHandler(sock_obj, self.certfile)
833
834 def handle_error(self):
835 raise
836
Trent Nelson78520002008-04-10 20:54:35 +0000837 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000838 self.flag = None
839 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000840 self.server = self.EchoServer(certfile)
841 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000842 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000843 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000844
845 def __str__(self):
846 return "<%s %s>" % (self.__class__.__name__, self.server)
847
848 def start (self, flag=None):
849 self.flag = flag
850 threading.Thread.start(self)
851
Antoine Pitrou480a1242010-04-28 21:37:09 +0000852 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000853 self.active = True
854 if self.flag:
855 self.flag.set()
856 while self.active:
857 try:
858 asyncore.loop(1)
859 except:
860 pass
861
Antoine Pitrou480a1242010-04-28 21:37:09 +0000862 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000863 self.active = False
864 self.server.close()
865
Antoine Pitrou480a1242010-04-28 21:37:09 +0000866 def bad_cert_test(certfile):
867 """
868 Launch a server with CERT_REQUIRED, and check that trying to
869 connect to it with the given client certificate fails.
870 """
Trent Nelson78520002008-04-10 20:54:35 +0000871 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000873 cacerts=CERTFILE, chatty=False,
874 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000875 flag = threading.Event()
876 server.start(flag)
877 # wait for it to start
878 flag.wait()
879 # try to connect
880 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000881 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000882 s = ssl.wrap_socket(socket.socket(),
883 certfile=certfile,
884 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000885 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000887 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000888 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000889 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000890 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000891 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000892 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000893 if x.errno != errno.ENOENT:
894 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000895 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000896 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000897 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000898 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000899 finally:
900 server.stop()
901 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000902
Antoine Pitroub5218772010-05-21 09:56:06 +0000903 def server_params_test(client_context, server_context, indata=b"FOO\n",
904 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000905 """
906 Launch a server, connect a client to it and try various reads
907 and writes.
908 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000909 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000910 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000911 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 flag = threading.Event()
913 server.start(flag)
914 # wait for it to start
915 flag.wait()
916 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000917 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000918 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000919 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000920 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000921 if connectionchatty:
922 if support.verbose:
923 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000924 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000925 s.write(arg)
926 outdata = s.read()
927 if connectionchatty:
928 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000929 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000930 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000931 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000932 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
933 % (outdata[:20], len(outdata),
934 indata[:20].lower(), len(indata)))
935 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000936 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000937 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000938 sys.stdout.write(" client: closing connection.\n")
939 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000940 finally:
941 server.stop()
942 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000943
Antoine Pitroub5218772010-05-21 09:56:06 +0000944 def try_protocol_combo(server_protocol, client_protocol, expect_success,
945 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000946 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000948 certtype = {
949 ssl.CERT_NONE: "CERT_NONE",
950 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
951 ssl.CERT_REQUIRED: "CERT_REQUIRED",
952 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000953 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000954 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 sys.stdout.write(formatstr %
956 (ssl.get_protocol_name(client_protocol),
957 ssl.get_protocol_name(server_protocol),
958 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000959 client_context = ssl.SSLContext(client_protocol)
960 client_context.options = ssl.OP_ALL | client_options
961 server_context = ssl.SSLContext(server_protocol)
962 server_context.options = ssl.OP_ALL | server_options
963 for ctx in (client_context, server_context):
964 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000965 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
966 # will send an SSLv3 hello (rather than SSLv2) starting from
967 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000968 ctx.set_ciphers("ALL")
969 ctx.load_cert_chain(CERTFILE)
970 ctx.load_verify_locations(CERTFILE)
971 try:
972 server_params_test(client_context, server_context,
973 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000974 # Protocol mismatch can result in either an SSLError, or a
975 # "Connection reset by peer" error.
976 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000977 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000979 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000980 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000981 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000982 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000983 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000984 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000985 "Client protocol %s succeeded with server protocol %s!"
986 % (ssl.get_protocol_name(client_protocol),
987 ssl.get_protocol_name(server_protocol)))
988
989
Bill Janssen6e027db2007-11-15 22:23:56 +0000990 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991
Antoine Pitrou23df4832010-08-04 17:14:06 +0000992 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000993 def test_echo(self):
994 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000995 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000996 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000997 for protocol in PROTOCOLS:
998 context = ssl.SSLContext(protocol)
999 context.load_cert_chain(CERTFILE)
1000 server_params_test(context, context,
1001 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002
Antoine Pitrou480a1242010-04-28 21:37:09 +00001003 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001004 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001005 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001006 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1007 context.verify_mode = ssl.CERT_REQUIRED
1008 context.load_verify_locations(CERTFILE)
1009 context.load_cert_chain(CERTFILE)
1010 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001011 flag = threading.Event()
1012 server.start(flag)
1013 # wait for it to start
1014 flag.wait()
1015 # try to connect
1016 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001017 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001018 s.connect((HOST, server.port))
1019 cert = s.getpeercert()
1020 self.assertTrue(cert, "Can't get peer certificate.")
1021 cipher = s.cipher()
1022 if support.verbose:
1023 sys.stdout.write(pprint.pformat(cert) + '\n')
1024 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1025 if 'subject' not in cert:
1026 self.fail("No subject field in certificate: %s." %
1027 pprint.pformat(cert))
1028 if ((('organizationName', 'Python Software Foundation'),)
1029 not in cert['subject']):
1030 self.fail(
1031 "Missing or invalid 'organizationName' field in certificate subject; "
1032 "should be 'Python Software Foundation'.")
1033 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 finally:
1035 server.stop()
1036 server.join()
1037
Antoine Pitrou480a1242010-04-28 21:37:09 +00001038 def test_empty_cert(self):
1039 """Connecting with an empty cert file"""
1040 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1041 "nullcert.pem"))
1042 def test_malformed_cert(self):
1043 """Connecting with a badly formatted certificate (syntax error)"""
1044 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1045 "badcert.pem"))
1046 def test_nonexisting_cert(self):
1047 """Connecting with a non-existing cert file"""
1048 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1049 "wrongcert.pem"))
1050 def test_malformed_key(self):
1051 """Connecting with a badly formatted key (syntax error)"""
1052 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1053 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001054
Antoine Pitrou480a1242010-04-28 21:37:09 +00001055 def test_rude_shutdown(self):
1056 """A brutal shutdown of an SSL server should raise an IOError
1057 in the client when attempting handshake.
1058 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001059 listener_ready = threading.Event()
1060 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001061
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001062 s = socket.socket()
1063 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001064
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001065 # `listener` runs in a thread. It sits in an accept() until
1066 # the main thread connects. Then it rudely closes the socket,
1067 # and sets Event `listener_gone` to let the main thread know
1068 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001069 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001070 s.listen(5)
1071 listener_ready.set()
1072 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001073 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001074 listener_gone.set()
1075
1076 def connector():
1077 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001078 c = socket.socket()
1079 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001080 listener_gone.wait()
1081 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001082 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001083 except IOError:
1084 pass
1085 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001086 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001087
1088 t = threading.Thread(target=listener)
1089 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001090 try:
1091 connector()
1092 finally:
1093 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001094
Antoine Pitrou23df4832010-08-04 17:14:06 +00001095 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001096 def test_protocol_sslv2(self):
1097 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001098 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001099 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001100 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1101 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1102 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1103 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1104 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1105 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001106 # SSLv23 client with specific SSL options
1107 if no_sslv2_implies_sslv3_hello():
1108 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1109 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1110 client_options=ssl.OP_NO_SSLv2)
1111 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1112 client_options=ssl.OP_NO_SSLv3)
1113 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1114 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001115
Antoine Pitrou23df4832010-08-04 17:14:06 +00001116 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001117 def test_protocol_sslv23(self):
1118 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001119 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001120 sys.stdout.write("\n")
1121 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001122 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001123 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001124 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001125 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001126 sys.stdout.write(
1127 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1128 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001129 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1130 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1131 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001132
Antoine Pitrou480a1242010-04-28 21:37:09 +00001133 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1134 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1135 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001136
Antoine Pitrou480a1242010-04-28 21:37:09 +00001137 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1138 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1139 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140
Antoine Pitroub5218772010-05-21 09:56:06 +00001141 # Server with specific SSL options
1142 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1143 server_options=ssl.OP_NO_SSLv3)
1144 # Will choose TLSv1
1145 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1146 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1147 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1148 server_options=ssl.OP_NO_TLSv1)
1149
1150
Antoine Pitrou23df4832010-08-04 17:14:06 +00001151 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 def test_protocol_sslv3(self):
1153 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001154 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001155 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001156 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1157 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1158 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1159 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1160 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1161 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001162 if no_sslv2_implies_sslv3_hello():
1163 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1164 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1165 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166
Antoine Pitrou23df4832010-08-04 17:14:06 +00001167 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001168 def test_protocol_tlsv1(self):
1169 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001170 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001171 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001172 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1173 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1174 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1175 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1176 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1177 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001178
Antoine Pitrou480a1242010-04-28 21:37:09 +00001179 def test_starttls(self):
1180 """Switching from clear text to encrypted and back again."""
1181 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 +00001182
Trent Nelson78520002008-04-10 20:54:35 +00001183 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001184 ssl_version=ssl.PROTOCOL_TLSv1,
1185 starttls_server=True,
1186 chatty=True,
1187 connectionchatty=True)
1188 flag = threading.Event()
1189 server.start(flag)
1190 # wait for it to start
1191 flag.wait()
1192 # try to connect
1193 wrapped = False
1194 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001195 s = socket.socket()
1196 s.setblocking(1)
1197 s.connect((HOST, server.port))
1198 if support.verbose:
1199 sys.stdout.write("\n")
1200 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001201 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001202 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001204 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001206 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001207 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001208 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001209 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001210 msg = outdata.strip().lower()
1211 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1212 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001213 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001214 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001215 " client: read %r from server, starting TLS...\n"
1216 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001217 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1218 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001219 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1220 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001221 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001222 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001223 " client: read %r from server, ending TLS...\n"
1224 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001225 s = conn.unwrap()
1226 wrapped = False
1227 else:
1228 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001229 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001230 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001231 if support.verbose:
1232 sys.stdout.write(" client: closing connection.\n")
1233 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001234 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001235 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001236 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001237 if wrapped:
1238 conn.close()
1239 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001240 s.close()
1241 finally:
1242 server.stop()
1243 server.join()
1244
Antoine Pitrou480a1242010-04-28 21:37:09 +00001245 def test_socketserver(self):
1246 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001247 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001248 flag = threading.Event()
1249 server.start(flag)
1250 # wait for it to start
1251 flag.wait()
1252 # try to connect
1253 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001254 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001255 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001256 with open(CERTFILE, 'rb') as f:
1257 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001258 d2 = ''
1259 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001260 url = 'https://%s:%d/%s' % (
1261 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001262 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001263 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001264 if dlen and (int(dlen) > 0):
1265 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001266 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001267 sys.stdout.write(
1268 " client: read %d bytes from remote server '%s'\n"
1269 % (len(d2), server))
1270 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001271 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001272 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001273 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001274 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001275 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001276 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001277 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001278 server.join()
1279
Antoine Pitrou480a1242010-04-28 21:37:09 +00001280 def test_asyncore_server(self):
1281 """Check the example asyncore integration."""
1282 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001283
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001284 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001285 sys.stdout.write("\n")
1286
Antoine Pitrou480a1242010-04-28 21:37:09 +00001287 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001288 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001289 flag = threading.Event()
1290 server.start(flag)
1291 # wait for it to start
1292 flag.wait()
1293 # try to connect
1294 try:
1295 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001296 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001297 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001298 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001299 " client: sending %r...\n" % indata)
1300 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001301 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001302 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001303 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001304 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001305 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001306 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1307 % (outdata[:20], len(outdata),
1308 indata[:20].lower(), len(indata)))
1309 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001310 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001311 sys.stdout.write(" client: closing connection.\n")
1312 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001313 if support.verbose:
1314 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001315 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001316 if support.verbose:
1317 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001318 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001319 if support.verbose:
1320 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001321 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001322 if support.verbose:
1323 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001324
Antoine Pitrou480a1242010-04-28 21:37:09 +00001325 def test_recv_send(self):
1326 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001327 if support.verbose:
1328 sys.stdout.write("\n")
1329
1330 server = ThreadedEchoServer(CERTFILE,
1331 certreqs=ssl.CERT_NONE,
1332 ssl_version=ssl.PROTOCOL_TLSv1,
1333 cacerts=CERTFILE,
1334 chatty=True,
1335 connectionchatty=False)
1336 flag = threading.Event()
1337 server.start(flag)
1338 # wait for it to start
1339 flag.wait()
1340 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001341 s = ssl.wrap_socket(socket.socket(),
1342 server_side=False,
1343 certfile=CERTFILE,
1344 ca_certs=CERTFILE,
1345 cert_reqs=ssl.CERT_NONE,
1346 ssl_version=ssl.PROTOCOL_TLSv1)
1347 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001348 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001349 # helper methods for standardising recv* method signatures
1350 def _recv_into():
1351 b = bytearray(b"\0"*100)
1352 count = s.recv_into(b)
1353 return b[:count]
1354
1355 def _recvfrom_into():
1356 b = bytearray(b"\0"*100)
1357 count, addr = s.recvfrom_into(b)
1358 return b[:count]
1359
1360 # (name, method, whether to expect success, *args)
1361 send_methods = [
1362 ('send', s.send, True, []),
1363 ('sendto', s.sendto, False, ["some.address"]),
1364 ('sendall', s.sendall, True, []),
1365 ]
1366 recv_methods = [
1367 ('recv', s.recv, True, []),
1368 ('recvfrom', s.recvfrom, False, ["some.address"]),
1369 ('recv_into', _recv_into, True, []),
1370 ('recvfrom_into', _recvfrom_into, False, []),
1371 ]
1372 data_prefix = "PREFIX_"
1373
1374 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001375 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001376 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001377 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001378 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001380 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001381 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001382 "<<{outdata:r}>> ({nout:d}) received; "
1383 "expected <<{indata:r}>> ({nin:d})\n".format(
1384 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001385 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001386 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001387 )
1388 )
1389 except ValueError as e:
1390 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001391 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001392 "Failed to send with method <<{name:s}>>; "
1393 "expected to succeed.\n".format(name=meth_name)
1394 )
1395 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001396 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001397 "Method <<{name:s}>> failed with unexpected "
1398 "exception message: {exp:s}\n".format(
1399 name=meth_name, exp=e
1400 )
1401 )
1402
1403 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001404 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001405 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001406 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001407 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001408 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001409 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001410 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001411 "<<{outdata:r}>> ({nout:d}) received; "
1412 "expected <<{indata:r}>> ({nin:d})\n".format(
1413 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001414 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001415 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001416 )
1417 )
1418 except ValueError as e:
1419 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001420 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001421 "Failed to receive with method <<{name:s}>>; "
1422 "expected to succeed.\n".format(name=meth_name)
1423 )
1424 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001425 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001426 "Method <<{name:s}>> failed with unexpected "
1427 "exception message: {exp:s}\n".format(
1428 name=meth_name, exp=e
1429 )
1430 )
1431 # consume data
1432 s.read()
1433
Antoine Pitrou480a1242010-04-28 21:37:09 +00001434 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001435 s.close()
1436 finally:
1437 server.stop()
1438 server.join()
1439
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001440 def test_handshake_timeout(self):
1441 # Issue #5103: SSL handshake must respect the socket timeout
1442 server = socket.socket(socket.AF_INET)
1443 host = "127.0.0.1"
1444 port = support.bind_port(server)
1445 started = threading.Event()
1446 finish = False
1447
1448 def serve():
1449 server.listen(5)
1450 started.set()
1451 conns = []
1452 while not finish:
1453 r, w, e = select.select([server], [], [], 0.1)
1454 if server in r:
1455 # Let the socket hang around rather than having
1456 # it closed by garbage collection.
1457 conns.append(server.accept()[0])
1458
1459 t = threading.Thread(target=serve)
1460 t.start()
1461 started.wait()
1462
1463 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001464 try:
1465 c = socket.socket(socket.AF_INET)
1466 c.settimeout(0.2)
1467 c.connect((host, port))
1468 # Will attempt handshake and time out
1469 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1470 ssl.wrap_socket, c)
1471 finally:
1472 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001473 try:
1474 c = socket.socket(socket.AF_INET)
1475 c = ssl.wrap_socket(c)
1476 c.settimeout(0.2)
1477 # Will attempt handshake and time out
1478 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1479 c.connect, (host, port))
1480 finally:
1481 c.close()
1482 finally:
1483 finish = True
1484 t.join()
1485 server.close()
1486
Bill Janssen58afe4c2008-09-08 16:45:19 +00001487
Thomas Woutersed03b412007-08-28 21:37:11 +00001488def test_main(verbose=False):
1489 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001490 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001491
Antoine Pitrou15cee622010-08-04 16:45:21 +00001492 if support.verbose:
1493 plats = {
1494 'Linux': platform.linux_distribution,
1495 'Mac': platform.mac_ver,
1496 'Windows': platform.win32_ver,
1497 }
1498 for name, func in plats.items():
1499 plat = func()
1500 if plat and plat[0]:
1501 plat = '%s %r' % (name, plat)
1502 break
1503 else:
1504 plat = repr(platform.platform())
1505 print("test_ssl: testing with %r %r" %
1506 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1507 print(" under %s" % plat)
1508
Antoine Pitrou152efa22010-05-16 18:19:27 +00001509 for filename in [
1510 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1511 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1512 BADCERT, BADKEY, EMPTYCERT]:
1513 if not os.path.exists(filename):
1514 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001515
Antoine Pitrou152efa22010-05-16 18:19:27 +00001516 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001517
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001518 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001519 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001520
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001521 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001522 thread_info = support.threading_setup()
1523 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001524 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001525
Antoine Pitrou480a1242010-04-28 21:37:09 +00001526 try:
1527 support.run_unittest(*tests)
1528 finally:
1529 if _have_threads:
1530 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001531
1532if __name__ == "__main__":
1533 test_main()