blob: c4644401806f80fbb2f9d223217674fd5bf60eb9 [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
Thomas Woutersed03b412007-08-28 21:37:11 +000018
Georg Brandl24420152008-05-26 16:32:26 +000019from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000020
Thomas Woutersed03b412007-08-28 21:37:11 +000021# Optionally test SSL support, if we have it in the tested platform
22skip_expected = False
23try:
24 import ssl
25except ImportError:
26 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000027else:
28 PROTOCOLS = [
29 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
30 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
31 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000032
Benjamin Petersonee8712c2008-05-20 21:35:26 +000033HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000034
35data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
36fsencode = lambda name: name.encode(sys.getfilesystemencoding(), "surrogateescape")
37
38CERTFILE = data_file("keycert.pem")
39BYTES_CERTFILE = fsencode(CERTFILE)
40ONLYCERT = data_file("ssl_cert.pem")
41ONLYKEY = data_file("ssl_key.pem")
42BYTES_ONLYCERT = fsencode(ONLYCERT)
43BYTES_ONLYKEY = fsencode(ONLYKEY)
44CAPATH = data_file("capath")
45BYTES_CAPATH = fsencode(CAPATH)
46
47SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
48
49EMPTYCERT = data_file("nullcert.pem")
50BADCERT = data_file("badcert.pem")
51WRONGCERT = data_file("XXXnonexisting.pem")
52BADKEY = data_file("badkey.pem")
53
Thomas Woutersed03b412007-08-28 21:37:11 +000054
Thomas Woutersed03b412007-08-28 21:37:11 +000055def handle_error(prefix):
56 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000057 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000058 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000059
Antoine Pitroub5218772010-05-21 09:56:06 +000060def can_clear_options():
61 # 0.9.8m or higher
62 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
63
64def no_sslv2_implies_sslv3_hello():
65 # 0.9.7h or higher
66 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
67
Thomas Woutersed03b412007-08-28 21:37:11 +000068
Antoine Pitrou152efa22010-05-16 18:19:27 +000069class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitrou480a1242010-04-28 21:37:09 +000071 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000072 ssl.PROTOCOL_SSLv2
73 ssl.PROTOCOL_SSLv23
74 ssl.PROTOCOL_SSLv3
75 ssl.PROTOCOL_TLSv1
76 ssl.CERT_NONE
77 ssl.CERT_OPTIONAL
78 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000079
Antoine Pitrou480a1242010-04-28 21:37:09 +000080 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000081 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000082 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000083 sys.stdout.write("\n RAND_status is %d (%s)\n"
84 % (v, (v and "sufficient randomness") or
85 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000086 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 ssl.RAND_egd(1)
88 except TypeError:
89 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000090 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000091 print("didn't raise TypeError")
92 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Antoine Pitrou480a1242010-04-28 21:37:09 +000094 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000095 # note that this uses an 'unofficial' function in _ssl.c,
96 # provided solely for this test, to exercise the certificate
97 # parsing code
98 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000099 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000100 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000101
Antoine Pitrou480a1242010-04-28 21:37:09 +0000102 def test_DER_to_PEM(self):
103 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
104 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 d1 = ssl.PEM_cert_to_DER_cert(pem)
106 p2 = ssl.DER_cert_to_PEM_cert(d1)
107 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000108 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000109 if not p2.startswith(ssl.PEM_HEADER + '\n'):
110 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
111 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
112 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000114 def test_openssl_version(self):
115 n = ssl.OPENSSL_VERSION_NUMBER
116 t = ssl.OPENSSL_VERSION_INFO
117 s = ssl.OPENSSL_VERSION
118 self.assertIsInstance(n, int)
119 self.assertIsInstance(t, tuple)
120 self.assertIsInstance(s, str)
121 # Some sanity checks follow
122 # >= 0.9
123 self.assertGreaterEqual(n, 0x900000)
124 # < 2.0
125 self.assertLess(n, 0x20000000)
126 major, minor, fix, patch, status = t
127 self.assertGreaterEqual(major, 0)
128 self.assertLess(major, 2)
129 self.assertGreaterEqual(minor, 0)
130 self.assertLess(minor, 256)
131 self.assertGreaterEqual(fix, 0)
132 self.assertLess(fix, 256)
133 self.assertGreaterEqual(patch, 0)
134 self.assertLessEqual(patch, 26)
135 self.assertGreaterEqual(status, 0)
136 self.assertLessEqual(status, 15)
137 # Version string as returned by OpenSSL, the format might change
138 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
139 (s, t))
140
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000141 def test_ciphers(self):
142 if not support.is_resource_enabled('network'):
143 return
144 remote = ("svn.python.org", 443)
145 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
146 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
147 s.connect(remote)
148 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
149 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
150 s.connect(remote)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000151 # Error checking can happen at instantiation or when connecting
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000152 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000153 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou30474062010-05-16 23:46:26 +0000154 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000155 s.connect(remote)
156
Antoine Pitrou9d543662010-04-23 23:10:32 +0000157 @support.cpython_only
158 def test_refcycle(self):
159 # Issue #7943: an SSL object doesn't create reference cycles with
160 # itself.
161 s = socket.socket(socket.AF_INET)
162 ss = ssl.wrap_socket(s)
163 wr = weakref.ref(ss)
164 del ss
165 self.assertEqual(wr(), None)
166
Antoine Pitrou40f08742010-04-24 22:04:40 +0000167 def test_timeout(self):
168 # Issue #8524: when creating an SSL socket, the timeout of the
169 # original socket should be retained.
170 for timeout in (None, 0.0, 5.0):
171 s = socket.socket(socket.AF_INET)
172 s.settimeout(timeout)
173 ss = ssl.wrap_socket(s)
174 self.assertEqual(timeout, ss.gettimeout())
175
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000176
Antoine Pitrou152efa22010-05-16 18:19:27 +0000177class ContextTests(unittest.TestCase):
178
179 def test_constructor(self):
180 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
181 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
182 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
183 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
184 self.assertRaises(TypeError, ssl.SSLContext)
185 self.assertRaises(ValueError, ssl.SSLContext, -1)
186 self.assertRaises(ValueError, ssl.SSLContext, 42)
187
188 def test_protocol(self):
189 for proto in PROTOCOLS:
190 ctx = ssl.SSLContext(proto)
191 self.assertEqual(ctx.protocol, proto)
192
193 def test_ciphers(self):
194 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
195 ctx.set_ciphers("ALL")
196 ctx.set_ciphers("DEFAULT")
197 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000198 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000199
Antoine Pitroub5218772010-05-21 09:56:06 +0000200 def test_options(self):
201 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
202 # OP_ALL is the default value
203 self.assertEqual(ssl.OP_ALL, ctx.options)
204 ctx.options |= ssl.OP_NO_SSLv2
205 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
206 ctx.options)
207 ctx.options |= ssl.OP_NO_SSLv3
208 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
209 ctx.options)
210 if can_clear_options():
211 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
212 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
213 ctx.options)
214 ctx.options = 0
215 self.assertEqual(0, ctx.options)
216 else:
217 with self.assertRaises(ValueError):
218 ctx.options = 0
219
Antoine Pitrou152efa22010-05-16 18:19:27 +0000220 def test_verify(self):
221 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
222 # Default value
223 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
224 ctx.verify_mode = ssl.CERT_OPTIONAL
225 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
226 ctx.verify_mode = ssl.CERT_REQUIRED
227 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
228 ctx.verify_mode = ssl.CERT_NONE
229 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
230 with self.assertRaises(TypeError):
231 ctx.verify_mode = None
232 with self.assertRaises(ValueError):
233 ctx.verify_mode = 42
234
235 def test_load_cert_chain(self):
236 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
237 # Combined key and cert in a single file
238 ctx.load_cert_chain(CERTFILE)
239 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
240 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
241 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
242 ctx.load_cert_chain(WRONGCERT)
243 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
244 ctx.load_cert_chain(BADCERT)
245 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
246 ctx.load_cert_chain(EMPTYCERT)
247 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000248 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000249 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
250 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
251 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
252 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
253 ctx.load_cert_chain(ONLYCERT)
254 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
255 ctx.load_cert_chain(ONLYKEY)
256 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
257 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
258 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000259 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000260 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
261 ctx.load_cert_chain(CERTFILE, ONLYKEY)
262
263 def test_load_verify_locations(self):
264 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
265 ctx.load_verify_locations(CERTFILE)
266 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
267 ctx.load_verify_locations(BYTES_CERTFILE)
268 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
269 self.assertRaises(TypeError, ctx.load_verify_locations)
270 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
271 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
272 ctx.load_verify_locations(WRONGCERT)
273 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
274 ctx.load_verify_locations(BADCERT)
275 ctx.load_verify_locations(CERTFILE, CAPATH)
276 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
277
278
Bill Janssen6e027db2007-11-15 22:23:56 +0000279class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000280
Antoine Pitrou480a1242010-04-28 21:37:09 +0000281 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000282 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
283 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000284 try:
285 s.connect(("svn.python.org", 443))
286 self.assertEqual({}, s.getpeercert())
287 finally:
288 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000289
290 # this should fail because we have no verification certs
291 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
292 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000293 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
294 s.connect, ("svn.python.org", 443))
295 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000296
297 # this should succeed because we specify the root cert
298 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
299 cert_reqs=ssl.CERT_REQUIRED,
300 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
301 try:
302 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000303 self.assertTrue(s.getpeercert())
304 finally:
305 s.close()
306
307 def test_connect_with_context(self):
308 # Same as test_connect, but with a separately created context
309 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
310 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
311 s.connect(("svn.python.org", 443))
312 try:
313 self.assertEqual({}, s.getpeercert())
314 finally:
315 s.close()
316 # This should fail because we have no verification certs
317 ctx.verify_mode = ssl.CERT_REQUIRED
318 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
319 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
320 s.connect, ("svn.python.org", 443))
321 s.close()
322 # This should succeed because we specify the root cert
323 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
324 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
325 s.connect(("svn.python.org", 443))
326 try:
327 cert = s.getpeercert()
328 self.assertTrue(cert)
329 finally:
330 s.close()
331
332 def test_connect_capath(self):
333 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000334 # NOTE: the subject hashing algorithm has been changed between
335 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
336 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000337 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000338 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
339 ctx.verify_mode = ssl.CERT_REQUIRED
340 ctx.load_verify_locations(capath=CAPATH)
341 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
342 s.connect(("svn.python.org", 443))
343 try:
344 cert = s.getpeercert()
345 self.assertTrue(cert)
346 finally:
347 s.close()
348 # Same with a bytes `capath` argument
349 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
350 ctx.verify_mode = ssl.CERT_REQUIRED
351 ctx.load_verify_locations(capath=BYTES_CAPATH)
352 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
353 s.connect(("svn.python.org", 443))
354 try:
355 cert = s.getpeercert()
356 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000357 finally:
358 s.close()
359
Antoine Pitroue3220242010-04-24 11:13:53 +0000360 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
361 def test_makefile_close(self):
362 # Issue #5238: creating a file-like object with makefile() shouldn't
363 # delay closing the underlying "real socket" (here tested with its
364 # file descriptor, hence skipping the test under Windows).
365 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
366 ss.connect(("svn.python.org", 443))
367 fd = ss.fileno()
368 f = ss.makefile()
369 f.close()
370 # The fd is still open
371 os.read(fd, 0)
372 # Closing the SSL socket should close the fd too
373 ss.close()
374 gc.collect()
375 with self.assertRaises(OSError) as e:
376 os.read(fd, 0)
377 self.assertEqual(e.exception.errno, errno.EBADF)
378
Antoine Pitrou480a1242010-04-28 21:37:09 +0000379 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000380 s = socket.socket(socket.AF_INET)
381 s.connect(("svn.python.org", 443))
382 s.setblocking(False)
383 s = ssl.wrap_socket(s,
384 cert_reqs=ssl.CERT_NONE,
385 do_handshake_on_connect=False)
386 count = 0
387 while True:
388 try:
389 count += 1
390 s.do_handshake()
391 break
392 except ssl.SSLError as err:
393 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
394 select.select([s], [], [])
395 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
396 select.select([], [s], [])
397 else:
398 raise
399 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000400 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000401 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000402
Antoine Pitrou480a1242010-04-28 21:37:09 +0000403 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000404 pem = ssl.get_server_certificate(("svn.python.org", 443))
405 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000406 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000407
408 return
409
410 try:
411 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
412 except ssl.SSLError as x:
413 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000414 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000415 sys.stdout.write("%s\n" % x)
416 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000417 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000418
419 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
420 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000421 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000422 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000423 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
424
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000425 def test_algorithms(self):
426 # Issue #8484: all algorithms should be available when verifying a
427 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000428 # SHA256 was added in OpenSSL 0.9.8
429 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
430 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000431 # NOTE: https://sha256.tbs-internet.com is another possible test host
432 remote = ("sha2.hboeck.de", 443)
433 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
434 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
435 cert_reqs=ssl.CERT_REQUIRED,
436 ca_certs=sha256_cert,)
437 with support.transient_internet():
438 try:
439 s.connect(remote)
440 if support.verbose:
441 sys.stdout.write("\nCipher with %r is %r\n" %
442 (remote, s.cipher()))
443 sys.stdout.write("Certificate is:\n%s\n" %
444 pprint.pformat(s.getpeercert()))
445 finally:
446 s.close()
447
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000448
449try:
450 import threading
451except ImportError:
452 _have_threads = False
453else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000454 _have_threads = True
455
456 class ThreadedEchoServer(threading.Thread):
457
458 class ConnectionHandler(threading.Thread):
459
460 """A mildly complicated class, because we want it to work both
461 with and without the SSL wrapper around the socket connection, so
462 that we can test the STARTTLS functionality."""
463
Bill Janssen6e027db2007-11-15 22:23:56 +0000464 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000465 self.server = server
466 self.running = False
467 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000468 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000469 self.sock.setblocking(1)
470 self.sslconn = None
471 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000472 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000473
Antoine Pitrou480a1242010-04-28 21:37:09 +0000474 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000475 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000476 self.sslconn = self.server.context.wrap_socket(
477 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000478 except ssl.SSLError:
479 # XXX Various errors can have happened here, for example
480 # a mismatching protocol version, an invalid certificate,
481 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000482 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000483 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000484 self.running = False
485 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000486 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000487 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000488 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000489 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000490 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000491 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000492 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
493 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000494 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000495 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
496 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000497 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000498 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
499 return True
500
501 def read(self):
502 if self.sslconn:
503 return self.sslconn.read()
504 else:
505 return self.sock.recv(1024)
506
507 def write(self, bytes):
508 if self.sslconn:
509 return self.sslconn.write(bytes)
510 else:
511 return self.sock.send(bytes)
512
513 def close(self):
514 if self.sslconn:
515 self.sslconn.close()
516 else:
517 self.sock.close()
518
Antoine Pitrou480a1242010-04-28 21:37:09 +0000519 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000520 self.running = True
521 if not self.server.starttls_server:
522 if not self.wrap_conn():
523 return
524 while self.running:
525 try:
526 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000527 stripped = msg.strip()
528 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000529 # eof, so quit this handler
530 self.running = False
531 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000532 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000533 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000534 sys.stdout.write(" server: client closed connection\n")
535 self.close()
536 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000537 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000538 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000539 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000540 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000541 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000542 if not self.wrap_conn():
543 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000544 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000545 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000546 if support.verbose and self.server.connectionchatty:
547 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000548 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000549 self.sock = self.sslconn.unwrap()
550 self.sslconn = None
551 if support.verbose and self.server.connectionchatty:
552 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000553 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000554 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000555 self.server.connectionchatty):
556 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000557 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
558 % (msg, ctype, msg.lower(), ctype))
559 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000560 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000561 if self.server.chatty:
562 handle_error("Test server failure:\n")
563 self.close()
564 self.running = False
565 # normally, we'd just stop here, but for the test
566 # harness, we want to stop the server
567 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000568
Antoine Pitroub5218772010-05-21 09:56:06 +0000569 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000570 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000571 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000572 ciphers=None, context=None):
573 if context:
574 self.context = context
575 else:
576 self.context = ssl.SSLContext(ssl_version
577 if ssl_version is not None
578 else ssl.PROTOCOL_TLSv1)
579 self.context.verify_mode = (certreqs if certreqs is not None
580 else ssl.CERT_NONE)
581 if cacerts:
582 self.context.load_verify_locations(cacerts)
583 if certificate:
584 self.context.load_cert_chain(certificate)
585 if ciphers:
586 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000587 self.chatty = chatty
588 self.connectionchatty = connectionchatty
589 self.starttls_server = starttls_server
590 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000591 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000593 self.active = False
594 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000595 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000596
Antoine Pitrou480a1242010-04-28 21:37:09 +0000597 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000598 self.flag = flag
599 threading.Thread.start(self)
600
Antoine Pitrou480a1242010-04-28 21:37:09 +0000601 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000602 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000603 self.sock.listen(5)
604 self.active = True
605 if self.flag:
606 # signal an event
607 self.flag.set()
608 while self.active:
609 try:
610 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000611 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000612 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000613 + repr(connaddr) + '\n')
614 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000615 handler.start()
616 except socket.timeout:
617 pass
618 except KeyboardInterrupt:
619 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000620 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000621
Antoine Pitrou480a1242010-04-28 21:37:09 +0000622 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000623 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000624
Bill Janssen54cc54c2007-12-14 22:08:56 +0000625 class OurHTTPSServer(threading.Thread):
626
627 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000628
629 class HTTPSServer(HTTPServer):
630
631 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000632 HTTPServer.__init__(self, server_address, RequestHandlerClass)
633 # we assume the certfile contains both private key and certificate
634 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000635 self.allow_reuse_address = True
636
Bill Janssen6e027db2007-11-15 22:23:56 +0000637 def __str__(self):
638 return ('<%s %s:%s>' %
639 (self.__class__.__name__,
640 self.server_name,
641 self.server_port))
642
Antoine Pitrou480a1242010-04-28 21:37:09 +0000643 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000644 # override this to wrap socket with SSL
645 sock, addr = self.socket.accept()
646 sslconn = ssl.wrap_socket(sock, server_side=True,
647 certfile=self.certfile)
648 return sslconn, addr
649
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000651 # need to override translate_path to get a known root,
652 # instead of using os.curdir, since the test could be
653 # run from anywhere
654
655 server_version = "TestHTTPS/1.0"
656
657 root = None
658
659 def translate_path(self, path):
660 """Translate a /-separated PATH to the local filename syntax.
661
662 Components that mean special things to the local file system
663 (e.g. drive or directory names) are ignored. (XXX They should
664 probably be diagnosed.)
665
666 """
667 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000668 path = urllib.parse.urlparse(path)[2]
669 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000670 words = path.split('/')
671 words = filter(None, words)
672 path = self.root
673 for word in words:
674 drive, word = os.path.splitdrive(word)
675 head, word = os.path.split(word)
676 if word in self.root: continue
677 path = os.path.join(path, word)
678 return path
679
680 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000681 # we override this to suppress logging unless "verbose"
682
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000683 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000684 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
685 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000686 self.server.server_port,
687 self.request.cipher(),
688 self.log_date_time_string(),
689 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000690
691
Trent Nelson78520002008-04-10 20:54:35 +0000692 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000693 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000694 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
695 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000696 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
697 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000698 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000699 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000700
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000701 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000702 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000703
Antoine Pitrou480a1242010-04-28 21:37:09 +0000704 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 self.flag = flag
706 threading.Thread.start(self)
707
Antoine Pitrou480a1242010-04-28 21:37:09 +0000708 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000709 if self.flag:
710 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000711 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000712
Antoine Pitrou480a1242010-04-28 21:37:09 +0000713 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000714 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000715
716
Bill Janssen54cc54c2007-12-14 22:08:56 +0000717 class AsyncoreEchoServer(threading.Thread):
718
719 # this one's based on asyncore.dispatcher
720
721 class EchoServer (asyncore.dispatcher):
722
723 class ConnectionHandler (asyncore.dispatcher_with_send):
724
725 def __init__(self, conn, certfile):
726 self.socket = ssl.wrap_socket(conn, server_side=True,
727 certfile=certfile,
728 do_handshake_on_connect=False)
729 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000730 self._ssl_accepting = True
731 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000732
733 def readable(self):
734 if isinstance(self.socket, ssl.SSLSocket):
735 while self.socket.pending() > 0:
736 self.handle_read_event()
737 return True
738
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000739 def _do_ssl_handshake(self):
740 try:
741 self.socket.do_handshake()
742 except ssl.SSLError as err:
743 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
744 ssl.SSL_ERROR_WANT_WRITE):
745 return
746 elif err.args[0] == ssl.SSL_ERROR_EOF:
747 return self.handle_close()
748 raise
749 except socket.error as err:
750 if err.args[0] == errno.ECONNABORTED:
751 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000752 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000753 self._ssl_accepting = False
754
755 def handle_read(self):
756 if self._ssl_accepting:
757 self._do_ssl_handshake()
758 else:
759 data = self.recv(1024)
760 if support.verbose:
761 sys.stdout.write(" server: read %s from client\n" % repr(data))
762 if not data:
763 self.close()
764 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000765 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000766
767 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000768 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000769 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000770 sys.stdout.write(" server: closed connection %s\n" % self.socket)
771
772 def handle_error(self):
773 raise
774
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000775 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000776 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000777 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
778 self.port = support.bind_port(sock, '')
779 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000780 self.listen(5)
781
782 def handle_accept(self):
783 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000784 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000785 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
786 self.ConnectionHandler(sock_obj, self.certfile)
787
788 def handle_error(self):
789 raise
790
Trent Nelson78520002008-04-10 20:54:35 +0000791 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000792 self.flag = None
793 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000794 self.server = self.EchoServer(certfile)
795 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000796 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000797 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000798
799 def __str__(self):
800 return "<%s %s>" % (self.__class__.__name__, self.server)
801
802 def start (self, flag=None):
803 self.flag = flag
804 threading.Thread.start(self)
805
Antoine Pitrou480a1242010-04-28 21:37:09 +0000806 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000807 self.active = True
808 if self.flag:
809 self.flag.set()
810 while self.active:
811 try:
812 asyncore.loop(1)
813 except:
814 pass
815
Antoine Pitrou480a1242010-04-28 21:37:09 +0000816 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000817 self.active = False
818 self.server.close()
819
Antoine Pitrou480a1242010-04-28 21:37:09 +0000820 def bad_cert_test(certfile):
821 """
822 Launch a server with CERT_REQUIRED, and check that trying to
823 connect to it with the given client certificate fails.
824 """
Trent Nelson78520002008-04-10 20:54:35 +0000825 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000826 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000827 cacerts=CERTFILE, chatty=False,
828 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829 flag = threading.Event()
830 server.start(flag)
831 # wait for it to start
832 flag.wait()
833 # try to connect
834 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000835 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000836 s = ssl.wrap_socket(socket.socket(),
837 certfile=certfile,
838 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000839 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000840 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000841 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000842 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000843 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000844 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000845 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000847 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848 finally:
849 server.stop()
850 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000851
Antoine Pitroub5218772010-05-21 09:56:06 +0000852 def server_params_test(client_context, server_context, indata=b"FOO\n",
853 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000854 """
855 Launch a server, connect a client to it and try various reads
856 and writes.
857 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000858 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000859 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000860 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 flag = threading.Event()
862 server.start(flag)
863 # wait for it to start
864 flag.wait()
865 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000867 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000868 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000869 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000870 if connectionchatty:
871 if support.verbose:
872 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000873 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000874 s.write(arg)
875 outdata = s.read()
876 if connectionchatty:
877 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000878 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000879 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000880 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000881 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
882 % (outdata[:20], len(outdata),
883 indata[:20].lower(), len(indata)))
884 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000885 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000886 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000887 sys.stdout.write(" client: closing connection.\n")
888 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000889 finally:
890 server.stop()
891 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000892
Antoine Pitroub5218772010-05-21 09:56:06 +0000893 def try_protocol_combo(server_protocol, client_protocol, expect_success,
894 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000895 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000897 certtype = {
898 ssl.CERT_NONE: "CERT_NONE",
899 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
900 ssl.CERT_REQUIRED: "CERT_REQUIRED",
901 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000902 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000903 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000904 sys.stdout.write(formatstr %
905 (ssl.get_protocol_name(client_protocol),
906 ssl.get_protocol_name(server_protocol),
907 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000908 client_context = ssl.SSLContext(client_protocol)
909 client_context.options = ssl.OP_ALL | client_options
910 server_context = ssl.SSLContext(server_protocol)
911 server_context.options = ssl.OP_ALL | server_options
912 for ctx in (client_context, server_context):
913 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000914 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
915 # will send an SSLv3 hello (rather than SSLv2) starting from
916 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000917 ctx.set_ciphers("ALL")
918 ctx.load_cert_chain(CERTFILE)
919 ctx.load_verify_locations(CERTFILE)
920 try:
921 server_params_test(client_context, server_context,
922 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000923 # Protocol mismatch can result in either an SSLError, or a
924 # "Connection reset by peer" error.
925 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000926 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000927 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000928 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000929 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000930 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000931 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000932 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000933 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000934 "Client protocol %s succeeded with server protocol %s!"
935 % (ssl.get_protocol_name(client_protocol),
936 ssl.get_protocol_name(server_protocol)))
937
938
Bill Janssen6e027db2007-11-15 22:23:56 +0000939 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000940
Antoine Pitrou480a1242010-04-28 21:37:09 +0000941 def test_echo(self):
942 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000943 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000944 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000945 for protocol in PROTOCOLS:
946 context = ssl.SSLContext(protocol)
947 context.load_cert_chain(CERTFILE)
948 server_params_test(context, context,
949 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000950
Antoine Pitrou480a1242010-04-28 21:37:09 +0000951 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000952 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000954 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
955 context.verify_mode = ssl.CERT_REQUIRED
956 context.load_verify_locations(CERTFILE)
957 context.load_cert_chain(CERTFILE)
958 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000959 flag = threading.Event()
960 server.start(flag)
961 # wait for it to start
962 flag.wait()
963 # try to connect
964 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000965 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000966 s.connect((HOST, server.port))
967 cert = s.getpeercert()
968 self.assertTrue(cert, "Can't get peer certificate.")
969 cipher = s.cipher()
970 if support.verbose:
971 sys.stdout.write(pprint.pformat(cert) + '\n')
972 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
973 if 'subject' not in cert:
974 self.fail("No subject field in certificate: %s." %
975 pprint.pformat(cert))
976 if ((('organizationName', 'Python Software Foundation'),)
977 not in cert['subject']):
978 self.fail(
979 "Missing or invalid 'organizationName' field in certificate subject; "
980 "should be 'Python Software Foundation'.")
981 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000982 finally:
983 server.stop()
984 server.join()
985
Antoine Pitrou480a1242010-04-28 21:37:09 +0000986 def test_empty_cert(self):
987 """Connecting with an empty cert file"""
988 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
989 "nullcert.pem"))
990 def test_malformed_cert(self):
991 """Connecting with a badly formatted certificate (syntax error)"""
992 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
993 "badcert.pem"))
994 def test_nonexisting_cert(self):
995 """Connecting with a non-existing cert file"""
996 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
997 "wrongcert.pem"))
998 def test_malformed_key(self):
999 """Connecting with a badly formatted key (syntax error)"""
1000 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1001 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002
Antoine Pitrou480a1242010-04-28 21:37:09 +00001003 def test_rude_shutdown(self):
1004 """A brutal shutdown of an SSL server should raise an IOError
1005 in the client when attempting handshake.
1006 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001007 listener_ready = threading.Event()
1008 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001009
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001010 s = socket.socket()
1011 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001012
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001013 # `listener` runs in a thread. It sits in an accept() until
1014 # the main thread connects. Then it rudely closes the socket,
1015 # and sets Event `listener_gone` to let the main thread know
1016 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001017 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001018 s.listen(5)
1019 listener_ready.set()
1020 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001021 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001022 listener_gone.set()
1023
1024 def connector():
1025 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001026 c = socket.socket()
1027 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001028 listener_gone.wait()
1029 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001030 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001031 except IOError:
1032 pass
1033 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001034 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001035
1036 t = threading.Thread(target=listener)
1037 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001038 try:
1039 connector()
1040 finally:
1041 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001042
Antoine Pitrou480a1242010-04-28 21:37:09 +00001043 def test_protocol_sslv2(self):
1044 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001045 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001046 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001047 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1048 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1049 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1050 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1051 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1052 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001053 # SSLv23 client with specific SSL options
1054 if no_sslv2_implies_sslv3_hello():
1055 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1056 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1057 client_options=ssl.OP_NO_SSLv2)
1058 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1059 client_options=ssl.OP_NO_SSLv3)
1060 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1061 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001062
Antoine Pitrou480a1242010-04-28 21:37:09 +00001063 def test_protocol_sslv23(self):
1064 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001065 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 sys.stdout.write("\n")
1067 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001068 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001069 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001070 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001071 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001072 sys.stdout.write(
1073 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1074 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001075 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1076 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1077 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001078
Antoine Pitrou480a1242010-04-28 21:37:09 +00001079 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1080 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1081 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001082
Antoine Pitrou480a1242010-04-28 21:37:09 +00001083 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1084 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1085 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086
Antoine Pitroub5218772010-05-21 09:56:06 +00001087 # Server with specific SSL options
1088 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1089 server_options=ssl.OP_NO_SSLv3)
1090 # Will choose TLSv1
1091 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1092 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1093 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1094 server_options=ssl.OP_NO_TLSv1)
1095
1096
Antoine Pitrou480a1242010-04-28 21:37:09 +00001097 def test_protocol_sslv3(self):
1098 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001099 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001100 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001101 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1102 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1103 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1104 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1105 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1106 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001107 if no_sslv2_implies_sslv3_hello():
1108 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1109 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1110 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001111
Antoine Pitrou480a1242010-04-28 21:37:09 +00001112 def test_protocol_tlsv1(self):
1113 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001115 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001116 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1117 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1118 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1119 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1120 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1121 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001122
Antoine Pitrou480a1242010-04-28 21:37:09 +00001123 def test_starttls(self):
1124 """Switching from clear text to encrypted and back again."""
1125 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 +00001126
Trent Nelson78520002008-04-10 20:54:35 +00001127 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001128 ssl_version=ssl.PROTOCOL_TLSv1,
1129 starttls_server=True,
1130 chatty=True,
1131 connectionchatty=True)
1132 flag = threading.Event()
1133 server.start(flag)
1134 # wait for it to start
1135 flag.wait()
1136 # try to connect
1137 wrapped = False
1138 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001139 s = socket.socket()
1140 s.setblocking(1)
1141 s.connect((HOST, server.port))
1142 if support.verbose:
1143 sys.stdout.write("\n")
1144 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001145 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001146 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001147 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001149 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001150 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001151 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001153 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001154 msg = outdata.strip().lower()
1155 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1156 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001157 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001158 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001159 " client: read %r from server, starting TLS...\n"
1160 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001161 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1162 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001163 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1164 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001165 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001166 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001167 " client: read %r from server, ending TLS...\n"
1168 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001169 s = conn.unwrap()
1170 wrapped = False
1171 else:
1172 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001173 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001175 if support.verbose:
1176 sys.stdout.write(" client: closing connection.\n")
1177 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001178 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001179 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001181 if wrapped:
1182 conn.close()
1183 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001184 s.close()
1185 finally:
1186 server.stop()
1187 server.join()
1188
Antoine Pitrou480a1242010-04-28 21:37:09 +00001189 def test_socketserver(self):
1190 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001191 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001192 flag = threading.Event()
1193 server.start(flag)
1194 # wait for it to start
1195 flag.wait()
1196 # try to connect
1197 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001198 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001199 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001200 with open(CERTFILE, 'rb') as f:
1201 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001202 d2 = ''
1203 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001204 url = 'https://%s:%d/%s' % (
1205 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001206 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001207 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001208 if dlen and (int(dlen) > 0):
1209 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001210 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 sys.stdout.write(
1212 " client: read %d bytes from remote server '%s'\n"
1213 % (len(d2), server))
1214 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001215 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001216 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001217 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001218 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001219 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001220 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001221 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001222 server.join()
1223
Antoine Pitrou480a1242010-04-28 21:37:09 +00001224 def test_asyncore_server(self):
1225 """Check the example asyncore integration."""
1226 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001227
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001228 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001229 sys.stdout.write("\n")
1230
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001232 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001233 flag = threading.Event()
1234 server.start(flag)
1235 # wait for it to start
1236 flag.wait()
1237 # try to connect
1238 try:
1239 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001240 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001241 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001242 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001243 " client: sending %r...\n" % indata)
1244 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001245 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001246 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001247 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001248 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001249 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001250 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1251 % (outdata[:20], len(outdata),
1252 indata[:20].lower(), len(indata)))
1253 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001254 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001255 sys.stdout.write(" client: closing connection.\n")
1256 s.close()
1257 finally:
1258 server.stop()
1259 server.join()
1260
Antoine Pitrou480a1242010-04-28 21:37:09 +00001261 def test_recv_send(self):
1262 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001263 if support.verbose:
1264 sys.stdout.write("\n")
1265
1266 server = ThreadedEchoServer(CERTFILE,
1267 certreqs=ssl.CERT_NONE,
1268 ssl_version=ssl.PROTOCOL_TLSv1,
1269 cacerts=CERTFILE,
1270 chatty=True,
1271 connectionchatty=False)
1272 flag = threading.Event()
1273 server.start(flag)
1274 # wait for it to start
1275 flag.wait()
1276 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001277 s = ssl.wrap_socket(socket.socket(),
1278 server_side=False,
1279 certfile=CERTFILE,
1280 ca_certs=CERTFILE,
1281 cert_reqs=ssl.CERT_NONE,
1282 ssl_version=ssl.PROTOCOL_TLSv1)
1283 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001284 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001285 # helper methods for standardising recv* method signatures
1286 def _recv_into():
1287 b = bytearray(b"\0"*100)
1288 count = s.recv_into(b)
1289 return b[:count]
1290
1291 def _recvfrom_into():
1292 b = bytearray(b"\0"*100)
1293 count, addr = s.recvfrom_into(b)
1294 return b[:count]
1295
1296 # (name, method, whether to expect success, *args)
1297 send_methods = [
1298 ('send', s.send, True, []),
1299 ('sendto', s.sendto, False, ["some.address"]),
1300 ('sendall', s.sendall, True, []),
1301 ]
1302 recv_methods = [
1303 ('recv', s.recv, True, []),
1304 ('recvfrom', s.recvfrom, False, ["some.address"]),
1305 ('recv_into', _recv_into, True, []),
1306 ('recvfrom_into', _recvfrom_into, False, []),
1307 ]
1308 data_prefix = "PREFIX_"
1309
1310 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001311 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001312 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001313 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001314 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001315 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001316 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001317 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001318 "<<{outdata:r}>> ({nout:d}) received; "
1319 "expected <<{indata:r}>> ({nin:d})\n".format(
1320 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001321 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001322 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001323 )
1324 )
1325 except ValueError as e:
1326 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001327 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001328 "Failed to send with method <<{name:s}>>; "
1329 "expected to succeed.\n".format(name=meth_name)
1330 )
1331 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001332 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001333 "Method <<{name:s}>> failed with unexpected "
1334 "exception message: {exp:s}\n".format(
1335 name=meth_name, exp=e
1336 )
1337 )
1338
1339 for meth_name, recv_meth, expect_success, args in recv_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 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001343 outdata = recv_meth(*args)
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 receiving 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 receive 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 # consume data
1368 s.read()
1369
Antoine Pitrou480a1242010-04-28 21:37:09 +00001370 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001371 s.close()
1372 finally:
1373 server.stop()
1374 server.join()
1375
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001376 def test_handshake_timeout(self):
1377 # Issue #5103: SSL handshake must respect the socket timeout
1378 server = socket.socket(socket.AF_INET)
1379 host = "127.0.0.1"
1380 port = support.bind_port(server)
1381 started = threading.Event()
1382 finish = False
1383
1384 def serve():
1385 server.listen(5)
1386 started.set()
1387 conns = []
1388 while not finish:
1389 r, w, e = select.select([server], [], [], 0.1)
1390 if server in r:
1391 # Let the socket hang around rather than having
1392 # it closed by garbage collection.
1393 conns.append(server.accept()[0])
1394
1395 t = threading.Thread(target=serve)
1396 t.start()
1397 started.wait()
1398
1399 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001400 try:
1401 c = socket.socket(socket.AF_INET)
1402 c.settimeout(0.2)
1403 c.connect((host, port))
1404 # Will attempt handshake and time out
1405 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1406 ssl.wrap_socket, c)
1407 finally:
1408 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001409 try:
1410 c = socket.socket(socket.AF_INET)
1411 c = ssl.wrap_socket(c)
1412 c.settimeout(0.2)
1413 # Will attempt handshake and time out
1414 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1415 c.connect, (host, port))
1416 finally:
1417 c.close()
1418 finally:
1419 finish = True
1420 t.join()
1421 server.close()
1422
Bill Janssen58afe4c2008-09-08 16:45:19 +00001423
Thomas Woutersed03b412007-08-28 21:37:11 +00001424def test_main(verbose=False):
1425 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001426 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001427
Antoine Pitrou152efa22010-05-16 18:19:27 +00001428 for filename in [
1429 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1430 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1431 BADCERT, BADKEY, EMPTYCERT]:
1432 if not os.path.exists(filename):
1433 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434
Antoine Pitrou152efa22010-05-16 18:19:27 +00001435 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001436
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001437 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001438 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001439
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001440 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001441 thread_info = support.threading_setup()
1442 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001443 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001444
Antoine Pitrou480a1242010-04-28 21:37:09 +00001445 try:
1446 support.run_unittest(*tests)
1447 finally:
1448 if _have_threads:
1449 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001450
1451if __name__ == "__main__":
1452 test_main()