blob: 80c586b5edeed92fc812a18cb99e077fda13d897 [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),
145 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
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"):
189 ctx.set_ciphers("^$:,;?*'dorothyx")
190
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
303 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
304 ctx.verify_mode = ssl.CERT_REQUIRED
305 ctx.load_verify_locations(capath=CAPATH)
306 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
307 s.connect(("svn.python.org", 443))
308 try:
309 cert = s.getpeercert()
310 self.assertTrue(cert)
311 finally:
312 s.close()
313 # Same with a bytes `capath` argument
314 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
315 ctx.verify_mode = ssl.CERT_REQUIRED
316 ctx.load_verify_locations(capath=BYTES_CAPATH)
317 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
318 s.connect(("svn.python.org", 443))
319 try:
320 cert = s.getpeercert()
321 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000322 finally:
323 s.close()
324
Antoine Pitroue3220242010-04-24 11:13:53 +0000325 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
326 def test_makefile_close(self):
327 # Issue #5238: creating a file-like object with makefile() shouldn't
328 # delay closing the underlying "real socket" (here tested with its
329 # file descriptor, hence skipping the test under Windows).
330 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
331 ss.connect(("svn.python.org", 443))
332 fd = ss.fileno()
333 f = ss.makefile()
334 f.close()
335 # The fd is still open
336 os.read(fd, 0)
337 # Closing the SSL socket should close the fd too
338 ss.close()
339 gc.collect()
340 with self.assertRaises(OSError) as e:
341 os.read(fd, 0)
342 self.assertEqual(e.exception.errno, errno.EBADF)
343
Antoine Pitrou480a1242010-04-28 21:37:09 +0000344 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000345 s = socket.socket(socket.AF_INET)
346 s.connect(("svn.python.org", 443))
347 s.setblocking(False)
348 s = ssl.wrap_socket(s,
349 cert_reqs=ssl.CERT_NONE,
350 do_handshake_on_connect=False)
351 count = 0
352 while True:
353 try:
354 count += 1
355 s.do_handshake()
356 break
357 except ssl.SSLError as err:
358 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
359 select.select([s], [], [])
360 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
361 select.select([], [s], [])
362 else:
363 raise
364 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000365 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000366 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000367
Antoine Pitrou480a1242010-04-28 21:37:09 +0000368 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000369 pem = ssl.get_server_certificate(("svn.python.org", 443))
370 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000371 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000372
373 return
374
375 try:
376 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
377 except ssl.SSLError as x:
378 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000379 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000380 sys.stdout.write("%s\n" % x)
381 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000382 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000383
384 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
385 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000386 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000387 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000388 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
389
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000390 def test_algorithms(self):
391 # Issue #8484: all algorithms should be available when verifying a
392 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000393 # SHA256 was added in OpenSSL 0.9.8
394 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
395 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000396 # NOTE: https://sha256.tbs-internet.com is another possible test host
397 remote = ("sha2.hboeck.de", 443)
398 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
399 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
400 cert_reqs=ssl.CERT_REQUIRED,
401 ca_certs=sha256_cert,)
402 with support.transient_internet():
403 try:
404 s.connect(remote)
405 if support.verbose:
406 sys.stdout.write("\nCipher with %r is %r\n" %
407 (remote, s.cipher()))
408 sys.stdout.write("Certificate is:\n%s\n" %
409 pprint.pformat(s.getpeercert()))
410 finally:
411 s.close()
412
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000413
414try:
415 import threading
416except ImportError:
417 _have_threads = False
418else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000419 _have_threads = True
420
421 class ThreadedEchoServer(threading.Thread):
422
423 class ConnectionHandler(threading.Thread):
424
425 """A mildly complicated class, because we want it to work both
426 with and without the SSL wrapper around the socket connection, so
427 that we can test the STARTTLS functionality."""
428
Bill Janssen6e027db2007-11-15 22:23:56 +0000429 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000430 self.server = server
431 self.running = False
432 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000433 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000434 self.sock.setblocking(1)
435 self.sslconn = None
436 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000437 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000438
Antoine Pitrou480a1242010-04-28 21:37:09 +0000439 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000440 try:
441 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
442 certfile=self.server.certificate,
443 ssl_version=self.server.protocol,
444 ca_certs=self.server.cacerts,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000445 cert_reqs=self.server.certreqs,
446 ciphers=self.server.ciphers)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000447 except ssl.SSLError:
448 # XXX Various errors can have happened here, for example
449 # a mismatching protocol version, an invalid certificate,
450 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000451 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000452 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000453 self.running = False
454 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000455 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000456 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000457 else:
458 if self.server.certreqs == ssl.CERT_REQUIRED:
459 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000460 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000461 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
462 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000463 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000464 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
465 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000466 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000467 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
468 return True
469
470 def read(self):
471 if self.sslconn:
472 return self.sslconn.read()
473 else:
474 return self.sock.recv(1024)
475
476 def write(self, bytes):
477 if self.sslconn:
478 return self.sslconn.write(bytes)
479 else:
480 return self.sock.send(bytes)
481
482 def close(self):
483 if self.sslconn:
484 self.sslconn.close()
485 else:
486 self.sock.close()
487
Antoine Pitrou480a1242010-04-28 21:37:09 +0000488 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000489 self.running = True
490 if not self.server.starttls_server:
491 if not self.wrap_conn():
492 return
493 while self.running:
494 try:
495 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000496 stripped = msg.strip()
497 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000498 # eof, so quit this handler
499 self.running = False
500 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000501 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000502 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000503 sys.stdout.write(" server: client closed connection\n")
504 self.close()
505 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000506 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000507 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000508 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000509 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000510 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000511 if not self.wrap_conn():
512 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000513 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000514 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000515 if support.verbose and self.server.connectionchatty:
516 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000517 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000518 self.sock = self.sslconn.unwrap()
519 self.sslconn = None
520 if support.verbose and self.server.connectionchatty:
521 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000522 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000523 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000524 self.server.connectionchatty):
525 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000526 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
527 % (msg, ctype, msg.lower(), ctype))
528 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000529 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000530 if self.server.chatty:
531 handle_error("Test server failure:\n")
532 self.close()
533 self.running = False
534 # normally, we'd just stop here, but for the test
535 # harness, we want to stop the server
536 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000537
Trent Nelson78520002008-04-10 20:54:35 +0000538 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000539 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000540 chatty=True, connectionchatty=False, starttls_server=False,
541 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000542 if ssl_version is None:
543 ssl_version = ssl.PROTOCOL_TLSv1
544 if certreqs is None:
545 certreqs = ssl.CERT_NONE
546 self.certificate = certificate
547 self.protocol = ssl_version
548 self.certreqs = certreqs
549 self.cacerts = cacerts
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000550 self.ciphers = ciphers
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000551 self.chatty = chatty
552 self.connectionchatty = connectionchatty
553 self.starttls_server = starttls_server
554 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000555 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000556 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000557 self.active = False
558 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000559 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000560
Antoine Pitrou480a1242010-04-28 21:37:09 +0000561 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000562 self.flag = flag
563 threading.Thread.start(self)
564
Antoine Pitrou480a1242010-04-28 21:37:09 +0000565 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000566 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000567 self.sock.listen(5)
568 self.active = True
569 if self.flag:
570 # signal an event
571 self.flag.set()
572 while self.active:
573 try:
574 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000575 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000576 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000577 + repr(connaddr) + '\n')
578 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000579 handler.start()
580 except socket.timeout:
581 pass
582 except KeyboardInterrupt:
583 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000584 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000585
Antoine Pitrou480a1242010-04-28 21:37:09 +0000586 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000587 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000588
Bill Janssen54cc54c2007-12-14 22:08:56 +0000589 class OurHTTPSServer(threading.Thread):
590
591 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592
593 class HTTPSServer(HTTPServer):
594
595 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000596 HTTPServer.__init__(self, server_address, RequestHandlerClass)
597 # we assume the certfile contains both private key and certificate
598 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000599 self.allow_reuse_address = True
600
Bill Janssen6e027db2007-11-15 22:23:56 +0000601 def __str__(self):
602 return ('<%s %s:%s>' %
603 (self.__class__.__name__,
604 self.server_name,
605 self.server_port))
606
Antoine Pitrou480a1242010-04-28 21:37:09 +0000607 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000608 # override this to wrap socket with SSL
609 sock, addr = self.socket.accept()
610 sslconn = ssl.wrap_socket(sock, server_side=True,
611 certfile=self.certfile)
612 return sslconn, addr
613
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000614 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000615 # need to override translate_path to get a known root,
616 # instead of using os.curdir, since the test could be
617 # run from anywhere
618
619 server_version = "TestHTTPS/1.0"
620
621 root = None
622
623 def translate_path(self, path):
624 """Translate a /-separated PATH to the local filename syntax.
625
626 Components that mean special things to the local file system
627 (e.g. drive or directory names) are ignored. (XXX They should
628 probably be diagnosed.)
629
630 """
631 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000632 path = urllib.parse.urlparse(path)[2]
633 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634 words = path.split('/')
635 words = filter(None, words)
636 path = self.root
637 for word in words:
638 drive, word = os.path.splitdrive(word)
639 head, word = os.path.split(word)
640 if word in self.root: continue
641 path = os.path.join(path, word)
642 return path
643
644 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645 # we override this to suppress logging unless "verbose"
646
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000647 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000648 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
649 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 self.server.server_port,
651 self.request.cipher(),
652 self.log_date_time_string(),
653 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000654
655
Trent Nelson78520002008-04-10 20:54:35 +0000656 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000658 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
659 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000660 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
661 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000662 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000663 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000664
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000666 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000667
Antoine Pitrou480a1242010-04-28 21:37:09 +0000668 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000669 self.flag = flag
670 threading.Thread.start(self)
671
Antoine Pitrou480a1242010-04-28 21:37:09 +0000672 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000673 if self.flag:
674 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000675 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000676
Antoine Pitrou480a1242010-04-28 21:37:09 +0000677 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000678 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000679
680
Bill Janssen54cc54c2007-12-14 22:08:56 +0000681 class AsyncoreEchoServer(threading.Thread):
682
683 # this one's based on asyncore.dispatcher
684
685 class EchoServer (asyncore.dispatcher):
686
687 class ConnectionHandler (asyncore.dispatcher_with_send):
688
689 def __init__(self, conn, certfile):
690 self.socket = ssl.wrap_socket(conn, server_side=True,
691 certfile=certfile,
692 do_handshake_on_connect=False)
693 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000694 self._ssl_accepting = True
695 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000696
697 def readable(self):
698 if isinstance(self.socket, ssl.SSLSocket):
699 while self.socket.pending() > 0:
700 self.handle_read_event()
701 return True
702
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000703 def _do_ssl_handshake(self):
704 try:
705 self.socket.do_handshake()
706 except ssl.SSLError as err:
707 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
708 ssl.SSL_ERROR_WANT_WRITE):
709 return
710 elif err.args[0] == ssl.SSL_ERROR_EOF:
711 return self.handle_close()
712 raise
713 except socket.error as err:
714 if err.args[0] == errno.ECONNABORTED:
715 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000716 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000717 self._ssl_accepting = False
718
719 def handle_read(self):
720 if self._ssl_accepting:
721 self._do_ssl_handshake()
722 else:
723 data = self.recv(1024)
724 if support.verbose:
725 sys.stdout.write(" server: read %s from client\n" % repr(data))
726 if not data:
727 self.close()
728 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000729 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000730
731 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000732 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000733 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000734 sys.stdout.write(" server: closed connection %s\n" % self.socket)
735
736 def handle_error(self):
737 raise
738
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000739 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000740 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000741 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
742 self.port = support.bind_port(sock, '')
743 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000744 self.listen(5)
745
746 def handle_accept(self):
747 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000748 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000749 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
750 self.ConnectionHandler(sock_obj, self.certfile)
751
752 def handle_error(self):
753 raise
754
Trent Nelson78520002008-04-10 20:54:35 +0000755 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000756 self.flag = None
757 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000758 self.server = self.EchoServer(certfile)
759 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000760 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000761 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000762
763 def __str__(self):
764 return "<%s %s>" % (self.__class__.__name__, self.server)
765
766 def start (self, flag=None):
767 self.flag = flag
768 threading.Thread.start(self)
769
Antoine Pitrou480a1242010-04-28 21:37:09 +0000770 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000771 self.active = True
772 if self.flag:
773 self.flag.set()
774 while self.active:
775 try:
776 asyncore.loop(1)
777 except:
778 pass
779
Antoine Pitrou480a1242010-04-28 21:37:09 +0000780 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000781 self.active = False
782 self.server.close()
783
Antoine Pitrou480a1242010-04-28 21:37:09 +0000784 def bad_cert_test(certfile):
785 """
786 Launch a server with CERT_REQUIRED, and check that trying to
787 connect to it with the given client certificate fails.
788 """
Trent Nelson78520002008-04-10 20:54:35 +0000789 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000790 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000791 cacerts=CERTFILE, chatty=False,
792 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000793 flag = threading.Event()
794 server.start(flag)
795 # wait for it to start
796 flag.wait()
797 # try to connect
798 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000799 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000800 s = ssl.wrap_socket(socket.socket(),
801 certfile=certfile,
802 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000803 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000804 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000805 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000806 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000807 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000808 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000809 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000810 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000811 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000812 finally:
813 server.stop()
814 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000815
Antoine Pitrou480a1242010-04-28 21:37:09 +0000816 def server_params_test(certfile, protocol, certreqs, cacertsfile,
817 client_certfile, client_protocol=None, indata=b"FOO\n",
818 ciphers=None, chatty=True, connectionchatty=False):
819 """
820 Launch a server, connect a client to it and try various reads
821 and writes.
822 """
Trent Nelson78520002008-04-10 20:54:35 +0000823 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000824 certreqs=certreqs,
825 ssl_version=protocol,
826 cacerts=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000827 ciphers=ciphers,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000828 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000829 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000830 flag = threading.Event()
831 server.start(flag)
832 # wait for it to start
833 flag.wait()
834 # try to connect
835 if client_protocol is None:
836 client_protocol = protocol
837 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000838 s = ssl.wrap_socket(socket.socket(),
839 certfile=client_certfile,
840 ca_certs=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000841 ciphers=ciphers,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000842 cert_reqs=certreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000843 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000844 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000845 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000846 if connectionchatty:
847 if support.verbose:
848 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000849 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000850 s.write(arg)
851 outdata = s.read()
852 if connectionchatty:
853 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000854 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000855 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000856 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000857 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
858 % (outdata[:20], len(outdata),
859 indata[:20].lower(), len(indata)))
860 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000861 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000862 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000863 sys.stdout.write(" client: closing connection.\n")
864 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865 finally:
866 server.stop()
867 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000868
Antoine Pitrou480a1242010-04-28 21:37:09 +0000869 def try_protocol_combo(server_protocol,
870 client_protocol,
871 expect_success,
872 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000873 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000874 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000875 certtype = {
876 ssl.CERT_NONE: "CERT_NONE",
877 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
878 ssl.CERT_REQUIRED: "CERT_REQUIRED",
879 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000880 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000881 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000882 sys.stdout.write(formatstr %
883 (ssl.get_protocol_name(client_protocol),
884 ssl.get_protocol_name(server_protocol),
885 certtype))
886 try:
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000887 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
888 # will send an SSLv3 hello (rather than SSLv2) starting from
889 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou480a1242010-04-28 21:37:09 +0000890 server_params_test(CERTFILE, server_protocol, certsreqs,
891 CERTFILE, CERTFILE, client_protocol,
892 ciphers="ALL", chatty=False,
893 connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000894 # Protocol mismatch can result in either an SSLError, or a
895 # "Connection reset by peer" error.
896 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000897 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000899 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000901 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000902 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000903 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000904 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905 "Client protocol %s succeeded with server protocol %s!"
906 % (ssl.get_protocol_name(client_protocol),
907 ssl.get_protocol_name(server_protocol)))
908
909
Bill Janssen6e027db2007-11-15 22:23:56 +0000910 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911
Antoine Pitrou480a1242010-04-28 21:37:09 +0000912 def test_echo(self):
913 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000914 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000916 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
917 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
918 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919
Antoine Pitrou480a1242010-04-28 21:37:09 +0000920 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000921 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 sys.stdout.write("\n")
923 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000924 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 certreqs=ssl.CERT_NONE,
926 ssl_version=ssl.PROTOCOL_SSLv23,
927 cacerts=CERTFILE,
928 chatty=False)
929 flag = threading.Event()
930 server.start(flag)
931 # wait for it to start
932 flag.wait()
933 # try to connect
934 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000935 s = ssl.wrap_socket(socket.socket(),
936 certfile=CERTFILE,
937 ca_certs=CERTFILE,
938 cert_reqs=ssl.CERT_REQUIRED,
939 ssl_version=ssl.PROTOCOL_SSLv23)
940 s.connect((HOST, server.port))
941 cert = s.getpeercert()
942 self.assertTrue(cert, "Can't get peer certificate.")
943 cipher = s.cipher()
944 if support.verbose:
945 sys.stdout.write(pprint.pformat(cert) + '\n')
946 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
947 if 'subject' not in cert:
948 self.fail("No subject field in certificate: %s." %
949 pprint.pformat(cert))
950 if ((('organizationName', 'Python Software Foundation'),)
951 not in cert['subject']):
952 self.fail(
953 "Missing or invalid 'organizationName' field in certificate subject; "
954 "should be 'Python Software Foundation'.")
955 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000956 finally:
957 server.stop()
958 server.join()
959
Antoine Pitrou480a1242010-04-28 21:37:09 +0000960 def test_empty_cert(self):
961 """Connecting with an empty cert file"""
962 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
963 "nullcert.pem"))
964 def test_malformed_cert(self):
965 """Connecting with a badly formatted certificate (syntax error)"""
966 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
967 "badcert.pem"))
968 def test_nonexisting_cert(self):
969 """Connecting with a non-existing cert file"""
970 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
971 "wrongcert.pem"))
972 def test_malformed_key(self):
973 """Connecting with a badly formatted key (syntax error)"""
974 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
975 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000976
Antoine Pitrou480a1242010-04-28 21:37:09 +0000977 def test_rude_shutdown(self):
978 """A brutal shutdown of an SSL server should raise an IOError
979 in the client when attempting handshake.
980 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000981 listener_ready = threading.Event()
982 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000983
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000984 s = socket.socket()
985 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000986
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000987 # `listener` runs in a thread. It sits in an accept() until
988 # the main thread connects. Then it rudely closes the socket,
989 # and sets Event `listener_gone` to let the main thread know
990 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000991 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000992 s.listen(5)
993 listener_ready.set()
994 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000995 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000996 listener_gone.set()
997
998 def connector():
999 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001000 c = socket.socket()
1001 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001002 listener_gone.wait()
1003 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001004 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001005 except IOError:
1006 pass
1007 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001008 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001009
1010 t = threading.Thread(target=listener)
1011 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001012 try:
1013 connector()
1014 finally:
1015 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001016
Antoine Pitrou480a1242010-04-28 21:37:09 +00001017 def test_protocol_sslv2(self):
1018 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001019 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001020 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001021 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1022 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1023 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1024 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1025 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1026 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027
Antoine Pitrou480a1242010-04-28 21:37:09 +00001028 def test_protocol_sslv23(self):
1029 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001030 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001031 sys.stdout.write("\n")
1032 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001033 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001034 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001035 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001036 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001037 sys.stdout.write(
1038 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1039 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001040 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1041 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1042 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001043
Antoine Pitrou480a1242010-04-28 21:37:09 +00001044 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1045 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1046 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
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_REQUIRED)
1049 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1050 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001051
Antoine Pitrou480a1242010-04-28 21:37:09 +00001052 def test_protocol_sslv3(self):
1053 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001054 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001055 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001056 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1057 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1058 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1059 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1060 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1061 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001062
Antoine Pitrou480a1242010-04-28 21:37:09 +00001063 def test_protocol_tlsv1(self):
1064 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001065 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1068 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1069 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1070 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1071 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1072 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073
Antoine Pitrou480a1242010-04-28 21:37:09 +00001074 def test_starttls(self):
1075 """Switching from clear text to encrypted and back again."""
1076 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 +00001077
Trent Nelson78520002008-04-10 20:54:35 +00001078 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001079 ssl_version=ssl.PROTOCOL_TLSv1,
1080 starttls_server=True,
1081 chatty=True,
1082 connectionchatty=True)
1083 flag = threading.Event()
1084 server.start(flag)
1085 # wait for it to start
1086 flag.wait()
1087 # try to connect
1088 wrapped = False
1089 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001090 s = socket.socket()
1091 s.setblocking(1)
1092 s.connect((HOST, server.port))
1093 if support.verbose:
1094 sys.stdout.write("\n")
1095 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001096 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001097 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001098 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001099 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001100 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001101 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001102 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001103 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001104 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001105 msg = outdata.strip().lower()
1106 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1107 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001108 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001109 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001110 " client: read %r from server, starting TLS...\n"
1111 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001112 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1113 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001114 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1115 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001116 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001117 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001118 " client: read %r from server, ending TLS...\n"
1119 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001120 s = conn.unwrap()
1121 wrapped = False
1122 else:
1123 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001124 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001125 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001126 if support.verbose:
1127 sys.stdout.write(" client: closing connection.\n")
1128 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001129 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001130 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001131 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001132 if wrapped:
1133 conn.close()
1134 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001135 s.close()
1136 finally:
1137 server.stop()
1138 server.join()
1139
Antoine Pitrou480a1242010-04-28 21:37:09 +00001140 def test_socketserver(self):
1141 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001142 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001143 flag = threading.Event()
1144 server.start(flag)
1145 # wait for it to start
1146 flag.wait()
1147 # try to connect
1148 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001149 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001151 with open(CERTFILE, 'rb') as f:
1152 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001153 d2 = ''
1154 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001155 url = 'https://%s:%d/%s' % (
1156 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001157 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001158 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001159 if dlen and (int(dlen) > 0):
1160 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001161 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001162 sys.stdout.write(
1163 " client: read %d bytes from remote server '%s'\n"
1164 % (len(d2), server))
1165 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001166 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001168 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001169 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001170 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001171 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001172 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001173 server.join()
1174
Antoine Pitrou480a1242010-04-28 21:37:09 +00001175 def test_asyncore_server(self):
1176 """Check the example asyncore integration."""
1177 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001178
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001179 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001180 sys.stdout.write("\n")
1181
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001183 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001184 flag = threading.Event()
1185 server.start(flag)
1186 # wait for it to start
1187 flag.wait()
1188 # try to connect
1189 try:
1190 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001191 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001192 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001193 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001194 " client: sending %r...\n" % indata)
1195 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001196 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001197 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001198 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001199 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001200 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001201 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1202 % (outdata[:20], len(outdata),
1203 indata[:20].lower(), len(indata)))
1204 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001205 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001206 sys.stdout.write(" client: closing connection.\n")
1207 s.close()
1208 finally:
1209 server.stop()
1210 server.join()
1211
Antoine Pitrou480a1242010-04-28 21:37:09 +00001212 def test_recv_send(self):
1213 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001214 if support.verbose:
1215 sys.stdout.write("\n")
1216
1217 server = ThreadedEchoServer(CERTFILE,
1218 certreqs=ssl.CERT_NONE,
1219 ssl_version=ssl.PROTOCOL_TLSv1,
1220 cacerts=CERTFILE,
1221 chatty=True,
1222 connectionchatty=False)
1223 flag = threading.Event()
1224 server.start(flag)
1225 # wait for it to start
1226 flag.wait()
1227 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001228 s = ssl.wrap_socket(socket.socket(),
1229 server_side=False,
1230 certfile=CERTFILE,
1231 ca_certs=CERTFILE,
1232 cert_reqs=ssl.CERT_NONE,
1233 ssl_version=ssl.PROTOCOL_TLSv1)
1234 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001235 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001236 # helper methods for standardising recv* method signatures
1237 def _recv_into():
1238 b = bytearray(b"\0"*100)
1239 count = s.recv_into(b)
1240 return b[:count]
1241
1242 def _recvfrom_into():
1243 b = bytearray(b"\0"*100)
1244 count, addr = s.recvfrom_into(b)
1245 return b[:count]
1246
1247 # (name, method, whether to expect success, *args)
1248 send_methods = [
1249 ('send', s.send, True, []),
1250 ('sendto', s.sendto, False, ["some.address"]),
1251 ('sendall', s.sendall, True, []),
1252 ]
1253 recv_methods = [
1254 ('recv', s.recv, True, []),
1255 ('recvfrom', s.recvfrom, False, ["some.address"]),
1256 ('recv_into', _recv_into, True, []),
1257 ('recvfrom_into', _recvfrom_into, False, []),
1258 ]
1259 data_prefix = "PREFIX_"
1260
1261 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001262 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001263 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001264 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001265 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001266 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001267 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001268 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001269 "<<{outdata:r}>> ({nout:d}) received; "
1270 "expected <<{indata:r}>> ({nin:d})\n".format(
1271 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001272 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001273 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001274 )
1275 )
1276 except ValueError as e:
1277 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001278 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001279 "Failed to send with method <<{name:s}>>; "
1280 "expected to succeed.\n".format(name=meth_name)
1281 )
1282 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001283 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001284 "Method <<{name:s}>> failed with unexpected "
1285 "exception message: {exp:s}\n".format(
1286 name=meth_name, exp=e
1287 )
1288 )
1289
1290 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001291 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001292 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001293 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001294 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001295 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001296 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001297 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 "<<{outdata:r}>> ({nout:d}) received; "
1299 "expected <<{indata:r}>> ({nin:d})\n".format(
1300 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001301 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001302 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001303 )
1304 )
1305 except ValueError as e:
1306 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001307 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001308 "Failed to receive with method <<{name:s}>>; "
1309 "expected to succeed.\n".format(name=meth_name)
1310 )
1311 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001312 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001313 "Method <<{name:s}>> failed with unexpected "
1314 "exception message: {exp:s}\n".format(
1315 name=meth_name, exp=e
1316 )
1317 )
1318 # consume data
1319 s.read()
1320
Antoine Pitrou480a1242010-04-28 21:37:09 +00001321 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001322 s.close()
1323 finally:
1324 server.stop()
1325 server.join()
1326
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001327 def test_handshake_timeout(self):
1328 # Issue #5103: SSL handshake must respect the socket timeout
1329 server = socket.socket(socket.AF_INET)
1330 host = "127.0.0.1"
1331 port = support.bind_port(server)
1332 started = threading.Event()
1333 finish = False
1334
1335 def serve():
1336 server.listen(5)
1337 started.set()
1338 conns = []
1339 while not finish:
1340 r, w, e = select.select([server], [], [], 0.1)
1341 if server in r:
1342 # Let the socket hang around rather than having
1343 # it closed by garbage collection.
1344 conns.append(server.accept()[0])
1345
1346 t = threading.Thread(target=serve)
1347 t.start()
1348 started.wait()
1349
1350 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001351 try:
1352 c = socket.socket(socket.AF_INET)
1353 c.settimeout(0.2)
1354 c.connect((host, port))
1355 # Will attempt handshake and time out
1356 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1357 ssl.wrap_socket, c)
1358 finally:
1359 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001360 try:
1361 c = socket.socket(socket.AF_INET)
1362 c = ssl.wrap_socket(c)
1363 c.settimeout(0.2)
1364 # Will attempt handshake and time out
1365 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1366 c.connect, (host, port))
1367 finally:
1368 c.close()
1369 finally:
1370 finish = True
1371 t.join()
1372 server.close()
1373
Bill Janssen58afe4c2008-09-08 16:45:19 +00001374
Thomas Woutersed03b412007-08-28 21:37:11 +00001375def test_main(verbose=False):
1376 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001377 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001378
Antoine Pitrou152efa22010-05-16 18:19:27 +00001379 for filename in [
1380 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1381 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1382 BADCERT, BADKEY, EMPTYCERT]:
1383 if not os.path.exists(filename):
1384 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001385
Antoine Pitrou152efa22010-05-16 18:19:27 +00001386 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001387
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001388 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001389 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001390
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001391 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001392 thread_info = support.threading_setup()
1393 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001394 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001395
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 try:
1397 support.run_unittest(*tests)
1398 finally:
1399 if _have_threads:
1400 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001401
1402if __name__ == "__main__":
1403 test_main()