blob: 1f216abe5ada1c1bfcf18bec6914a0f86b69c12c [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Jeremy Hylton1afc1692008-06-18 20:49:58 +000014import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000029else:
30 PROTOCOLS = [
31 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
32 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
33 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000034
Benjamin Petersonee8712c2008-05-20 21:35:26 +000035HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
37data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038
39CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
54
Thomas Woutersed03b412007-08-28 21:37:11 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056def handle_error(prefix):
57 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000059 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitroub5218772010-05-21 09:56:06 +000061def can_clear_options():
62 # 0.9.8m or higher
63 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
64
65def no_sslv2_implies_sslv3_hello():
66 # 0.9.7h or higher
67 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
68
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou23df4832010-08-04 17:14:06 +000070# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
71def skip_if_broken_ubuntu_ssl(func):
72 @functools.wraps(func)
73 def f(*args, **kwargs):
74 try:
75 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
76 except ssl.SSLError:
77 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
78 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
79 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
80 return func(*args, **kwargs)
81 return f
82
83
Antoine Pitrou152efa22010-05-16 18:19:27 +000084class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Antoine Pitrou480a1242010-04-28 21:37:09 +000086 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 ssl.PROTOCOL_SSLv2
88 ssl.PROTOCOL_SSLv23
89 ssl.PROTOCOL_SSLv3
90 ssl.PROTOCOL_TLSv1
91 ssl.CERT_NONE
92 ssl.CERT_OPTIONAL
93 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000097 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 sys.stdout.write("\n RAND_status is %d (%s)\n"
99 % (v, (v and "sufficient randomness") or
100 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000101 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102 ssl.RAND_egd(1)
103 except TypeError:
104 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000105 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 print("didn't raise TypeError")
107 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000108
Antoine Pitrou480a1242010-04-28 21:37:09 +0000109 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000110 # note that this uses an 'unofficial' function in _ssl.c,
111 # provided solely for this test, to exercise the certificate
112 # parsing code
113 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000116
Antoine Pitrou480a1242010-04-28 21:37:09 +0000117 def test_DER_to_PEM(self):
118 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
119 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 d1 = ssl.PEM_cert_to_DER_cert(pem)
121 p2 = ssl.DER_cert_to_PEM_cert(d1)
122 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000123 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000124 if not p2.startswith(ssl.PEM_HEADER + '\n'):
125 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
126 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
127 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000129 def test_openssl_version(self):
130 n = ssl.OPENSSL_VERSION_NUMBER
131 t = ssl.OPENSSL_VERSION_INFO
132 s = ssl.OPENSSL_VERSION
133 self.assertIsInstance(n, int)
134 self.assertIsInstance(t, tuple)
135 self.assertIsInstance(s, str)
136 # Some sanity checks follow
137 # >= 0.9
138 self.assertGreaterEqual(n, 0x900000)
139 # < 2.0
140 self.assertLess(n, 0x20000000)
141 major, minor, fix, patch, status = t
142 self.assertGreaterEqual(major, 0)
143 self.assertLess(major, 2)
144 self.assertGreaterEqual(minor, 0)
145 self.assertLess(minor, 256)
146 self.assertGreaterEqual(fix, 0)
147 self.assertLess(fix, 256)
148 self.assertGreaterEqual(patch, 0)
149 self.assertLessEqual(patch, 26)
150 self.assertGreaterEqual(status, 0)
151 self.assertLessEqual(status, 15)
152 # Version string as returned by OpenSSL, the format might change
153 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
154 (s, t))
155
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000156 def test_ciphers(self):
157 if not support.is_resource_enabled('network'):
158 return
159 remote = ("svn.python.org", 443)
160 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
161 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
162 s.connect(remote)
163 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
164 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
165 s.connect(remote)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000166 # Error checking can happen at instantiation or when connecting
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000167 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000168 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou30474062010-05-16 23:46:26 +0000169 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000170 s.connect(remote)
171
Antoine Pitrou9d543662010-04-23 23:10:32 +0000172 @support.cpython_only
173 def test_refcycle(self):
174 # Issue #7943: an SSL object doesn't create reference cycles with
175 # itself.
176 s = socket.socket(socket.AF_INET)
177 ss = ssl.wrap_socket(s)
178 wr = weakref.ref(ss)
179 del ss
180 self.assertEqual(wr(), None)
181
Antoine Pitrou40f08742010-04-24 22:04:40 +0000182 def test_timeout(self):
183 # Issue #8524: when creating an SSL socket, the timeout of the
184 # original socket should be retained.
185 for timeout in (None, 0.0, 5.0):
186 s = socket.socket(socket.AF_INET)
187 s.settimeout(timeout)
188 ss = ssl.wrap_socket(s)
189 self.assertEqual(timeout, ss.gettimeout())
190
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000191
Antoine Pitrou152efa22010-05-16 18:19:27 +0000192class ContextTests(unittest.TestCase):
193
Antoine Pitrou23df4832010-08-04 17:14:06 +0000194 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000195 def test_constructor(self):
196 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
197 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
198 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
199 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
200 self.assertRaises(TypeError, ssl.SSLContext)
201 self.assertRaises(ValueError, ssl.SSLContext, -1)
202 self.assertRaises(ValueError, ssl.SSLContext, 42)
203
Antoine Pitrou23df4832010-08-04 17:14:06 +0000204 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000205 def test_protocol(self):
206 for proto in PROTOCOLS:
207 ctx = ssl.SSLContext(proto)
208 self.assertEqual(ctx.protocol, proto)
209
210 def test_ciphers(self):
211 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
212 ctx.set_ciphers("ALL")
213 ctx.set_ciphers("DEFAULT")
214 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000215 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000216
Antoine Pitrou23df4832010-08-04 17:14:06 +0000217 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000218 def test_options(self):
219 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
220 # OP_ALL is the default value
221 self.assertEqual(ssl.OP_ALL, ctx.options)
222 ctx.options |= ssl.OP_NO_SSLv2
223 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
224 ctx.options)
225 ctx.options |= ssl.OP_NO_SSLv3
226 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
227 ctx.options)
228 if can_clear_options():
229 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
230 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
231 ctx.options)
232 ctx.options = 0
233 self.assertEqual(0, ctx.options)
234 else:
235 with self.assertRaises(ValueError):
236 ctx.options = 0
237
Antoine Pitrou152efa22010-05-16 18:19:27 +0000238 def test_verify(self):
239 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
240 # Default value
241 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
242 ctx.verify_mode = ssl.CERT_OPTIONAL
243 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
244 ctx.verify_mode = ssl.CERT_REQUIRED
245 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
246 ctx.verify_mode = ssl.CERT_NONE
247 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
248 with self.assertRaises(TypeError):
249 ctx.verify_mode = None
250 with self.assertRaises(ValueError):
251 ctx.verify_mode = 42
252
253 def test_load_cert_chain(self):
254 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
255 # Combined key and cert in a single file
256 ctx.load_cert_chain(CERTFILE)
257 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
258 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
259 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
260 ctx.load_cert_chain(WRONGCERT)
261 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
262 ctx.load_cert_chain(BADCERT)
263 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
264 ctx.load_cert_chain(EMPTYCERT)
265 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000266 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000267 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
268 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
269 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
270 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
271 ctx.load_cert_chain(ONLYCERT)
272 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
273 ctx.load_cert_chain(ONLYKEY)
274 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
275 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
276 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000277 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000278 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
279 ctx.load_cert_chain(CERTFILE, ONLYKEY)
280
281 def test_load_verify_locations(self):
282 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
283 ctx.load_verify_locations(CERTFILE)
284 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
285 ctx.load_verify_locations(BYTES_CERTFILE)
286 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
287 self.assertRaises(TypeError, ctx.load_verify_locations)
288 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
289 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
290 ctx.load_verify_locations(WRONGCERT)
291 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
292 ctx.load_verify_locations(BADCERT)
293 ctx.load_verify_locations(CERTFILE, CAPATH)
294 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
295
296
Bill Janssen6e027db2007-11-15 22:23:56 +0000297class NetworkedTests(unittest.TestCase):
Antoine Pitroud151e272010-08-14 16:32:10 +0000298 def setUp(self):
299 self.old_timeout = socket.getdefaulttimeout()
300 socket.setdefaulttimeout(30)
301
302 def tearDown(self):
303 socket.setdefaulttimeout(self.old_timeout)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000304
Antoine Pitrou480a1242010-04-28 21:37:09 +0000305 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000306 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
307 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000308 try:
309 s.connect(("svn.python.org", 443))
310 self.assertEqual({}, s.getpeercert())
311 finally:
312 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000313
314 # this should fail because we have no verification certs
315 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
316 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000317 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
318 s.connect, ("svn.python.org", 443))
319 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000320
321 # this should succeed because we specify the root cert
322 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
323 cert_reqs=ssl.CERT_REQUIRED,
324 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
325 try:
326 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000327 self.assertTrue(s.getpeercert())
328 finally:
329 s.close()
330
331 def test_connect_with_context(self):
332 # Same as test_connect, but with a separately created context
333 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
334 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
335 s.connect(("svn.python.org", 443))
336 try:
337 self.assertEqual({}, s.getpeercert())
338 finally:
339 s.close()
340 # This should fail because we have no verification certs
341 ctx.verify_mode = ssl.CERT_REQUIRED
342 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
343 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
344 s.connect, ("svn.python.org", 443))
345 s.close()
346 # This should succeed because we specify the root cert
347 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
348 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
349 s.connect(("svn.python.org", 443))
350 try:
351 cert = s.getpeercert()
352 self.assertTrue(cert)
353 finally:
354 s.close()
355
356 def test_connect_capath(self):
357 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000358 # NOTE: the subject hashing algorithm has been changed between
359 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
360 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000361 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000362 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
363 ctx.verify_mode = ssl.CERT_REQUIRED
364 ctx.load_verify_locations(capath=CAPATH)
365 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
366 s.connect(("svn.python.org", 443))
367 try:
368 cert = s.getpeercert()
369 self.assertTrue(cert)
370 finally:
371 s.close()
372 # Same with a bytes `capath` argument
373 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
374 ctx.verify_mode = ssl.CERT_REQUIRED
375 ctx.load_verify_locations(capath=BYTES_CAPATH)
376 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
377 s.connect(("svn.python.org", 443))
378 try:
379 cert = s.getpeercert()
380 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000381 finally:
382 s.close()
383
Antoine Pitroue3220242010-04-24 11:13:53 +0000384 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
385 def test_makefile_close(self):
386 # Issue #5238: creating a file-like object with makefile() shouldn't
387 # delay closing the underlying "real socket" (here tested with its
388 # file descriptor, hence skipping the test under Windows).
389 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
390 ss.connect(("svn.python.org", 443))
391 fd = ss.fileno()
392 f = ss.makefile()
393 f.close()
394 # The fd is still open
395 os.read(fd, 0)
396 # Closing the SSL socket should close the fd too
397 ss.close()
398 gc.collect()
399 with self.assertRaises(OSError) as e:
400 os.read(fd, 0)
401 self.assertEqual(e.exception.errno, errno.EBADF)
402
Antoine Pitrou480a1242010-04-28 21:37:09 +0000403 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000404 s = socket.socket(socket.AF_INET)
405 s.connect(("svn.python.org", 443))
406 s.setblocking(False)
407 s = ssl.wrap_socket(s,
408 cert_reqs=ssl.CERT_NONE,
409 do_handshake_on_connect=False)
410 count = 0
411 while True:
412 try:
413 count += 1
414 s.do_handshake()
415 break
416 except ssl.SSLError as err:
417 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
418 select.select([s], [], [])
419 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
420 select.select([], [s], [])
421 else:
422 raise
423 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000424 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000425 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000426
Antoine Pitrou480a1242010-04-28 21:37:09 +0000427 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000428 pem = ssl.get_server_certificate(("svn.python.org", 443))
429 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000430 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000431
432 return
433
434 try:
435 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
436 except ssl.SSLError as x:
437 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000438 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000439 sys.stdout.write("%s\n" % x)
440 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000441 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000442
443 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
444 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000445 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000446 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000447 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
448
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000449 def test_algorithms(self):
450 # Issue #8484: all algorithms should be available when verifying a
451 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000452 # SHA256 was added in OpenSSL 0.9.8
453 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
454 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000455 # NOTE: https://sha256.tbs-internet.com is another possible test host
456 remote = ("sha2.hboeck.de", 443)
457 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
458 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
459 cert_reqs=ssl.CERT_REQUIRED,
460 ca_certs=sha256_cert,)
461 with support.transient_internet():
462 try:
463 s.connect(remote)
464 if support.verbose:
465 sys.stdout.write("\nCipher with %r is %r\n" %
466 (remote, s.cipher()))
467 sys.stdout.write("Certificate is:\n%s\n" %
468 pprint.pformat(s.getpeercert()))
469 finally:
470 s.close()
471
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000472
473try:
474 import threading
475except ImportError:
476 _have_threads = False
477else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000478 _have_threads = True
479
480 class ThreadedEchoServer(threading.Thread):
481
482 class ConnectionHandler(threading.Thread):
483
484 """A mildly complicated class, because we want it to work both
485 with and without the SSL wrapper around the socket connection, so
486 that we can test the STARTTLS functionality."""
487
Bill Janssen6e027db2007-11-15 22:23:56 +0000488 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000489 self.server = server
490 self.running = False
491 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000492 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493 self.sock.setblocking(1)
494 self.sslconn = None
495 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000496 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000497
Antoine Pitrou480a1242010-04-28 21:37:09 +0000498 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000499 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000500 self.sslconn = self.server.context.wrap_socket(
501 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000502 except ssl.SSLError:
503 # XXX Various errors can have happened here, for example
504 # a mismatching protocol version, an invalid certificate,
505 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000506 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000507 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000508 self.running = False
509 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000510 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000511 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000513 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000514 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000515 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000516 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
517 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000518 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000519 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
520 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000521 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000522 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
523 return True
524
525 def read(self):
526 if self.sslconn:
527 return self.sslconn.read()
528 else:
529 return self.sock.recv(1024)
530
531 def write(self, bytes):
532 if self.sslconn:
533 return self.sslconn.write(bytes)
534 else:
535 return self.sock.send(bytes)
536
537 def close(self):
538 if self.sslconn:
539 self.sslconn.close()
540 else:
541 self.sock.close()
542
Antoine Pitrou480a1242010-04-28 21:37:09 +0000543 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000544 self.running = True
545 if not self.server.starttls_server:
546 if not self.wrap_conn():
547 return
548 while self.running:
549 try:
550 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000551 stripped = msg.strip()
552 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000553 # eof, so quit this handler
554 self.running = False
555 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000556 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000557 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000558 sys.stdout.write(" server: client closed connection\n")
559 self.close()
560 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000561 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000562 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000563 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000564 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000565 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000566 if not self.wrap_conn():
567 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000568 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000569 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000570 if support.verbose and self.server.connectionchatty:
571 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000572 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000573 self.sock = self.sslconn.unwrap()
574 self.sslconn = None
575 if support.verbose and self.server.connectionchatty:
576 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000577 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000578 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000579 self.server.connectionchatty):
580 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000581 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
582 % (msg, ctype, msg.lower(), ctype))
583 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000584 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000585 if self.server.chatty:
586 handle_error("Test server failure:\n")
587 self.close()
588 self.running = False
589 # normally, we'd just stop here, but for the test
590 # harness, we want to stop the server
591 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592
Antoine Pitroub5218772010-05-21 09:56:06 +0000593 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000594 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000595 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000596 ciphers=None, context=None):
597 if context:
598 self.context = context
599 else:
600 self.context = ssl.SSLContext(ssl_version
601 if ssl_version is not None
602 else ssl.PROTOCOL_TLSv1)
603 self.context.verify_mode = (certreqs if certreqs is not None
604 else ssl.CERT_NONE)
605 if cacerts:
606 self.context.load_verify_locations(cacerts)
607 if certificate:
608 self.context.load_cert_chain(certificate)
609 if ciphers:
610 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000611 self.chatty = chatty
612 self.connectionchatty = connectionchatty
613 self.starttls_server = starttls_server
614 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000615 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000616 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000617 self.active = False
618 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000619 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000620
Antoine Pitrou480a1242010-04-28 21:37:09 +0000621 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000622 self.flag = flag
623 threading.Thread.start(self)
624
Antoine Pitrou480a1242010-04-28 21:37:09 +0000625 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000626 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627 self.sock.listen(5)
628 self.active = True
629 if self.flag:
630 # signal an event
631 self.flag.set()
632 while self.active:
633 try:
634 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000635 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000636 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000637 + repr(connaddr) + '\n')
638 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 handler.start()
640 except socket.timeout:
641 pass
642 except KeyboardInterrupt:
643 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000644 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645
Antoine Pitrou480a1242010-04-28 21:37:09 +0000646 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000647 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000648
Bill Janssen54cc54c2007-12-14 22:08:56 +0000649 class OurHTTPSServer(threading.Thread):
650
651 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000652
653 class HTTPSServer(HTTPServer):
654
655 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000656 HTTPServer.__init__(self, server_address, RequestHandlerClass)
657 # we assume the certfile contains both private key and certificate
658 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000659 self.allow_reuse_address = True
660
Bill Janssen6e027db2007-11-15 22:23:56 +0000661 def __str__(self):
662 return ('<%s %s:%s>' %
663 (self.__class__.__name__,
664 self.server_name,
665 self.server_port))
666
Antoine Pitrou480a1242010-04-28 21:37:09 +0000667 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000668 # override this to wrap socket with SSL
669 sock, addr = self.socket.accept()
670 sslconn = ssl.wrap_socket(sock, server_side=True,
671 certfile=self.certfile)
672 return sslconn, addr
673
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000674 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000675 # need to override translate_path to get a known root,
676 # instead of using os.curdir, since the test could be
677 # run from anywhere
678
679 server_version = "TestHTTPS/1.0"
680
681 root = None
682
683 def translate_path(self, path):
684 """Translate a /-separated PATH to the local filename syntax.
685
686 Components that mean special things to the local file system
687 (e.g. drive or directory names) are ignored. (XXX They should
688 probably be diagnosed.)
689
690 """
691 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000692 path = urllib.parse.urlparse(path)[2]
693 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000694 words = path.split('/')
695 words = filter(None, words)
696 path = self.root
697 for word in words:
698 drive, word = os.path.splitdrive(word)
699 head, word = os.path.split(word)
700 if word in self.root: continue
701 path = os.path.join(path, word)
702 return path
703
704 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 # we override this to suppress logging unless "verbose"
706
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000707 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000708 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
709 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000710 self.server.server_port,
711 self.request.cipher(),
712 self.log_date_time_string(),
713 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000714
715
Trent Nelson78520002008-04-10 20:54:35 +0000716 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000717 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000718 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
719 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000720 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
721 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000722 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000723 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000724
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000725 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000726 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000727
Antoine Pitrou480a1242010-04-28 21:37:09 +0000728 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000729 self.flag = flag
730 threading.Thread.start(self)
731
Antoine Pitrou480a1242010-04-28 21:37:09 +0000732 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000733 if self.flag:
734 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000735 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000736
Antoine Pitrou480a1242010-04-28 21:37:09 +0000737 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000738 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739
740
Bill Janssen54cc54c2007-12-14 22:08:56 +0000741 class AsyncoreEchoServer(threading.Thread):
742
743 # this one's based on asyncore.dispatcher
744
745 class EchoServer (asyncore.dispatcher):
746
747 class ConnectionHandler (asyncore.dispatcher_with_send):
748
749 def __init__(self, conn, certfile):
750 self.socket = ssl.wrap_socket(conn, server_side=True,
751 certfile=certfile,
752 do_handshake_on_connect=False)
753 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000754 self._ssl_accepting = True
755 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000756
757 def readable(self):
758 if isinstance(self.socket, ssl.SSLSocket):
759 while self.socket.pending() > 0:
760 self.handle_read_event()
761 return True
762
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000763 def _do_ssl_handshake(self):
764 try:
765 self.socket.do_handshake()
766 except ssl.SSLError as err:
767 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
768 ssl.SSL_ERROR_WANT_WRITE):
769 return
770 elif err.args[0] == ssl.SSL_ERROR_EOF:
771 return self.handle_close()
772 raise
773 except socket.error as err:
774 if err.args[0] == errno.ECONNABORTED:
775 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000776 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000777 self._ssl_accepting = False
778
779 def handle_read(self):
780 if self._ssl_accepting:
781 self._do_ssl_handshake()
782 else:
783 data = self.recv(1024)
784 if support.verbose:
785 sys.stdout.write(" server: read %s from client\n" % repr(data))
786 if not data:
787 self.close()
788 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000789 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000790
791 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000792 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000793 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000794 sys.stdout.write(" server: closed connection %s\n" % self.socket)
795
796 def handle_error(self):
797 raise
798
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000799 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000800 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000801 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
802 self.port = support.bind_port(sock, '')
803 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000804 self.listen(5)
805
806 def handle_accept(self):
807 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000808 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000809 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
810 self.ConnectionHandler(sock_obj, self.certfile)
811
812 def handle_error(self):
813 raise
814
Trent Nelson78520002008-04-10 20:54:35 +0000815 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000816 self.flag = None
817 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000818 self.server = self.EchoServer(certfile)
819 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000820 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000821 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000822
823 def __str__(self):
824 return "<%s %s>" % (self.__class__.__name__, self.server)
825
826 def start (self, flag=None):
827 self.flag = flag
828 threading.Thread.start(self)
829
Antoine Pitrou480a1242010-04-28 21:37:09 +0000830 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000831 self.active = True
832 if self.flag:
833 self.flag.set()
834 while self.active:
835 try:
836 asyncore.loop(1)
837 except:
838 pass
839
Antoine Pitrou480a1242010-04-28 21:37:09 +0000840 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000841 self.active = False
842 self.server.close()
843
Antoine Pitrou480a1242010-04-28 21:37:09 +0000844 def bad_cert_test(certfile):
845 """
846 Launch a server with CERT_REQUIRED, and check that trying to
847 connect to it with the given client certificate fails.
848 """
Trent Nelson78520002008-04-10 20:54:35 +0000849 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000851 cacerts=CERTFILE, chatty=False,
852 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853 flag = threading.Event()
854 server.start(flag)
855 # wait for it to start
856 flag.wait()
857 # try to connect
858 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000859 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 s = ssl.wrap_socket(socket.socket(),
861 certfile=certfile,
862 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000863 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000864 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000865 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000866 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000867 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000868 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000869 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000871 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 finally:
873 server.stop()
874 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000875
Antoine Pitroub5218772010-05-21 09:56:06 +0000876 def server_params_test(client_context, server_context, indata=b"FOO\n",
877 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000878 """
879 Launch a server, connect a client to it and try various reads
880 and writes.
881 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000882 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000883 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000884 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000885 flag = threading.Event()
886 server.start(flag)
887 # wait for it to start
888 flag.wait()
889 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000890 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000891 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000892 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000893 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000894 if connectionchatty:
895 if support.verbose:
896 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000897 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000898 s.write(arg)
899 outdata = s.read()
900 if connectionchatty:
901 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000902 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000903 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000904 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000905 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
906 % (outdata[:20], len(outdata),
907 indata[:20].lower(), len(indata)))
908 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000909 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000910 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000911 sys.stdout.write(" client: closing connection.\n")
912 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000913 finally:
914 server.stop()
915 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000916
Antoine Pitroub5218772010-05-21 09:56:06 +0000917 def try_protocol_combo(server_protocol, client_protocol, expect_success,
918 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000919 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000920 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000921 certtype = {
922 ssl.CERT_NONE: "CERT_NONE",
923 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
924 ssl.CERT_REQUIRED: "CERT_REQUIRED",
925 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000926 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000927 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000928 sys.stdout.write(formatstr %
929 (ssl.get_protocol_name(client_protocol),
930 ssl.get_protocol_name(server_protocol),
931 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000932 client_context = ssl.SSLContext(client_protocol)
933 client_context.options = ssl.OP_ALL | client_options
934 server_context = ssl.SSLContext(server_protocol)
935 server_context.options = ssl.OP_ALL | server_options
936 for ctx in (client_context, server_context):
937 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000938 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
939 # will send an SSLv3 hello (rather than SSLv2) starting from
940 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000941 ctx.set_ciphers("ALL")
942 ctx.load_cert_chain(CERTFILE)
943 ctx.load_verify_locations(CERTFILE)
944 try:
945 server_params_test(client_context, server_context,
946 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000947 # Protocol mismatch can result in either an SSLError, or a
948 # "Connection reset by peer" error.
949 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000950 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000952 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000953 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000954 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000956 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000957 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000958 "Client protocol %s succeeded with server protocol %s!"
959 % (ssl.get_protocol_name(client_protocol),
960 ssl.get_protocol_name(server_protocol)))
961
962
Bill Janssen6e027db2007-11-15 22:23:56 +0000963 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000964
Antoine Pitrou23df4832010-08-04 17:14:06 +0000965 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000966 def test_echo(self):
967 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000968 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000969 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000970 for protocol in PROTOCOLS:
971 context = ssl.SSLContext(protocol)
972 context.load_cert_chain(CERTFILE)
973 server_params_test(context, context,
974 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975
Antoine Pitrou480a1242010-04-28 21:37:09 +0000976 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000977 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000979 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
980 context.verify_mode = ssl.CERT_REQUIRED
981 context.load_verify_locations(CERTFILE)
982 context.load_cert_chain(CERTFILE)
983 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 flag = threading.Event()
985 server.start(flag)
986 # wait for it to start
987 flag.wait()
988 # try to connect
989 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000990 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000991 s.connect((HOST, server.port))
992 cert = s.getpeercert()
993 self.assertTrue(cert, "Can't get peer certificate.")
994 cipher = s.cipher()
995 if support.verbose:
996 sys.stdout.write(pprint.pformat(cert) + '\n')
997 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
998 if 'subject' not in cert:
999 self.fail("No subject field in certificate: %s." %
1000 pprint.pformat(cert))
1001 if ((('organizationName', 'Python Software Foundation'),)
1002 not in cert['subject']):
1003 self.fail(
1004 "Missing or invalid 'organizationName' field in certificate subject; "
1005 "should be 'Python Software Foundation'.")
1006 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007 finally:
1008 server.stop()
1009 server.join()
1010
Antoine Pitrou480a1242010-04-28 21:37:09 +00001011 def test_empty_cert(self):
1012 """Connecting with an empty cert file"""
1013 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1014 "nullcert.pem"))
1015 def test_malformed_cert(self):
1016 """Connecting with a badly formatted certificate (syntax error)"""
1017 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1018 "badcert.pem"))
1019 def test_nonexisting_cert(self):
1020 """Connecting with a non-existing cert file"""
1021 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1022 "wrongcert.pem"))
1023 def test_malformed_key(self):
1024 """Connecting with a badly formatted key (syntax error)"""
1025 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1026 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027
Antoine Pitrou480a1242010-04-28 21:37:09 +00001028 def test_rude_shutdown(self):
1029 """A brutal shutdown of an SSL server should raise an IOError
1030 in the client when attempting handshake.
1031 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001032 listener_ready = threading.Event()
1033 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001034
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001035 s = socket.socket()
1036 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001037
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001038 # `listener` runs in a thread. It sits in an accept() until
1039 # the main thread connects. Then it rudely closes the socket,
1040 # and sets Event `listener_gone` to let the main thread know
1041 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001042 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001043 s.listen(5)
1044 listener_ready.set()
1045 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001046 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001047 listener_gone.set()
1048
1049 def connector():
1050 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001051 c = socket.socket()
1052 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001053 listener_gone.wait()
1054 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001055 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001056 except IOError:
1057 pass
1058 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001059 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001060
1061 t = threading.Thread(target=listener)
1062 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001063 try:
1064 connector()
1065 finally:
1066 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001067
Antoine Pitrou23df4832010-08-04 17:14:06 +00001068 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001069 def test_protocol_sslv2(self):
1070 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001071 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001072 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001073 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1074 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1075 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1076 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1077 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1078 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001079 # SSLv23 client with specific SSL options
1080 if no_sslv2_implies_sslv3_hello():
1081 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1082 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1083 client_options=ssl.OP_NO_SSLv2)
1084 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1085 client_options=ssl.OP_NO_SSLv3)
1086 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1087 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001088
Antoine Pitrou23df4832010-08-04 17:14:06 +00001089 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001090 def test_protocol_sslv23(self):
1091 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001092 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093 sys.stdout.write("\n")
1094 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001095 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001096 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001097 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001098 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001099 sys.stdout.write(
1100 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1101 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001102 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1103 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1104 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001105
Antoine Pitrou480a1242010-04-28 21:37:09 +00001106 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1107 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1108 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109
Antoine Pitrou480a1242010-04-28 21:37:09 +00001110 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1111 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1112 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001113
Antoine Pitroub5218772010-05-21 09:56:06 +00001114 # Server with specific SSL options
1115 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1116 server_options=ssl.OP_NO_SSLv3)
1117 # Will choose TLSv1
1118 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1119 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1120 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1121 server_options=ssl.OP_NO_TLSv1)
1122
1123
Antoine Pitrou23df4832010-08-04 17:14:06 +00001124 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001125 def test_protocol_sslv3(self):
1126 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001127 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001128 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001129 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1130 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1131 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1132 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1133 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1134 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001135 if no_sslv2_implies_sslv3_hello():
1136 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1137 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1138 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001139
Antoine Pitrou23df4832010-08-04 17:14:06 +00001140 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 def test_protocol_tlsv1(self):
1142 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001143 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1146 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1147 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1148 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1149 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1150 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001151
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 def test_starttls(self):
1153 """Switching from clear text to encrypted and back again."""
1154 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 +00001155
Trent Nelson78520002008-04-10 20:54:35 +00001156 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001157 ssl_version=ssl.PROTOCOL_TLSv1,
1158 starttls_server=True,
1159 chatty=True,
1160 connectionchatty=True)
1161 flag = threading.Event()
1162 server.start(flag)
1163 # wait for it to start
1164 flag.wait()
1165 # try to connect
1166 wrapped = False
1167 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001168 s = socket.socket()
1169 s.setblocking(1)
1170 s.connect((HOST, server.port))
1171 if support.verbose:
1172 sys.stdout.write("\n")
1173 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001174 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001175 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001176 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001177 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001178 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001179 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001180 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001181 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001182 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001183 msg = outdata.strip().lower()
1184 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1185 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001186 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001187 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001188 " client: read %r from server, starting TLS...\n"
1189 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001190 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1191 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001192 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1193 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001194 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001195 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001196 " client: read %r from server, ending TLS...\n"
1197 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001198 s = conn.unwrap()
1199 wrapped = False
1200 else:
1201 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001202 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001204 if support.verbose:
1205 sys.stdout.write(" client: closing connection.\n")
1206 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001207 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001208 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001209 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001210 if wrapped:
1211 conn.close()
1212 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001213 s.close()
1214 finally:
1215 server.stop()
1216 server.join()
1217
Antoine Pitrou480a1242010-04-28 21:37:09 +00001218 def test_socketserver(self):
1219 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001220 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001221 flag = threading.Event()
1222 server.start(flag)
1223 # wait for it to start
1224 flag.wait()
1225 # try to connect
1226 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001227 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001228 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001229 with open(CERTFILE, 'rb') as f:
1230 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 d2 = ''
1232 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001233 url = 'https://%s:%d/%s' % (
1234 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001235 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001236 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001237 if dlen and (int(dlen) > 0):
1238 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001239 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001240 sys.stdout.write(
1241 " client: read %d bytes from remote server '%s'\n"
1242 % (len(d2), server))
1243 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001244 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001245 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001246 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001247 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001248 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001249 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001250 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001251 server.join()
1252
Antoine Pitrou480a1242010-04-28 21:37:09 +00001253 def test_asyncore_server(self):
1254 """Check the example asyncore integration."""
1255 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001256
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001257 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001258 sys.stdout.write("\n")
1259
Antoine Pitrou480a1242010-04-28 21:37:09 +00001260 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001261 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001262 flag = threading.Event()
1263 server.start(flag)
1264 # wait for it to start
1265 flag.wait()
1266 # try to connect
1267 try:
1268 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001269 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001270 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001271 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001272 " client: sending %r...\n" % indata)
1273 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001274 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001275 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001276 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001277 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001278 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001279 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1280 % (outdata[:20], len(outdata),
1281 indata[:20].lower(), len(indata)))
1282 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001283 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001284 sys.stdout.write(" client: closing connection.\n")
1285 s.close()
1286 finally:
1287 server.stop()
1288 server.join()
1289
Antoine Pitrou480a1242010-04-28 21:37:09 +00001290 def test_recv_send(self):
1291 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001292 if support.verbose:
1293 sys.stdout.write("\n")
1294
1295 server = ThreadedEchoServer(CERTFILE,
1296 certreqs=ssl.CERT_NONE,
1297 ssl_version=ssl.PROTOCOL_TLSv1,
1298 cacerts=CERTFILE,
1299 chatty=True,
1300 connectionchatty=False)
1301 flag = threading.Event()
1302 server.start(flag)
1303 # wait for it to start
1304 flag.wait()
1305 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001306 s = ssl.wrap_socket(socket.socket(),
1307 server_side=False,
1308 certfile=CERTFILE,
1309 ca_certs=CERTFILE,
1310 cert_reqs=ssl.CERT_NONE,
1311 ssl_version=ssl.PROTOCOL_TLSv1)
1312 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001313 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001314 # helper methods for standardising recv* method signatures
1315 def _recv_into():
1316 b = bytearray(b"\0"*100)
1317 count = s.recv_into(b)
1318 return b[:count]
1319
1320 def _recvfrom_into():
1321 b = bytearray(b"\0"*100)
1322 count, addr = s.recvfrom_into(b)
1323 return b[:count]
1324
1325 # (name, method, whether to expect success, *args)
1326 send_methods = [
1327 ('send', s.send, True, []),
1328 ('sendto', s.sendto, False, ["some.address"]),
1329 ('sendall', s.sendall, True, []),
1330 ]
1331 recv_methods = [
1332 ('recv', s.recv, True, []),
1333 ('recvfrom', s.recvfrom, False, ["some.address"]),
1334 ('recv_into', _recv_into, True, []),
1335 ('recvfrom_into', _recvfrom_into, False, []),
1336 ]
1337 data_prefix = "PREFIX_"
1338
1339 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001340 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001341 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001342 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001343 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001344 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001345 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001346 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001347 "<<{outdata:r}>> ({nout:d}) received; "
1348 "expected <<{indata:r}>> ({nin:d})\n".format(
1349 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001350 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001351 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001352 )
1353 )
1354 except ValueError as e:
1355 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001356 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001357 "Failed to send with method <<{name:s}>>; "
1358 "expected to succeed.\n".format(name=meth_name)
1359 )
1360 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001361 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001362 "Method <<{name:s}>> failed with unexpected "
1363 "exception message: {exp:s}\n".format(
1364 name=meth_name, exp=e
1365 )
1366 )
1367
1368 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001369 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001370 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001371 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001372 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001373 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001374 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001375 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 "<<{outdata:r}>> ({nout:d}) received; "
1377 "expected <<{indata:r}>> ({nin:d})\n".format(
1378 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001381 )
1382 )
1383 except ValueError as e:
1384 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001385 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001386 "Failed to receive with method <<{name:s}>>; "
1387 "expected to succeed.\n".format(name=meth_name)
1388 )
1389 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001390 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001391 "Method <<{name:s}>> failed with unexpected "
1392 "exception message: {exp:s}\n".format(
1393 name=meth_name, exp=e
1394 )
1395 )
1396 # consume data
1397 s.read()
1398
Antoine Pitrou480a1242010-04-28 21:37:09 +00001399 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001400 s.close()
1401 finally:
1402 server.stop()
1403 server.join()
1404
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001405 def test_handshake_timeout(self):
1406 # Issue #5103: SSL handshake must respect the socket timeout
1407 server = socket.socket(socket.AF_INET)
1408 host = "127.0.0.1"
1409 port = support.bind_port(server)
1410 started = threading.Event()
1411 finish = False
1412
1413 def serve():
1414 server.listen(5)
1415 started.set()
1416 conns = []
1417 while not finish:
1418 r, w, e = select.select([server], [], [], 0.1)
1419 if server in r:
1420 # Let the socket hang around rather than having
1421 # it closed by garbage collection.
1422 conns.append(server.accept()[0])
1423
1424 t = threading.Thread(target=serve)
1425 t.start()
1426 started.wait()
1427
1428 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001429 try:
1430 c = socket.socket(socket.AF_INET)
1431 c.settimeout(0.2)
1432 c.connect((host, port))
1433 # Will attempt handshake and time out
1434 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1435 ssl.wrap_socket, c)
1436 finally:
1437 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001438 try:
1439 c = socket.socket(socket.AF_INET)
1440 c = ssl.wrap_socket(c)
1441 c.settimeout(0.2)
1442 # Will attempt handshake and time out
1443 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1444 c.connect, (host, port))
1445 finally:
1446 c.close()
1447 finally:
1448 finish = True
1449 t.join()
1450 server.close()
1451
Bill Janssen58afe4c2008-09-08 16:45:19 +00001452
Thomas Woutersed03b412007-08-28 21:37:11 +00001453def test_main(verbose=False):
1454 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001455 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001456
Antoine Pitrou15cee622010-08-04 16:45:21 +00001457 if support.verbose:
1458 plats = {
1459 'Linux': platform.linux_distribution,
1460 'Mac': platform.mac_ver,
1461 'Windows': platform.win32_ver,
1462 }
1463 for name, func in plats.items():
1464 plat = func()
1465 if plat and plat[0]:
1466 plat = '%s %r' % (name, plat)
1467 break
1468 else:
1469 plat = repr(platform.platform())
1470 print("test_ssl: testing with %r %r" %
1471 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1472 print(" under %s" % plat)
1473
Antoine Pitrou152efa22010-05-16 18:19:27 +00001474 for filename in [
1475 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1476 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1477 BADCERT, BADKEY, EMPTYCERT]:
1478 if not os.path.exists(filename):
1479 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001480
Antoine Pitrou152efa22010-05-16 18:19:27 +00001481 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001482
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001483 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001484 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001485
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001486 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001487 thread_info = support.threading_setup()
1488 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001489 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001490
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 try:
1492 support.run_unittest(*tests)
1493 finally:
1494 if _have_threads:
1495 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001496
1497if __name__ == "__main__":
1498 test_main()