blob: 9c0d263e0f1e634eeaf746c1ef81e714ec37d5e5 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Jeremy Hylton1afc1692008-06-18 20:49:58 +000014import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Thomas Woutersed03b412007-08-28 21:37:11 +000018
Georg Brandl24420152008-05-26 16:32:26 +000019from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000020
Thomas Woutersed03b412007-08-28 21:37:11 +000021# Optionally test SSL support, if we have it in the tested platform
22skip_expected = False
23try:
24 import ssl
25except ImportError:
26 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000027else:
28 PROTOCOLS = [
29 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
30 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
31 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000032
Benjamin Petersonee8712c2008-05-20 21:35:26 +000033HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000034
35data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
37CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000038BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000039ONLYCERT = data_file("ssl_cert.pem")
40ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000041BYTES_ONLYCERT = os.fsencode(ONLYCERT)
42BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000043CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000044BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045
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
Antoine Pitroub5218772010-05-21 09:56:06 +000059def can_clear_options():
60 # 0.9.8m or higher
61 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
62
63def no_sslv2_implies_sslv3_hello():
64 # 0.9.7h or higher
65 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
66
Thomas Woutersed03b412007-08-28 21:37:11 +000067
Antoine Pitrou152efa22010-05-16 18:19:27 +000068class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou480a1242010-04-28 21:37:09 +000070 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000071 ssl.PROTOCOL_SSLv2
72 ssl.PROTOCOL_SSLv23
73 ssl.PROTOCOL_SSLv3
74 ssl.PROTOCOL_TLSv1
75 ssl.CERT_NONE
76 ssl.CERT_OPTIONAL
77 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000078
Antoine Pitrou480a1242010-04-28 21:37:09 +000079 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000080 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000081 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000082 sys.stdout.write("\n RAND_status is %d (%s)\n"
83 % (v, (v and "sufficient randomness") or
84 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000085 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000086 ssl.RAND_egd(1)
87 except TypeError:
88 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000089 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000090 print("didn't raise TypeError")
91 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000092
Antoine Pitrou480a1242010-04-28 21:37:09 +000093 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000094 # note that this uses an 'unofficial' function in _ssl.c,
95 # provided solely for this test, to exercise the certificate
96 # parsing code
97 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000098 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000099 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000100
Antoine Pitrou480a1242010-04-28 21:37:09 +0000101 def test_DER_to_PEM(self):
102 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
103 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000104 d1 = ssl.PEM_cert_to_DER_cert(pem)
105 p2 = ssl.DER_cert_to_PEM_cert(d1)
106 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000107 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000108 if not p2.startswith(ssl.PEM_HEADER + '\n'):
109 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
110 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
111 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000112
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000113 def test_openssl_version(self):
114 n = ssl.OPENSSL_VERSION_NUMBER
115 t = ssl.OPENSSL_VERSION_INFO
116 s = ssl.OPENSSL_VERSION
117 self.assertIsInstance(n, int)
118 self.assertIsInstance(t, tuple)
119 self.assertIsInstance(s, str)
120 # Some sanity checks follow
121 # >= 0.9
122 self.assertGreaterEqual(n, 0x900000)
123 # < 2.0
124 self.assertLess(n, 0x20000000)
125 major, minor, fix, patch, status = t
126 self.assertGreaterEqual(major, 0)
127 self.assertLess(major, 2)
128 self.assertGreaterEqual(minor, 0)
129 self.assertLess(minor, 256)
130 self.assertGreaterEqual(fix, 0)
131 self.assertLess(fix, 256)
132 self.assertGreaterEqual(patch, 0)
133 self.assertLessEqual(patch, 26)
134 self.assertGreaterEqual(status, 0)
135 self.assertLessEqual(status, 15)
136 # Version string as returned by OpenSSL, the format might change
137 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
138 (s, t))
139
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000140 def test_ciphers(self):
141 if not support.is_resource_enabled('network'):
142 return
143 remote = ("svn.python.org", 443)
144 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
145 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
146 s.connect(remote)
147 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
148 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
149 s.connect(remote)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000150 # Error checking can happen at instantiation or when connecting
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000151 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000152 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou30474062010-05-16 23:46:26 +0000153 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000154 s.connect(remote)
155
Antoine Pitrou9d543662010-04-23 23:10:32 +0000156 @support.cpython_only
157 def test_refcycle(self):
158 # Issue #7943: an SSL object doesn't create reference cycles with
159 # itself.
160 s = socket.socket(socket.AF_INET)
161 ss = ssl.wrap_socket(s)
162 wr = weakref.ref(ss)
163 del ss
164 self.assertEqual(wr(), None)
165
Antoine Pitrou40f08742010-04-24 22:04:40 +0000166 def test_timeout(self):
167 # Issue #8524: when creating an SSL socket, the timeout of the
168 # original socket should be retained.
169 for timeout in (None, 0.0, 5.0):
170 s = socket.socket(socket.AF_INET)
171 s.settimeout(timeout)
172 ss = ssl.wrap_socket(s)
173 self.assertEqual(timeout, ss.gettimeout())
174
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000175
Antoine Pitrou152efa22010-05-16 18:19:27 +0000176class ContextTests(unittest.TestCase):
177
178 def test_constructor(self):
179 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
180 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
181 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
182 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
183 self.assertRaises(TypeError, ssl.SSLContext)
184 self.assertRaises(ValueError, ssl.SSLContext, -1)
185 self.assertRaises(ValueError, ssl.SSLContext, 42)
186
187 def test_protocol(self):
188 for proto in PROTOCOLS:
189 ctx = ssl.SSLContext(proto)
190 self.assertEqual(ctx.protocol, proto)
191
192 def test_ciphers(self):
193 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
194 ctx.set_ciphers("ALL")
195 ctx.set_ciphers("DEFAULT")
196 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000197 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000198
Antoine Pitroub5218772010-05-21 09:56:06 +0000199 def test_options(self):
200 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
201 # OP_ALL is the default value
202 self.assertEqual(ssl.OP_ALL, ctx.options)
203 ctx.options |= ssl.OP_NO_SSLv2
204 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
205 ctx.options)
206 ctx.options |= ssl.OP_NO_SSLv3
207 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
208 ctx.options)
209 if can_clear_options():
210 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
211 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
212 ctx.options)
213 ctx.options = 0
214 self.assertEqual(0, ctx.options)
215 else:
216 with self.assertRaises(ValueError):
217 ctx.options = 0
218
Antoine Pitrou152efa22010-05-16 18:19:27 +0000219 def test_verify(self):
220 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
221 # Default value
222 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
223 ctx.verify_mode = ssl.CERT_OPTIONAL
224 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
225 ctx.verify_mode = ssl.CERT_REQUIRED
226 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
227 ctx.verify_mode = ssl.CERT_NONE
228 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
229 with self.assertRaises(TypeError):
230 ctx.verify_mode = None
231 with self.assertRaises(ValueError):
232 ctx.verify_mode = 42
233
234 def test_load_cert_chain(self):
235 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
236 # Combined key and cert in a single file
237 ctx.load_cert_chain(CERTFILE)
238 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
239 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
240 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
241 ctx.load_cert_chain(WRONGCERT)
242 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
243 ctx.load_cert_chain(BADCERT)
244 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
245 ctx.load_cert_chain(EMPTYCERT)
246 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000247 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000248 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
249 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
250 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
251 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
252 ctx.load_cert_chain(ONLYCERT)
253 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
254 ctx.load_cert_chain(ONLYKEY)
255 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
256 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
257 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000258 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000259 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
260 ctx.load_cert_chain(CERTFILE, ONLYKEY)
261
262 def test_load_verify_locations(self):
263 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
264 ctx.load_verify_locations(CERTFILE)
265 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
266 ctx.load_verify_locations(BYTES_CERTFILE)
267 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
268 self.assertRaises(TypeError, ctx.load_verify_locations)
269 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
270 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
271 ctx.load_verify_locations(WRONGCERT)
272 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
273 ctx.load_verify_locations(BADCERT)
274 ctx.load_verify_locations(CERTFILE, CAPATH)
275 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
276
277
Bill Janssen6e027db2007-11-15 22:23:56 +0000278class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000279
Antoine Pitrou480a1242010-04-28 21:37:09 +0000280 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000281 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
282 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000283 try:
284 s.connect(("svn.python.org", 443))
285 self.assertEqual({}, s.getpeercert())
286 finally:
287 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000288
289 # this should fail because we have no verification certs
290 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
291 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000292 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
293 s.connect, ("svn.python.org", 443))
294 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000295
296 # this should succeed because we specify the root cert
297 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
298 cert_reqs=ssl.CERT_REQUIRED,
299 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
300 try:
301 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000302 self.assertTrue(s.getpeercert())
303 finally:
304 s.close()
305
306 def test_connect_with_context(self):
307 # Same as test_connect, but with a separately created context
308 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
309 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
310 s.connect(("svn.python.org", 443))
311 try:
312 self.assertEqual({}, s.getpeercert())
313 finally:
314 s.close()
315 # This should fail because we have no verification certs
316 ctx.verify_mode = ssl.CERT_REQUIRED
317 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
318 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
319 s.connect, ("svn.python.org", 443))
320 s.close()
321 # This should succeed because we specify the root cert
322 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
323 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
324 s.connect(("svn.python.org", 443))
325 try:
326 cert = s.getpeercert()
327 self.assertTrue(cert)
328 finally:
329 s.close()
330
331 def test_connect_capath(self):
332 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000333 # NOTE: the subject hashing algorithm has been changed between
334 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
335 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000336 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000337 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
338 ctx.verify_mode = ssl.CERT_REQUIRED
339 ctx.load_verify_locations(capath=CAPATH)
340 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
341 s.connect(("svn.python.org", 443))
342 try:
343 cert = s.getpeercert()
344 self.assertTrue(cert)
345 finally:
346 s.close()
347 # Same with a bytes `capath` argument
348 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
349 ctx.verify_mode = ssl.CERT_REQUIRED
350 ctx.load_verify_locations(capath=BYTES_CAPATH)
351 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
352 s.connect(("svn.python.org", 443))
353 try:
354 cert = s.getpeercert()
355 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000356 finally:
357 s.close()
358
Antoine Pitroue3220242010-04-24 11:13:53 +0000359 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
360 def test_makefile_close(self):
361 # Issue #5238: creating a file-like object with makefile() shouldn't
362 # delay closing the underlying "real socket" (here tested with its
363 # file descriptor, hence skipping the test under Windows).
364 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
365 ss.connect(("svn.python.org", 443))
366 fd = ss.fileno()
367 f = ss.makefile()
368 f.close()
369 # The fd is still open
370 os.read(fd, 0)
371 # Closing the SSL socket should close the fd too
372 ss.close()
373 gc.collect()
374 with self.assertRaises(OSError) as e:
375 os.read(fd, 0)
376 self.assertEqual(e.exception.errno, errno.EBADF)
377
Antoine Pitrou480a1242010-04-28 21:37:09 +0000378 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000379 s = socket.socket(socket.AF_INET)
380 s.connect(("svn.python.org", 443))
381 s.setblocking(False)
382 s = ssl.wrap_socket(s,
383 cert_reqs=ssl.CERT_NONE,
384 do_handshake_on_connect=False)
385 count = 0
386 while True:
387 try:
388 count += 1
389 s.do_handshake()
390 break
391 except ssl.SSLError as err:
392 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
393 select.select([s], [], [])
394 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
395 select.select([], [s], [])
396 else:
397 raise
398 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000399 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000400 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000401
Antoine Pitrou480a1242010-04-28 21:37:09 +0000402 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000403 pem = ssl.get_server_certificate(("svn.python.org", 443))
404 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000405 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000406
407 return
408
409 try:
410 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
411 except ssl.SSLError as x:
412 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000413 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000414 sys.stdout.write("%s\n" % x)
415 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000416 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000417
418 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
419 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000420 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000421 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000422 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
423
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000424 def test_algorithms(self):
425 # Issue #8484: all algorithms should be available when verifying a
426 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000427 # SHA256 was added in OpenSSL 0.9.8
428 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
429 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000430 # NOTE: https://sha256.tbs-internet.com is another possible test host
431 remote = ("sha2.hboeck.de", 443)
432 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
433 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
434 cert_reqs=ssl.CERT_REQUIRED,
435 ca_certs=sha256_cert,)
436 with support.transient_internet():
437 try:
438 s.connect(remote)
439 if support.verbose:
440 sys.stdout.write("\nCipher with %r is %r\n" %
441 (remote, s.cipher()))
442 sys.stdout.write("Certificate is:\n%s\n" %
443 pprint.pformat(s.getpeercert()))
444 finally:
445 s.close()
446
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000447
448try:
449 import threading
450except ImportError:
451 _have_threads = False
452else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000453 _have_threads = True
454
455 class ThreadedEchoServer(threading.Thread):
456
457 class ConnectionHandler(threading.Thread):
458
459 """A mildly complicated class, because we want it to work both
460 with and without the SSL wrapper around the socket connection, so
461 that we can test the STARTTLS functionality."""
462
Bill Janssen6e027db2007-11-15 22:23:56 +0000463 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000464 self.server = server
465 self.running = False
466 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000467 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000468 self.sock.setblocking(1)
469 self.sslconn = None
470 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000471 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000472
Antoine Pitrou480a1242010-04-28 21:37:09 +0000473 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000474 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000475 self.sslconn = self.server.context.wrap_socket(
476 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000477 except ssl.SSLError:
478 # XXX Various errors can have happened here, for example
479 # a mismatching protocol version, an invalid certificate,
480 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000481 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000482 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000483 self.running = False
484 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000485 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000486 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000487 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000488 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000489 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000490 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000491 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
492 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000493 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000494 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
495 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000496 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000497 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
498 return True
499
500 def read(self):
501 if self.sslconn:
502 return self.sslconn.read()
503 else:
504 return self.sock.recv(1024)
505
506 def write(self, bytes):
507 if self.sslconn:
508 return self.sslconn.write(bytes)
509 else:
510 return self.sock.send(bytes)
511
512 def close(self):
513 if self.sslconn:
514 self.sslconn.close()
515 else:
516 self.sock.close()
517
Antoine Pitrou480a1242010-04-28 21:37:09 +0000518 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000519 self.running = True
520 if not self.server.starttls_server:
521 if not self.wrap_conn():
522 return
523 while self.running:
524 try:
525 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000526 stripped = msg.strip()
527 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 # eof, so quit this handler
529 self.running = False
530 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000531 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000532 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000533 sys.stdout.write(" server: client closed connection\n")
534 self.close()
535 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000536 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000537 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000538 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000539 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000540 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000541 if not self.wrap_conn():
542 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000543 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000544 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000545 if support.verbose and self.server.connectionchatty:
546 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000547 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000548 self.sock = self.sslconn.unwrap()
549 self.sslconn = None
550 if support.verbose and self.server.connectionchatty:
551 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000552 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000553 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000554 self.server.connectionchatty):
555 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000556 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
557 % (msg, ctype, msg.lower(), ctype))
558 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000559 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000560 if self.server.chatty:
561 handle_error("Test server failure:\n")
562 self.close()
563 self.running = False
564 # normally, we'd just stop here, but for the test
565 # harness, we want to stop the server
566 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000567
Antoine Pitroub5218772010-05-21 09:56:06 +0000568 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000569 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000570 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000571 ciphers=None, context=None):
572 if context:
573 self.context = context
574 else:
575 self.context = ssl.SSLContext(ssl_version
576 if ssl_version is not None
577 else ssl.PROTOCOL_TLSv1)
578 self.context.verify_mode = (certreqs if certreqs is not None
579 else ssl.CERT_NONE)
580 if cacerts:
581 self.context.load_verify_locations(cacerts)
582 if certificate:
583 self.context.load_cert_chain(certificate)
584 if ciphers:
585 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000586 self.chatty = chatty
587 self.connectionchatty = connectionchatty
588 self.starttls_server = starttls_server
589 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000590 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000591 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592 self.active = False
593 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000594 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000595
Antoine Pitrou480a1242010-04-28 21:37:09 +0000596 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000597 self.flag = flag
598 threading.Thread.start(self)
599
Antoine Pitrou480a1242010-04-28 21:37:09 +0000600 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000601 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000602 self.sock.listen(5)
603 self.active = True
604 if self.flag:
605 # signal an event
606 self.flag.set()
607 while self.active:
608 try:
609 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000610 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000611 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000612 + repr(connaddr) + '\n')
613 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000614 handler.start()
615 except socket.timeout:
616 pass
617 except KeyboardInterrupt:
618 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000619 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000620
Antoine Pitrou480a1242010-04-28 21:37:09 +0000621 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000622 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000623
Bill Janssen54cc54c2007-12-14 22:08:56 +0000624 class OurHTTPSServer(threading.Thread):
625
626 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627
628 class HTTPSServer(HTTPServer):
629
630 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000631 HTTPServer.__init__(self, server_address, RequestHandlerClass)
632 # we assume the certfile contains both private key and certificate
633 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634 self.allow_reuse_address = True
635
Bill Janssen6e027db2007-11-15 22:23:56 +0000636 def __str__(self):
637 return ('<%s %s:%s>' %
638 (self.__class__.__name__,
639 self.server_name,
640 self.server_port))
641
Antoine Pitrou480a1242010-04-28 21:37:09 +0000642 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000643 # override this to wrap socket with SSL
644 sock, addr = self.socket.accept()
645 sslconn = ssl.wrap_socket(sock, server_side=True,
646 certfile=self.certfile)
647 return sslconn, addr
648
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000649 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 # need to override translate_path to get a known root,
651 # instead of using os.curdir, since the test could be
652 # run from anywhere
653
654 server_version = "TestHTTPS/1.0"
655
656 root = None
657
658 def translate_path(self, path):
659 """Translate a /-separated PATH to the local filename syntax.
660
661 Components that mean special things to the local file system
662 (e.g. drive or directory names) are ignored. (XXX They should
663 probably be diagnosed.)
664
665 """
666 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000667 path = urllib.parse.urlparse(path)[2]
668 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000669 words = path.split('/')
670 words = filter(None, words)
671 path = self.root
672 for word in words:
673 drive, word = os.path.splitdrive(word)
674 head, word = os.path.split(word)
675 if word in self.root: continue
676 path = os.path.join(path, word)
677 return path
678
679 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000680 # we override this to suppress logging unless "verbose"
681
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000682 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000683 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
684 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000685 self.server.server_port,
686 self.request.cipher(),
687 self.log_date_time_string(),
688 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000689
690
Trent Nelson78520002008-04-10 20:54:35 +0000691 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000692 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000693 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
694 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000695 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
696 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000697 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000698 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000699
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000700 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000701 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000702
Antoine Pitrou480a1242010-04-28 21:37:09 +0000703 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000704 self.flag = flag
705 threading.Thread.start(self)
706
Antoine Pitrou480a1242010-04-28 21:37:09 +0000707 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000708 if self.flag:
709 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000710 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000711
Antoine Pitrou480a1242010-04-28 21:37:09 +0000712 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000713 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000714
715
Bill Janssen54cc54c2007-12-14 22:08:56 +0000716 class AsyncoreEchoServer(threading.Thread):
717
718 # this one's based on asyncore.dispatcher
719
720 class EchoServer (asyncore.dispatcher):
721
722 class ConnectionHandler (asyncore.dispatcher_with_send):
723
724 def __init__(self, conn, certfile):
725 self.socket = ssl.wrap_socket(conn, server_side=True,
726 certfile=certfile,
727 do_handshake_on_connect=False)
728 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000729 self._ssl_accepting = True
730 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000731
732 def readable(self):
733 if isinstance(self.socket, ssl.SSLSocket):
734 while self.socket.pending() > 0:
735 self.handle_read_event()
736 return True
737
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000738 def _do_ssl_handshake(self):
739 try:
740 self.socket.do_handshake()
741 except ssl.SSLError as err:
742 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
743 ssl.SSL_ERROR_WANT_WRITE):
744 return
745 elif err.args[0] == ssl.SSL_ERROR_EOF:
746 return self.handle_close()
747 raise
748 except socket.error as err:
749 if err.args[0] == errno.ECONNABORTED:
750 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000751 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000752 self._ssl_accepting = False
753
754 def handle_read(self):
755 if self._ssl_accepting:
756 self._do_ssl_handshake()
757 else:
758 data = self.recv(1024)
759 if support.verbose:
760 sys.stdout.write(" server: read %s from client\n" % repr(data))
761 if not data:
762 self.close()
763 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000764 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000765
766 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000767 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000768 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000769 sys.stdout.write(" server: closed connection %s\n" % self.socket)
770
771 def handle_error(self):
772 raise
773
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000774 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000775 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000776 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
777 self.port = support.bind_port(sock, '')
778 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000779 self.listen(5)
780
781 def handle_accept(self):
782 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000783 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000784 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
785 self.ConnectionHandler(sock_obj, self.certfile)
786
787 def handle_error(self):
788 raise
789
Trent Nelson78520002008-04-10 20:54:35 +0000790 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000791 self.flag = None
792 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000793 self.server = self.EchoServer(certfile)
794 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000795 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000796 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000797
798 def __str__(self):
799 return "<%s %s>" % (self.__class__.__name__, self.server)
800
801 def start (self, flag=None):
802 self.flag = flag
803 threading.Thread.start(self)
804
Antoine Pitrou480a1242010-04-28 21:37:09 +0000805 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000806 self.active = True
807 if self.flag:
808 self.flag.set()
809 while self.active:
810 try:
811 asyncore.loop(1)
812 except:
813 pass
814
Antoine Pitrou480a1242010-04-28 21:37:09 +0000815 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000816 self.active = False
817 self.server.close()
818
Antoine Pitrou480a1242010-04-28 21:37:09 +0000819 def bad_cert_test(certfile):
820 """
821 Launch a server with CERT_REQUIRED, and check that trying to
822 connect to it with the given client certificate fails.
823 """
Trent Nelson78520002008-04-10 20:54:35 +0000824 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000825 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000826 cacerts=CERTFILE, chatty=False,
827 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000828 flag = threading.Event()
829 server.start(flag)
830 # wait for it to start
831 flag.wait()
832 # try to connect
833 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000834 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000835 s = ssl.wrap_socket(socket.socket(),
836 certfile=certfile,
837 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000838 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000839 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000840 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000841 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000842 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000843 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000844 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000845 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000846 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000847 finally:
848 server.stop()
849 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000850
Antoine Pitroub5218772010-05-21 09:56:06 +0000851 def server_params_test(client_context, server_context, indata=b"FOO\n",
852 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000853 """
854 Launch a server, connect a client to it and try various reads
855 and writes.
856 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000857 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000858 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000859 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 flag = threading.Event()
861 server.start(flag)
862 # wait for it to start
863 flag.wait()
864 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000866 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000867 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000868 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000869 if connectionchatty:
870 if support.verbose:
871 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000872 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000873 s.write(arg)
874 outdata = s.read()
875 if connectionchatty:
876 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000877 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000878 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000879 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000880 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
881 % (outdata[:20], len(outdata),
882 indata[:20].lower(), len(indata)))
883 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000884 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000885 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000886 sys.stdout.write(" client: closing connection.\n")
887 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000888 finally:
889 server.stop()
890 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000891
Antoine Pitroub5218772010-05-21 09:56:06 +0000892 def try_protocol_combo(server_protocol, client_protocol, expect_success,
893 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000894 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000896 certtype = {
897 ssl.CERT_NONE: "CERT_NONE",
898 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
899 ssl.CERT_REQUIRED: "CERT_REQUIRED",
900 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000901 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000902 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903 sys.stdout.write(formatstr %
904 (ssl.get_protocol_name(client_protocol),
905 ssl.get_protocol_name(server_protocol),
906 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000907 client_context = ssl.SSLContext(client_protocol)
908 client_context.options = ssl.OP_ALL | client_options
909 server_context = ssl.SSLContext(server_protocol)
910 server_context.options = ssl.OP_ALL | server_options
911 for ctx in (client_context, server_context):
912 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000913 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
914 # will send an SSLv3 hello (rather than SSLv2) starting from
915 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000916 ctx.set_ciphers("ALL")
917 ctx.load_cert_chain(CERTFILE)
918 ctx.load_verify_locations(CERTFILE)
919 try:
920 server_params_test(client_context, server_context,
921 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000922 # Protocol mismatch can result in either an SSLError, or a
923 # "Connection reset by peer" error.
924 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000925 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000926 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000927 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000928 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000929 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000931 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000932 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 "Client protocol %s succeeded with server protocol %s!"
934 % (ssl.get_protocol_name(client_protocol),
935 ssl.get_protocol_name(server_protocol)))
936
937
Bill Janssen6e027db2007-11-15 22:23:56 +0000938 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000939
Antoine Pitrou480a1242010-04-28 21:37:09 +0000940 def test_echo(self):
941 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000942 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000943 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000944 for protocol in PROTOCOLS:
945 context = ssl.SSLContext(protocol)
946 context.load_cert_chain(CERTFILE)
947 server_params_test(context, context,
948 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949
Antoine Pitrou480a1242010-04-28 21:37:09 +0000950 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000951 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000952 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000953 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
954 context.verify_mode = ssl.CERT_REQUIRED
955 context.load_verify_locations(CERTFILE)
956 context.load_cert_chain(CERTFILE)
957 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000958 flag = threading.Event()
959 server.start(flag)
960 # wait for it to start
961 flag.wait()
962 # try to connect
963 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000964 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000965 s.connect((HOST, server.port))
966 cert = s.getpeercert()
967 self.assertTrue(cert, "Can't get peer certificate.")
968 cipher = s.cipher()
969 if support.verbose:
970 sys.stdout.write(pprint.pformat(cert) + '\n')
971 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
972 if 'subject' not in cert:
973 self.fail("No subject field in certificate: %s." %
974 pprint.pformat(cert))
975 if ((('organizationName', 'Python Software Foundation'),)
976 not in cert['subject']):
977 self.fail(
978 "Missing or invalid 'organizationName' field in certificate subject; "
979 "should be 'Python Software Foundation'.")
980 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 finally:
982 server.stop()
983 server.join()
984
Antoine Pitrou480a1242010-04-28 21:37:09 +0000985 def test_empty_cert(self):
986 """Connecting with an empty cert file"""
987 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
988 "nullcert.pem"))
989 def test_malformed_cert(self):
990 """Connecting with a badly formatted certificate (syntax error)"""
991 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
992 "badcert.pem"))
993 def test_nonexisting_cert(self):
994 """Connecting with a non-existing cert file"""
995 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
996 "wrongcert.pem"))
997 def test_malformed_key(self):
998 """Connecting with a badly formatted key (syntax error)"""
999 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1000 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001
Antoine Pitrou480a1242010-04-28 21:37:09 +00001002 def test_rude_shutdown(self):
1003 """A brutal shutdown of an SSL server should raise an IOError
1004 in the client when attempting handshake.
1005 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001006 listener_ready = threading.Event()
1007 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001008
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001009 s = socket.socket()
1010 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001011
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001012 # `listener` runs in a thread. It sits in an accept() until
1013 # the main thread connects. Then it rudely closes the socket,
1014 # and sets Event `listener_gone` to let the main thread know
1015 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001016 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001017 s.listen(5)
1018 listener_ready.set()
1019 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001020 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001021 listener_gone.set()
1022
1023 def connector():
1024 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001025 c = socket.socket()
1026 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001027 listener_gone.wait()
1028 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001029 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001030 except IOError:
1031 pass
1032 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001033 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001034
1035 t = threading.Thread(target=listener)
1036 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001037 try:
1038 connector()
1039 finally:
1040 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001041
Antoine Pitrou480a1242010-04-28 21:37:09 +00001042 def test_protocol_sslv2(self):
1043 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001044 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001045 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001046 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1047 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1048 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1049 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1050 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1051 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001052 # SSLv23 client with specific SSL options
1053 if no_sslv2_implies_sslv3_hello():
1054 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1055 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1056 client_options=ssl.OP_NO_SSLv2)
1057 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1058 client_options=ssl.OP_NO_SSLv3)
1059 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1060 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001061
Antoine Pitrou480a1242010-04-28 21:37:09 +00001062 def test_protocol_sslv23(self):
1063 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001064 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001065 sys.stdout.write("\n")
1066 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001068 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001069 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001070 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001071 sys.stdout.write(
1072 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1073 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001074 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1075 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1076 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077
Antoine Pitrou480a1242010-04-28 21:37:09 +00001078 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1079 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1080 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001081
Antoine Pitrou480a1242010-04-28 21:37:09 +00001082 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1083 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1084 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001085
Antoine Pitroub5218772010-05-21 09:56:06 +00001086 # Server with specific SSL options
1087 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1088 server_options=ssl.OP_NO_SSLv3)
1089 # Will choose TLSv1
1090 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1091 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1092 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1093 server_options=ssl.OP_NO_TLSv1)
1094
1095
Antoine Pitrou480a1242010-04-28 21:37:09 +00001096 def test_protocol_sslv3(self):
1097 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001098 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001099 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001100 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1101 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1102 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1103 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1104 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1105 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001106 if no_sslv2_implies_sslv3_hello():
1107 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1108 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1109 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001110
Antoine Pitrou480a1242010-04-28 21:37:09 +00001111 def test_protocol_tlsv1(self):
1112 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001113 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001114 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001115 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1116 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1117 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1118 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1119 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1120 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001121
Antoine Pitrou480a1242010-04-28 21:37:09 +00001122 def test_starttls(self):
1123 """Switching from clear text to encrypted and back again."""
1124 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 +00001125
Trent Nelson78520002008-04-10 20:54:35 +00001126 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127 ssl_version=ssl.PROTOCOL_TLSv1,
1128 starttls_server=True,
1129 chatty=True,
1130 connectionchatty=True)
1131 flag = threading.Event()
1132 server.start(flag)
1133 # wait for it to start
1134 flag.wait()
1135 # try to connect
1136 wrapped = False
1137 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001138 s = socket.socket()
1139 s.setblocking(1)
1140 s.connect((HOST, server.port))
1141 if support.verbose:
1142 sys.stdout.write("\n")
1143 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001144 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001145 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001146 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001148 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001149 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001151 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001152 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001153 msg = outdata.strip().lower()
1154 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1155 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001156 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001157 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001158 " client: read %r from server, starting TLS...\n"
1159 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001160 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1161 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001162 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1163 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001164 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001165 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001166 " client: read %r from server, ending TLS...\n"
1167 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001168 s = conn.unwrap()
1169 wrapped = False
1170 else:
1171 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001172 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001174 if support.verbose:
1175 sys.stdout.write(" client: closing connection.\n")
1176 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001177 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001178 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001179 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001180 if wrapped:
1181 conn.close()
1182 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001183 s.close()
1184 finally:
1185 server.stop()
1186 server.join()
1187
Antoine Pitrou480a1242010-04-28 21:37:09 +00001188 def test_socketserver(self):
1189 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001190 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001191 flag = threading.Event()
1192 server.start(flag)
1193 # wait for it to start
1194 flag.wait()
1195 # try to connect
1196 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001197 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001198 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001199 with open(CERTFILE, 'rb') as f:
1200 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001201 d2 = ''
1202 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001203 url = 'https://%s:%d/%s' % (
1204 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001205 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001206 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001207 if dlen and (int(dlen) > 0):
1208 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001209 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001210 sys.stdout.write(
1211 " client: read %d bytes from remote server '%s'\n"
1212 % (len(d2), server))
1213 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001214 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001215 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001216 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001217 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001218 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001219 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001220 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001221 server.join()
1222
Antoine Pitrou480a1242010-04-28 21:37:09 +00001223 def test_asyncore_server(self):
1224 """Check the example asyncore integration."""
1225 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001226
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001227 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001228 sys.stdout.write("\n")
1229
Antoine Pitrou480a1242010-04-28 21:37:09 +00001230 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001231 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001232 flag = threading.Event()
1233 server.start(flag)
1234 # wait for it to start
1235 flag.wait()
1236 # try to connect
1237 try:
1238 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001239 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001240 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001241 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 " client: sending %r...\n" % indata)
1243 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001244 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001245 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001246 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001247 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001248 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1250 % (outdata[:20], len(outdata),
1251 indata[:20].lower(), len(indata)))
1252 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001253 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001254 sys.stdout.write(" client: closing connection.\n")
1255 s.close()
1256 finally:
1257 server.stop()
1258 server.join()
1259
Antoine Pitrou480a1242010-04-28 21:37:09 +00001260 def test_recv_send(self):
1261 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001262 if support.verbose:
1263 sys.stdout.write("\n")
1264
1265 server = ThreadedEchoServer(CERTFILE,
1266 certreqs=ssl.CERT_NONE,
1267 ssl_version=ssl.PROTOCOL_TLSv1,
1268 cacerts=CERTFILE,
1269 chatty=True,
1270 connectionchatty=False)
1271 flag = threading.Event()
1272 server.start(flag)
1273 # wait for it to start
1274 flag.wait()
1275 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001276 s = ssl.wrap_socket(socket.socket(),
1277 server_side=False,
1278 certfile=CERTFILE,
1279 ca_certs=CERTFILE,
1280 cert_reqs=ssl.CERT_NONE,
1281 ssl_version=ssl.PROTOCOL_TLSv1)
1282 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001283 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001284 # helper methods for standardising recv* method signatures
1285 def _recv_into():
1286 b = bytearray(b"\0"*100)
1287 count = s.recv_into(b)
1288 return b[:count]
1289
1290 def _recvfrom_into():
1291 b = bytearray(b"\0"*100)
1292 count, addr = s.recvfrom_into(b)
1293 return b[:count]
1294
1295 # (name, method, whether to expect success, *args)
1296 send_methods = [
1297 ('send', s.send, True, []),
1298 ('sendto', s.sendto, False, ["some.address"]),
1299 ('sendall', s.sendall, True, []),
1300 ]
1301 recv_methods = [
1302 ('recv', s.recv, True, []),
1303 ('recvfrom', s.recvfrom, False, ["some.address"]),
1304 ('recv_into', _recv_into, True, []),
1305 ('recvfrom_into', _recvfrom_into, False, []),
1306 ]
1307 data_prefix = "PREFIX_"
1308
1309 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001310 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001311 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001312 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001313 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001314 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001315 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001316 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001317 "<<{outdata:r}>> ({nout:d}) received; "
1318 "expected <<{indata:r}>> ({nin:d})\n".format(
1319 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001320 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001321 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001322 )
1323 )
1324 except ValueError as e:
1325 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001326 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001327 "Failed to send with method <<{name:s}>>; "
1328 "expected to succeed.\n".format(name=meth_name)
1329 )
1330 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001331 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001332 "Method <<{name:s}>> failed with unexpected "
1333 "exception message: {exp:s}\n".format(
1334 name=meth_name, exp=e
1335 )
1336 )
1337
1338 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001339 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001340 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001342 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001343 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001344 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001345 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001346 "<<{outdata:r}>> ({nout:d}) received; "
1347 "expected <<{indata:r}>> ({nin:d})\n".format(
1348 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001349 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001350 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001351 )
1352 )
1353 except ValueError as e:
1354 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001355 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001356 "Failed to receive with method <<{name:s}>>; "
1357 "expected to succeed.\n".format(name=meth_name)
1358 )
1359 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001360 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001361 "Method <<{name:s}>> failed with unexpected "
1362 "exception message: {exp:s}\n".format(
1363 name=meth_name, exp=e
1364 )
1365 )
1366 # consume data
1367 s.read()
1368
Antoine Pitrou480a1242010-04-28 21:37:09 +00001369 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001370 s.close()
1371 finally:
1372 server.stop()
1373 server.join()
1374
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001375 def test_handshake_timeout(self):
1376 # Issue #5103: SSL handshake must respect the socket timeout
1377 server = socket.socket(socket.AF_INET)
1378 host = "127.0.0.1"
1379 port = support.bind_port(server)
1380 started = threading.Event()
1381 finish = False
1382
1383 def serve():
1384 server.listen(5)
1385 started.set()
1386 conns = []
1387 while not finish:
1388 r, w, e = select.select([server], [], [], 0.1)
1389 if server in r:
1390 # Let the socket hang around rather than having
1391 # it closed by garbage collection.
1392 conns.append(server.accept()[0])
1393
1394 t = threading.Thread(target=serve)
1395 t.start()
1396 started.wait()
1397
1398 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001399 try:
1400 c = socket.socket(socket.AF_INET)
1401 c.settimeout(0.2)
1402 c.connect((host, port))
1403 # Will attempt handshake and time out
1404 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1405 ssl.wrap_socket, c)
1406 finally:
1407 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001408 try:
1409 c = socket.socket(socket.AF_INET)
1410 c = ssl.wrap_socket(c)
1411 c.settimeout(0.2)
1412 # Will attempt handshake and time out
1413 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1414 c.connect, (host, port))
1415 finally:
1416 c.close()
1417 finally:
1418 finish = True
1419 t.join()
1420 server.close()
1421
Bill Janssen58afe4c2008-09-08 16:45:19 +00001422
Thomas Woutersed03b412007-08-28 21:37:11 +00001423def test_main(verbose=False):
1424 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001425 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001426
Antoine Pitrou152efa22010-05-16 18:19:27 +00001427 for filename in [
1428 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1429 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1430 BADCERT, BADKEY, EMPTYCERT]:
1431 if not os.path.exists(filename):
1432 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001433
Antoine Pitrou152efa22010-05-16 18:19:27 +00001434 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001435
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001436 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001437 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001438
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001439 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001440 thread_info = support.threading_setup()
1441 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001442 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001443
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 try:
1445 support.run_unittest(*tests)
1446 finally:
1447 if _have_threads:
1448 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001449
1450if __name__ == "__main__":
1451 test_main()