blob: cf5abe2becad495b2efd94b0a0654b9192527113 [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 Pitrou65ec8ae2010-05-16 19:56:32 +0000146 cert_reqs=ssl.CERT_NONE, ciphers="xyzzy")
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 Pitrou65ec8ae2010-05-16 19:56:32 +0000190 ctx.set_ciphers("xyzzy")
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
220 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
221 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
222 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
223 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
224 ctx.load_cert_chain(ONLYCERT)
225 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
226 ctx.load_cert_chain(ONLYKEY)
227 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
228 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
229 # Mismatching key and cert
230 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
231 ctx.load_cert_chain(CERTFILE, ONLYKEY)
232
233 def test_load_verify_locations(self):
234 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
235 ctx.load_verify_locations(CERTFILE)
236 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
237 ctx.load_verify_locations(BYTES_CERTFILE)
238 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
239 self.assertRaises(TypeError, ctx.load_verify_locations)
240 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
241 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
242 ctx.load_verify_locations(WRONGCERT)
243 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
244 ctx.load_verify_locations(BADCERT)
245 ctx.load_verify_locations(CERTFILE, CAPATH)
246 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
247
248
Bill Janssen6e027db2007-11-15 22:23:56 +0000249class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000250
Antoine Pitrou480a1242010-04-28 21:37:09 +0000251 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000252 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
253 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000254 try:
255 s.connect(("svn.python.org", 443))
256 self.assertEqual({}, s.getpeercert())
257 finally:
258 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000259
260 # this should fail because we have no verification certs
261 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
262 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000263 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
264 s.connect, ("svn.python.org", 443))
265 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000266
267 # this should succeed because we specify the root cert
268 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
269 cert_reqs=ssl.CERT_REQUIRED,
270 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
271 try:
272 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000273 self.assertTrue(s.getpeercert())
274 finally:
275 s.close()
276
277 def test_connect_with_context(self):
278 # Same as test_connect, but with a separately created context
279 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
280 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
281 s.connect(("svn.python.org", 443))
282 try:
283 self.assertEqual({}, s.getpeercert())
284 finally:
285 s.close()
286 # This should fail because we have no verification certs
287 ctx.verify_mode = ssl.CERT_REQUIRED
288 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
289 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
290 s.connect, ("svn.python.org", 443))
291 s.close()
292 # This should succeed because we specify the root cert
293 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
294 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
295 s.connect(("svn.python.org", 443))
296 try:
297 cert = s.getpeercert()
298 self.assertTrue(cert)
299 finally:
300 s.close()
301
302 def test_connect_capath(self):
303 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000304 # NOTE: the subject hashing algorithm has been changed between
305 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
306 # contain both versions of each certificate (same content, different
307 # filename) for this test to be portable accross OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000308 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
309 ctx.verify_mode = ssl.CERT_REQUIRED
310 ctx.load_verify_locations(capath=CAPATH)
311 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
312 s.connect(("svn.python.org", 443))
313 try:
314 cert = s.getpeercert()
315 self.assertTrue(cert)
316 finally:
317 s.close()
318 # Same with a bytes `capath` argument
319 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
320 ctx.verify_mode = ssl.CERT_REQUIRED
321 ctx.load_verify_locations(capath=BYTES_CAPATH)
322 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
323 s.connect(("svn.python.org", 443))
324 try:
325 cert = s.getpeercert()
326 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000327 finally:
328 s.close()
329
Antoine Pitroue3220242010-04-24 11:13:53 +0000330 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
331 def test_makefile_close(self):
332 # Issue #5238: creating a file-like object with makefile() shouldn't
333 # delay closing the underlying "real socket" (here tested with its
334 # file descriptor, hence skipping the test under Windows).
335 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
336 ss.connect(("svn.python.org", 443))
337 fd = ss.fileno()
338 f = ss.makefile()
339 f.close()
340 # The fd is still open
341 os.read(fd, 0)
342 # Closing the SSL socket should close the fd too
343 ss.close()
344 gc.collect()
345 with self.assertRaises(OSError) as e:
346 os.read(fd, 0)
347 self.assertEqual(e.exception.errno, errno.EBADF)
348
Antoine Pitrou480a1242010-04-28 21:37:09 +0000349 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000350 s = socket.socket(socket.AF_INET)
351 s.connect(("svn.python.org", 443))
352 s.setblocking(False)
353 s = ssl.wrap_socket(s,
354 cert_reqs=ssl.CERT_NONE,
355 do_handshake_on_connect=False)
356 count = 0
357 while True:
358 try:
359 count += 1
360 s.do_handshake()
361 break
362 except ssl.SSLError as err:
363 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
364 select.select([s], [], [])
365 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
366 select.select([], [s], [])
367 else:
368 raise
369 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000370 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000371 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000372
Antoine Pitrou480a1242010-04-28 21:37:09 +0000373 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000374 pem = ssl.get_server_certificate(("svn.python.org", 443))
375 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000376 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000377
378 return
379
380 try:
381 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
382 except ssl.SSLError as x:
383 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000384 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000385 sys.stdout.write("%s\n" % x)
386 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000387 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000388
389 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
390 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000391 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000392 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000393 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
394
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000395 def test_algorithms(self):
396 # Issue #8484: all algorithms should be available when verifying a
397 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000398 # SHA256 was added in OpenSSL 0.9.8
399 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
400 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000401 # NOTE: https://sha256.tbs-internet.com is another possible test host
402 remote = ("sha2.hboeck.de", 443)
403 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
404 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
405 cert_reqs=ssl.CERT_REQUIRED,
406 ca_certs=sha256_cert,)
407 with support.transient_internet():
408 try:
409 s.connect(remote)
410 if support.verbose:
411 sys.stdout.write("\nCipher with %r is %r\n" %
412 (remote, s.cipher()))
413 sys.stdout.write("Certificate is:\n%s\n" %
414 pprint.pformat(s.getpeercert()))
415 finally:
416 s.close()
417
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000418
419try:
420 import threading
421except ImportError:
422 _have_threads = False
423else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000424 _have_threads = True
425
426 class ThreadedEchoServer(threading.Thread):
427
428 class ConnectionHandler(threading.Thread):
429
430 """A mildly complicated class, because we want it to work both
431 with and without the SSL wrapper around the socket connection, so
432 that we can test the STARTTLS functionality."""
433
Bill Janssen6e027db2007-11-15 22:23:56 +0000434 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000435 self.server = server
436 self.running = False
437 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000438 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000439 self.sock.setblocking(1)
440 self.sslconn = None
441 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000442 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000443
Antoine Pitrou480a1242010-04-28 21:37:09 +0000444 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000445 try:
446 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
447 certfile=self.server.certificate,
448 ssl_version=self.server.protocol,
449 ca_certs=self.server.cacerts,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000450 cert_reqs=self.server.certreqs,
451 ciphers=self.server.ciphers)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000452 except ssl.SSLError:
453 # XXX Various errors can have happened here, for example
454 # a mismatching protocol version, an invalid certificate,
455 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000456 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000457 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000458 self.running = False
459 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000460 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000461 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000462 else:
463 if self.server.certreqs == ssl.CERT_REQUIRED:
464 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000465 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000466 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
467 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000468 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000469 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
470 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000471 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000472 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
473 return True
474
475 def read(self):
476 if self.sslconn:
477 return self.sslconn.read()
478 else:
479 return self.sock.recv(1024)
480
481 def write(self, bytes):
482 if self.sslconn:
483 return self.sslconn.write(bytes)
484 else:
485 return self.sock.send(bytes)
486
487 def close(self):
488 if self.sslconn:
489 self.sslconn.close()
490 else:
491 self.sock.close()
492
Antoine Pitrou480a1242010-04-28 21:37:09 +0000493 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000494 self.running = True
495 if not self.server.starttls_server:
496 if not self.wrap_conn():
497 return
498 while self.running:
499 try:
500 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000501 stripped = msg.strip()
502 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000503 # eof, so quit this handler
504 self.running = False
505 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000506 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000507 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000508 sys.stdout.write(" server: client closed connection\n")
509 self.close()
510 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000511 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000512 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000513 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000514 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000515 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000516 if not self.wrap_conn():
517 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000518 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000519 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000520 if support.verbose and self.server.connectionchatty:
521 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000522 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000523 self.sock = self.sslconn.unwrap()
524 self.sslconn = None
525 if support.verbose and self.server.connectionchatty:
526 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000527 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000528 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000529 self.server.connectionchatty):
530 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000531 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
532 % (msg, ctype, msg.lower(), ctype))
533 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000534 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000535 if self.server.chatty:
536 handle_error("Test server failure:\n")
537 self.close()
538 self.running = False
539 # normally, we'd just stop here, but for the test
540 # harness, we want to stop the server
541 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000542
Trent Nelson78520002008-04-10 20:54:35 +0000543 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000544 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000545 chatty=True, connectionchatty=False, starttls_server=False,
546 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000547 if ssl_version is None:
548 ssl_version = ssl.PROTOCOL_TLSv1
549 if certreqs is None:
550 certreqs = ssl.CERT_NONE
551 self.certificate = certificate
552 self.protocol = ssl_version
553 self.certreqs = certreqs
554 self.cacerts = cacerts
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000555 self.ciphers = ciphers
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000556 self.chatty = chatty
557 self.connectionchatty = connectionchatty
558 self.starttls_server = starttls_server
559 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000560 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000561 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000562 self.active = False
563 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000564 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000565
Antoine Pitrou480a1242010-04-28 21:37:09 +0000566 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000567 self.flag = flag
568 threading.Thread.start(self)
569
Antoine Pitrou480a1242010-04-28 21:37:09 +0000570 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000571 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000572 self.sock.listen(5)
573 self.active = True
574 if self.flag:
575 # signal an event
576 self.flag.set()
577 while self.active:
578 try:
579 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000580 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000581 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000582 + repr(connaddr) + '\n')
583 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000584 handler.start()
585 except socket.timeout:
586 pass
587 except KeyboardInterrupt:
588 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000589 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000590
Antoine Pitrou480a1242010-04-28 21:37:09 +0000591 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000593
Bill Janssen54cc54c2007-12-14 22:08:56 +0000594 class OurHTTPSServer(threading.Thread):
595
596 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000597
598 class HTTPSServer(HTTPServer):
599
600 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000601 HTTPServer.__init__(self, server_address, RequestHandlerClass)
602 # we assume the certfile contains both private key and certificate
603 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000604 self.allow_reuse_address = True
605
Bill Janssen6e027db2007-11-15 22:23:56 +0000606 def __str__(self):
607 return ('<%s %s:%s>' %
608 (self.__class__.__name__,
609 self.server_name,
610 self.server_port))
611
Antoine Pitrou480a1242010-04-28 21:37:09 +0000612 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000613 # override this to wrap socket with SSL
614 sock, addr = self.socket.accept()
615 sslconn = ssl.wrap_socket(sock, server_side=True,
616 certfile=self.certfile)
617 return sslconn, addr
618
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000619 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000620 # need to override translate_path to get a known root,
621 # instead of using os.curdir, since the test could be
622 # run from anywhere
623
624 server_version = "TestHTTPS/1.0"
625
626 root = None
627
628 def translate_path(self, path):
629 """Translate a /-separated PATH to the local filename syntax.
630
631 Components that mean special things to the local file system
632 (e.g. drive or directory names) are ignored. (XXX They should
633 probably be diagnosed.)
634
635 """
636 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000637 path = urllib.parse.urlparse(path)[2]
638 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 words = path.split('/')
640 words = filter(None, words)
641 path = self.root
642 for word in words:
643 drive, word = os.path.splitdrive(word)
644 head, word = os.path.split(word)
645 if word in self.root: continue
646 path = os.path.join(path, word)
647 return path
648
649 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 # we override this to suppress logging unless "verbose"
651
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000652 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000653 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
654 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000655 self.server.server_port,
656 self.request.cipher(),
657 self.log_date_time_string(),
658 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000659
660
Trent Nelson78520002008-04-10 20:54:35 +0000661 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000663 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
664 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000665 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
666 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000667 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000668 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000669
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000670 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000671 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000672
Antoine Pitrou480a1242010-04-28 21:37:09 +0000673 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000674 self.flag = flag
675 threading.Thread.start(self)
676
Antoine Pitrou480a1242010-04-28 21:37:09 +0000677 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000678 if self.flag:
679 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000680 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000681
Antoine Pitrou480a1242010-04-28 21:37:09 +0000682 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000683 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000684
685
Bill Janssen54cc54c2007-12-14 22:08:56 +0000686 class AsyncoreEchoServer(threading.Thread):
687
688 # this one's based on asyncore.dispatcher
689
690 class EchoServer (asyncore.dispatcher):
691
692 class ConnectionHandler (asyncore.dispatcher_with_send):
693
694 def __init__(self, conn, certfile):
695 self.socket = ssl.wrap_socket(conn, server_side=True,
696 certfile=certfile,
697 do_handshake_on_connect=False)
698 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000699 self._ssl_accepting = True
700 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000701
702 def readable(self):
703 if isinstance(self.socket, ssl.SSLSocket):
704 while self.socket.pending() > 0:
705 self.handle_read_event()
706 return True
707
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000708 def _do_ssl_handshake(self):
709 try:
710 self.socket.do_handshake()
711 except ssl.SSLError as err:
712 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
713 ssl.SSL_ERROR_WANT_WRITE):
714 return
715 elif err.args[0] == ssl.SSL_ERROR_EOF:
716 return self.handle_close()
717 raise
718 except socket.error as err:
719 if err.args[0] == errno.ECONNABORTED:
720 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000721 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000722 self._ssl_accepting = False
723
724 def handle_read(self):
725 if self._ssl_accepting:
726 self._do_ssl_handshake()
727 else:
728 data = self.recv(1024)
729 if support.verbose:
730 sys.stdout.write(" server: read %s from client\n" % repr(data))
731 if not data:
732 self.close()
733 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000734 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000735
736 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000737 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000738 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000739 sys.stdout.write(" server: closed connection %s\n" % self.socket)
740
741 def handle_error(self):
742 raise
743
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000744 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000745 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000746 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
747 self.port = support.bind_port(sock, '')
748 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000749 self.listen(5)
750
751 def handle_accept(self):
752 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000753 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000754 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
755 self.ConnectionHandler(sock_obj, self.certfile)
756
757 def handle_error(self):
758 raise
759
Trent Nelson78520002008-04-10 20:54:35 +0000760 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000761 self.flag = None
762 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000763 self.server = self.EchoServer(certfile)
764 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000765 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000766 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000767
768 def __str__(self):
769 return "<%s %s>" % (self.__class__.__name__, self.server)
770
771 def start (self, flag=None):
772 self.flag = flag
773 threading.Thread.start(self)
774
Antoine Pitrou480a1242010-04-28 21:37:09 +0000775 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000776 self.active = True
777 if self.flag:
778 self.flag.set()
779 while self.active:
780 try:
781 asyncore.loop(1)
782 except:
783 pass
784
Antoine Pitrou480a1242010-04-28 21:37:09 +0000785 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000786 self.active = False
787 self.server.close()
788
Antoine Pitrou480a1242010-04-28 21:37:09 +0000789 def bad_cert_test(certfile):
790 """
791 Launch a server with CERT_REQUIRED, and check that trying to
792 connect to it with the given client certificate fails.
793 """
Trent Nelson78520002008-04-10 20:54:35 +0000794 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000795 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000796 cacerts=CERTFILE, chatty=False,
797 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000798 flag = threading.Event()
799 server.start(flag)
800 # wait for it to start
801 flag.wait()
802 # try to connect
803 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000804 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000805 s = ssl.wrap_socket(socket.socket(),
806 certfile=certfile,
807 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000808 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000809 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000810 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000811 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000812 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000813 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000814 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000815 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000816 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000817 finally:
818 server.stop()
819 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000820
Antoine Pitrou480a1242010-04-28 21:37:09 +0000821 def server_params_test(certfile, protocol, certreqs, cacertsfile,
822 client_certfile, client_protocol=None, indata=b"FOO\n",
823 ciphers=None, chatty=True, connectionchatty=False):
824 """
825 Launch a server, connect a client to it and try various reads
826 and writes.
827 """
Trent Nelson78520002008-04-10 20:54:35 +0000828 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829 certreqs=certreqs,
830 ssl_version=protocol,
831 cacerts=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000832 ciphers=ciphers,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000833 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000834 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000835 flag = threading.Event()
836 server.start(flag)
837 # wait for it to start
838 flag.wait()
839 # try to connect
840 if client_protocol is None:
841 client_protocol = protocol
842 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000843 s = ssl.wrap_socket(socket.socket(),
844 certfile=client_certfile,
845 ca_certs=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000846 ciphers=ciphers,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000847 cert_reqs=certreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000848 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000849 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000850 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000851 if connectionchatty:
852 if support.verbose:
853 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000854 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000855 s.write(arg)
856 outdata = s.read()
857 if connectionchatty:
858 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000859 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000860 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000861 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000862 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
863 % (outdata[:20], len(outdata),
864 indata[:20].lower(), len(indata)))
865 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000866 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000867 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000868 sys.stdout.write(" client: closing connection.\n")
869 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 finally:
871 server.stop()
872 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000873
Antoine Pitrou480a1242010-04-28 21:37:09 +0000874 def try_protocol_combo(server_protocol,
875 client_protocol,
876 expect_success,
877 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000878 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000880 certtype = {
881 ssl.CERT_NONE: "CERT_NONE",
882 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
883 ssl.CERT_REQUIRED: "CERT_REQUIRED",
884 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000885 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000886 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000887 sys.stdout.write(formatstr %
888 (ssl.get_protocol_name(client_protocol),
889 ssl.get_protocol_name(server_protocol),
890 certtype))
891 try:
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000892 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
893 # will send an SSLv3 hello (rather than SSLv2) starting from
894 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou480a1242010-04-28 21:37:09 +0000895 server_params_test(CERTFILE, server_protocol, certsreqs,
896 CERTFILE, CERTFILE, client_protocol,
897 ciphers="ALL", chatty=False,
898 connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000899 # Protocol mismatch can result in either an SSLError, or a
900 # "Connection reset by peer" error.
901 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000902 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000904 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000905 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000906 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000908 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000909 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000910 "Client protocol %s succeeded with server protocol %s!"
911 % (ssl.get_protocol_name(client_protocol),
912 ssl.get_protocol_name(server_protocol)))
913
914
Bill Janssen6e027db2007-11-15 22:23:56 +0000915 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000916
Antoine Pitrou480a1242010-04-28 21:37:09 +0000917 def test_echo(self):
918 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000919 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000920 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000921 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
922 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
923 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924
Antoine Pitrou480a1242010-04-28 21:37:09 +0000925 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000926 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000927 sys.stdout.write("\n")
928 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000929 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 certreqs=ssl.CERT_NONE,
931 ssl_version=ssl.PROTOCOL_SSLv23,
932 cacerts=CERTFILE,
933 chatty=False)
934 flag = threading.Event()
935 server.start(flag)
936 # wait for it to start
937 flag.wait()
938 # try to connect
939 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000940 s = ssl.wrap_socket(socket.socket(),
941 certfile=CERTFILE,
942 ca_certs=CERTFILE,
943 cert_reqs=ssl.CERT_REQUIRED,
944 ssl_version=ssl.PROTOCOL_SSLv23)
945 s.connect((HOST, server.port))
946 cert = s.getpeercert()
947 self.assertTrue(cert, "Can't get peer certificate.")
948 cipher = s.cipher()
949 if support.verbose:
950 sys.stdout.write(pprint.pformat(cert) + '\n')
951 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
952 if 'subject' not in cert:
953 self.fail("No subject field in certificate: %s." %
954 pprint.pformat(cert))
955 if ((('organizationName', 'Python Software Foundation'),)
956 not in cert['subject']):
957 self.fail(
958 "Missing or invalid 'organizationName' field in certificate subject; "
959 "should be 'Python Software Foundation'.")
960 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000961 finally:
962 server.stop()
963 server.join()
964
Antoine Pitrou480a1242010-04-28 21:37:09 +0000965 def test_empty_cert(self):
966 """Connecting with an empty cert file"""
967 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
968 "nullcert.pem"))
969 def test_malformed_cert(self):
970 """Connecting with a badly formatted certificate (syntax error)"""
971 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
972 "badcert.pem"))
973 def test_nonexisting_cert(self):
974 """Connecting with a non-existing cert file"""
975 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
976 "wrongcert.pem"))
977 def test_malformed_key(self):
978 """Connecting with a badly formatted key (syntax error)"""
979 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
980 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981
Antoine Pitrou480a1242010-04-28 21:37:09 +0000982 def test_rude_shutdown(self):
983 """A brutal shutdown of an SSL server should raise an IOError
984 in the client when attempting handshake.
985 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000986 listener_ready = threading.Event()
987 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000988
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000989 s = socket.socket()
990 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000991
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000992 # `listener` runs in a thread. It sits in an accept() until
993 # the main thread connects. Then it rudely closes the socket,
994 # and sets Event `listener_gone` to let the main thread know
995 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000996 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000997 s.listen(5)
998 listener_ready.set()
999 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001000 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001001 listener_gone.set()
1002
1003 def connector():
1004 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001005 c = socket.socket()
1006 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001007 listener_gone.wait()
1008 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001009 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001010 except IOError:
1011 pass
1012 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001013 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001014
1015 t = threading.Thread(target=listener)
1016 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001017 try:
1018 connector()
1019 finally:
1020 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001021
Antoine Pitrou480a1242010-04-28 21:37:09 +00001022 def test_protocol_sslv2(self):
1023 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001024 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001025 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1027 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1028 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1029 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1030 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1031 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001032
Antoine Pitrou480a1242010-04-28 21:37:09 +00001033 def test_protocol_sslv23(self):
1034 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001035 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001036 sys.stdout.write("\n")
1037 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001038 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001039 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001040 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001041 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001042 sys.stdout.write(
1043 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1044 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001045 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1046 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1047 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001048
Antoine Pitrou480a1242010-04-28 21:37:09 +00001049 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1050 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1051 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001052
Antoine Pitrou480a1242010-04-28 21:37:09 +00001053 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1054 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1055 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001056
Antoine Pitrou480a1242010-04-28 21:37:09 +00001057 def test_protocol_sslv3(self):
1058 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001059 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001060 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001061 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1062 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1063 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1064 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1065 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1066 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001067
Antoine Pitrou480a1242010-04-28 21:37:09 +00001068 def test_protocol_tlsv1(self):
1069 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001070 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001071 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001072 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1073 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1074 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1075 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1076 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1077 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001078
Antoine Pitrou480a1242010-04-28 21:37:09 +00001079 def test_starttls(self):
1080 """Switching from clear text to encrypted and back again."""
1081 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 +00001082
Trent Nelson78520002008-04-10 20:54:35 +00001083 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001084 ssl_version=ssl.PROTOCOL_TLSv1,
1085 starttls_server=True,
1086 chatty=True,
1087 connectionchatty=True)
1088 flag = threading.Event()
1089 server.start(flag)
1090 # wait for it to start
1091 flag.wait()
1092 # try to connect
1093 wrapped = False
1094 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001095 s = socket.socket()
1096 s.setblocking(1)
1097 s.connect((HOST, server.port))
1098 if support.verbose:
1099 sys.stdout.write("\n")
1100 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001101 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001102 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001103 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001104 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001105 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001106 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001108 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001109 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001110 msg = outdata.strip().lower()
1111 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1112 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001113 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001114 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001115 " client: read %r from server, starting TLS...\n"
1116 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001117 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1118 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001119 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1120 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001121 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001122 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001123 " client: read %r from server, ending TLS...\n"
1124 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001125 s = conn.unwrap()
1126 wrapped = False
1127 else:
1128 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001129 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001130 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001131 if support.verbose:
1132 sys.stdout.write(" client: closing connection.\n")
1133 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001134 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001135 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001136 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001137 if wrapped:
1138 conn.close()
1139 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140 s.close()
1141 finally:
1142 server.stop()
1143 server.join()
1144
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 def test_socketserver(self):
1146 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001147 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148 flag = threading.Event()
1149 server.start(flag)
1150 # wait for it to start
1151 flag.wait()
1152 # try to connect
1153 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001154 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001155 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001156 with open(CERTFILE, 'rb') as f:
1157 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001158 d2 = ''
1159 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001160 url = 'https://%s:%d/%s' % (
1161 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001162 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001163 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001164 if dlen and (int(dlen) > 0):
1165 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001166 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167 sys.stdout.write(
1168 " client: read %d bytes from remote server '%s'\n"
1169 % (len(d2), server))
1170 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001171 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001172 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001173 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001174 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001175 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001176 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001177 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001178 server.join()
1179
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 def test_asyncore_server(self):
1181 """Check the example asyncore integration."""
1182 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001183
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001184 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001185 sys.stdout.write("\n")
1186
Antoine Pitrou480a1242010-04-28 21:37:09 +00001187 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001188 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001189 flag = threading.Event()
1190 server.start(flag)
1191 # wait for it to start
1192 flag.wait()
1193 # try to connect
1194 try:
1195 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001196 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001197 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001198 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001199 " client: sending %r...\n" % indata)
1200 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001201 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001202 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001204 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001205 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001206 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1207 % (outdata[:20], len(outdata),
1208 indata[:20].lower(), len(indata)))
1209 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001210 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001211 sys.stdout.write(" client: closing connection.\n")
1212 s.close()
1213 finally:
1214 server.stop()
1215 server.join()
1216
Antoine Pitrou480a1242010-04-28 21:37:09 +00001217 def test_recv_send(self):
1218 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001219 if support.verbose:
1220 sys.stdout.write("\n")
1221
1222 server = ThreadedEchoServer(CERTFILE,
1223 certreqs=ssl.CERT_NONE,
1224 ssl_version=ssl.PROTOCOL_TLSv1,
1225 cacerts=CERTFILE,
1226 chatty=True,
1227 connectionchatty=False)
1228 flag = threading.Event()
1229 server.start(flag)
1230 # wait for it to start
1231 flag.wait()
1232 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001233 s = ssl.wrap_socket(socket.socket(),
1234 server_side=False,
1235 certfile=CERTFILE,
1236 ca_certs=CERTFILE,
1237 cert_reqs=ssl.CERT_NONE,
1238 ssl_version=ssl.PROTOCOL_TLSv1)
1239 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001240 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001241 # helper methods for standardising recv* method signatures
1242 def _recv_into():
1243 b = bytearray(b"\0"*100)
1244 count = s.recv_into(b)
1245 return b[:count]
1246
1247 def _recvfrom_into():
1248 b = bytearray(b"\0"*100)
1249 count, addr = s.recvfrom_into(b)
1250 return b[:count]
1251
1252 # (name, method, whether to expect success, *args)
1253 send_methods = [
1254 ('send', s.send, True, []),
1255 ('sendto', s.sendto, False, ["some.address"]),
1256 ('sendall', s.sendall, True, []),
1257 ]
1258 recv_methods = [
1259 ('recv', s.recv, True, []),
1260 ('recvfrom', s.recvfrom, False, ["some.address"]),
1261 ('recv_into', _recv_into, True, []),
1262 ('recvfrom_into', _recvfrom_into, False, []),
1263 ]
1264 data_prefix = "PREFIX_"
1265
1266 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001267 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001268 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001269 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001270 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001271 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001272 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001273 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001274 "<<{outdata:r}>> ({nout:d}) received; "
1275 "expected <<{indata:r}>> ({nin:d})\n".format(
1276 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001277 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001278 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001279 )
1280 )
1281 except ValueError as e:
1282 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001283 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001284 "Failed to send with method <<{name:s}>>; "
1285 "expected to succeed.\n".format(name=meth_name)
1286 )
1287 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001288 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001289 "Method <<{name:s}>> failed with unexpected "
1290 "exception message: {exp:s}\n".format(
1291 name=meth_name, exp=e
1292 )
1293 )
1294
1295 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001296 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001297 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001299 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001300 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001301 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001302 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001303 "<<{outdata:r}>> ({nout:d}) received; "
1304 "expected <<{indata:r}>> ({nin:d})\n".format(
1305 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001306 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001307 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001308 )
1309 )
1310 except ValueError as e:
1311 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001312 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001313 "Failed to receive with method <<{name:s}>>; "
1314 "expected to succeed.\n".format(name=meth_name)
1315 )
1316 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001317 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001318 "Method <<{name:s}>> failed with unexpected "
1319 "exception message: {exp:s}\n".format(
1320 name=meth_name, exp=e
1321 )
1322 )
1323 # consume data
1324 s.read()
1325
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001327 s.close()
1328 finally:
1329 server.stop()
1330 server.join()
1331
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001332 def test_handshake_timeout(self):
1333 # Issue #5103: SSL handshake must respect the socket timeout
1334 server = socket.socket(socket.AF_INET)
1335 host = "127.0.0.1"
1336 port = support.bind_port(server)
1337 started = threading.Event()
1338 finish = False
1339
1340 def serve():
1341 server.listen(5)
1342 started.set()
1343 conns = []
1344 while not finish:
1345 r, w, e = select.select([server], [], [], 0.1)
1346 if server in r:
1347 # Let the socket hang around rather than having
1348 # it closed by garbage collection.
1349 conns.append(server.accept()[0])
1350
1351 t = threading.Thread(target=serve)
1352 t.start()
1353 started.wait()
1354
1355 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001356 try:
1357 c = socket.socket(socket.AF_INET)
1358 c.settimeout(0.2)
1359 c.connect((host, port))
1360 # Will attempt handshake and time out
1361 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1362 ssl.wrap_socket, c)
1363 finally:
1364 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001365 try:
1366 c = socket.socket(socket.AF_INET)
1367 c = ssl.wrap_socket(c)
1368 c.settimeout(0.2)
1369 # Will attempt handshake and time out
1370 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1371 c.connect, (host, port))
1372 finally:
1373 c.close()
1374 finally:
1375 finish = True
1376 t.join()
1377 server.close()
1378
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379
Thomas Woutersed03b412007-08-28 21:37:11 +00001380def test_main(verbose=False):
1381 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001382 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001383
Antoine Pitrou152efa22010-05-16 18:19:27 +00001384 for filename in [
1385 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1386 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1387 BADCERT, BADKEY, EMPTYCERT]:
1388 if not os.path.exists(filename):
1389 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001390
Antoine Pitrou152efa22010-05-16 18:19:27 +00001391 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001392
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001393 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001394 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001395
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001396 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001397 thread_info = support.threading_setup()
1398 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001399 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001400
Antoine Pitrou480a1242010-04-28 21:37:09 +00001401 try:
1402 support.run_unittest(*tests)
1403 finally:
1404 if _have_threads:
1405 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001406
1407if __name__ == "__main__":
1408 test_main()