blob: c9dc47af9f82f8fad22c37ae113b40f639c2e96f [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
60
Antoine Pitrou152efa22010-05-16 18:19:27 +000061class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000062
Antoine Pitrou480a1242010-04-28 21:37:09 +000063 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000064 ssl.PROTOCOL_SSLv2
65 ssl.PROTOCOL_SSLv23
66 ssl.PROTOCOL_SSLv3
67 ssl.PROTOCOL_TLSv1
68 ssl.CERT_NONE
69 ssl.CERT_OPTIONAL
70 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000071
Antoine Pitrou480a1242010-04-28 21:37:09 +000072 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000073 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000074 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000075 sys.stdout.write("\n RAND_status is %d (%s)\n"
76 % (v, (v and "sufficient randomness") or
77 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000078 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000079 ssl.RAND_egd(1)
80 except TypeError:
81 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000082 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000083 print("didn't raise TypeError")
84 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Antoine Pitrou480a1242010-04-28 21:37:09 +000086 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 # note that this uses an 'unofficial' function in _ssl.c,
88 # provided solely for this test, to exercise the certificate
89 # parsing code
90 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000091 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000092 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Antoine Pitrou480a1242010-04-28 21:37:09 +000094 def test_DER_to_PEM(self):
95 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
96 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 d1 = ssl.PEM_cert_to_DER_cert(pem)
98 p2 = ssl.DER_cert_to_PEM_cert(d1)
99 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000100 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000101 if not p2.startswith(ssl.PEM_HEADER + '\n'):
102 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
103 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
104 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000106 def test_openssl_version(self):
107 n = ssl.OPENSSL_VERSION_NUMBER
108 t = ssl.OPENSSL_VERSION_INFO
109 s = ssl.OPENSSL_VERSION
110 self.assertIsInstance(n, int)
111 self.assertIsInstance(t, tuple)
112 self.assertIsInstance(s, str)
113 # Some sanity checks follow
114 # >= 0.9
115 self.assertGreaterEqual(n, 0x900000)
116 # < 2.0
117 self.assertLess(n, 0x20000000)
118 major, minor, fix, patch, status = t
119 self.assertGreaterEqual(major, 0)
120 self.assertLess(major, 2)
121 self.assertGreaterEqual(minor, 0)
122 self.assertLess(minor, 256)
123 self.assertGreaterEqual(fix, 0)
124 self.assertLess(fix, 256)
125 self.assertGreaterEqual(patch, 0)
126 self.assertLessEqual(patch, 26)
127 self.assertGreaterEqual(status, 0)
128 self.assertLessEqual(status, 15)
129 # Version string as returned by OpenSSL, the format might change
130 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
131 (s, t))
132
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000133 def test_ciphers(self):
134 if not support.is_resource_enabled('network'):
135 return
136 remote = ("svn.python.org", 443)
137 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
138 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
139 s.connect(remote)
140 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
141 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
142 s.connect(remote)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000143 # Error checking can happen at instantiation or when connecting
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000144 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000145 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou30474062010-05-16 23:46:26 +0000146 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000147 s.connect(remote)
148
Antoine Pitrou9d543662010-04-23 23:10:32 +0000149 @support.cpython_only
150 def test_refcycle(self):
151 # Issue #7943: an SSL object doesn't create reference cycles with
152 # itself.
153 s = socket.socket(socket.AF_INET)
154 ss = ssl.wrap_socket(s)
155 wr = weakref.ref(ss)
156 del ss
157 self.assertEqual(wr(), None)
158
Antoine Pitrou40f08742010-04-24 22:04:40 +0000159 def test_timeout(self):
160 # Issue #8524: when creating an SSL socket, the timeout of the
161 # original socket should be retained.
162 for timeout in (None, 0.0, 5.0):
163 s = socket.socket(socket.AF_INET)
164 s.settimeout(timeout)
165 ss = ssl.wrap_socket(s)
166 self.assertEqual(timeout, ss.gettimeout())
167
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000168
Antoine Pitrou152efa22010-05-16 18:19:27 +0000169class ContextTests(unittest.TestCase):
170
171 def test_constructor(self):
172 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
173 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
174 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
175 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
176 self.assertRaises(TypeError, ssl.SSLContext)
177 self.assertRaises(ValueError, ssl.SSLContext, -1)
178 self.assertRaises(ValueError, ssl.SSLContext, 42)
179
180 def test_protocol(self):
181 for proto in PROTOCOLS:
182 ctx = ssl.SSLContext(proto)
183 self.assertEqual(ctx.protocol, proto)
184
185 def test_ciphers(self):
186 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
187 ctx.set_ciphers("ALL")
188 ctx.set_ciphers("DEFAULT")
189 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000190 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000191
192 def test_verify(self):
193 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
194 # Default value
195 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
196 ctx.verify_mode = ssl.CERT_OPTIONAL
197 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
198 ctx.verify_mode = ssl.CERT_REQUIRED
199 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
200 ctx.verify_mode = ssl.CERT_NONE
201 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
202 with self.assertRaises(TypeError):
203 ctx.verify_mode = None
204 with self.assertRaises(ValueError):
205 ctx.verify_mode = 42
206
207 def test_load_cert_chain(self):
208 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
209 # Combined key and cert in a single file
210 ctx.load_cert_chain(CERTFILE)
211 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
212 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
213 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
214 ctx.load_cert_chain(WRONGCERT)
215 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
216 ctx.load_cert_chain(BADCERT)
217 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
218 ctx.load_cert_chain(EMPTYCERT)
219 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000220 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000221 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
222 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
223 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
224 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
225 ctx.load_cert_chain(ONLYCERT)
226 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
227 ctx.load_cert_chain(ONLYKEY)
228 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
229 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
230 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000231 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000232 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
233 ctx.load_cert_chain(CERTFILE, ONLYKEY)
234
235 def test_load_verify_locations(self):
236 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
237 ctx.load_verify_locations(CERTFILE)
238 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
239 ctx.load_verify_locations(BYTES_CERTFILE)
240 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
241 self.assertRaises(TypeError, ctx.load_verify_locations)
242 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
243 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
244 ctx.load_verify_locations(WRONGCERT)
245 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
246 ctx.load_verify_locations(BADCERT)
247 ctx.load_verify_locations(CERTFILE, CAPATH)
248 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
249
250
Bill Janssen6e027db2007-11-15 22:23:56 +0000251class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000252
Antoine Pitrou480a1242010-04-28 21:37:09 +0000253 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000254 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
255 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000256 try:
257 s.connect(("svn.python.org", 443))
258 self.assertEqual({}, s.getpeercert())
259 finally:
260 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000261
262 # this should fail because we have no verification certs
263 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
264 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000265 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
266 s.connect, ("svn.python.org", 443))
267 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000268
269 # this should succeed because we specify the root cert
270 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
271 cert_reqs=ssl.CERT_REQUIRED,
272 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
273 try:
274 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000275 self.assertTrue(s.getpeercert())
276 finally:
277 s.close()
278
279 def test_connect_with_context(self):
280 # Same as test_connect, but with a separately created context
281 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
282 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
283 s.connect(("svn.python.org", 443))
284 try:
285 self.assertEqual({}, s.getpeercert())
286 finally:
287 s.close()
288 # This should fail because we have no verification certs
289 ctx.verify_mode = ssl.CERT_REQUIRED
290 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
291 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
292 s.connect, ("svn.python.org", 443))
293 s.close()
294 # This should succeed because we specify the root cert
295 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
296 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
297 s.connect(("svn.python.org", 443))
298 try:
299 cert = s.getpeercert()
300 self.assertTrue(cert)
301 finally:
302 s.close()
303
304 def test_connect_capath(self):
305 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000306 # NOTE: the subject hashing algorithm has been changed between
307 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
308 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000309 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000310 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
311 ctx.verify_mode = ssl.CERT_REQUIRED
312 ctx.load_verify_locations(capath=CAPATH)
313 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
314 s.connect(("svn.python.org", 443))
315 try:
316 cert = s.getpeercert()
317 self.assertTrue(cert)
318 finally:
319 s.close()
320 # Same with a bytes `capath` argument
321 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
322 ctx.verify_mode = ssl.CERT_REQUIRED
323 ctx.load_verify_locations(capath=BYTES_CAPATH)
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)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000329 finally:
330 s.close()
331
Antoine Pitroue3220242010-04-24 11:13:53 +0000332 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
333 def test_makefile_close(self):
334 # Issue #5238: creating a file-like object with makefile() shouldn't
335 # delay closing the underlying "real socket" (here tested with its
336 # file descriptor, hence skipping the test under Windows).
337 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
338 ss.connect(("svn.python.org", 443))
339 fd = ss.fileno()
340 f = ss.makefile()
341 f.close()
342 # The fd is still open
343 os.read(fd, 0)
344 # Closing the SSL socket should close the fd too
345 ss.close()
346 gc.collect()
347 with self.assertRaises(OSError) as e:
348 os.read(fd, 0)
349 self.assertEqual(e.exception.errno, errno.EBADF)
350
Antoine Pitrou480a1242010-04-28 21:37:09 +0000351 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000352 s = socket.socket(socket.AF_INET)
353 s.connect(("svn.python.org", 443))
354 s.setblocking(False)
355 s = ssl.wrap_socket(s,
356 cert_reqs=ssl.CERT_NONE,
357 do_handshake_on_connect=False)
358 count = 0
359 while True:
360 try:
361 count += 1
362 s.do_handshake()
363 break
364 except ssl.SSLError as err:
365 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
366 select.select([s], [], [])
367 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
368 select.select([], [s], [])
369 else:
370 raise
371 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000372 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000373 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000374
Antoine Pitrou480a1242010-04-28 21:37:09 +0000375 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000376 pem = ssl.get_server_certificate(("svn.python.org", 443))
377 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000378 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000379
380 return
381
382 try:
383 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
384 except ssl.SSLError as x:
385 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000386 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000387 sys.stdout.write("%s\n" % x)
388 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000389 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000390
391 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
392 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000393 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000394 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000395 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
396
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000397 def test_algorithms(self):
398 # Issue #8484: all algorithms should be available when verifying a
399 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000400 # SHA256 was added in OpenSSL 0.9.8
401 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
402 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000403 # NOTE: https://sha256.tbs-internet.com is another possible test host
404 remote = ("sha2.hboeck.de", 443)
405 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
406 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
407 cert_reqs=ssl.CERT_REQUIRED,
408 ca_certs=sha256_cert,)
409 with support.transient_internet():
410 try:
411 s.connect(remote)
412 if support.verbose:
413 sys.stdout.write("\nCipher with %r is %r\n" %
414 (remote, s.cipher()))
415 sys.stdout.write("Certificate is:\n%s\n" %
416 pprint.pformat(s.getpeercert()))
417 finally:
418 s.close()
419
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000420
421try:
422 import threading
423except ImportError:
424 _have_threads = False
425else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000426 _have_threads = True
427
428 class ThreadedEchoServer(threading.Thread):
429
430 class ConnectionHandler(threading.Thread):
431
432 """A mildly complicated class, because we want it to work both
433 with and without the SSL wrapper around the socket connection, so
434 that we can test the STARTTLS functionality."""
435
Bill Janssen6e027db2007-11-15 22:23:56 +0000436 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000437 self.server = server
438 self.running = False
439 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000440 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000441 self.sock.setblocking(1)
442 self.sslconn = None
443 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000444 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000445
Antoine Pitrou480a1242010-04-28 21:37:09 +0000446 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000447 try:
448 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
449 certfile=self.server.certificate,
450 ssl_version=self.server.protocol,
451 ca_certs=self.server.cacerts,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000452 cert_reqs=self.server.certreqs,
453 ciphers=self.server.ciphers)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000454 except ssl.SSLError:
455 # XXX Various errors can have happened here, for example
456 # a mismatching protocol version, an invalid certificate,
457 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000458 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000459 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000460 self.running = False
461 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000462 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000463 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000464 else:
465 if self.server.certreqs == ssl.CERT_REQUIRED:
466 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000467 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000468 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
469 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000470 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000471 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
472 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000473 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000474 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
475 return True
476
477 def read(self):
478 if self.sslconn:
479 return self.sslconn.read()
480 else:
481 return self.sock.recv(1024)
482
483 def write(self, bytes):
484 if self.sslconn:
485 return self.sslconn.write(bytes)
486 else:
487 return self.sock.send(bytes)
488
489 def close(self):
490 if self.sslconn:
491 self.sslconn.close()
492 else:
493 self.sock.close()
494
Antoine Pitrou480a1242010-04-28 21:37:09 +0000495 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000496 self.running = True
497 if not self.server.starttls_server:
498 if not self.wrap_conn():
499 return
500 while self.running:
501 try:
502 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000503 stripped = msg.strip()
504 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505 # eof, so quit this handler
506 self.running = False
507 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000508 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000509 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000510 sys.stdout.write(" server: client closed connection\n")
511 self.close()
512 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000513 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000514 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000515 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000516 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000517 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000518 if not self.wrap_conn():
519 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000520 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000521 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000522 if support.verbose and self.server.connectionchatty:
523 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000524 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000525 self.sock = self.sslconn.unwrap()
526 self.sslconn = None
527 if support.verbose and self.server.connectionchatty:
528 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000529 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000530 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000531 self.server.connectionchatty):
532 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000533 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
534 % (msg, ctype, msg.lower(), ctype))
535 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000536 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000537 if self.server.chatty:
538 handle_error("Test server failure:\n")
539 self.close()
540 self.running = False
541 # normally, we'd just stop here, but for the test
542 # harness, we want to stop the server
543 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000544
Trent Nelson78520002008-04-10 20:54:35 +0000545 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000546 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000547 chatty=True, connectionchatty=False, starttls_server=False,
548 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000549 if ssl_version is None:
550 ssl_version = ssl.PROTOCOL_TLSv1
551 if certreqs is None:
552 certreqs = ssl.CERT_NONE
553 self.certificate = certificate
554 self.protocol = ssl_version
555 self.certreqs = certreqs
556 self.cacerts = cacerts
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000557 self.ciphers = ciphers
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000558 self.chatty = chatty
559 self.connectionchatty = connectionchatty
560 self.starttls_server = starttls_server
561 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000562 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000563 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000564 self.active = False
565 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000566 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000567
Antoine Pitrou480a1242010-04-28 21:37:09 +0000568 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000569 self.flag = flag
570 threading.Thread.start(self)
571
Antoine Pitrou480a1242010-04-28 21:37:09 +0000572 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000573 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000574 self.sock.listen(5)
575 self.active = True
576 if self.flag:
577 # signal an event
578 self.flag.set()
579 while self.active:
580 try:
581 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000582 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000583 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000584 + repr(connaddr) + '\n')
585 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000586 handler.start()
587 except socket.timeout:
588 pass
589 except KeyboardInterrupt:
590 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000591 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592
Antoine Pitrou480a1242010-04-28 21:37:09 +0000593 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000594 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000595
Bill Janssen54cc54c2007-12-14 22:08:56 +0000596 class OurHTTPSServer(threading.Thread):
597
598 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000599
600 class HTTPSServer(HTTPServer):
601
602 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000603 HTTPServer.__init__(self, server_address, RequestHandlerClass)
604 # we assume the certfile contains both private key and certificate
605 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000606 self.allow_reuse_address = True
607
Bill Janssen6e027db2007-11-15 22:23:56 +0000608 def __str__(self):
609 return ('<%s %s:%s>' %
610 (self.__class__.__name__,
611 self.server_name,
612 self.server_port))
613
Antoine Pitrou480a1242010-04-28 21:37:09 +0000614 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000615 # override this to wrap socket with SSL
616 sock, addr = self.socket.accept()
617 sslconn = ssl.wrap_socket(sock, server_side=True,
618 certfile=self.certfile)
619 return sslconn, addr
620
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000621 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000622 # need to override translate_path to get a known root,
623 # instead of using os.curdir, since the test could be
624 # run from anywhere
625
626 server_version = "TestHTTPS/1.0"
627
628 root = None
629
630 def translate_path(self, path):
631 """Translate a /-separated PATH to the local filename syntax.
632
633 Components that mean special things to the local file system
634 (e.g. drive or directory names) are ignored. (XXX They should
635 probably be diagnosed.)
636
637 """
638 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000639 path = urllib.parse.urlparse(path)[2]
640 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000641 words = path.split('/')
642 words = filter(None, words)
643 path = self.root
644 for word in words:
645 drive, word = os.path.splitdrive(word)
646 head, word = os.path.split(word)
647 if word in self.root: continue
648 path = os.path.join(path, word)
649 return path
650
651 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000652 # we override this to suppress logging unless "verbose"
653
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000654 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000655 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
656 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657 self.server.server_port,
658 self.request.cipher(),
659 self.log_date_time_string(),
660 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000661
662
Trent Nelson78520002008-04-10 20:54:35 +0000663 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000664 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
666 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000667 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
668 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000669 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000670 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000671
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000672 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000673 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000674
Antoine Pitrou480a1242010-04-28 21:37:09 +0000675 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000676 self.flag = flag
677 threading.Thread.start(self)
678
Antoine Pitrou480a1242010-04-28 21:37:09 +0000679 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000680 if self.flag:
681 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000682 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000683
Antoine Pitrou480a1242010-04-28 21:37:09 +0000684 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000685 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000686
687
Bill Janssen54cc54c2007-12-14 22:08:56 +0000688 class AsyncoreEchoServer(threading.Thread):
689
690 # this one's based on asyncore.dispatcher
691
692 class EchoServer (asyncore.dispatcher):
693
694 class ConnectionHandler (asyncore.dispatcher_with_send):
695
696 def __init__(self, conn, certfile):
697 self.socket = ssl.wrap_socket(conn, server_side=True,
698 certfile=certfile,
699 do_handshake_on_connect=False)
700 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000701 self._ssl_accepting = True
702 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000703
704 def readable(self):
705 if isinstance(self.socket, ssl.SSLSocket):
706 while self.socket.pending() > 0:
707 self.handle_read_event()
708 return True
709
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000710 def _do_ssl_handshake(self):
711 try:
712 self.socket.do_handshake()
713 except ssl.SSLError as err:
714 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
715 ssl.SSL_ERROR_WANT_WRITE):
716 return
717 elif err.args[0] == ssl.SSL_ERROR_EOF:
718 return self.handle_close()
719 raise
720 except socket.error as err:
721 if err.args[0] == errno.ECONNABORTED:
722 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000723 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000724 self._ssl_accepting = False
725
726 def handle_read(self):
727 if self._ssl_accepting:
728 self._do_ssl_handshake()
729 else:
730 data = self.recv(1024)
731 if support.verbose:
732 sys.stdout.write(" server: read %s from client\n" % repr(data))
733 if not data:
734 self.close()
735 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000736 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000737
738 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000739 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000740 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000741 sys.stdout.write(" server: closed connection %s\n" % self.socket)
742
743 def handle_error(self):
744 raise
745
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000746 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000747 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000748 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
749 self.port = support.bind_port(sock, '')
750 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000751 self.listen(5)
752
753 def handle_accept(self):
754 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000755 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000756 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
757 self.ConnectionHandler(sock_obj, self.certfile)
758
759 def handle_error(self):
760 raise
761
Trent Nelson78520002008-04-10 20:54:35 +0000762 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000763 self.flag = None
764 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000765 self.server = self.EchoServer(certfile)
766 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000767 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000768 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000769
770 def __str__(self):
771 return "<%s %s>" % (self.__class__.__name__, self.server)
772
773 def start (self, flag=None):
774 self.flag = flag
775 threading.Thread.start(self)
776
Antoine Pitrou480a1242010-04-28 21:37:09 +0000777 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000778 self.active = True
779 if self.flag:
780 self.flag.set()
781 while self.active:
782 try:
783 asyncore.loop(1)
784 except:
785 pass
786
Antoine Pitrou480a1242010-04-28 21:37:09 +0000787 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000788 self.active = False
789 self.server.close()
790
Antoine Pitrou480a1242010-04-28 21:37:09 +0000791 def bad_cert_test(certfile):
792 """
793 Launch a server with CERT_REQUIRED, and check that trying to
794 connect to it with the given client certificate fails.
795 """
Trent Nelson78520002008-04-10 20:54:35 +0000796 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000797 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000798 cacerts=CERTFILE, chatty=False,
799 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000800 flag = threading.Event()
801 server.start(flag)
802 # wait for it to start
803 flag.wait()
804 # try to connect
805 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000806 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000807 s = ssl.wrap_socket(socket.socket(),
808 certfile=certfile,
809 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000810 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000811 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000812 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000813 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000814 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000815 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000816 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000817 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000818 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000819 finally:
820 server.stop()
821 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000822
Antoine Pitrou480a1242010-04-28 21:37:09 +0000823 def server_params_test(certfile, protocol, certreqs, cacertsfile,
824 client_certfile, client_protocol=None, indata=b"FOO\n",
825 ciphers=None, chatty=True, connectionchatty=False):
826 """
827 Launch a server, connect a client to it and try various reads
828 and writes.
829 """
Trent Nelson78520002008-04-10 20:54:35 +0000830 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000831 certreqs=certreqs,
832 ssl_version=protocol,
833 cacerts=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000834 ciphers=ciphers,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000835 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000836 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000837 flag = threading.Event()
838 server.start(flag)
839 # wait for it to start
840 flag.wait()
841 # try to connect
842 if client_protocol is None:
843 client_protocol = protocol
844 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000845 s = ssl.wrap_socket(socket.socket(),
846 certfile=client_certfile,
847 ca_certs=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000848 ciphers=ciphers,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000849 cert_reqs=certreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000850 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000851 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000852 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000853 if connectionchatty:
854 if support.verbose:
855 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000856 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000857 s.write(arg)
858 outdata = s.read()
859 if connectionchatty:
860 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000861 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000862 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000863 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000864 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
865 % (outdata[:20], len(outdata),
866 indata[:20].lower(), len(indata)))
867 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000868 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000869 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000870 sys.stdout.write(" client: closing connection.\n")
871 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 finally:
873 server.stop()
874 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000875
Antoine Pitrou480a1242010-04-28 21:37:09 +0000876 def try_protocol_combo(server_protocol,
877 client_protocol,
878 expect_success,
879 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000880 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000882 certtype = {
883 ssl.CERT_NONE: "CERT_NONE",
884 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
885 ssl.CERT_REQUIRED: "CERT_REQUIRED",
886 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000887 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000888 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000889 sys.stdout.write(formatstr %
890 (ssl.get_protocol_name(client_protocol),
891 ssl.get_protocol_name(server_protocol),
892 certtype))
893 try:
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000894 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
895 # will send an SSLv3 hello (rather than SSLv2) starting from
896 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou480a1242010-04-28 21:37:09 +0000897 server_params_test(CERTFILE, server_protocol, certsreqs,
898 CERTFILE, CERTFILE, client_protocol,
899 ciphers="ALL", chatty=False,
900 connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000901 # Protocol mismatch can result in either an SSLError, or a
902 # "Connection reset by peer" error.
903 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000904 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000906 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000907 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000908 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000910 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000911 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 "Client protocol %s succeeded with server protocol %s!"
913 % (ssl.get_protocol_name(client_protocol),
914 ssl.get_protocol_name(server_protocol)))
915
916
Bill Janssen6e027db2007-11-15 22:23:56 +0000917 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918
Antoine Pitrou480a1242010-04-28 21:37:09 +0000919 def test_echo(self):
920 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000921 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000923 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
924 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
925 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000926
Antoine Pitrou480a1242010-04-28 21:37:09 +0000927 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000928 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000929 sys.stdout.write("\n")
930 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000931 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000932 certreqs=ssl.CERT_NONE,
933 ssl_version=ssl.PROTOCOL_SSLv23,
934 cacerts=CERTFILE,
935 chatty=False)
936 flag = threading.Event()
937 server.start(flag)
938 # wait for it to start
939 flag.wait()
940 # try to connect
941 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000942 s = ssl.wrap_socket(socket.socket(),
943 certfile=CERTFILE,
944 ca_certs=CERTFILE,
945 cert_reqs=ssl.CERT_REQUIRED,
946 ssl_version=ssl.PROTOCOL_SSLv23)
947 s.connect((HOST, server.port))
948 cert = s.getpeercert()
949 self.assertTrue(cert, "Can't get peer certificate.")
950 cipher = s.cipher()
951 if support.verbose:
952 sys.stdout.write(pprint.pformat(cert) + '\n')
953 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
954 if 'subject' not in cert:
955 self.fail("No subject field in certificate: %s." %
956 pprint.pformat(cert))
957 if ((('organizationName', 'Python Software Foundation'),)
958 not in cert['subject']):
959 self.fail(
960 "Missing or invalid 'organizationName' field in certificate subject; "
961 "should be 'Python Software Foundation'.")
962 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963 finally:
964 server.stop()
965 server.join()
966
Antoine Pitrou480a1242010-04-28 21:37:09 +0000967 def test_empty_cert(self):
968 """Connecting with an empty cert file"""
969 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
970 "nullcert.pem"))
971 def test_malformed_cert(self):
972 """Connecting with a badly formatted certificate (syntax error)"""
973 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
974 "badcert.pem"))
975 def test_nonexisting_cert(self):
976 """Connecting with a non-existing cert file"""
977 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
978 "wrongcert.pem"))
979 def test_malformed_key(self):
980 """Connecting with a badly formatted key (syntax error)"""
981 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
982 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000983
Antoine Pitrou480a1242010-04-28 21:37:09 +0000984 def test_rude_shutdown(self):
985 """A brutal shutdown of an SSL server should raise an IOError
986 in the client when attempting handshake.
987 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000988 listener_ready = threading.Event()
989 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000990
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000991 s = socket.socket()
992 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000993
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000994 # `listener` runs in a thread. It sits in an accept() until
995 # the main thread connects. Then it rudely closes the socket,
996 # and sets Event `listener_gone` to let the main thread know
997 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000998 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000999 s.listen(5)
1000 listener_ready.set()
1001 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001002 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001003 listener_gone.set()
1004
1005 def connector():
1006 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001007 c = socket.socket()
1008 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001009 listener_gone.wait()
1010 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001011 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001012 except IOError:
1013 pass
1014 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001015 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001016
1017 t = threading.Thread(target=listener)
1018 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001019 try:
1020 connector()
1021 finally:
1022 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001023
Antoine Pitrou480a1242010-04-28 21:37:09 +00001024 def test_protocol_sslv2(self):
1025 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001026 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001028 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1029 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1030 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1031 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1032 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1033 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034
Antoine Pitrou480a1242010-04-28 21:37:09 +00001035 def test_protocol_sslv23(self):
1036 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001037 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001038 sys.stdout.write("\n")
1039 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001040 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001041 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001042 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001043 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001044 sys.stdout.write(
1045 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1046 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001047 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1048 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1049 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001050
Antoine Pitrou480a1242010-04-28 21:37:09 +00001051 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1052 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1053 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001054
Antoine Pitrou480a1242010-04-28 21:37:09 +00001055 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1056 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1057 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001058
Antoine Pitrou480a1242010-04-28 21:37:09 +00001059 def test_protocol_sslv3(self):
1060 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001061 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001062 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001063 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1064 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1065 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1066 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1067 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1068 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001069
Antoine Pitrou480a1242010-04-28 21:37:09 +00001070 def test_protocol_tlsv1(self):
1071 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001072 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001074 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1075 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1076 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1077 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1078 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1079 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001080
Antoine Pitrou480a1242010-04-28 21:37:09 +00001081 def test_starttls(self):
1082 """Switching from clear text to encrypted and back again."""
1083 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 +00001084
Trent Nelson78520002008-04-10 20:54:35 +00001085 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086 ssl_version=ssl.PROTOCOL_TLSv1,
1087 starttls_server=True,
1088 chatty=True,
1089 connectionchatty=True)
1090 flag = threading.Event()
1091 server.start(flag)
1092 # wait for it to start
1093 flag.wait()
1094 # try to connect
1095 wrapped = False
1096 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001097 s = socket.socket()
1098 s.setblocking(1)
1099 s.connect((HOST, server.port))
1100 if support.verbose:
1101 sys.stdout.write("\n")
1102 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001103 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001104 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001105 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001106 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001107 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001108 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001110 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001111 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001112 msg = outdata.strip().lower()
1113 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1114 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001115 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001116 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001117 " client: read %r from server, starting TLS...\n"
1118 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001119 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1120 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001121 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1122 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001123 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001124 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001125 " client: read %r from server, ending TLS...\n"
1126 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001127 s = conn.unwrap()
1128 wrapped = False
1129 else:
1130 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001131 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001132 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001133 if support.verbose:
1134 sys.stdout.write(" client: closing connection.\n")
1135 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001136 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001137 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001138 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001139 if wrapped:
1140 conn.close()
1141 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001142 s.close()
1143 finally:
1144 server.stop()
1145 server.join()
1146
Antoine Pitrou480a1242010-04-28 21:37:09 +00001147 def test_socketserver(self):
1148 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001149 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 flag = threading.Event()
1151 server.start(flag)
1152 # wait for it to start
1153 flag.wait()
1154 # try to connect
1155 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001156 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001157 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001158 with open(CERTFILE, 'rb') as f:
1159 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001160 d2 = ''
1161 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001162 url = 'https://%s:%d/%s' % (
1163 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001164 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001165 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 if dlen and (int(dlen) > 0):
1167 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001168 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001169 sys.stdout.write(
1170 " client: read %d bytes from remote server '%s'\n"
1171 % (len(d2), server))
1172 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001173 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001175 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001176 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001177 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001178 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001179 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001180 server.join()
1181
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 def test_asyncore_server(self):
1183 """Check the example asyncore integration."""
1184 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001185
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001186 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001187 sys.stdout.write("\n")
1188
Antoine Pitrou480a1242010-04-28 21:37:09 +00001189 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001190 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001191 flag = threading.Event()
1192 server.start(flag)
1193 # wait for it to start
1194 flag.wait()
1195 # try to connect
1196 try:
1197 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001198 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001199 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001200 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001201 " client: sending %r...\n" % indata)
1202 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001203 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001204 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001206 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001207 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001208 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1209 % (outdata[:20], len(outdata),
1210 indata[:20].lower(), len(indata)))
1211 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001212 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001213 sys.stdout.write(" client: closing connection.\n")
1214 s.close()
1215 finally:
1216 server.stop()
1217 server.join()
1218
Antoine Pitrou480a1242010-04-28 21:37:09 +00001219 def test_recv_send(self):
1220 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001221 if support.verbose:
1222 sys.stdout.write("\n")
1223
1224 server = ThreadedEchoServer(CERTFILE,
1225 certreqs=ssl.CERT_NONE,
1226 ssl_version=ssl.PROTOCOL_TLSv1,
1227 cacerts=CERTFILE,
1228 chatty=True,
1229 connectionchatty=False)
1230 flag = threading.Event()
1231 server.start(flag)
1232 # wait for it to start
1233 flag.wait()
1234 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001235 s = ssl.wrap_socket(socket.socket(),
1236 server_side=False,
1237 certfile=CERTFILE,
1238 ca_certs=CERTFILE,
1239 cert_reqs=ssl.CERT_NONE,
1240 ssl_version=ssl.PROTOCOL_TLSv1)
1241 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001242 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001243 # helper methods for standardising recv* method signatures
1244 def _recv_into():
1245 b = bytearray(b"\0"*100)
1246 count = s.recv_into(b)
1247 return b[:count]
1248
1249 def _recvfrom_into():
1250 b = bytearray(b"\0"*100)
1251 count, addr = s.recvfrom_into(b)
1252 return b[:count]
1253
1254 # (name, method, whether to expect success, *args)
1255 send_methods = [
1256 ('send', s.send, True, []),
1257 ('sendto', s.sendto, False, ["some.address"]),
1258 ('sendall', s.sendall, True, []),
1259 ]
1260 recv_methods = [
1261 ('recv', s.recv, True, []),
1262 ('recvfrom', s.recvfrom, False, ["some.address"]),
1263 ('recv_into', _recv_into, True, []),
1264 ('recvfrom_into', _recvfrom_into, False, []),
1265 ]
1266 data_prefix = "PREFIX_"
1267
1268 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001269 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001270 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001271 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001272 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001273 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001274 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001275 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001276 "<<{outdata:r}>> ({nout:d}) received; "
1277 "expected <<{indata:r}>> ({nin:d})\n".format(
1278 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001279 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001280 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001281 )
1282 )
1283 except ValueError as e:
1284 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001285 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001286 "Failed to send with method <<{name:s}>>; "
1287 "expected to succeed.\n".format(name=meth_name)
1288 )
1289 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001290 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001291 "Method <<{name:s}>> failed with unexpected "
1292 "exception message: {exp:s}\n".format(
1293 name=meth_name, exp=e
1294 )
1295 )
1296
1297 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001299 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001300 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001301 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001302 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001303 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001304 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001305 "<<{outdata:r}>> ({nout:d}) received; "
1306 "expected <<{indata:r}>> ({nin:d})\n".format(
1307 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001308 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001309 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001310 )
1311 )
1312 except ValueError as e:
1313 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001314 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001315 "Failed to receive with method <<{name:s}>>; "
1316 "expected to succeed.\n".format(name=meth_name)
1317 )
1318 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001319 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001320 "Method <<{name:s}>> failed with unexpected "
1321 "exception message: {exp:s}\n".format(
1322 name=meth_name, exp=e
1323 )
1324 )
1325 # consume data
1326 s.read()
1327
Antoine Pitrou480a1242010-04-28 21:37:09 +00001328 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001329 s.close()
1330 finally:
1331 server.stop()
1332 server.join()
1333
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001334 def test_handshake_timeout(self):
1335 # Issue #5103: SSL handshake must respect the socket timeout
1336 server = socket.socket(socket.AF_INET)
1337 host = "127.0.0.1"
1338 port = support.bind_port(server)
1339 started = threading.Event()
1340 finish = False
1341
1342 def serve():
1343 server.listen(5)
1344 started.set()
1345 conns = []
1346 while not finish:
1347 r, w, e = select.select([server], [], [], 0.1)
1348 if server in r:
1349 # Let the socket hang around rather than having
1350 # it closed by garbage collection.
1351 conns.append(server.accept()[0])
1352
1353 t = threading.Thread(target=serve)
1354 t.start()
1355 started.wait()
1356
1357 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001358 try:
1359 c = socket.socket(socket.AF_INET)
1360 c.settimeout(0.2)
1361 c.connect((host, port))
1362 # Will attempt handshake and time out
1363 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1364 ssl.wrap_socket, c)
1365 finally:
1366 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001367 try:
1368 c = socket.socket(socket.AF_INET)
1369 c = ssl.wrap_socket(c)
1370 c.settimeout(0.2)
1371 # Will attempt handshake and time out
1372 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1373 c.connect, (host, port))
1374 finally:
1375 c.close()
1376 finally:
1377 finish = True
1378 t.join()
1379 server.close()
1380
Bill Janssen58afe4c2008-09-08 16:45:19 +00001381
Thomas Woutersed03b412007-08-28 21:37:11 +00001382def test_main(verbose=False):
1383 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001384 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001385
Antoine Pitrou152efa22010-05-16 18:19:27 +00001386 for filename in [
1387 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1388 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1389 BADCERT, BADKEY, EMPTYCERT]:
1390 if not os.path.exists(filename):
1391 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001392
Antoine Pitrou152efa22010-05-16 18:19:27 +00001393 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001394
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001395 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001396 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001397
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001398 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001399 thread_info = support.threading_setup()
1400 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001401 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001402
Antoine Pitrou480a1242010-04-28 21:37:09 +00001403 try:
1404 support.run_unittest(*tests)
1405 finally:
1406 if _have_threads:
1407 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001408
1409if __name__ == "__main__":
1410 test_main()