blob: b96c86847f46af1ced22c2f50b7360670a2cb853 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Jeremy Hylton1afc1692008-06-18 20:49:58 +000014import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000029else:
30 PROTOCOLS = [
31 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
32 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
33 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000034
Benjamin Petersonee8712c2008-05-20 21:35:26 +000035HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
37data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038
39CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
54
Thomas Woutersed03b412007-08-28 21:37:11 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056def handle_error(prefix):
57 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000059 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitroub5218772010-05-21 09:56:06 +000061def can_clear_options():
62 # 0.9.8m or higher
63 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
64
65def no_sslv2_implies_sslv3_hello():
66 # 0.9.7h or higher
67 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
68
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou23df4832010-08-04 17:14:06 +000070# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
71def skip_if_broken_ubuntu_ssl(func):
72 @functools.wraps(func)
73 def f(*args, **kwargs):
74 try:
75 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
76 except ssl.SSLError:
77 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
78 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
79 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
80 return func(*args, **kwargs)
81 return f
82
83
Antoine Pitrou152efa22010-05-16 18:19:27 +000084class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Antoine Pitrou480a1242010-04-28 21:37:09 +000086 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 ssl.PROTOCOL_SSLv2
88 ssl.PROTOCOL_SSLv23
89 ssl.PROTOCOL_SSLv3
90 ssl.PROTOCOL_TLSv1
91 ssl.CERT_NONE
92 ssl.CERT_OPTIONAL
93 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000097 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 sys.stdout.write("\n RAND_status is %d (%s)\n"
99 % (v, (v and "sufficient randomness") or
100 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000101 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102 ssl.RAND_egd(1)
103 except TypeError:
104 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000105 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 print("didn't raise TypeError")
107 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000108
Antoine Pitrou480a1242010-04-28 21:37:09 +0000109 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000110 # note that this uses an 'unofficial' function in _ssl.c,
111 # provided solely for this test, to exercise the certificate
112 # parsing code
113 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000116
Antoine Pitrou480a1242010-04-28 21:37:09 +0000117 def test_DER_to_PEM(self):
118 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
119 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 d1 = ssl.PEM_cert_to_DER_cert(pem)
121 p2 = ssl.DER_cert_to_PEM_cert(d1)
122 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000123 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000124 if not p2.startswith(ssl.PEM_HEADER + '\n'):
125 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
126 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
127 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000129 def test_openssl_version(self):
130 n = ssl.OPENSSL_VERSION_NUMBER
131 t = ssl.OPENSSL_VERSION_INFO
132 s = ssl.OPENSSL_VERSION
133 self.assertIsInstance(n, int)
134 self.assertIsInstance(t, tuple)
135 self.assertIsInstance(s, str)
136 # Some sanity checks follow
137 # >= 0.9
138 self.assertGreaterEqual(n, 0x900000)
139 # < 2.0
140 self.assertLess(n, 0x20000000)
141 major, minor, fix, patch, status = t
142 self.assertGreaterEqual(major, 0)
143 self.assertLess(major, 2)
144 self.assertGreaterEqual(minor, 0)
145 self.assertLess(minor, 256)
146 self.assertGreaterEqual(fix, 0)
147 self.assertLess(fix, 256)
148 self.assertGreaterEqual(patch, 0)
149 self.assertLessEqual(patch, 26)
150 self.assertGreaterEqual(status, 0)
151 self.assertLessEqual(status, 15)
152 # Version string as returned by OpenSSL, the format might change
153 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
154 (s, t))
155
Antoine Pitrou9d543662010-04-23 23:10:32 +0000156 @support.cpython_only
157 def test_refcycle(self):
158 # Issue #7943: an SSL object doesn't create reference cycles with
159 # itself.
160 s = socket.socket(socket.AF_INET)
161 ss = ssl.wrap_socket(s)
162 wr = weakref.ref(ss)
163 del ss
164 self.assertEqual(wr(), None)
165
Antoine Pitrou40f08742010-04-24 22:04:40 +0000166 def test_timeout(self):
167 # Issue #8524: when creating an SSL socket, the timeout of the
168 # original socket should be retained.
169 for timeout in (None, 0.0, 5.0):
170 s = socket.socket(socket.AF_INET)
171 s.settimeout(timeout)
172 ss = ssl.wrap_socket(s)
173 self.assertEqual(timeout, ss.gettimeout())
174
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000175 def test_errors(self):
176 sock = socket.socket()
177 with self.assertRaisesRegexp(ValueError, "certfile must be specified"):
178 ssl.wrap_socket(sock, server_side=True)
179 ssl.wrap_socket(sock, server_side=True, certfile="")
180 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
181 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
182 s.connect, (HOST, 8080))
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000183 with self.assertRaises(IOError) as err:
184 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT)
185 self.assertEqual(err.errno, errno.ENOENT)
186 # XXX - temporarily disabled as per issue #9711
187 #with self.assertRaises(IOError) as err:
188 # ssl.wrap_socket(socket.socket(), keyfile=WRONGCERT)
189 # self.assertEqual(err.errno, errno.ENOENT)
190 with self.assertRaises(IOError) as err:
191 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT, keyfile=WRONGCERT)
192 self.assertEqual(err.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000193
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000194
Antoine Pitrou152efa22010-05-16 18:19:27 +0000195class ContextTests(unittest.TestCase):
196
Antoine Pitrou23df4832010-08-04 17:14:06 +0000197 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000198 def test_constructor(self):
199 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
200 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
201 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
202 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
203 self.assertRaises(TypeError, ssl.SSLContext)
204 self.assertRaises(ValueError, ssl.SSLContext, -1)
205 self.assertRaises(ValueError, ssl.SSLContext, 42)
206
Antoine Pitrou23df4832010-08-04 17:14:06 +0000207 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000208 def test_protocol(self):
209 for proto in PROTOCOLS:
210 ctx = ssl.SSLContext(proto)
211 self.assertEqual(ctx.protocol, proto)
212
213 def test_ciphers(self):
214 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
215 ctx.set_ciphers("ALL")
216 ctx.set_ciphers("DEFAULT")
217 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000218 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000219
Antoine Pitrou23df4832010-08-04 17:14:06 +0000220 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000221 def test_options(self):
222 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
223 # OP_ALL is the default value
224 self.assertEqual(ssl.OP_ALL, ctx.options)
225 ctx.options |= ssl.OP_NO_SSLv2
226 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
227 ctx.options)
228 ctx.options |= ssl.OP_NO_SSLv3
229 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
230 ctx.options)
231 if can_clear_options():
232 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
233 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
234 ctx.options)
235 ctx.options = 0
236 self.assertEqual(0, ctx.options)
237 else:
238 with self.assertRaises(ValueError):
239 ctx.options = 0
240
Antoine Pitrou152efa22010-05-16 18:19:27 +0000241 def test_verify(self):
242 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
243 # Default value
244 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
245 ctx.verify_mode = ssl.CERT_OPTIONAL
246 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
247 ctx.verify_mode = ssl.CERT_REQUIRED
248 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
249 ctx.verify_mode = ssl.CERT_NONE
250 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
251 with self.assertRaises(TypeError):
252 ctx.verify_mode = None
253 with self.assertRaises(ValueError):
254 ctx.verify_mode = 42
255
256 def test_load_cert_chain(self):
257 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
258 # Combined key and cert in a single file
259 ctx.load_cert_chain(CERTFILE)
260 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
261 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000262 with self.assertRaises(IOError) as err:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000263 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000264 self.assertEqual(err.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000265 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
266 ctx.load_cert_chain(BADCERT)
267 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
268 ctx.load_cert_chain(EMPTYCERT)
269 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000270 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000271 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
272 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
273 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
274 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
275 ctx.load_cert_chain(ONLYCERT)
276 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
277 ctx.load_cert_chain(ONLYKEY)
278 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
279 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
280 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000281 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000282 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
283 ctx.load_cert_chain(CERTFILE, ONLYKEY)
284
285 def test_load_verify_locations(self):
286 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
287 ctx.load_verify_locations(CERTFILE)
288 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
289 ctx.load_verify_locations(BYTES_CERTFILE)
290 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
291 self.assertRaises(TypeError, ctx.load_verify_locations)
292 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000293 with self.assertRaises(IOError) as err:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000294 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000295 self.assertEqual(err.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000296 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
297 ctx.load_verify_locations(BADCERT)
298 ctx.load_verify_locations(CERTFILE, CAPATH)
299 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
300
301
Bill Janssen6e027db2007-11-15 22:23:56 +0000302class NetworkedTests(unittest.TestCase):
Antoine Pitroud151e272010-08-14 16:32:10 +0000303 def setUp(self):
304 self.old_timeout = socket.getdefaulttimeout()
305 socket.setdefaulttimeout(30)
306
307 def tearDown(self):
308 socket.setdefaulttimeout(self.old_timeout)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000309
Antoine Pitrou480a1242010-04-28 21:37:09 +0000310 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000311 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
312 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000313 try:
314 s.connect(("svn.python.org", 443))
315 self.assertEqual({}, s.getpeercert())
316 finally:
317 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000318
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)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000322 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
323 s.connect, ("svn.python.org", 443))
324 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000325
326 # 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))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000332 self.assertTrue(s.getpeercert())
333 finally:
334 s.close()
335
336 def test_connect_with_context(self):
337 # Same as test_connect, but with a separately created context
338 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
339 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
340 s.connect(("svn.python.org", 443))
341 try:
342 self.assertEqual({}, s.getpeercert())
343 finally:
344 s.close()
345 # This should fail because we have no verification certs
346 ctx.verify_mode = ssl.CERT_REQUIRED
347 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
348 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
349 s.connect, ("svn.python.org", 443))
350 s.close()
351 # This should succeed because we specify the root cert
352 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
353 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
354 s.connect(("svn.python.org", 443))
355 try:
356 cert = s.getpeercert()
357 self.assertTrue(cert)
358 finally:
359 s.close()
360
361 def test_connect_capath(self):
362 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000363 # NOTE: the subject hashing algorithm has been changed between
364 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
365 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000366 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000367 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
368 ctx.verify_mode = ssl.CERT_REQUIRED
369 ctx.load_verify_locations(capath=CAPATH)
370 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
371 s.connect(("svn.python.org", 443))
372 try:
373 cert = s.getpeercert()
374 self.assertTrue(cert)
375 finally:
376 s.close()
377 # Same with a bytes `capath` argument
378 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
379 ctx.verify_mode = ssl.CERT_REQUIRED
380 ctx.load_verify_locations(capath=BYTES_CAPATH)
381 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
382 s.connect(("svn.python.org", 443))
383 try:
384 cert = s.getpeercert()
385 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000386 finally:
387 s.close()
388
Antoine Pitroue3220242010-04-24 11:13:53 +0000389 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
390 def test_makefile_close(self):
391 # Issue #5238: creating a file-like object with makefile() shouldn't
392 # delay closing the underlying "real socket" (here tested with its
393 # file descriptor, hence skipping the test under Windows).
394 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
395 ss.connect(("svn.python.org", 443))
396 fd = ss.fileno()
397 f = ss.makefile()
398 f.close()
399 # The fd is still open
400 os.read(fd, 0)
401 # Closing the SSL socket should close the fd too
402 ss.close()
403 gc.collect()
404 with self.assertRaises(OSError) as e:
405 os.read(fd, 0)
406 self.assertEqual(e.exception.errno, errno.EBADF)
407
Antoine Pitrou480a1242010-04-28 21:37:09 +0000408 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000409 s = socket.socket(socket.AF_INET)
410 s.connect(("svn.python.org", 443))
411 s.setblocking(False)
412 s = ssl.wrap_socket(s,
413 cert_reqs=ssl.CERT_NONE,
414 do_handshake_on_connect=False)
415 count = 0
416 while True:
417 try:
418 count += 1
419 s.do_handshake()
420 break
421 except ssl.SSLError as err:
422 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
423 select.select([s], [], [])
424 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
425 select.select([], [s], [])
426 else:
427 raise
428 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000429 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000430 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000431
Antoine Pitrou480a1242010-04-28 21:37:09 +0000432 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000433 pem = ssl.get_server_certificate(("svn.python.org", 443))
434 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000435 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000436
Bill Janssen54cc54c2007-12-14 22:08:56 +0000437 try:
438 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
439 except ssl.SSLError as x:
440 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000441 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000442 sys.stdout.write("%s\n" % x)
443 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000444 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000445
446 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
447 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000448 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000449 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000450 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
451
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000452 def test_ciphers(self):
453 remote = ("svn.python.org", 443)
454 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
455 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
456 s.connect(remote)
457 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
458 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
459 s.connect(remote)
460 # Error checking can happen at instantiation or when connecting
461 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
462 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
463 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
464 s.connect(remote)
465
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000466 def test_algorithms(self):
467 # Issue #8484: all algorithms should be available when verifying a
468 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000469 # SHA256 was added in OpenSSL 0.9.8
470 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
471 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000472 # NOTE: https://sha256.tbs-internet.com is another possible test host
473 remote = ("sha2.hboeck.de", 443)
474 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
475 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
476 cert_reqs=ssl.CERT_REQUIRED,
477 ca_certs=sha256_cert,)
478 with support.transient_internet():
479 try:
480 s.connect(remote)
481 if support.verbose:
482 sys.stdout.write("\nCipher with %r is %r\n" %
483 (remote, s.cipher()))
484 sys.stdout.write("Certificate is:\n%s\n" %
485 pprint.pformat(s.getpeercert()))
486 finally:
487 s.close()
488
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000489
490try:
491 import threading
492except ImportError:
493 _have_threads = False
494else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000495 _have_threads = True
496
497 class ThreadedEchoServer(threading.Thread):
498
499 class ConnectionHandler(threading.Thread):
500
501 """A mildly complicated class, because we want it to work both
502 with and without the SSL wrapper around the socket connection, so
503 that we can test the STARTTLS functionality."""
504
Bill Janssen6e027db2007-11-15 22:23:56 +0000505 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000506 self.server = server
507 self.running = False
508 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000509 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000510 self.sock.setblocking(1)
511 self.sslconn = None
512 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000513 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000514
Antoine Pitrou480a1242010-04-28 21:37:09 +0000515 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000516 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000517 self.sslconn = self.server.context.wrap_socket(
518 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000519 except ssl.SSLError:
520 # XXX Various errors can have happened here, for example
521 # a mismatching protocol version, an invalid certificate,
522 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000523 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000524 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000525 self.running = False
526 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000527 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000529 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000530 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000531 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000532 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000533 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
534 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000535 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000536 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
537 cipher = self.sslconn.cipher()
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(" server: connection cipher is now " + str(cipher) + "\n")
540 return True
541
542 def read(self):
543 if self.sslconn:
544 return self.sslconn.read()
545 else:
546 return self.sock.recv(1024)
547
548 def write(self, bytes):
549 if self.sslconn:
550 return self.sslconn.write(bytes)
551 else:
552 return self.sock.send(bytes)
553
554 def close(self):
555 if self.sslconn:
556 self.sslconn.close()
557 else:
558 self.sock.close()
559
Antoine Pitrou480a1242010-04-28 21:37:09 +0000560 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000561 self.running = True
562 if not self.server.starttls_server:
563 if not self.wrap_conn():
564 return
565 while self.running:
566 try:
567 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000568 stripped = msg.strip()
569 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000570 # eof, so quit this handler
571 self.running = False
572 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000573 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000574 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000575 sys.stdout.write(" server: client closed connection\n")
576 self.close()
577 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000578 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000579 stripped == b'STARTTLS'):
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: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000582 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000583 if not self.wrap_conn():
584 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000585 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000586 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000587 if support.verbose and self.server.connectionchatty:
588 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000589 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000590 self.sock = self.sslconn.unwrap()
591 self.sslconn = None
592 if support.verbose and self.server.connectionchatty:
593 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000594 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000595 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000596 self.server.connectionchatty):
597 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000598 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
599 % (msg, ctype, msg.lower(), ctype))
600 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000601 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000602 if self.server.chatty:
603 handle_error("Test server failure:\n")
604 self.close()
605 self.running = False
606 # normally, we'd just stop here, but for the test
607 # harness, we want to stop the server
608 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000609
Antoine Pitroub5218772010-05-21 09:56:06 +0000610 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000611 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000612 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000613 ciphers=None, context=None):
614 if context:
615 self.context = context
616 else:
617 self.context = ssl.SSLContext(ssl_version
618 if ssl_version is not None
619 else ssl.PROTOCOL_TLSv1)
620 self.context.verify_mode = (certreqs if certreqs is not None
621 else ssl.CERT_NONE)
622 if cacerts:
623 self.context.load_verify_locations(cacerts)
624 if certificate:
625 self.context.load_cert_chain(certificate)
626 if ciphers:
627 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000628 self.chatty = chatty
629 self.connectionchatty = connectionchatty
630 self.starttls_server = starttls_server
631 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000632 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000633 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634 self.active = False
635 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000636 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000637
Antoine Pitrou480a1242010-04-28 21:37:09 +0000638 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 self.flag = flag
640 threading.Thread.start(self)
641
Antoine Pitrou480a1242010-04-28 21:37:09 +0000642 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000643 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000644 self.sock.listen(5)
645 self.active = True
646 if self.flag:
647 # signal an event
648 self.flag.set()
649 while self.active:
650 try:
651 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000652 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000653 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000654 + repr(connaddr) + '\n')
655 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000656 handler.start()
657 except socket.timeout:
658 pass
659 except KeyboardInterrupt:
660 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000661 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662
Antoine Pitrou480a1242010-04-28 21:37:09 +0000663 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000664 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665
Bill Janssen54cc54c2007-12-14 22:08:56 +0000666 class OurHTTPSServer(threading.Thread):
667
668 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000669
670 class HTTPSServer(HTTPServer):
671
672 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000673 HTTPServer.__init__(self, server_address, RequestHandlerClass)
674 # we assume the certfile contains both private key and certificate
675 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000676 self.allow_reuse_address = True
677
Bill Janssen6e027db2007-11-15 22:23:56 +0000678 def __str__(self):
679 return ('<%s %s:%s>' %
680 (self.__class__.__name__,
681 self.server_name,
682 self.server_port))
683
Antoine Pitrou480a1242010-04-28 21:37:09 +0000684 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000685 # override this to wrap socket with SSL
686 sock, addr = self.socket.accept()
687 sslconn = ssl.wrap_socket(sock, server_side=True,
688 certfile=self.certfile)
689 return sslconn, addr
690
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000691 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000692 # need to override translate_path to get a known root,
693 # instead of using os.curdir, since the test could be
694 # run from anywhere
695
696 server_version = "TestHTTPS/1.0"
697
698 root = None
699
700 def translate_path(self, path):
701 """Translate a /-separated PATH to the local filename syntax.
702
703 Components that mean special things to the local file system
704 (e.g. drive or directory names) are ignored. (XXX They should
705 probably be diagnosed.)
706
707 """
708 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000709 path = urllib.parse.urlparse(path)[2]
710 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000711 words = path.split('/')
712 words = filter(None, words)
713 path = self.root
714 for word in words:
715 drive, word = os.path.splitdrive(word)
716 head, word = os.path.split(word)
717 if word in self.root: continue
718 path = os.path.join(path, word)
719 return path
720
721 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000722 # we override this to suppress logging unless "verbose"
723
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000724 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000725 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
726 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000727 self.server.server_port,
728 self.request.cipher(),
729 self.log_date_time_string(),
730 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000731
732
Trent Nelson78520002008-04-10 20:54:35 +0000733 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000734 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000735 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
736 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000737 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
738 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000739 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000740 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000741
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000742 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000743 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000744
Antoine Pitrou480a1242010-04-28 21:37:09 +0000745 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000746 self.flag = flag
747 threading.Thread.start(self)
748
Antoine Pitrou480a1242010-04-28 21:37:09 +0000749 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750 if self.flag:
751 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000752 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000753
Antoine Pitrou480a1242010-04-28 21:37:09 +0000754 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000755 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756
757
Bill Janssen54cc54c2007-12-14 22:08:56 +0000758 class AsyncoreEchoServer(threading.Thread):
759
760 # this one's based on asyncore.dispatcher
761
762 class EchoServer (asyncore.dispatcher):
763
764 class ConnectionHandler (asyncore.dispatcher_with_send):
765
766 def __init__(self, conn, certfile):
767 self.socket = ssl.wrap_socket(conn, server_side=True,
768 certfile=certfile,
769 do_handshake_on_connect=False)
770 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000771 self._ssl_accepting = True
772 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000773
774 def readable(self):
775 if isinstance(self.socket, ssl.SSLSocket):
776 while self.socket.pending() > 0:
777 self.handle_read_event()
778 return True
779
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000780 def _do_ssl_handshake(self):
781 try:
782 self.socket.do_handshake()
783 except ssl.SSLError as err:
784 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
785 ssl.SSL_ERROR_WANT_WRITE):
786 return
787 elif err.args[0] == ssl.SSL_ERROR_EOF:
788 return self.handle_close()
789 raise
790 except socket.error as err:
791 if err.args[0] == errno.ECONNABORTED:
792 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000793 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000794 self._ssl_accepting = False
795
796 def handle_read(self):
797 if self._ssl_accepting:
798 self._do_ssl_handshake()
799 else:
800 data = self.recv(1024)
801 if support.verbose:
802 sys.stdout.write(" server: read %s from client\n" % repr(data))
803 if not data:
804 self.close()
805 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000806 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000807
808 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000809 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000810 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000811 sys.stdout.write(" server: closed connection %s\n" % self.socket)
812
813 def handle_error(self):
814 raise
815
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000816 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000817 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000818 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
819 self.port = support.bind_port(sock, '')
820 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000821 self.listen(5)
822
823 def handle_accept(self):
824 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000825 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000826 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
827 self.ConnectionHandler(sock_obj, self.certfile)
828
829 def handle_error(self):
830 raise
831
Trent Nelson78520002008-04-10 20:54:35 +0000832 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000833 self.flag = None
834 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000835 self.server = self.EchoServer(certfile)
836 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000837 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000838 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000839
840 def __str__(self):
841 return "<%s %s>" % (self.__class__.__name__, self.server)
842
843 def start (self, flag=None):
844 self.flag = flag
845 threading.Thread.start(self)
846
Antoine Pitrou480a1242010-04-28 21:37:09 +0000847 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000848 self.active = True
849 if self.flag:
850 self.flag.set()
851 while self.active:
852 try:
853 asyncore.loop(1)
854 except:
855 pass
856
Antoine Pitrou480a1242010-04-28 21:37:09 +0000857 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000858 self.active = False
859 self.server.close()
860
Antoine Pitrou480a1242010-04-28 21:37:09 +0000861 def bad_cert_test(certfile):
862 """
863 Launch a server with CERT_REQUIRED, and check that trying to
864 connect to it with the given client certificate fails.
865 """
Trent Nelson78520002008-04-10 20:54:35 +0000866 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000867 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000868 cacerts=CERTFILE, chatty=False,
869 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 flag = threading.Event()
871 server.start(flag)
872 # wait for it to start
873 flag.wait()
874 # try to connect
875 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000876 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000877 s = ssl.wrap_socket(socket.socket(),
878 certfile=certfile,
879 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000880 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000882 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000883 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000884 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000885 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000886 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000887 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000888 if x.errno != errno.ENOENT:
889 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000890 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000891 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000893 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000894 finally:
895 server.stop()
896 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000897
Antoine Pitroub5218772010-05-21 09:56:06 +0000898 def server_params_test(client_context, server_context, indata=b"FOO\n",
899 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 """
901 Launch a server, connect a client to it and try various reads
902 and writes.
903 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000904 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000906 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 flag = threading.Event()
908 server.start(flag)
909 # wait for it to start
910 flag.wait()
911 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000913 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000914 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000915 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000916 if connectionchatty:
917 if support.verbose:
918 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000919 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000920 s.write(arg)
921 outdata = s.read()
922 if connectionchatty:
923 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000924 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000925 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000926 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000927 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
928 % (outdata[:20], len(outdata),
929 indata[:20].lower(), len(indata)))
930 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000931 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000932 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000933 sys.stdout.write(" client: closing connection.\n")
934 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 finally:
936 server.stop()
937 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000938
Antoine Pitroub5218772010-05-21 09:56:06 +0000939 def try_protocol_combo(server_protocol, client_protocol, expect_success,
940 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000941 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000942 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000943 certtype = {
944 ssl.CERT_NONE: "CERT_NONE",
945 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
946 ssl.CERT_REQUIRED: "CERT_REQUIRED",
947 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000948 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000949 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000950 sys.stdout.write(formatstr %
951 (ssl.get_protocol_name(client_protocol),
952 ssl.get_protocol_name(server_protocol),
953 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000954 client_context = ssl.SSLContext(client_protocol)
955 client_context.options = ssl.OP_ALL | client_options
956 server_context = ssl.SSLContext(server_protocol)
957 server_context.options = ssl.OP_ALL | server_options
958 for ctx in (client_context, server_context):
959 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000960 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
961 # will send an SSLv3 hello (rather than SSLv2) starting from
962 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000963 ctx.set_ciphers("ALL")
964 ctx.load_cert_chain(CERTFILE)
965 ctx.load_verify_locations(CERTFILE)
966 try:
967 server_params_test(client_context, server_context,
968 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000969 # Protocol mismatch can result in either an SSLError, or a
970 # "Connection reset by peer" error.
971 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000972 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000973 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000974 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000975 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000976 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000977 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000978 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000979 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980 "Client protocol %s succeeded with server protocol %s!"
981 % (ssl.get_protocol_name(client_protocol),
982 ssl.get_protocol_name(server_protocol)))
983
984
Bill Janssen6e027db2007-11-15 22:23:56 +0000985 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986
Antoine Pitrou23df4832010-08-04 17:14:06 +0000987 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000988 def test_echo(self):
989 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000990 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000992 for protocol in PROTOCOLS:
993 context = ssl.SSLContext(protocol)
994 context.load_cert_chain(CERTFILE)
995 server_params_test(context, context,
996 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000997
Antoine Pitrou480a1242010-04-28 21:37:09 +0000998 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000999 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001000 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001001 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1002 context.verify_mode = ssl.CERT_REQUIRED
1003 context.load_verify_locations(CERTFILE)
1004 context.load_cert_chain(CERTFILE)
1005 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001006 flag = threading.Event()
1007 server.start(flag)
1008 # wait for it to start
1009 flag.wait()
1010 # try to connect
1011 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001012 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001013 s.connect((HOST, server.port))
1014 cert = s.getpeercert()
1015 self.assertTrue(cert, "Can't get peer certificate.")
1016 cipher = s.cipher()
1017 if support.verbose:
1018 sys.stdout.write(pprint.pformat(cert) + '\n')
1019 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1020 if 'subject' not in cert:
1021 self.fail("No subject field in certificate: %s." %
1022 pprint.pformat(cert))
1023 if ((('organizationName', 'Python Software Foundation'),)
1024 not in cert['subject']):
1025 self.fail(
1026 "Missing or invalid 'organizationName' field in certificate subject; "
1027 "should be 'Python Software Foundation'.")
1028 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001029 finally:
1030 server.stop()
1031 server.join()
1032
Antoine Pitrou480a1242010-04-28 21:37:09 +00001033 def test_empty_cert(self):
1034 """Connecting with an empty cert file"""
1035 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1036 "nullcert.pem"))
1037 def test_malformed_cert(self):
1038 """Connecting with a badly formatted certificate (syntax error)"""
1039 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1040 "badcert.pem"))
1041 def test_nonexisting_cert(self):
1042 """Connecting with a non-existing cert file"""
1043 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1044 "wrongcert.pem"))
1045 def test_malformed_key(self):
1046 """Connecting with a badly formatted key (syntax error)"""
1047 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1048 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001049
Antoine Pitrou480a1242010-04-28 21:37:09 +00001050 def test_rude_shutdown(self):
1051 """A brutal shutdown of an SSL server should raise an IOError
1052 in the client when attempting handshake.
1053 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001054 listener_ready = threading.Event()
1055 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001056
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001057 s = socket.socket()
1058 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001059
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001060 # `listener` runs in a thread. It sits in an accept() until
1061 # the main thread connects. Then it rudely closes the socket,
1062 # and sets Event `listener_gone` to let the main thread know
1063 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001064 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001065 s.listen(5)
1066 listener_ready.set()
1067 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001068 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001069 listener_gone.set()
1070
1071 def connector():
1072 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001073 c = socket.socket()
1074 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001075 listener_gone.wait()
1076 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001077 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001078 except IOError:
1079 pass
1080 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001081 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001082
1083 t = threading.Thread(target=listener)
1084 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001085 try:
1086 connector()
1087 finally:
1088 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001089
Antoine Pitrou23df4832010-08-04 17:14:06 +00001090 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 def test_protocol_sslv2(self):
1092 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001093 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001094 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001095 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1096 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1097 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1098 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1099 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1100 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001101 # SSLv23 client with specific SSL options
1102 if no_sslv2_implies_sslv3_hello():
1103 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1104 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1105 client_options=ssl.OP_NO_SSLv2)
1106 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1107 client_options=ssl.OP_NO_SSLv3)
1108 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1109 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001110
Antoine Pitrou23df4832010-08-04 17:14:06 +00001111 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001112 def test_protocol_sslv23(self):
1113 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001115 sys.stdout.write("\n")
1116 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001117 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001118 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001119 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001120 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001121 sys.stdout.write(
1122 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1123 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001124 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1125 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1126 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127
Antoine Pitrou480a1242010-04-28 21:37:09 +00001128 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1129 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1130 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001131
Antoine Pitrou480a1242010-04-28 21:37:09 +00001132 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1133 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1134 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001135
Antoine Pitroub5218772010-05-21 09:56:06 +00001136 # Server with specific SSL options
1137 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1138 server_options=ssl.OP_NO_SSLv3)
1139 # Will choose TLSv1
1140 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1141 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1142 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1143 server_options=ssl.OP_NO_TLSv1)
1144
1145
Antoine Pitrou23df4832010-08-04 17:14:06 +00001146 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001147 def test_protocol_sslv3(self):
1148 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001149 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001151 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1152 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1153 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1154 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1155 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1156 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001157 if no_sslv2_implies_sslv3_hello():
1158 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1159 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1160 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001161
Antoine Pitrou23df4832010-08-04 17:14:06 +00001162 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001163 def test_protocol_tlsv1(self):
1164 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001165 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001167 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1168 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1169 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1170 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1171 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1172 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001173
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 def test_starttls(self):
1175 """Switching from clear text to encrypted and back again."""
1176 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 +00001177
Trent Nelson78520002008-04-10 20:54:35 +00001178 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 ssl_version=ssl.PROTOCOL_TLSv1,
1180 starttls_server=True,
1181 chatty=True,
1182 connectionchatty=True)
1183 flag = threading.Event()
1184 server.start(flag)
1185 # wait for it to start
1186 flag.wait()
1187 # try to connect
1188 wrapped = False
1189 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001190 s = socket.socket()
1191 s.setblocking(1)
1192 s.connect((HOST, server.port))
1193 if support.verbose:
1194 sys.stdout.write("\n")
1195 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001196 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001197 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001198 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001199 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001200 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001201 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001202 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001204 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 msg = outdata.strip().lower()
1206 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1207 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001208 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001209 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001210 " client: read %r from server, starting TLS...\n"
1211 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001212 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1213 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001214 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1215 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001216 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001217 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001218 " client: read %r from server, ending TLS...\n"
1219 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001220 s = conn.unwrap()
1221 wrapped = False
1222 else:
1223 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001224 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001225 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001226 if support.verbose:
1227 sys.stdout.write(" client: closing connection.\n")
1228 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001229 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001230 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001232 if wrapped:
1233 conn.close()
1234 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001235 s.close()
1236 finally:
1237 server.stop()
1238 server.join()
1239
Antoine Pitrou480a1242010-04-28 21:37:09 +00001240 def test_socketserver(self):
1241 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001242 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 flag = threading.Event()
1244 server.start(flag)
1245 # wait for it to start
1246 flag.wait()
1247 # try to connect
1248 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001249 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001250 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001251 with open(CERTFILE, 'rb') as f:
1252 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001253 d2 = ''
1254 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001255 url = 'https://%s:%d/%s' % (
1256 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001257 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001258 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001259 if dlen and (int(dlen) > 0):
1260 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001261 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001262 sys.stdout.write(
1263 " client: read %d bytes from remote server '%s'\n"
1264 % (len(d2), server))
1265 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001266 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001267 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001268 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001269 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001270 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001271 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001272 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001273 server.join()
1274
Antoine Pitrou480a1242010-04-28 21:37:09 +00001275 def test_asyncore_server(self):
1276 """Check the example asyncore integration."""
1277 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001278
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001279 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001280 sys.stdout.write("\n")
1281
Antoine Pitrou480a1242010-04-28 21:37:09 +00001282 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001283 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001284 flag = threading.Event()
1285 server.start(flag)
1286 # wait for it to start
1287 flag.wait()
1288 # try to connect
1289 try:
1290 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001291 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001292 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001293 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001294 " client: sending %r...\n" % indata)
1295 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001296 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001297 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001299 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001300 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001301 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1302 % (outdata[:20], len(outdata),
1303 indata[:20].lower(), len(indata)))
1304 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001305 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001306 sys.stdout.write(" client: closing connection.\n")
1307 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001308 if support.verbose:
1309 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001310 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001311 if support.verbose:
1312 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001313 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001314 if support.verbose:
1315 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001316 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001317 if support.verbose:
1318 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001319
Antoine Pitrou480a1242010-04-28 21:37:09 +00001320 def test_recv_send(self):
1321 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001322 if support.verbose:
1323 sys.stdout.write("\n")
1324
1325 server = ThreadedEchoServer(CERTFILE,
1326 certreqs=ssl.CERT_NONE,
1327 ssl_version=ssl.PROTOCOL_TLSv1,
1328 cacerts=CERTFILE,
1329 chatty=True,
1330 connectionchatty=False)
1331 flag = threading.Event()
1332 server.start(flag)
1333 # wait for it to start
1334 flag.wait()
1335 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001336 s = ssl.wrap_socket(socket.socket(),
1337 server_side=False,
1338 certfile=CERTFILE,
1339 ca_certs=CERTFILE,
1340 cert_reqs=ssl.CERT_NONE,
1341 ssl_version=ssl.PROTOCOL_TLSv1)
1342 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001343 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001344 # helper methods for standardising recv* method signatures
1345 def _recv_into():
1346 b = bytearray(b"\0"*100)
1347 count = s.recv_into(b)
1348 return b[:count]
1349
1350 def _recvfrom_into():
1351 b = bytearray(b"\0"*100)
1352 count, addr = s.recvfrom_into(b)
1353 return b[:count]
1354
1355 # (name, method, whether to expect success, *args)
1356 send_methods = [
1357 ('send', s.send, True, []),
1358 ('sendto', s.sendto, False, ["some.address"]),
1359 ('sendall', s.sendall, True, []),
1360 ]
1361 recv_methods = [
1362 ('recv', s.recv, True, []),
1363 ('recvfrom', s.recvfrom, False, ["some.address"]),
1364 ('recv_into', _recv_into, True, []),
1365 ('recvfrom_into', _recvfrom_into, False, []),
1366 ]
1367 data_prefix = "PREFIX_"
1368
1369 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001370 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001371 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001372 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001373 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001374 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001375 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001376 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001377 "<<{outdata:r}>> ({nout:d}) received; "
1378 "expected <<{indata:r}>> ({nin:d})\n".format(
1379 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001380 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001382 )
1383 )
1384 except ValueError as e:
1385 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001386 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001387 "Failed to send with method <<{name:s}>>; "
1388 "expected to succeed.\n".format(name=meth_name)
1389 )
1390 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001391 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001392 "Method <<{name:s}>> failed with unexpected "
1393 "exception message: {exp:s}\n".format(
1394 name=meth_name, exp=e
1395 )
1396 )
1397
1398 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001399 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001400 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001401 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001402 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001403 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001404 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001405 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001406 "<<{outdata:r}>> ({nout:d}) received; "
1407 "expected <<{indata:r}>> ({nin:d})\n".format(
1408 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001409 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001410 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001411 )
1412 )
1413 except ValueError as e:
1414 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001415 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001416 "Failed to receive with method <<{name:s}>>; "
1417 "expected to succeed.\n".format(name=meth_name)
1418 )
1419 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001420 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001421 "Method <<{name:s}>> failed with unexpected "
1422 "exception message: {exp:s}\n".format(
1423 name=meth_name, exp=e
1424 )
1425 )
1426 # consume data
1427 s.read()
1428
Antoine Pitrou480a1242010-04-28 21:37:09 +00001429 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001430 s.close()
1431 finally:
1432 server.stop()
1433 server.join()
1434
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001435 def test_handshake_timeout(self):
1436 # Issue #5103: SSL handshake must respect the socket timeout
1437 server = socket.socket(socket.AF_INET)
1438 host = "127.0.0.1"
1439 port = support.bind_port(server)
1440 started = threading.Event()
1441 finish = False
1442
1443 def serve():
1444 server.listen(5)
1445 started.set()
1446 conns = []
1447 while not finish:
1448 r, w, e = select.select([server], [], [], 0.1)
1449 if server in r:
1450 # Let the socket hang around rather than having
1451 # it closed by garbage collection.
1452 conns.append(server.accept()[0])
1453
1454 t = threading.Thread(target=serve)
1455 t.start()
1456 started.wait()
1457
1458 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001459 try:
1460 c = socket.socket(socket.AF_INET)
1461 c.settimeout(0.2)
1462 c.connect((host, port))
1463 # Will attempt handshake and time out
1464 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1465 ssl.wrap_socket, c)
1466 finally:
1467 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001468 try:
1469 c = socket.socket(socket.AF_INET)
1470 c = ssl.wrap_socket(c)
1471 c.settimeout(0.2)
1472 # Will attempt handshake and time out
1473 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1474 c.connect, (host, port))
1475 finally:
1476 c.close()
1477 finally:
1478 finish = True
1479 t.join()
1480 server.close()
1481
Bill Janssen58afe4c2008-09-08 16:45:19 +00001482
Thomas Woutersed03b412007-08-28 21:37:11 +00001483def test_main(verbose=False):
1484 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001485 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001486
Antoine Pitrou15cee622010-08-04 16:45:21 +00001487 if support.verbose:
1488 plats = {
1489 'Linux': platform.linux_distribution,
1490 'Mac': platform.mac_ver,
1491 'Windows': platform.win32_ver,
1492 }
1493 for name, func in plats.items():
1494 plat = func()
1495 if plat and plat[0]:
1496 plat = '%s %r' % (name, plat)
1497 break
1498 else:
1499 plat = repr(platform.platform())
1500 print("test_ssl: testing with %r %r" %
1501 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1502 print(" under %s" % plat)
1503
Antoine Pitrou152efa22010-05-16 18:19:27 +00001504 for filename in [
1505 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1506 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1507 BADCERT, BADKEY, EMPTYCERT]:
1508 if not os.path.exists(filename):
1509 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001510
Antoine Pitrou152efa22010-05-16 18:19:27 +00001511 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001512
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001513 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001514 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001515
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001516 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001517 thread_info = support.threading_setup()
1518 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001519 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001520
Antoine Pitrou480a1242010-04-28 21:37:09 +00001521 try:
1522 support.run_unittest(*tests)
1523 finally:
1524 if _have_threads:
1525 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001526
1527if __name__ == "__main__":
1528 test_main()