blob: 36ed3aa91246dd9ae2c63b09bfbb301ee2d6a365 [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
27
Benjamin Petersonee8712c2008-05-20 21:35:26 +000028HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000029PROTOCOLS = [
30 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
31 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
32]
33
34data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
35fsencode = lambda name: name.encode(sys.getfilesystemencoding(), "surrogateescape")
36
37CERTFILE = data_file("keycert.pem")
38BYTES_CERTFILE = fsencode(CERTFILE)
39ONLYCERT = data_file("ssl_cert.pem")
40ONLYKEY = data_file("ssl_key.pem")
41BYTES_ONLYCERT = fsencode(ONLYCERT)
42BYTES_ONLYKEY = fsencode(ONLYKEY)
43CAPATH = data_file("capath")
44BYTES_CAPATH = fsencode(CAPATH)
45
46SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
47
48EMPTYCERT = data_file("nullcert.pem")
49BADCERT = data_file("badcert.pem")
50WRONGCERT = data_file("XXXnonexisting.pem")
51BADKEY = data_file("badkey.pem")
52
Thomas Woutersed03b412007-08-28 21:37:11 +000053
Thomas Woutersed03b412007-08-28 21:37:11 +000054def handle_error(prefix):
55 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000056 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000057 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000058
59
Antoine Pitrou152efa22010-05-16 18:19:27 +000060class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000061
Antoine Pitrou480a1242010-04-28 21:37:09 +000062 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000063 ssl.PROTOCOL_SSLv2
64 ssl.PROTOCOL_SSLv23
65 ssl.PROTOCOL_SSLv3
66 ssl.PROTOCOL_TLSv1
67 ssl.CERT_NONE
68 ssl.CERT_OPTIONAL
69 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitrou480a1242010-04-28 21:37:09 +000071 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000072 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000073 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000074 sys.stdout.write("\n RAND_status is %d (%s)\n"
75 % (v, (v and "sufficient randomness") or
76 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000077 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000078 ssl.RAND_egd(1)
79 except TypeError:
80 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000081 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000082 print("didn't raise TypeError")
83 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000084
Antoine Pitrou480a1242010-04-28 21:37:09 +000085 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000086 # note that this uses an 'unofficial' function in _ssl.c,
87 # provided solely for this test, to exercise the certificate
88 # parsing code
89 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000090 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000091 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +000092
Antoine Pitrou480a1242010-04-28 21:37:09 +000093 def test_DER_to_PEM(self):
94 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
95 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 d1 = ssl.PEM_cert_to_DER_cert(pem)
97 p2 = ssl.DER_cert_to_PEM_cert(d1)
98 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +000099 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000100 if not p2.startswith(ssl.PEM_HEADER + '\n'):
101 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
102 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
103 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000104
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000105 def test_openssl_version(self):
106 n = ssl.OPENSSL_VERSION_NUMBER
107 t = ssl.OPENSSL_VERSION_INFO
108 s = ssl.OPENSSL_VERSION
109 self.assertIsInstance(n, int)
110 self.assertIsInstance(t, tuple)
111 self.assertIsInstance(s, str)
112 # Some sanity checks follow
113 # >= 0.9
114 self.assertGreaterEqual(n, 0x900000)
115 # < 2.0
116 self.assertLess(n, 0x20000000)
117 major, minor, fix, patch, status = t
118 self.assertGreaterEqual(major, 0)
119 self.assertLess(major, 2)
120 self.assertGreaterEqual(minor, 0)
121 self.assertLess(minor, 256)
122 self.assertGreaterEqual(fix, 0)
123 self.assertLess(fix, 256)
124 self.assertGreaterEqual(patch, 0)
125 self.assertLessEqual(patch, 26)
126 self.assertGreaterEqual(status, 0)
127 self.assertLessEqual(status, 15)
128 # Version string as returned by OpenSSL, the format might change
129 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
130 (s, t))
131
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000132 def test_ciphers(self):
133 if not support.is_resource_enabled('network'):
134 return
135 remote = ("svn.python.org", 443)
136 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
137 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
138 s.connect(remote)
139 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
140 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
141 s.connect(remote)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000142 # Error checking can happen at instantiation or when connecting
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000143 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000144 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou65ec8ae2010-05-16 19:56:32 +0000145 cert_reqs=ssl.CERT_NONE, ciphers="xyzzy")
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000146 s.connect(remote)
147
Antoine Pitrou9d543662010-04-23 23:10:32 +0000148 @support.cpython_only
149 def test_refcycle(self):
150 # Issue #7943: an SSL object doesn't create reference cycles with
151 # itself.
152 s = socket.socket(socket.AF_INET)
153 ss = ssl.wrap_socket(s)
154 wr = weakref.ref(ss)
155 del ss
156 self.assertEqual(wr(), None)
157
Antoine Pitrou40f08742010-04-24 22:04:40 +0000158 def test_timeout(self):
159 # Issue #8524: when creating an SSL socket, the timeout of the
160 # original socket should be retained.
161 for timeout in (None, 0.0, 5.0):
162 s = socket.socket(socket.AF_INET)
163 s.settimeout(timeout)
164 ss = ssl.wrap_socket(s)
165 self.assertEqual(timeout, ss.gettimeout())
166
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000167
Antoine Pitrou152efa22010-05-16 18:19:27 +0000168class ContextTests(unittest.TestCase):
169
170 def test_constructor(self):
171 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
172 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
173 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
174 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
175 self.assertRaises(TypeError, ssl.SSLContext)
176 self.assertRaises(ValueError, ssl.SSLContext, -1)
177 self.assertRaises(ValueError, ssl.SSLContext, 42)
178
179 def test_protocol(self):
180 for proto in PROTOCOLS:
181 ctx = ssl.SSLContext(proto)
182 self.assertEqual(ctx.protocol, proto)
183
184 def test_ciphers(self):
185 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
186 ctx.set_ciphers("ALL")
187 ctx.set_ciphers("DEFAULT")
188 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou65ec8ae2010-05-16 19:56:32 +0000189 ctx.set_ciphers("xyzzy")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000190
191 def test_verify(self):
192 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
193 # Default value
194 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
195 ctx.verify_mode = ssl.CERT_OPTIONAL
196 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
197 ctx.verify_mode = ssl.CERT_REQUIRED
198 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
199 ctx.verify_mode = ssl.CERT_NONE
200 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
201 with self.assertRaises(TypeError):
202 ctx.verify_mode = None
203 with self.assertRaises(ValueError):
204 ctx.verify_mode = 42
205
206 def test_load_cert_chain(self):
207 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
208 # Combined key and cert in a single file
209 ctx.load_cert_chain(CERTFILE)
210 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
211 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
212 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
213 ctx.load_cert_chain(WRONGCERT)
214 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
215 ctx.load_cert_chain(BADCERT)
216 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
217 ctx.load_cert_chain(EMPTYCERT)
218 # Separate key and cert
219 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
220 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
221 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
222 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
223 ctx.load_cert_chain(ONLYCERT)
224 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
225 ctx.load_cert_chain(ONLYKEY)
226 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
227 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
228 # Mismatching key and cert
229 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
230 ctx.load_cert_chain(CERTFILE, ONLYKEY)
231
232 def test_load_verify_locations(self):
233 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
234 ctx.load_verify_locations(CERTFILE)
235 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
236 ctx.load_verify_locations(BYTES_CERTFILE)
237 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
238 self.assertRaises(TypeError, ctx.load_verify_locations)
239 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
240 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
241 ctx.load_verify_locations(WRONGCERT)
242 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
243 ctx.load_verify_locations(BADCERT)
244 ctx.load_verify_locations(CERTFILE, CAPATH)
245 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
246
247
Bill Janssen6e027db2007-11-15 22:23:56 +0000248class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000249
Antoine Pitrou480a1242010-04-28 21:37:09 +0000250 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000251 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
252 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000253 try:
254 s.connect(("svn.python.org", 443))
255 self.assertEqual({}, s.getpeercert())
256 finally:
257 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000258
259 # this should fail because we have no verification certs
260 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
261 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000262 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
263 s.connect, ("svn.python.org", 443))
264 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000265
266 # this should succeed because we specify the root cert
267 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
268 cert_reqs=ssl.CERT_REQUIRED,
269 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
270 try:
271 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000272 self.assertTrue(s.getpeercert())
273 finally:
274 s.close()
275
276 def test_connect_with_context(self):
277 # Same as test_connect, but with a separately created context
278 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
279 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
280 s.connect(("svn.python.org", 443))
281 try:
282 self.assertEqual({}, s.getpeercert())
283 finally:
284 s.close()
285 # This should fail because we have no verification certs
286 ctx.verify_mode = ssl.CERT_REQUIRED
287 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
288 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
289 s.connect, ("svn.python.org", 443))
290 s.close()
291 # This should succeed because we specify the root cert
292 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
293 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
294 s.connect(("svn.python.org", 443))
295 try:
296 cert = s.getpeercert()
297 self.assertTrue(cert)
298 finally:
299 s.close()
300
301 def test_connect_capath(self):
302 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000303 # NOTE: the subject hashing algorithm has been changed between
304 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
305 # contain both versions of each certificate (same content, different
306 # filename) for this test to be portable accross OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000307 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
308 ctx.verify_mode = ssl.CERT_REQUIRED
309 ctx.load_verify_locations(capath=CAPATH)
310 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
311 s.connect(("svn.python.org", 443))
312 try:
313 cert = s.getpeercert()
314 self.assertTrue(cert)
315 finally:
316 s.close()
317 # Same with a bytes `capath` argument
318 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
319 ctx.verify_mode = ssl.CERT_REQUIRED
320 ctx.load_verify_locations(capath=BYTES_CAPATH)
321 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
322 s.connect(("svn.python.org", 443))
323 try:
324 cert = s.getpeercert()
325 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000326 finally:
327 s.close()
328
Antoine Pitroue3220242010-04-24 11:13:53 +0000329 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
330 def test_makefile_close(self):
331 # Issue #5238: creating a file-like object with makefile() shouldn't
332 # delay closing the underlying "real socket" (here tested with its
333 # file descriptor, hence skipping the test under Windows).
334 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
335 ss.connect(("svn.python.org", 443))
336 fd = ss.fileno()
337 f = ss.makefile()
338 f.close()
339 # The fd is still open
340 os.read(fd, 0)
341 # Closing the SSL socket should close the fd too
342 ss.close()
343 gc.collect()
344 with self.assertRaises(OSError) as e:
345 os.read(fd, 0)
346 self.assertEqual(e.exception.errno, errno.EBADF)
347
Antoine Pitrou480a1242010-04-28 21:37:09 +0000348 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000349 s = socket.socket(socket.AF_INET)
350 s.connect(("svn.python.org", 443))
351 s.setblocking(False)
352 s = ssl.wrap_socket(s,
353 cert_reqs=ssl.CERT_NONE,
354 do_handshake_on_connect=False)
355 count = 0
356 while True:
357 try:
358 count += 1
359 s.do_handshake()
360 break
361 except ssl.SSLError as err:
362 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
363 select.select([s], [], [])
364 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
365 select.select([], [s], [])
366 else:
367 raise
368 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000369 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000370 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000371
Antoine Pitrou480a1242010-04-28 21:37:09 +0000372 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000373 pem = ssl.get_server_certificate(("svn.python.org", 443))
374 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000375 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000376
377 return
378
379 try:
380 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
381 except ssl.SSLError as x:
382 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000383 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000384 sys.stdout.write("%s\n" % x)
385 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000386 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000387
388 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
389 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000390 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000391 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000392 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
393
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000394 def test_algorithms(self):
395 # Issue #8484: all algorithms should be available when verifying a
396 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000397 # SHA256 was added in OpenSSL 0.9.8
398 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
399 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000400 # NOTE: https://sha256.tbs-internet.com is another possible test host
401 remote = ("sha2.hboeck.de", 443)
402 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
403 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
404 cert_reqs=ssl.CERT_REQUIRED,
405 ca_certs=sha256_cert,)
406 with support.transient_internet():
407 try:
408 s.connect(remote)
409 if support.verbose:
410 sys.stdout.write("\nCipher with %r is %r\n" %
411 (remote, s.cipher()))
412 sys.stdout.write("Certificate is:\n%s\n" %
413 pprint.pformat(s.getpeercert()))
414 finally:
415 s.close()
416
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000417
418try:
419 import threading
420except ImportError:
421 _have_threads = False
422else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000423 _have_threads = True
424
425 class ThreadedEchoServer(threading.Thread):
426
427 class ConnectionHandler(threading.Thread):
428
429 """A mildly complicated class, because we want it to work both
430 with and without the SSL wrapper around the socket connection, so
431 that we can test the STARTTLS functionality."""
432
Bill Janssen6e027db2007-11-15 22:23:56 +0000433 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000434 self.server = server
435 self.running = False
436 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000437 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000438 self.sock.setblocking(1)
439 self.sslconn = None
440 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000441 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000442
Antoine Pitrou480a1242010-04-28 21:37:09 +0000443 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000444 try:
445 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
446 certfile=self.server.certificate,
447 ssl_version=self.server.protocol,
448 ca_certs=self.server.cacerts,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000449 cert_reqs=self.server.certreqs,
450 ciphers=self.server.ciphers)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000451 except ssl.SSLError:
452 # XXX Various errors can have happened here, for example
453 # a mismatching protocol version, an invalid certificate,
454 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000455 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000456 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000457 self.running = False
458 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000459 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000460 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000461 else:
462 if self.server.certreqs == ssl.CERT_REQUIRED:
463 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000464 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000465 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
466 cert_binary = self.sslconn.getpeercert(True)
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(" cert binary is " + str(len(cert_binary)) + " bytes\n")
469 cipher = self.sslconn.cipher()
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(" server: connection cipher is now " + str(cipher) + "\n")
472 return True
473
474 def read(self):
475 if self.sslconn:
476 return self.sslconn.read()
477 else:
478 return self.sock.recv(1024)
479
480 def write(self, bytes):
481 if self.sslconn:
482 return self.sslconn.write(bytes)
483 else:
484 return self.sock.send(bytes)
485
486 def close(self):
487 if self.sslconn:
488 self.sslconn.close()
489 else:
490 self.sock.close()
491
Antoine Pitrou480a1242010-04-28 21:37:09 +0000492 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493 self.running = True
494 if not self.server.starttls_server:
495 if not self.wrap_conn():
496 return
497 while self.running:
498 try:
499 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000500 stripped = msg.strip()
501 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000502 # eof, so quit this handler
503 self.running = False
504 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000505 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000506 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000507 sys.stdout.write(" server: client closed connection\n")
508 self.close()
509 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000510 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000511 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000512 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000513 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000514 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000515 if not self.wrap_conn():
516 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000517 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000518 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000519 if support.verbose and self.server.connectionchatty:
520 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000521 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000522 self.sock = self.sslconn.unwrap()
523 self.sslconn = None
524 if support.verbose and self.server.connectionchatty:
525 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000526 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000527 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 self.server.connectionchatty):
529 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000530 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
531 % (msg, ctype, msg.lower(), ctype))
532 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000533 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000534 if self.server.chatty:
535 handle_error("Test server failure:\n")
536 self.close()
537 self.running = False
538 # normally, we'd just stop here, but for the test
539 # harness, we want to stop the server
540 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000541
Trent Nelson78520002008-04-10 20:54:35 +0000542 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000543 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000544 chatty=True, connectionchatty=False, starttls_server=False,
545 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000546 if ssl_version is None:
547 ssl_version = ssl.PROTOCOL_TLSv1
548 if certreqs is None:
549 certreqs = ssl.CERT_NONE
550 self.certificate = certificate
551 self.protocol = ssl_version
552 self.certreqs = certreqs
553 self.cacerts = cacerts
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000554 self.ciphers = ciphers
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000555 self.chatty = chatty
556 self.connectionchatty = connectionchatty
557 self.starttls_server = starttls_server
558 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000559 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000560 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000561 self.active = False
562 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000563 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000564
Antoine Pitrou480a1242010-04-28 21:37:09 +0000565 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000566 self.flag = flag
567 threading.Thread.start(self)
568
Antoine Pitrou480a1242010-04-28 21:37:09 +0000569 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000570 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000571 self.sock.listen(5)
572 self.active = True
573 if self.flag:
574 # signal an event
575 self.flag.set()
576 while self.active:
577 try:
578 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000579 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000580 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000581 + repr(connaddr) + '\n')
582 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000583 handler.start()
584 except socket.timeout:
585 pass
586 except KeyboardInterrupt:
587 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000588 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000589
Antoine Pitrou480a1242010-04-28 21:37:09 +0000590 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000591 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592
Bill Janssen54cc54c2007-12-14 22:08:56 +0000593 class OurHTTPSServer(threading.Thread):
594
595 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000596
597 class HTTPSServer(HTTPServer):
598
599 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000600 HTTPServer.__init__(self, server_address, RequestHandlerClass)
601 # we assume the certfile contains both private key and certificate
602 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000603 self.allow_reuse_address = True
604
Bill Janssen6e027db2007-11-15 22:23:56 +0000605 def __str__(self):
606 return ('<%s %s:%s>' %
607 (self.__class__.__name__,
608 self.server_name,
609 self.server_port))
610
Antoine Pitrou480a1242010-04-28 21:37:09 +0000611 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000612 # override this to wrap socket with SSL
613 sock, addr = self.socket.accept()
614 sslconn = ssl.wrap_socket(sock, server_side=True,
615 certfile=self.certfile)
616 return sslconn, addr
617
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000618 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000619 # need to override translate_path to get a known root,
620 # instead of using os.curdir, since the test could be
621 # run from anywhere
622
623 server_version = "TestHTTPS/1.0"
624
625 root = None
626
627 def translate_path(self, path):
628 """Translate a /-separated PATH to the local filename syntax.
629
630 Components that mean special things to the local file system
631 (e.g. drive or directory names) are ignored. (XXX They should
632 probably be diagnosed.)
633
634 """
635 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000636 path = urllib.parse.urlparse(path)[2]
637 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000638 words = path.split('/')
639 words = filter(None, words)
640 path = self.root
641 for word in words:
642 drive, word = os.path.splitdrive(word)
643 head, word = os.path.split(word)
644 if word in self.root: continue
645 path = os.path.join(path, word)
646 return path
647
648 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000649 # we override this to suppress logging unless "verbose"
650
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000651 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000652 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
653 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000654 self.server.server_port,
655 self.request.cipher(),
656 self.log_date_time_string(),
657 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000658
659
Trent Nelson78520002008-04-10 20:54:35 +0000660 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000661 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
663 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000664 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
665 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000666 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000667 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000668
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000669 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000670 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000671
Antoine Pitrou480a1242010-04-28 21:37:09 +0000672 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000673 self.flag = flag
674 threading.Thread.start(self)
675
Antoine Pitrou480a1242010-04-28 21:37:09 +0000676 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000677 if self.flag:
678 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000679 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000680
Antoine Pitrou480a1242010-04-28 21:37:09 +0000681 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000682 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000683
684
Bill Janssen54cc54c2007-12-14 22:08:56 +0000685 class AsyncoreEchoServer(threading.Thread):
686
687 # this one's based on asyncore.dispatcher
688
689 class EchoServer (asyncore.dispatcher):
690
691 class ConnectionHandler (asyncore.dispatcher_with_send):
692
693 def __init__(self, conn, certfile):
694 self.socket = ssl.wrap_socket(conn, server_side=True,
695 certfile=certfile,
696 do_handshake_on_connect=False)
697 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000698 self._ssl_accepting = True
699 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000700
701 def readable(self):
702 if isinstance(self.socket, ssl.SSLSocket):
703 while self.socket.pending() > 0:
704 self.handle_read_event()
705 return True
706
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000707 def _do_ssl_handshake(self):
708 try:
709 self.socket.do_handshake()
710 except ssl.SSLError as err:
711 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
712 ssl.SSL_ERROR_WANT_WRITE):
713 return
714 elif err.args[0] == ssl.SSL_ERROR_EOF:
715 return self.handle_close()
716 raise
717 except socket.error as err:
718 if err.args[0] == errno.ECONNABORTED:
719 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000720 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000721 self._ssl_accepting = False
722
723 def handle_read(self):
724 if self._ssl_accepting:
725 self._do_ssl_handshake()
726 else:
727 data = self.recv(1024)
728 if support.verbose:
729 sys.stdout.write(" server: read %s from client\n" % repr(data))
730 if not data:
731 self.close()
732 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000733 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000734
735 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000736 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000737 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000738 sys.stdout.write(" server: closed connection %s\n" % self.socket)
739
740 def handle_error(self):
741 raise
742
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000743 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000744 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000745 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
746 self.port = support.bind_port(sock, '')
747 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000748 self.listen(5)
749
750 def handle_accept(self):
751 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000752 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000753 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
754 self.ConnectionHandler(sock_obj, self.certfile)
755
756 def handle_error(self):
757 raise
758
Trent Nelson78520002008-04-10 20:54:35 +0000759 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000760 self.flag = None
761 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000762 self.server = self.EchoServer(certfile)
763 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000764 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000765 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000766
767 def __str__(self):
768 return "<%s %s>" % (self.__class__.__name__, self.server)
769
770 def start (self, flag=None):
771 self.flag = flag
772 threading.Thread.start(self)
773
Antoine Pitrou480a1242010-04-28 21:37:09 +0000774 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000775 self.active = True
776 if self.flag:
777 self.flag.set()
778 while self.active:
779 try:
780 asyncore.loop(1)
781 except:
782 pass
783
Antoine Pitrou480a1242010-04-28 21:37:09 +0000784 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000785 self.active = False
786 self.server.close()
787
Antoine Pitrou480a1242010-04-28 21:37:09 +0000788 def bad_cert_test(certfile):
789 """
790 Launch a server with CERT_REQUIRED, and check that trying to
791 connect to it with the given client certificate fails.
792 """
Trent Nelson78520002008-04-10 20:54:35 +0000793 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000794 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000795 cacerts=CERTFILE, chatty=False,
796 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000797 flag = threading.Event()
798 server.start(flag)
799 # wait for it to start
800 flag.wait()
801 # try to connect
802 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000803 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000804 s = ssl.wrap_socket(socket.socket(),
805 certfile=certfile,
806 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000807 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000808 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000809 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000810 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000811 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000812 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000813 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000814 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000815 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000816 finally:
817 server.stop()
818 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000819
Antoine Pitrou480a1242010-04-28 21:37:09 +0000820 def server_params_test(certfile, protocol, certreqs, cacertsfile,
821 client_certfile, client_protocol=None, indata=b"FOO\n",
822 ciphers=None, chatty=True, connectionchatty=False):
823 """
824 Launch a server, connect a client to it and try various reads
825 and writes.
826 """
Trent Nelson78520002008-04-10 20:54:35 +0000827 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000828 certreqs=certreqs,
829 ssl_version=protocol,
830 cacerts=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000831 ciphers=ciphers,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000832 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000833 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000834 flag = threading.Event()
835 server.start(flag)
836 # wait for it to start
837 flag.wait()
838 # try to connect
839 if client_protocol is None:
840 client_protocol = protocol
841 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000842 s = ssl.wrap_socket(socket.socket(),
843 certfile=client_certfile,
844 ca_certs=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000845 ciphers=ciphers,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000846 cert_reqs=certreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000847 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000848 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000849 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000850 if connectionchatty:
851 if support.verbose:
852 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000853 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000854 s.write(arg)
855 outdata = s.read()
856 if connectionchatty:
857 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000858 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000859 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000860 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000861 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
862 % (outdata[:20], len(outdata),
863 indata[:20].lower(), len(indata)))
864 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000865 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000866 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000867 sys.stdout.write(" client: closing connection.\n")
868 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000869 finally:
870 server.stop()
871 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000872
Antoine Pitrou480a1242010-04-28 21:37:09 +0000873 def try_protocol_combo(server_protocol,
874 client_protocol,
875 expect_success,
876 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000877 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000879 certtype = {
880 ssl.CERT_NONE: "CERT_NONE",
881 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
882 ssl.CERT_REQUIRED: "CERT_REQUIRED",
883 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000884 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000885 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886 sys.stdout.write(formatstr %
887 (ssl.get_protocol_name(client_protocol),
888 ssl.get_protocol_name(server_protocol),
889 certtype))
890 try:
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000891 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
892 # will send an SSLv3 hello (rather than SSLv2) starting from
893 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou480a1242010-04-28 21:37:09 +0000894 server_params_test(CERTFILE, server_protocol, certsreqs,
895 CERTFILE, CERTFILE, client_protocol,
896 ciphers="ALL", chatty=False,
897 connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000898 # Protocol mismatch can result in either an SSLError, or a
899 # "Connection reset by peer" error.
900 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000901 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000902 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000903 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000904 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000905 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000906 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000907 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000908 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 "Client protocol %s succeeded with server protocol %s!"
910 % (ssl.get_protocol_name(client_protocol),
911 ssl.get_protocol_name(server_protocol)))
912
913
Bill Janssen6e027db2007-11-15 22:23:56 +0000914 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915
Antoine Pitrou480a1242010-04-28 21:37:09 +0000916 def test_echo(self):
917 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000918 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000920 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
921 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
922 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923
Antoine Pitrou480a1242010-04-28 21:37:09 +0000924 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000925 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000926 sys.stdout.write("\n")
927 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000928 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000929 certreqs=ssl.CERT_NONE,
930 ssl_version=ssl.PROTOCOL_SSLv23,
931 cacerts=CERTFILE,
932 chatty=False)
933 flag = threading.Event()
934 server.start(flag)
935 # wait for it to start
936 flag.wait()
937 # try to connect
938 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000939 s = ssl.wrap_socket(socket.socket(),
940 certfile=CERTFILE,
941 ca_certs=CERTFILE,
942 cert_reqs=ssl.CERT_REQUIRED,
943 ssl_version=ssl.PROTOCOL_SSLv23)
944 s.connect((HOST, server.port))
945 cert = s.getpeercert()
946 self.assertTrue(cert, "Can't get peer certificate.")
947 cipher = s.cipher()
948 if support.verbose:
949 sys.stdout.write(pprint.pformat(cert) + '\n')
950 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
951 if 'subject' not in cert:
952 self.fail("No subject field in certificate: %s." %
953 pprint.pformat(cert))
954 if ((('organizationName', 'Python Software Foundation'),)
955 not in cert['subject']):
956 self.fail(
957 "Missing or invalid 'organizationName' field in certificate subject; "
958 "should be 'Python Software Foundation'.")
959 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960 finally:
961 server.stop()
962 server.join()
963
Antoine Pitrou480a1242010-04-28 21:37:09 +0000964 def test_empty_cert(self):
965 """Connecting with an empty cert file"""
966 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
967 "nullcert.pem"))
968 def test_malformed_cert(self):
969 """Connecting with a badly formatted certificate (syntax error)"""
970 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
971 "badcert.pem"))
972 def test_nonexisting_cert(self):
973 """Connecting with a non-existing cert file"""
974 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
975 "wrongcert.pem"))
976 def test_malformed_key(self):
977 """Connecting with a badly formatted key (syntax error)"""
978 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
979 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980
Antoine Pitrou480a1242010-04-28 21:37:09 +0000981 def test_rude_shutdown(self):
982 """A brutal shutdown of an SSL server should raise an IOError
983 in the client when attempting handshake.
984 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000985 listener_ready = threading.Event()
986 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000987
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000988 s = socket.socket()
989 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000990
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000991 # `listener` runs in a thread. It sits in an accept() until
992 # the main thread connects. Then it rudely closes the socket,
993 # and sets Event `listener_gone` to let the main thread know
994 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000995 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000996 s.listen(5)
997 listener_ready.set()
998 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000999 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001000 listener_gone.set()
1001
1002 def connector():
1003 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001004 c = socket.socket()
1005 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001006 listener_gone.wait()
1007 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001008 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001009 except IOError:
1010 pass
1011 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001012 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001013
1014 t = threading.Thread(target=listener)
1015 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001016 try:
1017 connector()
1018 finally:
1019 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001020
Antoine Pitrou480a1242010-04-28 21:37:09 +00001021 def test_protocol_sslv2(self):
1022 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001023 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001024 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001025 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1026 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1027 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1028 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1029 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1030 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001031
Antoine Pitrou480a1242010-04-28 21:37:09 +00001032 def test_protocol_sslv23(self):
1033 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001034 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001035 sys.stdout.write("\n")
1036 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001037 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001038 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001039 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001040 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001041 sys.stdout.write(
1042 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1043 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001044 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1045 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1046 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001047
Antoine Pitrou480a1242010-04-28 21:37:09 +00001048 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1049 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1050 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001051
Antoine Pitrou480a1242010-04-28 21:37:09 +00001052 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1053 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1054 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001055
Antoine Pitrou480a1242010-04-28 21:37:09 +00001056 def test_protocol_sslv3(self):
1057 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001059 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001060 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1061 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1062 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1063 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1064 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1065 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 def test_protocol_tlsv1(self):
1068 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001069 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001070 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001071 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1072 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1073 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1074 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1075 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1076 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077
Antoine Pitrou480a1242010-04-28 21:37:09 +00001078 def test_starttls(self):
1079 """Switching from clear text to encrypted and back again."""
1080 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 +00001081
Trent Nelson78520002008-04-10 20:54:35 +00001082 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001083 ssl_version=ssl.PROTOCOL_TLSv1,
1084 starttls_server=True,
1085 chatty=True,
1086 connectionchatty=True)
1087 flag = threading.Event()
1088 server.start(flag)
1089 # wait for it to start
1090 flag.wait()
1091 # try to connect
1092 wrapped = False
1093 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001094 s = socket.socket()
1095 s.setblocking(1)
1096 s.connect((HOST, server.port))
1097 if support.verbose:
1098 sys.stdout.write("\n")
1099 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001100 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001101 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001102 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001103 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001105 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001106 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001107 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001108 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001109 msg = outdata.strip().lower()
1110 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1111 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001112 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001113 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001114 " client: read %r from server, starting TLS...\n"
1115 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001116 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1117 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001118 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1119 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001120 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001121 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001122 " client: read %r from server, ending TLS...\n"
1123 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001124 s = conn.unwrap()
1125 wrapped = False
1126 else:
1127 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001128 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001129 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001130 if support.verbose:
1131 sys.stdout.write(" client: closing connection.\n")
1132 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001133 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001134 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001135 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001136 if wrapped:
1137 conn.close()
1138 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001139 s.close()
1140 finally:
1141 server.stop()
1142 server.join()
1143
Antoine Pitrou480a1242010-04-28 21:37:09 +00001144 def test_socketserver(self):
1145 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001146 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147 flag = threading.Event()
1148 server.start(flag)
1149 # wait for it to start
1150 flag.wait()
1151 # try to connect
1152 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001153 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001154 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001155 with open(CERTFILE, 'rb') as f:
1156 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001157 d2 = ''
1158 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001159 url = 'https://%s:%d/%s' % (
1160 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001161 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001162 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163 if dlen and (int(dlen) > 0):
1164 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001165 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 sys.stdout.write(
1167 " client: read %d bytes from remote server '%s'\n"
1168 % (len(d2), server))
1169 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001170 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001171 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001172 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001173 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001175 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001176 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001177 server.join()
1178
Antoine Pitrou480a1242010-04-28 21:37:09 +00001179 def test_asyncore_server(self):
1180 """Check the example asyncore integration."""
1181 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001182
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001183 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001184 sys.stdout.write("\n")
1185
Antoine Pitrou480a1242010-04-28 21:37:09 +00001186 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001187 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001188 flag = threading.Event()
1189 server.start(flag)
1190 # wait for it to start
1191 flag.wait()
1192 # try to connect
1193 try:
1194 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001195 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001196 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001197 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001198 " client: sending %r...\n" % indata)
1199 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001200 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001201 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001202 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001203 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001204 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1206 % (outdata[:20], len(outdata),
1207 indata[:20].lower(), len(indata)))
1208 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001209 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001210 sys.stdout.write(" client: closing connection.\n")
1211 s.close()
1212 finally:
1213 server.stop()
1214 server.join()
1215
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 def test_recv_send(self):
1217 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001218 if support.verbose:
1219 sys.stdout.write("\n")
1220
1221 server = ThreadedEchoServer(CERTFILE,
1222 certreqs=ssl.CERT_NONE,
1223 ssl_version=ssl.PROTOCOL_TLSv1,
1224 cacerts=CERTFILE,
1225 chatty=True,
1226 connectionchatty=False)
1227 flag = threading.Event()
1228 server.start(flag)
1229 # wait for it to start
1230 flag.wait()
1231 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001232 s = ssl.wrap_socket(socket.socket(),
1233 server_side=False,
1234 certfile=CERTFILE,
1235 ca_certs=CERTFILE,
1236 cert_reqs=ssl.CERT_NONE,
1237 ssl_version=ssl.PROTOCOL_TLSv1)
1238 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001239 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001240 # helper methods for standardising recv* method signatures
1241 def _recv_into():
1242 b = bytearray(b"\0"*100)
1243 count = s.recv_into(b)
1244 return b[:count]
1245
1246 def _recvfrom_into():
1247 b = bytearray(b"\0"*100)
1248 count, addr = s.recvfrom_into(b)
1249 return b[:count]
1250
1251 # (name, method, whether to expect success, *args)
1252 send_methods = [
1253 ('send', s.send, True, []),
1254 ('sendto', s.sendto, False, ["some.address"]),
1255 ('sendall', s.sendall, True, []),
1256 ]
1257 recv_methods = [
1258 ('recv', s.recv, True, []),
1259 ('recvfrom', s.recvfrom, False, ["some.address"]),
1260 ('recv_into', _recv_into, True, []),
1261 ('recvfrom_into', _recvfrom_into, False, []),
1262 ]
1263 data_prefix = "PREFIX_"
1264
1265 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001266 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001267 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001268 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001269 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001270 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001271 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001272 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001273 "<<{outdata:r}>> ({nout:d}) received; "
1274 "expected <<{indata:r}>> ({nin:d})\n".format(
1275 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001276 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001277 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001278 )
1279 )
1280 except ValueError as e:
1281 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001282 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001283 "Failed to send with method <<{name:s}>>; "
1284 "expected to succeed.\n".format(name=meth_name)
1285 )
1286 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001287 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001288 "Method <<{name:s}>> failed with unexpected "
1289 "exception message: {exp:s}\n".format(
1290 name=meth_name, exp=e
1291 )
1292 )
1293
1294 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001295 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001296 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001297 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001298 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001299 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001300 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001301 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001302 "<<{outdata:r}>> ({nout:d}) received; "
1303 "expected <<{indata:r}>> ({nin:d})\n".format(
1304 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001305 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001306 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001307 )
1308 )
1309 except ValueError as e:
1310 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001311 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001312 "Failed to receive with method <<{name:s}>>; "
1313 "expected to succeed.\n".format(name=meth_name)
1314 )
1315 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001316 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001317 "Method <<{name:s}>> failed with unexpected "
1318 "exception message: {exp:s}\n".format(
1319 name=meth_name, exp=e
1320 )
1321 )
1322 # consume data
1323 s.read()
1324
Antoine Pitrou480a1242010-04-28 21:37:09 +00001325 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001326 s.close()
1327 finally:
1328 server.stop()
1329 server.join()
1330
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001331 def test_handshake_timeout(self):
1332 # Issue #5103: SSL handshake must respect the socket timeout
1333 server = socket.socket(socket.AF_INET)
1334 host = "127.0.0.1"
1335 port = support.bind_port(server)
1336 started = threading.Event()
1337 finish = False
1338
1339 def serve():
1340 server.listen(5)
1341 started.set()
1342 conns = []
1343 while not finish:
1344 r, w, e = select.select([server], [], [], 0.1)
1345 if server in r:
1346 # Let the socket hang around rather than having
1347 # it closed by garbage collection.
1348 conns.append(server.accept()[0])
1349
1350 t = threading.Thread(target=serve)
1351 t.start()
1352 started.wait()
1353
1354 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001355 try:
1356 c = socket.socket(socket.AF_INET)
1357 c.settimeout(0.2)
1358 c.connect((host, port))
1359 # Will attempt handshake and time out
1360 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1361 ssl.wrap_socket, c)
1362 finally:
1363 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001364 try:
1365 c = socket.socket(socket.AF_INET)
1366 c = ssl.wrap_socket(c)
1367 c.settimeout(0.2)
1368 # Will attempt handshake and time out
1369 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1370 c.connect, (host, port))
1371 finally:
1372 c.close()
1373 finally:
1374 finish = True
1375 t.join()
1376 server.close()
1377
Bill Janssen58afe4c2008-09-08 16:45:19 +00001378
Thomas Woutersed03b412007-08-28 21:37:11 +00001379def test_main(verbose=False):
1380 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001381 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001382
Antoine Pitrou152efa22010-05-16 18:19:27 +00001383 for filename in [
1384 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1385 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1386 BADCERT, BADKEY, EMPTYCERT]:
1387 if not os.path.exists(filename):
1388 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001389
Antoine Pitrou152efa22010-05-16 18:19:27 +00001390 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001391
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001392 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001393 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001394
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001396 thread_info = support.threading_setup()
1397 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001398 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001399
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 try:
1401 support.run_unittest(*tests)
1402 finally:
1403 if _have_threads:
1404 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001405
1406if __name__ == "__main__":
1407 test_main()