blob: 748406ad8976305fc964bc208891ef98767e53ff [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):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000308
Antoine Pitrou480a1242010-04-28 21:37:09 +0000309 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000310 with support.transient_internet("svn.python.org"):
311 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
312 cert_reqs=ssl.CERT_NONE)
313 try:
314 s.connect(("svn.python.org", 443))
315 self.assertEqual({}, s.getpeercert())
316 finally:
317 s.close()
318
319 # this should fail because we have no verification certs
320 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
321 cert_reqs=ssl.CERT_REQUIRED)
322 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
323 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000324 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000325
Antoine Pitrou350c7222010-09-09 13:31:46 +0000326 # this should succeed because we specify the root cert
327 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
328 cert_reqs=ssl.CERT_REQUIRED,
329 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
330 try:
331 s.connect(("svn.python.org", 443))
332 self.assertTrue(s.getpeercert())
333 finally:
334 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000335
336 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000337 with support.transient_internet("svn.python.org"):
338 # Same as test_connect, but with a separately created context
339 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
340 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
341 s.connect(("svn.python.org", 443))
342 try:
343 self.assertEqual({}, s.getpeercert())
344 finally:
345 s.close()
346 # This should fail because we have no verification certs
347 ctx.verify_mode = ssl.CERT_REQUIRED
348 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
349 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
350 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000351 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000352 # This should succeed because we specify the root cert
353 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
354 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
355 s.connect(("svn.python.org", 443))
356 try:
357 cert = s.getpeercert()
358 self.assertTrue(cert)
359 finally:
360 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000361
362 def test_connect_capath(self):
363 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000364 # NOTE: the subject hashing algorithm has been changed between
365 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
366 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000367 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000368 with support.transient_internet("svn.python.org"):
369 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
370 ctx.verify_mode = ssl.CERT_REQUIRED
371 ctx.load_verify_locations(capath=CAPATH)
372 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
373 s.connect(("svn.python.org", 443))
374 try:
375 cert = s.getpeercert()
376 self.assertTrue(cert)
377 finally:
378 s.close()
379 # Same with a bytes `capath` argument
380 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
381 ctx.verify_mode = ssl.CERT_REQUIRED
382 ctx.load_verify_locations(capath=BYTES_CAPATH)
383 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
384 s.connect(("svn.python.org", 443))
385 try:
386 cert = s.getpeercert()
387 self.assertTrue(cert)
388 finally:
389 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000390
Antoine Pitroue3220242010-04-24 11:13:53 +0000391 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
392 def test_makefile_close(self):
393 # Issue #5238: creating a file-like object with makefile() shouldn't
394 # delay closing the underlying "real socket" (here tested with its
395 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000396 with support.transient_internet("svn.python.org"):
397 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
398 ss.connect(("svn.python.org", 443))
399 fd = ss.fileno()
400 f = ss.makefile()
401 f.close()
402 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000403 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000404 # Closing the SSL socket should close the fd too
405 ss.close()
406 gc.collect()
407 with self.assertRaises(OSError) as e:
408 os.read(fd, 0)
409 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000410
Antoine Pitrou480a1242010-04-28 21:37:09 +0000411 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000412 with support.transient_internet("svn.python.org"):
413 s = socket.socket(socket.AF_INET)
414 s.connect(("svn.python.org", 443))
415 s.setblocking(False)
416 s = ssl.wrap_socket(s,
417 cert_reqs=ssl.CERT_NONE,
418 do_handshake_on_connect=False)
419 count = 0
420 while True:
421 try:
422 count += 1
423 s.do_handshake()
424 break
425 except ssl.SSLError as err:
426 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
427 select.select([s], [], [])
428 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
429 select.select([], [s], [])
430 else:
431 raise
432 s.close()
433 if support.verbose:
434 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000435
Antoine Pitrou480a1242010-04-28 21:37:09 +0000436 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000437 with support.transient_internet("svn.python.org"):
438 pem = ssl.get_server_certificate(("svn.python.org", 443))
439 if not pem:
440 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000441
Antoine Pitrou350c7222010-09-09 13:31:46 +0000442 try:
443 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
444 except ssl.SSLError as x:
445 #should fail
446 if support.verbose:
447 sys.stdout.write("%s\n" % x)
448 else:
449 self.fail("Got server certificate %s for svn.python.org!" % pem)
450
451 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
452 if not pem:
453 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000454 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000455 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000456
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000457 def test_ciphers(self):
458 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000459 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000460 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000461 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000462 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000463 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
464 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
465 s.connect(remote)
466 # Error checking can happen at instantiation or when connecting
467 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
468 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
469 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
470 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000471
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000472 def test_algorithms(self):
473 # Issue #8484: all algorithms should be available when verifying a
474 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000475 # SHA256 was added in OpenSSL 0.9.8
476 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
477 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000478 # NOTE: https://sha256.tbs-internet.com is another possible test host
479 remote = ("sha2.hboeck.de", 443)
480 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000481 with support.transient_internet("sha2.hboeck.de"):
482 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
483 cert_reqs=ssl.CERT_REQUIRED,
484 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000485 try:
486 s.connect(remote)
487 if support.verbose:
488 sys.stdout.write("\nCipher with %r is %r\n" %
489 (remote, s.cipher()))
490 sys.stdout.write("Certificate is:\n%s\n" %
491 pprint.pformat(s.getpeercert()))
492 finally:
493 s.close()
494
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000495
496try:
497 import threading
498except ImportError:
499 _have_threads = False
500else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000501 _have_threads = True
502
503 class ThreadedEchoServer(threading.Thread):
504
505 class ConnectionHandler(threading.Thread):
506
507 """A mildly complicated class, because we want it to work both
508 with and without the SSL wrapper around the socket connection, so
509 that we can test the STARTTLS functionality."""
510
Bill Janssen6e027db2007-11-15 22:23:56 +0000511 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512 self.server = server
513 self.running = False
514 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000515 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000516 self.sock.setblocking(1)
517 self.sslconn = None
518 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000519 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000520
Antoine Pitrou480a1242010-04-28 21:37:09 +0000521 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000522 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000523 self.sslconn = self.server.context.wrap_socket(
524 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000525 except ssl.SSLError:
526 # XXX Various errors can have happened here, for example
527 # a mismatching protocol version, an invalid certificate,
528 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000529 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000530 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000531 self.running = False
532 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000533 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000534 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000535 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000536 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000537 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000538 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000539 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
540 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000541 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000542 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
543 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000544 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000545 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
546 return True
547
548 def read(self):
549 if self.sslconn:
550 return self.sslconn.read()
551 else:
552 return self.sock.recv(1024)
553
554 def write(self, bytes):
555 if self.sslconn:
556 return self.sslconn.write(bytes)
557 else:
558 return self.sock.send(bytes)
559
560 def close(self):
561 if self.sslconn:
562 self.sslconn.close()
563 else:
564 self.sock.close()
565
Antoine Pitrou480a1242010-04-28 21:37:09 +0000566 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000567 self.running = True
568 if not self.server.starttls_server:
569 if not self.wrap_conn():
570 return
571 while self.running:
572 try:
573 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000574 stripped = msg.strip()
575 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000576 # eof, so quit this handler
577 self.running = False
578 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000579 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000580 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000581 sys.stdout.write(" server: client closed connection\n")
582 self.close()
583 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000584 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000585 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000586 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000587 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000588 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000589 if not self.wrap_conn():
590 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000591 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000592 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000593 if support.verbose and self.server.connectionchatty:
594 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000595 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000596 self.sock = self.sslconn.unwrap()
597 self.sslconn = None
598 if support.verbose and self.server.connectionchatty:
599 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000600 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000601 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000602 self.server.connectionchatty):
603 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000604 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
605 % (msg, ctype, msg.lower(), ctype))
606 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000607 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000608 if self.server.chatty:
609 handle_error("Test server failure:\n")
610 self.close()
611 self.running = False
612 # normally, we'd just stop here, but for the test
613 # harness, we want to stop the server
614 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000615
Antoine Pitroub5218772010-05-21 09:56:06 +0000616 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000617 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000618 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000619 ciphers=None, context=None):
620 if context:
621 self.context = context
622 else:
623 self.context = ssl.SSLContext(ssl_version
624 if ssl_version is not None
625 else ssl.PROTOCOL_TLSv1)
626 self.context.verify_mode = (certreqs if certreqs is not None
627 else ssl.CERT_NONE)
628 if cacerts:
629 self.context.load_verify_locations(cacerts)
630 if certificate:
631 self.context.load_cert_chain(certificate)
632 if ciphers:
633 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634 self.chatty = chatty
635 self.connectionchatty = connectionchatty
636 self.starttls_server = starttls_server
637 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000638 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000640 self.active = False
641 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000642 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000643
Antoine Pitrou480a1242010-04-28 21:37:09 +0000644 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645 self.flag = flag
646 threading.Thread.start(self)
647
Antoine Pitrou480a1242010-04-28 21:37:09 +0000648 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000649 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 self.sock.listen(5)
651 self.active = True
652 if self.flag:
653 # signal an event
654 self.flag.set()
655 while self.active:
656 try:
657 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000658 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000659 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000660 + repr(connaddr) + '\n')
661 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 handler.start()
663 except socket.timeout:
664 pass
665 except KeyboardInterrupt:
666 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000667 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000668
Antoine Pitrou480a1242010-04-28 21:37:09 +0000669 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000670 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000671
Bill Janssen54cc54c2007-12-14 22:08:56 +0000672 class OurHTTPSServer(threading.Thread):
673
674 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000675
676 class HTTPSServer(HTTPServer):
677
678 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000679 HTTPServer.__init__(self, server_address, RequestHandlerClass)
680 # we assume the certfile contains both private key and certificate
681 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000682 self.allow_reuse_address = True
683
Bill Janssen6e027db2007-11-15 22:23:56 +0000684 def __str__(self):
685 return ('<%s %s:%s>' %
686 (self.__class__.__name__,
687 self.server_name,
688 self.server_port))
689
Antoine Pitrou480a1242010-04-28 21:37:09 +0000690 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000691 # override this to wrap socket with SSL
692 sock, addr = self.socket.accept()
693 sslconn = ssl.wrap_socket(sock, server_side=True,
694 certfile=self.certfile)
695 return sslconn, addr
696
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000697 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000698 # need to override translate_path to get a known root,
699 # instead of using os.curdir, since the test could be
700 # run from anywhere
701
702 server_version = "TestHTTPS/1.0"
703
704 root = None
705
706 def translate_path(self, path):
707 """Translate a /-separated PATH to the local filename syntax.
708
709 Components that mean special things to the local file system
710 (e.g. drive or directory names) are ignored. (XXX They should
711 probably be diagnosed.)
712
713 """
714 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000715 path = urllib.parse.urlparse(path)[2]
716 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000717 words = path.split('/')
718 words = filter(None, words)
719 path = self.root
720 for word in words:
721 drive, word = os.path.splitdrive(word)
722 head, word = os.path.split(word)
723 if word in self.root: continue
724 path = os.path.join(path, word)
725 return path
726
727 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000728 # we override this to suppress logging unless "verbose"
729
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000730 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000731 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
732 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000733 self.server.server_port,
734 self.request.cipher(),
735 self.log_date_time_string(),
736 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000737
738
Trent Nelson78520002008-04-10 20:54:35 +0000739 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000740 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000741 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
742 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000743 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
744 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000745 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000746 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000747
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000748 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000749 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750
Antoine Pitrou480a1242010-04-28 21:37:09 +0000751 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000752 self.flag = flag
753 threading.Thread.start(self)
754
Antoine Pitrou480a1242010-04-28 21:37:09 +0000755 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756 if self.flag:
757 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000758 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000759
Antoine Pitrou480a1242010-04-28 21:37:09 +0000760 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000761 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000762
763
Bill Janssen54cc54c2007-12-14 22:08:56 +0000764 class AsyncoreEchoServer(threading.Thread):
765
766 # this one's based on asyncore.dispatcher
767
768 class EchoServer (asyncore.dispatcher):
769
770 class ConnectionHandler (asyncore.dispatcher_with_send):
771
772 def __init__(self, conn, certfile):
773 self.socket = ssl.wrap_socket(conn, server_side=True,
774 certfile=certfile,
775 do_handshake_on_connect=False)
776 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000777 self._ssl_accepting = True
778 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000779
780 def readable(self):
781 if isinstance(self.socket, ssl.SSLSocket):
782 while self.socket.pending() > 0:
783 self.handle_read_event()
784 return True
785
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000786 def _do_ssl_handshake(self):
787 try:
788 self.socket.do_handshake()
789 except ssl.SSLError as err:
790 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
791 ssl.SSL_ERROR_WANT_WRITE):
792 return
793 elif err.args[0] == ssl.SSL_ERROR_EOF:
794 return self.handle_close()
795 raise
796 except socket.error as err:
797 if err.args[0] == errno.ECONNABORTED:
798 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000799 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000800 self._ssl_accepting = False
801
802 def handle_read(self):
803 if self._ssl_accepting:
804 self._do_ssl_handshake()
805 else:
806 data = self.recv(1024)
807 if support.verbose:
808 sys.stdout.write(" server: read %s from client\n" % repr(data))
809 if not data:
810 self.close()
811 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000812 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000813
814 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000815 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000816 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000817 sys.stdout.write(" server: closed connection %s\n" % self.socket)
818
819 def handle_error(self):
820 raise
821
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000822 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000823 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000824 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
825 self.port = support.bind_port(sock, '')
826 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000827 self.listen(5)
828
829 def handle_accept(self):
830 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000831 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000832 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
833 self.ConnectionHandler(sock_obj, self.certfile)
834
835 def handle_error(self):
836 raise
837
Trent Nelson78520002008-04-10 20:54:35 +0000838 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000839 self.flag = None
840 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000841 self.server = self.EchoServer(certfile)
842 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000843 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000844 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000845
846 def __str__(self):
847 return "<%s %s>" % (self.__class__.__name__, self.server)
848
849 def start (self, flag=None):
850 self.flag = flag
851 threading.Thread.start(self)
852
Antoine Pitrou480a1242010-04-28 21:37:09 +0000853 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000854 self.active = True
855 if self.flag:
856 self.flag.set()
857 while self.active:
858 try:
859 asyncore.loop(1)
860 except:
861 pass
862
Antoine Pitrou480a1242010-04-28 21:37:09 +0000863 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000864 self.active = False
865 self.server.close()
866
Antoine Pitrou480a1242010-04-28 21:37:09 +0000867 def bad_cert_test(certfile):
868 """
869 Launch a server with CERT_REQUIRED, and check that trying to
870 connect to it with the given client certificate fails.
871 """
Trent Nelson78520002008-04-10 20:54:35 +0000872 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000874 cacerts=CERTFILE, chatty=False,
875 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000876 flag = threading.Event()
877 server.start(flag)
878 # wait for it to start
879 flag.wait()
880 # try to connect
881 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000882 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000883 s = ssl.wrap_socket(socket.socket(),
884 certfile=certfile,
885 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000886 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000887 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000888 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000889 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000890 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000891 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000892 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000893 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000894 if x.errno != errno.ENOENT:
895 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000896 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000897 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000899 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000900 finally:
901 server.stop()
902 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000903
Antoine Pitroub5218772010-05-21 09:56:06 +0000904 def server_params_test(client_context, server_context, indata=b"FOO\n",
905 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000906 """
907 Launch a server, connect a client to it and try various reads
908 and writes.
909 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000910 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000912 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000913 flag = threading.Event()
914 server.start(flag)
915 # wait for it to start
916 flag.wait()
917 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000919 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000920 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000921 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000922 if connectionchatty:
923 if support.verbose:
924 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000925 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000926 s.write(arg)
927 outdata = s.read()
928 if connectionchatty:
929 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000930 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000931 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000932 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000933 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
934 % (outdata[:20], len(outdata),
935 indata[:20].lower(), len(indata)))
936 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000937 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000938 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000939 sys.stdout.write(" client: closing connection.\n")
940 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941 finally:
942 server.stop()
943 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000944
Antoine Pitroub5218772010-05-21 09:56:06 +0000945 def try_protocol_combo(server_protocol, client_protocol, expect_success,
946 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000947 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000948 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000949 certtype = {
950 ssl.CERT_NONE: "CERT_NONE",
951 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
952 ssl.CERT_REQUIRED: "CERT_REQUIRED",
953 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000954 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000955 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000956 sys.stdout.write(formatstr %
957 (ssl.get_protocol_name(client_protocol),
958 ssl.get_protocol_name(server_protocol),
959 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000960 client_context = ssl.SSLContext(client_protocol)
961 client_context.options = ssl.OP_ALL | client_options
962 server_context = ssl.SSLContext(server_protocol)
963 server_context.options = ssl.OP_ALL | server_options
964 for ctx in (client_context, server_context):
965 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000966 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
967 # will send an SSLv3 hello (rather than SSLv2) starting from
968 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000969 ctx.set_ciphers("ALL")
970 ctx.load_cert_chain(CERTFILE)
971 ctx.load_verify_locations(CERTFILE)
972 try:
973 server_params_test(client_context, server_context,
974 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000975 # Protocol mismatch can result in either an SSLError, or a
976 # "Connection reset by peer" error.
977 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000978 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000980 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000981 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000982 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000983 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000984 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000985 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986 "Client protocol %s succeeded with server protocol %s!"
987 % (ssl.get_protocol_name(client_protocol),
988 ssl.get_protocol_name(server_protocol)))
989
990
Bill Janssen6e027db2007-11-15 22:23:56 +0000991 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000992
Antoine Pitrou23df4832010-08-04 17:14:06 +0000993 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000994 def test_echo(self):
995 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000996 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000997 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000998 for protocol in PROTOCOLS:
999 context = ssl.SSLContext(protocol)
1000 context.load_cert_chain(CERTFILE)
1001 server_params_test(context, context,
1002 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003
Antoine Pitrou480a1242010-04-28 21:37:09 +00001004 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001005 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001006 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001007 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1008 context.verify_mode = ssl.CERT_REQUIRED
1009 context.load_verify_locations(CERTFILE)
1010 context.load_cert_chain(CERTFILE)
1011 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001012 flag = threading.Event()
1013 server.start(flag)
1014 # wait for it to start
1015 flag.wait()
1016 # try to connect
1017 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001018 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001019 s.connect((HOST, server.port))
1020 cert = s.getpeercert()
1021 self.assertTrue(cert, "Can't get peer certificate.")
1022 cipher = s.cipher()
1023 if support.verbose:
1024 sys.stdout.write(pprint.pformat(cert) + '\n')
1025 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1026 if 'subject' not in cert:
1027 self.fail("No subject field in certificate: %s." %
1028 pprint.pformat(cert))
1029 if ((('organizationName', 'Python Software Foundation'),)
1030 not in cert['subject']):
1031 self.fail(
1032 "Missing or invalid 'organizationName' field in certificate subject; "
1033 "should be 'Python Software Foundation'.")
1034 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001035 finally:
1036 server.stop()
1037 server.join()
1038
Antoine Pitrou480a1242010-04-28 21:37:09 +00001039 def test_empty_cert(self):
1040 """Connecting with an empty cert file"""
1041 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1042 "nullcert.pem"))
1043 def test_malformed_cert(self):
1044 """Connecting with a badly formatted certificate (syntax error)"""
1045 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1046 "badcert.pem"))
1047 def test_nonexisting_cert(self):
1048 """Connecting with a non-existing cert file"""
1049 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1050 "wrongcert.pem"))
1051 def test_malformed_key(self):
1052 """Connecting with a badly formatted key (syntax error)"""
1053 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1054 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001055
Antoine Pitrou480a1242010-04-28 21:37:09 +00001056 def test_rude_shutdown(self):
1057 """A brutal shutdown of an SSL server should raise an IOError
1058 in the client when attempting handshake.
1059 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001060 listener_ready = threading.Event()
1061 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001062
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001063 s = socket.socket()
1064 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001065
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001066 # `listener` runs in a thread. It sits in an accept() until
1067 # the main thread connects. Then it rudely closes the socket,
1068 # and sets Event `listener_gone` to let the main thread know
1069 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001070 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001071 s.listen(5)
1072 listener_ready.set()
1073 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001074 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001075 listener_gone.set()
1076
1077 def connector():
1078 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001079 c = socket.socket()
1080 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001081 listener_gone.wait()
1082 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001083 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001084 except IOError:
1085 pass
1086 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001087 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001088
1089 t = threading.Thread(target=listener)
1090 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001091 try:
1092 connector()
1093 finally:
1094 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001095
Antoine Pitrou23df4832010-08-04 17:14:06 +00001096 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001097 def test_protocol_sslv2(self):
1098 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001099 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001100 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001101 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1102 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1103 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1104 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1105 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1106 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001107 # SSLv23 client with specific SSL options
1108 if no_sslv2_implies_sslv3_hello():
1109 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1110 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1111 client_options=ssl.OP_NO_SSLv2)
1112 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1113 client_options=ssl.OP_NO_SSLv3)
1114 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1115 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001116
Antoine Pitrou23df4832010-08-04 17:14:06 +00001117 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001118 def test_protocol_sslv23(self):
1119 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001120 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001121 sys.stdout.write("\n")
1122 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001123 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001124 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001126 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127 sys.stdout.write(
1128 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1129 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001130 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1131 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1132 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001133
Antoine Pitrou480a1242010-04-28 21:37:09 +00001134 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1135 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1136 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001137
Antoine Pitrou480a1242010-04-28 21:37:09 +00001138 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1139 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1140 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001141
Antoine Pitroub5218772010-05-21 09:56:06 +00001142 # Server with specific SSL options
1143 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1144 server_options=ssl.OP_NO_SSLv3)
1145 # Will choose TLSv1
1146 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1147 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1148 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1149 server_options=ssl.OP_NO_TLSv1)
1150
1151
Antoine Pitrou23df4832010-08-04 17:14:06 +00001152 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001153 def test_protocol_sslv3(self):
1154 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001155 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001157 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1158 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1159 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1160 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1161 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1162 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001163 if no_sslv2_implies_sslv3_hello():
1164 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1165 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1166 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167
Antoine Pitrou23df4832010-08-04 17:14:06 +00001168 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001169 def test_protocol_tlsv1(self):
1170 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001171 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001172 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1174 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1175 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1176 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1177 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1178 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 def test_starttls(self):
1181 """Switching from clear text to encrypted and back again."""
1182 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 +00001183
Trent Nelson78520002008-04-10 20:54:35 +00001184 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001185 ssl_version=ssl.PROTOCOL_TLSv1,
1186 starttls_server=True,
1187 chatty=True,
1188 connectionchatty=True)
1189 flag = threading.Event()
1190 server.start(flag)
1191 # wait for it to start
1192 flag.wait()
1193 # try to connect
1194 wrapped = False
1195 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001196 s = socket.socket()
1197 s.setblocking(1)
1198 s.connect((HOST, server.port))
1199 if support.verbose:
1200 sys.stdout.write("\n")
1201 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001202 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001203 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001204 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001205 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001206 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001207 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001208 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001209 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001210 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001211 msg = outdata.strip().lower()
1212 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1213 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001214 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001215 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 " client: read %r from server, starting TLS...\n"
1217 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001218 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1219 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001220 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1221 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001222 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001223 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001224 " client: read %r from server, ending TLS...\n"
1225 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001226 s = conn.unwrap()
1227 wrapped = False
1228 else:
1229 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001230 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001232 if support.verbose:
1233 sys.stdout.write(" client: closing connection.\n")
1234 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001235 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001236 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001237 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001238 if wrapped:
1239 conn.close()
1240 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241 s.close()
1242 finally:
1243 server.stop()
1244 server.join()
1245
Antoine Pitrou480a1242010-04-28 21:37:09 +00001246 def test_socketserver(self):
1247 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001248 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001249 flag = threading.Event()
1250 server.start(flag)
1251 # wait for it to start
1252 flag.wait()
1253 # try to connect
1254 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001255 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001256 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001257 with open(CERTFILE, 'rb') as f:
1258 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001259 d2 = ''
1260 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001261 url = 'https://%s:%d/%s' % (
1262 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001263 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001264 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001265 if dlen and (int(dlen) > 0):
1266 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001267 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001268 sys.stdout.write(
1269 " client: read %d bytes from remote server '%s'\n"
1270 % (len(d2), server))
1271 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001272 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001273 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001274 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001275 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001276 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001277 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001278 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001279 server.join()
1280
Antoine Pitrou480a1242010-04-28 21:37:09 +00001281 def test_asyncore_server(self):
1282 """Check the example asyncore integration."""
1283 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001284
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001285 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001286 sys.stdout.write("\n")
1287
Antoine Pitrou480a1242010-04-28 21:37:09 +00001288 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001289 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001290 flag = threading.Event()
1291 server.start(flag)
1292 # wait for it to start
1293 flag.wait()
1294 # try to connect
1295 try:
1296 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001297 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001298 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001299 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001300 " client: sending %r...\n" % indata)
1301 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001302 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001303 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001304 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001305 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001306 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001307 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1308 % (outdata[:20], len(outdata),
1309 indata[:20].lower(), len(indata)))
1310 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001311 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001312 sys.stdout.write(" client: closing connection.\n")
1313 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001314 if support.verbose:
1315 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001316 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001317 if support.verbose:
1318 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001319 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001320 if support.verbose:
1321 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001322 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001323 if support.verbose:
1324 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001325
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 def test_recv_send(self):
1327 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001328 if support.verbose:
1329 sys.stdout.write("\n")
1330
1331 server = ThreadedEchoServer(CERTFILE,
1332 certreqs=ssl.CERT_NONE,
1333 ssl_version=ssl.PROTOCOL_TLSv1,
1334 cacerts=CERTFILE,
1335 chatty=True,
1336 connectionchatty=False)
1337 flag = threading.Event()
1338 server.start(flag)
1339 # wait for it to start
1340 flag.wait()
1341 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001342 s = ssl.wrap_socket(socket.socket(),
1343 server_side=False,
1344 certfile=CERTFILE,
1345 ca_certs=CERTFILE,
1346 cert_reqs=ssl.CERT_NONE,
1347 ssl_version=ssl.PROTOCOL_TLSv1)
1348 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001349 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001350 # helper methods for standardising recv* method signatures
1351 def _recv_into():
1352 b = bytearray(b"\0"*100)
1353 count = s.recv_into(b)
1354 return b[:count]
1355
1356 def _recvfrom_into():
1357 b = bytearray(b"\0"*100)
1358 count, addr = s.recvfrom_into(b)
1359 return b[:count]
1360
1361 # (name, method, whether to expect success, *args)
1362 send_methods = [
1363 ('send', s.send, True, []),
1364 ('sendto', s.sendto, False, ["some.address"]),
1365 ('sendall', s.sendall, True, []),
1366 ]
1367 recv_methods = [
1368 ('recv', s.recv, True, []),
1369 ('recvfrom', s.recvfrom, False, ["some.address"]),
1370 ('recv_into', _recv_into, True, []),
1371 ('recvfrom_into', _recvfrom_into, False, []),
1372 ]
1373 data_prefix = "PREFIX_"
1374
1375 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001377 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001378 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001380 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001381 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001382 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 "<<{outdata:r}>> ({nout:d}) received; "
1384 "expected <<{indata:r}>> ({nin:d})\n".format(
1385 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001386 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001387 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001388 )
1389 )
1390 except ValueError as e:
1391 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001392 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001393 "Failed to send with method <<{name:s}>>; "
1394 "expected to succeed.\n".format(name=meth_name)
1395 )
1396 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001397 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001398 "Method <<{name:s}>> failed with unexpected "
1399 "exception message: {exp:s}\n".format(
1400 name=meth_name, exp=e
1401 )
1402 )
1403
1404 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001405 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001406 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001407 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001408 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001409 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001410 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001411 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001412 "<<{outdata:r}>> ({nout:d}) received; "
1413 "expected <<{indata:r}>> ({nin:d})\n".format(
1414 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001415 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001416 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001417 )
1418 )
1419 except ValueError as e:
1420 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001421 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001422 "Failed to receive with method <<{name:s}>>; "
1423 "expected to succeed.\n".format(name=meth_name)
1424 )
1425 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001426 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001427 "Method <<{name:s}>> failed with unexpected "
1428 "exception message: {exp:s}\n".format(
1429 name=meth_name, exp=e
1430 )
1431 )
1432 # consume data
1433 s.read()
1434
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001436 s.close()
1437 finally:
1438 server.stop()
1439 server.join()
1440
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001441 def test_handshake_timeout(self):
1442 # Issue #5103: SSL handshake must respect the socket timeout
1443 server = socket.socket(socket.AF_INET)
1444 host = "127.0.0.1"
1445 port = support.bind_port(server)
1446 started = threading.Event()
1447 finish = False
1448
1449 def serve():
1450 server.listen(5)
1451 started.set()
1452 conns = []
1453 while not finish:
1454 r, w, e = select.select([server], [], [], 0.1)
1455 if server in r:
1456 # Let the socket hang around rather than having
1457 # it closed by garbage collection.
1458 conns.append(server.accept()[0])
1459
1460 t = threading.Thread(target=serve)
1461 t.start()
1462 started.wait()
1463
1464 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001465 try:
1466 c = socket.socket(socket.AF_INET)
1467 c.settimeout(0.2)
1468 c.connect((host, port))
1469 # Will attempt handshake and time out
1470 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1471 ssl.wrap_socket, c)
1472 finally:
1473 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001474 try:
1475 c = socket.socket(socket.AF_INET)
1476 c = ssl.wrap_socket(c)
1477 c.settimeout(0.2)
1478 # Will attempt handshake and time out
1479 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1480 c.connect, (host, port))
1481 finally:
1482 c.close()
1483 finally:
1484 finish = True
1485 t.join()
1486 server.close()
1487
Bill Janssen58afe4c2008-09-08 16:45:19 +00001488
Thomas Woutersed03b412007-08-28 21:37:11 +00001489def test_main(verbose=False):
1490 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001491 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001492
Antoine Pitrou15cee622010-08-04 16:45:21 +00001493 if support.verbose:
1494 plats = {
1495 'Linux': platform.linux_distribution,
1496 'Mac': platform.mac_ver,
1497 'Windows': platform.win32_ver,
1498 }
1499 for name, func in plats.items():
1500 plat = func()
1501 if plat and plat[0]:
1502 plat = '%s %r' % (name, plat)
1503 break
1504 else:
1505 plat = repr(platform.platform())
1506 print("test_ssl: testing with %r %r" %
1507 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1508 print(" under %s" % plat)
1509
Antoine Pitrou152efa22010-05-16 18:19:27 +00001510 for filename in [
1511 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1512 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1513 BADCERT, BADKEY, EMPTYCERT]:
1514 if not os.path.exists(filename):
1515 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001516
Antoine Pitrou152efa22010-05-16 18:19:27 +00001517 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001518
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001519 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001520 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001521
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001522 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001523 thread_info = support.threading_setup()
1524 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001525 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001526
Antoine Pitrou480a1242010-04-28 21:37:09 +00001527 try:
1528 support.run_unittest(*tests)
1529 finally:
1530 if _have_threads:
1531 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001532
1533if __name__ == "__main__":
1534 test_main()