blob: 9003a82c77f2af4934f8288cffb8d90366258fe0 [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
Bill Janssen54cc54c2007-12-14 22:08:56 +0000432 try:
433 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
434 except ssl.SSLError as x:
435 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000436 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000437 sys.stdout.write("%s\n" % x)
438 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000439 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000440
441 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
442 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000443 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000444 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000445 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
446
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000447 def test_algorithms(self):
448 # Issue #8484: all algorithms should be available when verifying a
449 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000450 # SHA256 was added in OpenSSL 0.9.8
451 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
452 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000453 # NOTE: https://sha256.tbs-internet.com is another possible test host
454 remote = ("sha2.hboeck.de", 443)
455 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
456 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
457 cert_reqs=ssl.CERT_REQUIRED,
458 ca_certs=sha256_cert,)
459 with support.transient_internet():
460 try:
461 s.connect(remote)
462 if support.verbose:
463 sys.stdout.write("\nCipher with %r is %r\n" %
464 (remote, s.cipher()))
465 sys.stdout.write("Certificate is:\n%s\n" %
466 pprint.pformat(s.getpeercert()))
467 finally:
468 s.close()
469
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000470
471try:
472 import threading
473except ImportError:
474 _have_threads = False
475else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000476 _have_threads = True
477
478 class ThreadedEchoServer(threading.Thread):
479
480 class ConnectionHandler(threading.Thread):
481
482 """A mildly complicated class, because we want it to work both
483 with and without the SSL wrapper around the socket connection, so
484 that we can test the STARTTLS functionality."""
485
Bill Janssen6e027db2007-11-15 22:23:56 +0000486 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000487 self.server = server
488 self.running = False
489 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000490 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000491 self.sock.setblocking(1)
492 self.sslconn = None
493 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000494 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000495
Antoine Pitrou480a1242010-04-28 21:37:09 +0000496 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000497 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000498 self.sslconn = self.server.context.wrap_socket(
499 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000500 except ssl.SSLError:
501 # XXX Various errors can have happened here, for example
502 # a mismatching protocol version, an invalid certificate,
503 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000504 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000505 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000506 self.running = False
507 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000508 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000509 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000510 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000511 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000513 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000514 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
515 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000516 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000517 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
518 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000519 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000520 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
521 return True
522
523 def read(self):
524 if self.sslconn:
525 return self.sslconn.read()
526 else:
527 return self.sock.recv(1024)
528
529 def write(self, bytes):
530 if self.sslconn:
531 return self.sslconn.write(bytes)
532 else:
533 return self.sock.send(bytes)
534
535 def close(self):
536 if self.sslconn:
537 self.sslconn.close()
538 else:
539 self.sock.close()
540
Antoine Pitrou480a1242010-04-28 21:37:09 +0000541 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000542 self.running = True
543 if not self.server.starttls_server:
544 if not self.wrap_conn():
545 return
546 while self.running:
547 try:
548 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000549 stripped = msg.strip()
550 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000551 # eof, so quit this handler
552 self.running = False
553 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000554 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000555 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000556 sys.stdout.write(" server: client closed connection\n")
557 self.close()
558 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000559 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000560 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000561 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000562 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000563 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000564 if not self.wrap_conn():
565 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000566 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000567 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000568 if support.verbose and self.server.connectionchatty:
569 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000570 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000571 self.sock = self.sslconn.unwrap()
572 self.sslconn = None
573 if support.verbose and self.server.connectionchatty:
574 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000575 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000576 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000577 self.server.connectionchatty):
578 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000579 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
580 % (msg, ctype, msg.lower(), ctype))
581 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000582 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000583 if self.server.chatty:
584 handle_error("Test server failure:\n")
585 self.close()
586 self.running = False
587 # normally, we'd just stop here, but for the test
588 # harness, we want to stop the server
589 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000590
Antoine Pitroub5218772010-05-21 09:56:06 +0000591 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000592 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000593 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000594 ciphers=None, context=None):
595 if context:
596 self.context = context
597 else:
598 self.context = ssl.SSLContext(ssl_version
599 if ssl_version is not None
600 else ssl.PROTOCOL_TLSv1)
601 self.context.verify_mode = (certreqs if certreqs is not None
602 else ssl.CERT_NONE)
603 if cacerts:
604 self.context.load_verify_locations(cacerts)
605 if certificate:
606 self.context.load_cert_chain(certificate)
607 if ciphers:
608 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000609 self.chatty = chatty
610 self.connectionchatty = connectionchatty
611 self.starttls_server = starttls_server
612 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000613 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000614 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000615 self.active = False
616 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000617 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000618
Antoine Pitrou480a1242010-04-28 21:37:09 +0000619 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000620 self.flag = flag
621 threading.Thread.start(self)
622
Antoine Pitrou480a1242010-04-28 21:37:09 +0000623 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000624 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000625 self.sock.listen(5)
626 self.active = True
627 if self.flag:
628 # signal an event
629 self.flag.set()
630 while self.active:
631 try:
632 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000633 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000635 + repr(connaddr) + '\n')
636 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000637 handler.start()
638 except socket.timeout:
639 pass
640 except KeyboardInterrupt:
641 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000642 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000643
Antoine Pitrou480a1242010-04-28 21:37:09 +0000644 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000646
Bill Janssen54cc54c2007-12-14 22:08:56 +0000647 class OurHTTPSServer(threading.Thread):
648
649 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650
651 class HTTPSServer(HTTPServer):
652
653 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000654 HTTPServer.__init__(self, server_address, RequestHandlerClass)
655 # we assume the certfile contains both private key and certificate
656 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657 self.allow_reuse_address = True
658
Bill Janssen6e027db2007-11-15 22:23:56 +0000659 def __str__(self):
660 return ('<%s %s:%s>' %
661 (self.__class__.__name__,
662 self.server_name,
663 self.server_port))
664
Antoine Pitrou480a1242010-04-28 21:37:09 +0000665 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000666 # override this to wrap socket with SSL
667 sock, addr = self.socket.accept()
668 sslconn = ssl.wrap_socket(sock, server_side=True,
669 certfile=self.certfile)
670 return sslconn, addr
671
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000672 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000673 # need to override translate_path to get a known root,
674 # instead of using os.curdir, since the test could be
675 # run from anywhere
676
677 server_version = "TestHTTPS/1.0"
678
679 root = None
680
681 def translate_path(self, path):
682 """Translate a /-separated PATH to the local filename syntax.
683
684 Components that mean special things to the local file system
685 (e.g. drive or directory names) are ignored. (XXX They should
686 probably be diagnosed.)
687
688 """
689 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000690 path = urllib.parse.urlparse(path)[2]
691 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000692 words = path.split('/')
693 words = filter(None, words)
694 path = self.root
695 for word in words:
696 drive, word = os.path.splitdrive(word)
697 head, word = os.path.split(word)
698 if word in self.root: continue
699 path = os.path.join(path, word)
700 return path
701
702 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000703 # we override this to suppress logging unless "verbose"
704
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000705 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000706 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
707 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000708 self.server.server_port,
709 self.request.cipher(),
710 self.log_date_time_string(),
711 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000712
713
Trent Nelson78520002008-04-10 20:54:35 +0000714 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000715 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000716 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
717 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000718 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
719 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000720 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000721 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000722
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000723 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000724 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000725
Antoine Pitrou480a1242010-04-28 21:37:09 +0000726 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000727 self.flag = flag
728 threading.Thread.start(self)
729
Antoine Pitrou480a1242010-04-28 21:37:09 +0000730 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000731 if self.flag:
732 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000733 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000734
Antoine Pitrou480a1242010-04-28 21:37:09 +0000735 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000736 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000737
738
Bill Janssen54cc54c2007-12-14 22:08:56 +0000739 class AsyncoreEchoServer(threading.Thread):
740
741 # this one's based on asyncore.dispatcher
742
743 class EchoServer (asyncore.dispatcher):
744
745 class ConnectionHandler (asyncore.dispatcher_with_send):
746
747 def __init__(self, conn, certfile):
748 self.socket = ssl.wrap_socket(conn, server_side=True,
749 certfile=certfile,
750 do_handshake_on_connect=False)
751 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000752 self._ssl_accepting = True
753 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000754
755 def readable(self):
756 if isinstance(self.socket, ssl.SSLSocket):
757 while self.socket.pending() > 0:
758 self.handle_read_event()
759 return True
760
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000761 def _do_ssl_handshake(self):
762 try:
763 self.socket.do_handshake()
764 except ssl.SSLError as err:
765 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
766 ssl.SSL_ERROR_WANT_WRITE):
767 return
768 elif err.args[0] == ssl.SSL_ERROR_EOF:
769 return self.handle_close()
770 raise
771 except socket.error as err:
772 if err.args[0] == errno.ECONNABORTED:
773 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000774 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000775 self._ssl_accepting = False
776
777 def handle_read(self):
778 if self._ssl_accepting:
779 self._do_ssl_handshake()
780 else:
781 data = self.recv(1024)
782 if support.verbose:
783 sys.stdout.write(" server: read %s from client\n" % repr(data))
784 if not data:
785 self.close()
786 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000787 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000788
789 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000790 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000791 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000792 sys.stdout.write(" server: closed connection %s\n" % self.socket)
793
794 def handle_error(self):
795 raise
796
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000797 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000798 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000799 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
800 self.port = support.bind_port(sock, '')
801 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000802 self.listen(5)
803
804 def handle_accept(self):
805 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000806 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000807 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
808 self.ConnectionHandler(sock_obj, self.certfile)
809
810 def handle_error(self):
811 raise
812
Trent Nelson78520002008-04-10 20:54:35 +0000813 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000814 self.flag = None
815 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000816 self.server = self.EchoServer(certfile)
817 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000818 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000819 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000820
821 def __str__(self):
822 return "<%s %s>" % (self.__class__.__name__, self.server)
823
824 def start (self, flag=None):
825 self.flag = flag
826 threading.Thread.start(self)
827
Antoine Pitrou480a1242010-04-28 21:37:09 +0000828 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000829 self.active = True
830 if self.flag:
831 self.flag.set()
832 while self.active:
833 try:
834 asyncore.loop(1)
835 except:
836 pass
837
Antoine Pitrou480a1242010-04-28 21:37:09 +0000838 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000839 self.active = False
840 self.server.close()
841
Antoine Pitrou480a1242010-04-28 21:37:09 +0000842 def bad_cert_test(certfile):
843 """
844 Launch a server with CERT_REQUIRED, and check that trying to
845 connect to it with the given client certificate fails.
846 """
Trent Nelson78520002008-04-10 20:54:35 +0000847 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000849 cacerts=CERTFILE, chatty=False,
850 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851 flag = threading.Event()
852 server.start(flag)
853 # wait for it to start
854 flag.wait()
855 # try to connect
856 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000857 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000858 s = ssl.wrap_socket(socket.socket(),
859 certfile=certfile,
860 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000861 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000863 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000864 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000865 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000866 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000867 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000869 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 finally:
871 server.stop()
872 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000873
Antoine Pitroub5218772010-05-21 09:56:06 +0000874 def server_params_test(client_context, server_context, indata=b"FOO\n",
875 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000876 """
877 Launch a server, connect a client to it and try various reads
878 and writes.
879 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000880 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000882 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000883 flag = threading.Event()
884 server.start(flag)
885 # wait for it to start
886 flag.wait()
887 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000888 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000889 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000890 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000891 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000892 if connectionchatty:
893 if support.verbose:
894 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000895 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000896 s.write(arg)
897 outdata = s.read()
898 if connectionchatty:
899 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000901 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000902 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000903 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
904 % (outdata[:20], len(outdata),
905 indata[:20].lower(), len(indata)))
906 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000907 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000908 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000909 sys.stdout.write(" client: closing connection.\n")
910 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911 finally:
912 server.stop()
913 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000914
Antoine Pitroub5218772010-05-21 09:56:06 +0000915 def try_protocol_combo(server_protocol, client_protocol, expect_success,
916 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000917 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000919 certtype = {
920 ssl.CERT_NONE: "CERT_NONE",
921 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
922 ssl.CERT_REQUIRED: "CERT_REQUIRED",
923 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000924 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000925 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000926 sys.stdout.write(formatstr %
927 (ssl.get_protocol_name(client_protocol),
928 ssl.get_protocol_name(server_protocol),
929 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000930 client_context = ssl.SSLContext(client_protocol)
931 client_context.options = ssl.OP_ALL | client_options
932 server_context = ssl.SSLContext(server_protocol)
933 server_context.options = ssl.OP_ALL | server_options
934 for ctx in (client_context, server_context):
935 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000936 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
937 # will send an SSLv3 hello (rather than SSLv2) starting from
938 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000939 ctx.set_ciphers("ALL")
940 ctx.load_cert_chain(CERTFILE)
941 ctx.load_verify_locations(CERTFILE)
942 try:
943 server_params_test(client_context, server_context,
944 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000945 # Protocol mismatch can result in either an SSLError, or a
946 # "Connection reset by peer" error.
947 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000948 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000950 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000951 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000952 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000954 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000955 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000956 "Client protocol %s succeeded with server protocol %s!"
957 % (ssl.get_protocol_name(client_protocol),
958 ssl.get_protocol_name(server_protocol)))
959
960
Bill Janssen6e027db2007-11-15 22:23:56 +0000961 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000962
Antoine Pitrou23df4832010-08-04 17:14:06 +0000963 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000964 def test_echo(self):
965 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000966 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000967 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000968 for protocol in PROTOCOLS:
969 context = ssl.SSLContext(protocol)
970 context.load_cert_chain(CERTFILE)
971 server_params_test(context, context,
972 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000973
Antoine Pitrou480a1242010-04-28 21:37:09 +0000974 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000975 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000976 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000977 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
978 context.verify_mode = ssl.CERT_REQUIRED
979 context.load_verify_locations(CERTFILE)
980 context.load_cert_chain(CERTFILE)
981 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000982 flag = threading.Event()
983 server.start(flag)
984 # wait for it to start
985 flag.wait()
986 # try to connect
987 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000988 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000989 s.connect((HOST, server.port))
990 cert = s.getpeercert()
991 self.assertTrue(cert, "Can't get peer certificate.")
992 cipher = s.cipher()
993 if support.verbose:
994 sys.stdout.write(pprint.pformat(cert) + '\n')
995 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
996 if 'subject' not in cert:
997 self.fail("No subject field in certificate: %s." %
998 pprint.pformat(cert))
999 if ((('organizationName', 'Python Software Foundation'),)
1000 not in cert['subject']):
1001 self.fail(
1002 "Missing or invalid 'organizationName' field in certificate subject; "
1003 "should be 'Python Software Foundation'.")
1004 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001005 finally:
1006 server.stop()
1007 server.join()
1008
Antoine Pitrou480a1242010-04-28 21:37:09 +00001009 def test_empty_cert(self):
1010 """Connecting with an empty cert file"""
1011 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1012 "nullcert.pem"))
1013 def test_malformed_cert(self):
1014 """Connecting with a badly formatted certificate (syntax error)"""
1015 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1016 "badcert.pem"))
1017 def test_nonexisting_cert(self):
1018 """Connecting with a non-existing cert file"""
1019 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1020 "wrongcert.pem"))
1021 def test_malformed_key(self):
1022 """Connecting with a badly formatted key (syntax error)"""
1023 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1024 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001025
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 def test_rude_shutdown(self):
1027 """A brutal shutdown of an SSL server should raise an IOError
1028 in the client when attempting handshake.
1029 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001030 listener_ready = threading.Event()
1031 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001032
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001033 s = socket.socket()
1034 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001035
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001036 # `listener` runs in a thread. It sits in an accept() until
1037 # the main thread connects. Then it rudely closes the socket,
1038 # and sets Event `listener_gone` to let the main thread know
1039 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001040 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001041 s.listen(5)
1042 listener_ready.set()
1043 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001044 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001045 listener_gone.set()
1046
1047 def connector():
1048 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001049 c = socket.socket()
1050 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001051 listener_gone.wait()
1052 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001053 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001054 except IOError:
1055 pass
1056 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001057 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001058
1059 t = threading.Thread(target=listener)
1060 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001061 try:
1062 connector()
1063 finally:
1064 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001065
Antoine Pitrou23df4832010-08-04 17:14:06 +00001066 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 def test_protocol_sslv2(self):
1068 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001069 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001070 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001071 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1072 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1073 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1074 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1075 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1076 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001077 # SSLv23 client with specific SSL options
1078 if no_sslv2_implies_sslv3_hello():
1079 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1080 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1081 client_options=ssl.OP_NO_SSLv2)
1082 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1083 client_options=ssl.OP_NO_SSLv3)
1084 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1085 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086
Antoine Pitrou23df4832010-08-04 17:14:06 +00001087 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001088 def test_protocol_sslv23(self):
1089 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001090 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001091 sys.stdout.write("\n")
1092 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001093 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001094 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001095 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001096 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001097 sys.stdout.write(
1098 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1099 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001100 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1101 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1102 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001103
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1105 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1106 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107
Antoine Pitrou480a1242010-04-28 21:37:09 +00001108 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1109 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1110 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001111
Antoine Pitroub5218772010-05-21 09:56:06 +00001112 # Server with specific SSL options
1113 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1114 server_options=ssl.OP_NO_SSLv3)
1115 # Will choose TLSv1
1116 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1117 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1118 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1119 server_options=ssl.OP_NO_TLSv1)
1120
1121
Antoine Pitrou23df4832010-08-04 17:14:06 +00001122 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001123 def test_protocol_sslv3(self):
1124 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001125 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001126 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001127 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1128 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1129 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1130 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1131 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1132 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001133 if no_sslv2_implies_sslv3_hello():
1134 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1135 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1136 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001137
Antoine Pitrou23df4832010-08-04 17:14:06 +00001138 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 def test_protocol_tlsv1(self):
1140 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001141 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001142 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001143 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1144 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1145 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1146 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1147 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1148 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001149
Antoine Pitrou480a1242010-04-28 21:37:09 +00001150 def test_starttls(self):
1151 """Switching from clear text to encrypted and back again."""
1152 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 +00001153
Trent Nelson78520002008-04-10 20:54:35 +00001154 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001155 ssl_version=ssl.PROTOCOL_TLSv1,
1156 starttls_server=True,
1157 chatty=True,
1158 connectionchatty=True)
1159 flag = threading.Event()
1160 server.start(flag)
1161 # wait for it to start
1162 flag.wait()
1163 # try to connect
1164 wrapped = False
1165 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001166 s = socket.socket()
1167 s.setblocking(1)
1168 s.connect((HOST, server.port))
1169 if support.verbose:
1170 sys.stdout.write("\n")
1171 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001172 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001173 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001175 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001176 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001177 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001178 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001179 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001180 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001181 msg = outdata.strip().lower()
1182 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1183 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001184 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001185 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001186 " client: read %r from server, starting TLS...\n"
1187 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001188 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1189 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001190 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1191 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001192 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001193 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001194 " client: read %r from server, ending TLS...\n"
1195 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001196 s = conn.unwrap()
1197 wrapped = False
1198 else:
1199 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001200 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001201 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001202 if support.verbose:
1203 sys.stdout.write(" client: closing connection.\n")
1204 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001206 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001207 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001208 if wrapped:
1209 conn.close()
1210 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 s.close()
1212 finally:
1213 server.stop()
1214 server.join()
1215
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 def test_socketserver(self):
1217 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001218 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001219 flag = threading.Event()
1220 server.start(flag)
1221 # wait for it to start
1222 flag.wait()
1223 # try to connect
1224 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001225 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001226 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001227 with open(CERTFILE, 'rb') as f:
1228 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001229 d2 = ''
1230 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001231 url = 'https://%s:%d/%s' % (
1232 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001233 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001234 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001235 if dlen and (int(dlen) > 0):
1236 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001237 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001238 sys.stdout.write(
1239 " client: read %d bytes from remote server '%s'\n"
1240 % (len(d2), server))
1241 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001242 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001244 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001245 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001246 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001247 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001248 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001249 server.join()
1250
Antoine Pitrou480a1242010-04-28 21:37:09 +00001251 def test_asyncore_server(self):
1252 """Check the example asyncore integration."""
1253 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001254
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001255 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001256 sys.stdout.write("\n")
1257
Antoine Pitrou480a1242010-04-28 21:37:09 +00001258 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001259 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001260 flag = threading.Event()
1261 server.start(flag)
1262 # wait for it to start
1263 flag.wait()
1264 # try to connect
1265 try:
1266 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001267 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001268 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001269 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001270 " client: sending %r...\n" % indata)
1271 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001272 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001273 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001274 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001275 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001276 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001277 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1278 % (outdata[:20], len(outdata),
1279 indata[:20].lower(), len(indata)))
1280 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001281 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001282 sys.stdout.write(" client: closing connection.\n")
1283 s.close()
1284 finally:
1285 server.stop()
1286 server.join()
1287
Antoine Pitrou480a1242010-04-28 21:37:09 +00001288 def test_recv_send(self):
1289 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001290 if support.verbose:
1291 sys.stdout.write("\n")
1292
1293 server = ThreadedEchoServer(CERTFILE,
1294 certreqs=ssl.CERT_NONE,
1295 ssl_version=ssl.PROTOCOL_TLSv1,
1296 cacerts=CERTFILE,
1297 chatty=True,
1298 connectionchatty=False)
1299 flag = threading.Event()
1300 server.start(flag)
1301 # wait for it to start
1302 flag.wait()
1303 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001304 s = ssl.wrap_socket(socket.socket(),
1305 server_side=False,
1306 certfile=CERTFILE,
1307 ca_certs=CERTFILE,
1308 cert_reqs=ssl.CERT_NONE,
1309 ssl_version=ssl.PROTOCOL_TLSv1)
1310 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001311 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001312 # helper methods for standardising recv* method signatures
1313 def _recv_into():
1314 b = bytearray(b"\0"*100)
1315 count = s.recv_into(b)
1316 return b[:count]
1317
1318 def _recvfrom_into():
1319 b = bytearray(b"\0"*100)
1320 count, addr = s.recvfrom_into(b)
1321 return b[:count]
1322
1323 # (name, method, whether to expect success, *args)
1324 send_methods = [
1325 ('send', s.send, True, []),
1326 ('sendto', s.sendto, False, ["some.address"]),
1327 ('sendall', s.sendall, True, []),
1328 ]
1329 recv_methods = [
1330 ('recv', s.recv, True, []),
1331 ('recvfrom', s.recvfrom, False, ["some.address"]),
1332 ('recv_into', _recv_into, True, []),
1333 ('recvfrom_into', _recvfrom_into, False, []),
1334 ]
1335 data_prefix = "PREFIX_"
1336
1337 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001338 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001339 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001340 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001341 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001342 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001343 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001344 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001345 "<<{outdata:r}>> ({nout:d}) received; "
1346 "expected <<{indata:r}>> ({nin:d})\n".format(
1347 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001348 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001349 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001350 )
1351 )
1352 except ValueError as e:
1353 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001354 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001355 "Failed to send with method <<{name:s}>>; "
1356 "expected to succeed.\n".format(name=meth_name)
1357 )
1358 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001359 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001360 "Method <<{name:s}>> failed with unexpected "
1361 "exception message: {exp:s}\n".format(
1362 name=meth_name, exp=e
1363 )
1364 )
1365
1366 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001367 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001368 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001369 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001370 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001371 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001372 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001373 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001374 "<<{outdata:r}>> ({nout:d}) received; "
1375 "expected <<{indata:r}>> ({nin:d})\n".format(
1376 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001377 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001378 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379 )
1380 )
1381 except ValueError as e:
1382 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001383 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001384 "Failed to receive with method <<{name:s}>>; "
1385 "expected to succeed.\n".format(name=meth_name)
1386 )
1387 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001388 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001389 "Method <<{name:s}>> failed with unexpected "
1390 "exception message: {exp:s}\n".format(
1391 name=meth_name, exp=e
1392 )
1393 )
1394 # consume data
1395 s.read()
1396
Antoine Pitrou480a1242010-04-28 21:37:09 +00001397 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001398 s.close()
1399 finally:
1400 server.stop()
1401 server.join()
1402
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001403 def test_handshake_timeout(self):
1404 # Issue #5103: SSL handshake must respect the socket timeout
1405 server = socket.socket(socket.AF_INET)
1406 host = "127.0.0.1"
1407 port = support.bind_port(server)
1408 started = threading.Event()
1409 finish = False
1410
1411 def serve():
1412 server.listen(5)
1413 started.set()
1414 conns = []
1415 while not finish:
1416 r, w, e = select.select([server], [], [], 0.1)
1417 if server in r:
1418 # Let the socket hang around rather than having
1419 # it closed by garbage collection.
1420 conns.append(server.accept()[0])
1421
1422 t = threading.Thread(target=serve)
1423 t.start()
1424 started.wait()
1425
1426 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001427 try:
1428 c = socket.socket(socket.AF_INET)
1429 c.settimeout(0.2)
1430 c.connect((host, port))
1431 # Will attempt handshake and time out
1432 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1433 ssl.wrap_socket, c)
1434 finally:
1435 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001436 try:
1437 c = socket.socket(socket.AF_INET)
1438 c = ssl.wrap_socket(c)
1439 c.settimeout(0.2)
1440 # Will attempt handshake and time out
1441 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1442 c.connect, (host, port))
1443 finally:
1444 c.close()
1445 finally:
1446 finish = True
1447 t.join()
1448 server.close()
1449
Bill Janssen58afe4c2008-09-08 16:45:19 +00001450
Thomas Woutersed03b412007-08-28 21:37:11 +00001451def test_main(verbose=False):
1452 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001453 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001454
Antoine Pitrou15cee622010-08-04 16:45:21 +00001455 if support.verbose:
1456 plats = {
1457 'Linux': platform.linux_distribution,
1458 'Mac': platform.mac_ver,
1459 'Windows': platform.win32_ver,
1460 }
1461 for name, func in plats.items():
1462 plat = func()
1463 if plat and plat[0]:
1464 plat = '%s %r' % (name, plat)
1465 break
1466 else:
1467 plat = repr(platform.platform())
1468 print("test_ssl: testing with %r %r" %
1469 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1470 print(" under %s" % plat)
1471
Antoine Pitrou152efa22010-05-16 18:19:27 +00001472 for filename in [
1473 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1474 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1475 BADCERT, BADKEY, EMPTYCERT]:
1476 if not os.path.exists(filename):
1477 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478
Antoine Pitrou152efa22010-05-16 18:19:27 +00001479 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001480
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001481 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001482 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001483
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001484 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001485 thread_info = support.threading_setup()
1486 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001487 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001488
Antoine Pitrou968dc032010-08-15 22:16:23 +00001489 old_verbose = support.verbose
Antoine Pitrou480a1242010-04-28 21:37:09 +00001490 try:
Antoine Pitrou968dc032010-08-15 22:16:23 +00001491 support.verbose = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 support.run_unittest(*tests)
1493 finally:
Antoine Pitrou968dc032010-08-15 22:16:23 +00001494 support.verbose = old_verbose
Antoine Pitrou480a1242010-04-28 21:37:09 +00001495 if _have_threads:
1496 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001497
1498if __name__ == "__main__":
1499 test_main()