blob: 175091c46e134c220b6af973c84fe018429e0cb0 [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
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000029else:
30 PROTOCOLS = [
31 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
32 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
33 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000034
Benjamin Petersonee8712c2008-05-20 21:35:26 +000035HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
37data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038
39CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
54
Thomas Woutersed03b412007-08-28 21:37:11 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056def handle_error(prefix):
57 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000059 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitroub5218772010-05-21 09:56:06 +000061def can_clear_options():
62 # 0.9.8m or higher
63 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
64
65def no_sslv2_implies_sslv3_hello():
66 # 0.9.7h or higher
67 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
68
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou23df4832010-08-04 17:14:06 +000070# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
71def skip_if_broken_ubuntu_ssl(func):
72 @functools.wraps(func)
73 def f(*args, **kwargs):
74 try:
75 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
76 except ssl.SSLError:
77 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
78 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
79 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
80 return func(*args, **kwargs)
81 return f
82
83
Antoine Pitrou152efa22010-05-16 18:19:27 +000084class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Antoine Pitrou480a1242010-04-28 21:37:09 +000086 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 ssl.PROTOCOL_SSLv2
88 ssl.PROTOCOL_SSLv23
89 ssl.PROTOCOL_SSLv3
90 ssl.PROTOCOL_TLSv1
91 ssl.CERT_NONE
92 ssl.CERT_OPTIONAL
93 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000097 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 sys.stdout.write("\n RAND_status is %d (%s)\n"
99 % (v, (v and "sufficient randomness") or
100 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000101 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102 ssl.RAND_egd(1)
103 except TypeError:
104 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000105 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 print("didn't raise TypeError")
107 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000108
Antoine Pitrou480a1242010-04-28 21:37:09 +0000109 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000110 # note that this uses an 'unofficial' function in _ssl.c,
111 # provided solely for this test, to exercise the certificate
112 # parsing code
113 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000116
Antoine Pitrou480a1242010-04-28 21:37:09 +0000117 def test_DER_to_PEM(self):
118 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
119 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 d1 = ssl.PEM_cert_to_DER_cert(pem)
121 p2 = ssl.DER_cert_to_PEM_cert(d1)
122 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000123 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000124 if not p2.startswith(ssl.PEM_HEADER + '\n'):
125 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
126 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
127 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000129 def test_openssl_version(self):
130 n = ssl.OPENSSL_VERSION_NUMBER
131 t = ssl.OPENSSL_VERSION_INFO
132 s = ssl.OPENSSL_VERSION
133 self.assertIsInstance(n, int)
134 self.assertIsInstance(t, tuple)
135 self.assertIsInstance(s, str)
136 # Some sanity checks follow
137 # >= 0.9
138 self.assertGreaterEqual(n, 0x900000)
139 # < 2.0
140 self.assertLess(n, 0x20000000)
141 major, minor, fix, patch, status = t
142 self.assertGreaterEqual(major, 0)
143 self.assertLess(major, 2)
144 self.assertGreaterEqual(minor, 0)
145 self.assertLess(minor, 256)
146 self.assertGreaterEqual(fix, 0)
147 self.assertLess(fix, 256)
148 self.assertGreaterEqual(patch, 0)
149 self.assertLessEqual(patch, 26)
150 self.assertGreaterEqual(status, 0)
151 self.assertLessEqual(status, 15)
152 # Version string as returned by OpenSSL, the format might change
153 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
154 (s, t))
155
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000156 def test_ciphers(self):
157 if not support.is_resource_enabled('network'):
158 return
159 remote = ("svn.python.org", 443)
160 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
161 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
162 s.connect(remote)
163 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
164 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
165 s.connect(remote)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000166 # Error checking can happen at instantiation or when connecting
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000167 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000168 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou30474062010-05-16 23:46:26 +0000169 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000170 s.connect(remote)
171
Antoine Pitrou9d543662010-04-23 23:10:32 +0000172 @support.cpython_only
173 def test_refcycle(self):
174 # Issue #7943: an SSL object doesn't create reference cycles with
175 # itself.
176 s = socket.socket(socket.AF_INET)
177 ss = ssl.wrap_socket(s)
178 wr = weakref.ref(ss)
179 del ss
180 self.assertEqual(wr(), None)
181
Antoine Pitrou40f08742010-04-24 22:04:40 +0000182 def test_timeout(self):
183 # Issue #8524: when creating an SSL socket, the timeout of the
184 # original socket should be retained.
185 for timeout in (None, 0.0, 5.0):
186 s = socket.socket(socket.AF_INET)
187 s.settimeout(timeout)
188 ss = ssl.wrap_socket(s)
189 self.assertEqual(timeout, ss.gettimeout())
190
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000191
Antoine Pitrou152efa22010-05-16 18:19:27 +0000192class ContextTests(unittest.TestCase):
193
Antoine Pitrou23df4832010-08-04 17:14:06 +0000194 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000195 def test_constructor(self):
196 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
197 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
198 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
199 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
200 self.assertRaises(TypeError, ssl.SSLContext)
201 self.assertRaises(ValueError, ssl.SSLContext, -1)
202 self.assertRaises(ValueError, ssl.SSLContext, 42)
203
Antoine Pitrou23df4832010-08-04 17:14:06 +0000204 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000205 def test_protocol(self):
206 for proto in PROTOCOLS:
207 ctx = ssl.SSLContext(proto)
208 self.assertEqual(ctx.protocol, proto)
209
210 def test_ciphers(self):
211 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
212 ctx.set_ciphers("ALL")
213 ctx.set_ciphers("DEFAULT")
214 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000215 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000216
Antoine Pitrou23df4832010-08-04 17:14:06 +0000217 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000218 def test_options(self):
219 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
220 # OP_ALL is the default value
221 self.assertEqual(ssl.OP_ALL, ctx.options)
222 ctx.options |= ssl.OP_NO_SSLv2
223 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
224 ctx.options)
225 ctx.options |= ssl.OP_NO_SSLv3
226 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
227 ctx.options)
228 if can_clear_options():
229 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
230 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
231 ctx.options)
232 ctx.options = 0
233 self.assertEqual(0, ctx.options)
234 else:
235 with self.assertRaises(ValueError):
236 ctx.options = 0
237
Antoine Pitrou152efa22010-05-16 18:19:27 +0000238 def test_verify(self):
239 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
240 # Default value
241 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
242 ctx.verify_mode = ssl.CERT_OPTIONAL
243 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
244 ctx.verify_mode = ssl.CERT_REQUIRED
245 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
246 ctx.verify_mode = ssl.CERT_NONE
247 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
248 with self.assertRaises(TypeError):
249 ctx.verify_mode = None
250 with self.assertRaises(ValueError):
251 ctx.verify_mode = 42
252
253 def test_load_cert_chain(self):
254 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
255 # Combined key and cert in a single file
256 ctx.load_cert_chain(CERTFILE)
257 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
258 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
259 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
260 ctx.load_cert_chain(WRONGCERT)
261 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
262 ctx.load_cert_chain(BADCERT)
263 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
264 ctx.load_cert_chain(EMPTYCERT)
265 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000266 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000267 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
268 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
269 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
270 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
271 ctx.load_cert_chain(ONLYCERT)
272 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
273 ctx.load_cert_chain(ONLYKEY)
274 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
275 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
276 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000277 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000278 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
279 ctx.load_cert_chain(CERTFILE, ONLYKEY)
280
281 def test_load_verify_locations(self):
282 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
283 ctx.load_verify_locations(CERTFILE)
284 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
285 ctx.load_verify_locations(BYTES_CERTFILE)
286 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
287 self.assertRaises(TypeError, ctx.load_verify_locations)
288 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
289 with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
290 ctx.load_verify_locations(WRONGCERT)
291 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
292 ctx.load_verify_locations(BADCERT)
293 ctx.load_verify_locations(CERTFILE, CAPATH)
294 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
295
296
Bill Janssen6e027db2007-11-15 22:23:56 +0000297class NetworkedTests(unittest.TestCase):
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000298 timeout = 30
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000299
Antoine Pitrou480a1242010-04-28 21:37:09 +0000300 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000301 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
302 cert_reqs=ssl.CERT_NONE)
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000303 s.settimeout(self.timeout)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000304 try:
305 s.connect(("svn.python.org", 443))
306 self.assertEqual({}, s.getpeercert())
307 finally:
308 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000309
310 # this should fail because we have no verification certs
311 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
312 cert_reqs=ssl.CERT_REQUIRED)
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000313 s.settimeout(self.timeout)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000314 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
315 s.connect, ("svn.python.org", 443))
316 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000317
318 # this should succeed because we specify the root cert
319 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
320 cert_reqs=ssl.CERT_REQUIRED,
321 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000322 s.settimeout(self.timeout)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000323 try:
324 s.connect(("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000325 self.assertTrue(s.getpeercert())
326 finally:
327 s.close()
328
329 def test_connect_with_context(self):
330 # Same as test_connect, but with a separately created context
331 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
332 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000333 s.settimeout(self.timeout)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000334 s.connect(("svn.python.org", 443))
335 try:
336 self.assertEqual({}, s.getpeercert())
337 finally:
338 s.close()
339 # This should fail because we have no verification certs
340 ctx.verify_mode = ssl.CERT_REQUIRED
341 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000342 s.settimeout(self.timeout)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000343 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
344 s.connect, ("svn.python.org", 443))
345 s.close()
346 # This should succeed because we specify the root cert
347 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
348 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000349 s.settimeout(self.timeout)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000350 s.connect(("svn.python.org", 443))
351 try:
352 cert = s.getpeercert()
353 self.assertTrue(cert)
354 finally:
355 s.close()
356
357 def test_connect_capath(self):
358 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000359 # NOTE: the subject hashing algorithm has been changed between
360 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
361 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000362 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou152efa22010-05-16 18:19:27 +0000363 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
364 ctx.verify_mode = ssl.CERT_REQUIRED
365 ctx.load_verify_locations(capath=CAPATH)
366 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000367 s.settimeout(self.timeout)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000368 s.connect(("svn.python.org", 443))
369 try:
370 cert = s.getpeercert()
371 self.assertTrue(cert)
372 finally:
373 s.close()
374 # Same with a bytes `capath` argument
375 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
376 ctx.verify_mode = ssl.CERT_REQUIRED
377 ctx.load_verify_locations(capath=BYTES_CAPATH)
378 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000379 s.settimeout(self.timeout)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000380 s.connect(("svn.python.org", 443))
381 try:
382 cert = s.getpeercert()
383 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000384 finally:
385 s.close()
386
Antoine Pitroue3220242010-04-24 11:13:53 +0000387 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
388 def test_makefile_close(self):
389 # Issue #5238: creating a file-like object with makefile() shouldn't
390 # delay closing the underlying "real socket" (here tested with its
391 # file descriptor, hence skipping the test under Windows).
392 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000393 ss.settimeout(self.timeout)
Antoine Pitroue3220242010-04-24 11:13:53 +0000394 ss.connect(("svn.python.org", 443))
395 fd = ss.fileno()
396 f = ss.makefile()
397 f.close()
398 # The fd is still open
399 os.read(fd, 0)
400 # Closing the SSL socket should close the fd too
401 ss.close()
402 gc.collect()
403 with self.assertRaises(OSError) as e:
404 os.read(fd, 0)
405 self.assertEqual(e.exception.errno, errno.EBADF)
406
Antoine Pitrou480a1242010-04-28 21:37:09 +0000407 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000408 s = socket.socket(socket.AF_INET)
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000409 s.settimeout(self.timeout)
Bill Janssen6e027db2007-11-15 22:23:56 +0000410 s.connect(("svn.python.org", 443))
411 s.setblocking(False)
412 s = ssl.wrap_socket(s,
413 cert_reqs=ssl.CERT_NONE,
414 do_handshake_on_connect=False)
415 count = 0
416 while True:
417 try:
418 count += 1
419 s.do_handshake()
420 break
421 except ssl.SSLError as err:
422 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
423 select.select([s], [], [])
424 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
425 select.select([], [s], [])
426 else:
427 raise
428 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000429 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000430 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000431
Antoine Pitrou480a1242010-04-28 21:37:09 +0000432 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000433 pem = ssl.get_server_certificate(("svn.python.org", 443))
434 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000435 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000436
437 return
438
439 try:
440 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
441 except ssl.SSLError as x:
442 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000443 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000444 sys.stdout.write("%s\n" % x)
445 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000446 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000447
448 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
449 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000450 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000451 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000452 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
453
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000454 def test_algorithms(self):
455 # Issue #8484: all algorithms should be available when verifying a
456 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000457 # SHA256 was added in OpenSSL 0.9.8
458 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
459 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000460 # NOTE: https://sha256.tbs-internet.com is another possible test host
461 remote = ("sha2.hboeck.de", 443)
462 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
463 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
464 cert_reqs=ssl.CERT_REQUIRED,
465 ca_certs=sha256_cert,)
Antoine Pitrou35bebe12010-08-14 16:24:38 +0000466 s.settimeout(self.timeout)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000467 with support.transient_internet():
468 try:
469 s.connect(remote)
470 if support.verbose:
471 sys.stdout.write("\nCipher with %r is %r\n" %
472 (remote, s.cipher()))
473 sys.stdout.write("Certificate is:\n%s\n" %
474 pprint.pformat(s.getpeercert()))
475 finally:
476 s.close()
477
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000478
479try:
480 import threading
481except ImportError:
482 _have_threads = False
483else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000484 _have_threads = True
485
486 class ThreadedEchoServer(threading.Thread):
487
488 class ConnectionHandler(threading.Thread):
489
490 """A mildly complicated class, because we want it to work both
491 with and without the SSL wrapper around the socket connection, so
492 that we can test the STARTTLS functionality."""
493
Bill Janssen6e027db2007-11-15 22:23:56 +0000494 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000495 self.server = server
496 self.running = False
497 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000498 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000499 self.sock.setblocking(1)
500 self.sslconn = None
501 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000502 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000503
Antoine Pitrou480a1242010-04-28 21:37:09 +0000504 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000506 self.sslconn = self.server.context.wrap_socket(
507 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000508 except ssl.SSLError:
509 # XXX Various errors can have happened here, for example
510 # a mismatching protocol version, an invalid certificate,
511 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000513 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000514 self.running = False
515 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000516 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000517 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000518 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000519 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000520 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000521 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000522 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
523 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000524 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000525 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
526 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000527 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
529 return True
530
531 def read(self):
532 if self.sslconn:
533 return self.sslconn.read()
534 else:
535 return self.sock.recv(1024)
536
537 def write(self, bytes):
538 if self.sslconn:
539 return self.sslconn.write(bytes)
540 else:
541 return self.sock.send(bytes)
542
543 def close(self):
544 if self.sslconn:
545 self.sslconn.close()
546 else:
547 self.sock.close()
548
Antoine Pitrou480a1242010-04-28 21:37:09 +0000549 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000550 self.running = True
551 if not self.server.starttls_server:
552 if not self.wrap_conn():
553 return
554 while self.running:
555 try:
556 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000557 stripped = msg.strip()
558 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000559 # eof, so quit this handler
560 self.running = False
561 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000562 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000563 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000564 sys.stdout.write(" server: client closed connection\n")
565 self.close()
566 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000567 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000568 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000569 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000570 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000571 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000572 if not self.wrap_conn():
573 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000574 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000575 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000576 if support.verbose and self.server.connectionchatty:
577 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000578 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000579 self.sock = self.sslconn.unwrap()
580 self.sslconn = None
581 if support.verbose and self.server.connectionchatty:
582 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000583 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000584 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000585 self.server.connectionchatty):
586 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000587 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
588 % (msg, ctype, msg.lower(), ctype))
589 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000590 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000591 if self.server.chatty:
592 handle_error("Test server failure:\n")
593 self.close()
594 self.running = False
595 # normally, we'd just stop here, but for the test
596 # harness, we want to stop the server
597 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000598
Antoine Pitroub5218772010-05-21 09:56:06 +0000599 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000600 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000601 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000602 ciphers=None, context=None):
603 if context:
604 self.context = context
605 else:
606 self.context = ssl.SSLContext(ssl_version
607 if ssl_version is not None
608 else ssl.PROTOCOL_TLSv1)
609 self.context.verify_mode = (certreqs if certreqs is not None
610 else ssl.CERT_NONE)
611 if cacerts:
612 self.context.load_verify_locations(cacerts)
613 if certificate:
614 self.context.load_cert_chain(certificate)
615 if ciphers:
616 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000617 self.chatty = chatty
618 self.connectionchatty = connectionchatty
619 self.starttls_server = starttls_server
620 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000621 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000622 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000623 self.active = False
624 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000625 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000626
Antoine Pitrou480a1242010-04-28 21:37:09 +0000627 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000628 self.flag = flag
629 threading.Thread.start(self)
630
Antoine Pitrou480a1242010-04-28 21:37:09 +0000631 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000632 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000633 self.sock.listen(5)
634 self.active = True
635 if self.flag:
636 # signal an event
637 self.flag.set()
638 while self.active:
639 try:
640 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000641 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000642 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000643 + repr(connaddr) + '\n')
644 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645 handler.start()
646 except socket.timeout:
647 pass
648 except KeyboardInterrupt:
649 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000650 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000651
Antoine Pitrou480a1242010-04-28 21:37:09 +0000652 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000653 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000654
Bill Janssen54cc54c2007-12-14 22:08:56 +0000655 class OurHTTPSServer(threading.Thread):
656
657 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000658
659 class HTTPSServer(HTTPServer):
660
661 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 HTTPServer.__init__(self, server_address, RequestHandlerClass)
663 # we assume the certfile contains both private key and certificate
664 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665 self.allow_reuse_address = True
666
Bill Janssen6e027db2007-11-15 22:23:56 +0000667 def __str__(self):
668 return ('<%s %s:%s>' %
669 (self.__class__.__name__,
670 self.server_name,
671 self.server_port))
672
Antoine Pitrou480a1242010-04-28 21:37:09 +0000673 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000674 # override this to wrap socket with SSL
675 sock, addr = self.socket.accept()
676 sslconn = ssl.wrap_socket(sock, server_side=True,
677 certfile=self.certfile)
678 return sslconn, addr
679
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000680 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000681 # need to override translate_path to get a known root,
682 # instead of using os.curdir, since the test could be
683 # run from anywhere
684
685 server_version = "TestHTTPS/1.0"
686
687 root = None
688
689 def translate_path(self, path):
690 """Translate a /-separated PATH to the local filename syntax.
691
692 Components that mean special things to the local file system
693 (e.g. drive or directory names) are ignored. (XXX They should
694 probably be diagnosed.)
695
696 """
697 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000698 path = urllib.parse.urlparse(path)[2]
699 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000700 words = path.split('/')
701 words = filter(None, words)
702 path = self.root
703 for word in words:
704 drive, word = os.path.splitdrive(word)
705 head, word = os.path.split(word)
706 if word in self.root: continue
707 path = os.path.join(path, word)
708 return path
709
710 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000711 # we override this to suppress logging unless "verbose"
712
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000713 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000714 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
715 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000716 self.server.server_port,
717 self.request.cipher(),
718 self.log_date_time_string(),
719 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000720
721
Trent Nelson78520002008-04-10 20:54:35 +0000722 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000723 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000724 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
725 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000726 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
727 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000728 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000729 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000730
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000731 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000732 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000733
Antoine Pitrou480a1242010-04-28 21:37:09 +0000734 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000735 self.flag = flag
736 threading.Thread.start(self)
737
Antoine Pitrou480a1242010-04-28 21:37:09 +0000738 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 if self.flag:
740 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000741 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000742
Antoine Pitrou480a1242010-04-28 21:37:09 +0000743 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000744 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000745
746
Bill Janssen54cc54c2007-12-14 22:08:56 +0000747 class AsyncoreEchoServer(threading.Thread):
748
749 # this one's based on asyncore.dispatcher
750
751 class EchoServer (asyncore.dispatcher):
752
753 class ConnectionHandler (asyncore.dispatcher_with_send):
754
755 def __init__(self, conn, certfile):
756 self.socket = ssl.wrap_socket(conn, server_side=True,
757 certfile=certfile,
758 do_handshake_on_connect=False)
759 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000760 self._ssl_accepting = True
761 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000762
763 def readable(self):
764 if isinstance(self.socket, ssl.SSLSocket):
765 while self.socket.pending() > 0:
766 self.handle_read_event()
767 return True
768
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000769 def _do_ssl_handshake(self):
770 try:
771 self.socket.do_handshake()
772 except ssl.SSLError as err:
773 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
774 ssl.SSL_ERROR_WANT_WRITE):
775 return
776 elif err.args[0] == ssl.SSL_ERROR_EOF:
777 return self.handle_close()
778 raise
779 except socket.error as err:
780 if err.args[0] == errno.ECONNABORTED:
781 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000782 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000783 self._ssl_accepting = False
784
785 def handle_read(self):
786 if self._ssl_accepting:
787 self._do_ssl_handshake()
788 else:
789 data = self.recv(1024)
790 if support.verbose:
791 sys.stdout.write(" server: read %s from client\n" % repr(data))
792 if not data:
793 self.close()
794 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000795 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000796
797 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000798 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000799 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000800 sys.stdout.write(" server: closed connection %s\n" % self.socket)
801
802 def handle_error(self):
803 raise
804
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000805 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000806 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000807 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
808 self.port = support.bind_port(sock, '')
809 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000810 self.listen(5)
811
812 def handle_accept(self):
813 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000814 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000815 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
816 self.ConnectionHandler(sock_obj, self.certfile)
817
818 def handle_error(self):
819 raise
820
Trent Nelson78520002008-04-10 20:54:35 +0000821 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000822 self.flag = None
823 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000824 self.server = self.EchoServer(certfile)
825 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000826 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000827 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000828
829 def __str__(self):
830 return "<%s %s>" % (self.__class__.__name__, self.server)
831
832 def start (self, flag=None):
833 self.flag = flag
834 threading.Thread.start(self)
835
Antoine Pitrou480a1242010-04-28 21:37:09 +0000836 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000837 self.active = True
838 if self.flag:
839 self.flag.set()
840 while self.active:
841 try:
842 asyncore.loop(1)
843 except:
844 pass
845
Antoine Pitrou480a1242010-04-28 21:37:09 +0000846 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000847 self.active = False
848 self.server.close()
849
Antoine Pitrou480a1242010-04-28 21:37:09 +0000850 def bad_cert_test(certfile):
851 """
852 Launch a server with CERT_REQUIRED, and check that trying to
853 connect to it with the given client certificate fails.
854 """
Trent Nelson78520002008-04-10 20:54:35 +0000855 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000857 cacerts=CERTFILE, chatty=False,
858 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000859 flag = threading.Event()
860 server.start(flag)
861 # wait for it to start
862 flag.wait()
863 # try to connect
864 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000865 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 s = ssl.wrap_socket(socket.socket(),
867 certfile=certfile,
868 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000869 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000871 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000872 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000873 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000874 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000875 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000876 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000877 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878 finally:
879 server.stop()
880 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000881
Antoine Pitroub5218772010-05-21 09:56:06 +0000882 def server_params_test(client_context, server_context, indata=b"FOO\n",
883 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000884 """
885 Launch a server, connect a client to it and try various reads
886 and writes.
887 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000888 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000889 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000890 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000891 flag = threading.Event()
892 server.start(flag)
893 # wait for it to start
894 flag.wait()
895 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000897 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000898 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000899 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000900 if connectionchatty:
901 if support.verbose:
902 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000903 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000904 s.write(arg)
905 outdata = s.read()
906 if connectionchatty:
907 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000908 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000909 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000910 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000911 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
912 % (outdata[:20], len(outdata),
913 indata[:20].lower(), len(indata)))
914 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000915 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000916 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000917 sys.stdout.write(" client: closing connection.\n")
918 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919 finally:
920 server.stop()
921 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000922
Antoine Pitroub5218772010-05-21 09:56:06 +0000923 def try_protocol_combo(server_protocol, client_protocol, expect_success,
924 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000925 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000926 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000927 certtype = {
928 ssl.CERT_NONE: "CERT_NONE",
929 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
930 ssl.CERT_REQUIRED: "CERT_REQUIRED",
931 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000932 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000933 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000934 sys.stdout.write(formatstr %
935 (ssl.get_protocol_name(client_protocol),
936 ssl.get_protocol_name(server_protocol),
937 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000938 client_context = ssl.SSLContext(client_protocol)
939 client_context.options = ssl.OP_ALL | client_options
940 server_context = ssl.SSLContext(server_protocol)
941 server_context.options = ssl.OP_ALL | server_options
942 for ctx in (client_context, server_context):
943 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000944 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
945 # will send an SSLv3 hello (rather than SSLv2) starting from
946 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000947 ctx.set_ciphers("ALL")
948 ctx.load_cert_chain(CERTFILE)
949 ctx.load_verify_locations(CERTFILE)
950 try:
951 server_params_test(client_context, server_context,
952 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000953 # Protocol mismatch can result in either an SSLError, or a
954 # "Connection reset by peer" error.
955 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000956 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000957 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000958 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000959 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000960 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000961 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000962 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000963 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000964 "Client protocol %s succeeded with server protocol %s!"
965 % (ssl.get_protocol_name(client_protocol),
966 ssl.get_protocol_name(server_protocol)))
967
968
Bill Janssen6e027db2007-11-15 22:23:56 +0000969 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970
Antoine Pitrou23df4832010-08-04 17:14:06 +0000971 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +0000972 def test_echo(self):
973 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000974 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000976 for protocol in PROTOCOLS:
977 context = ssl.SSLContext(protocol)
978 context.load_cert_chain(CERTFILE)
979 server_params_test(context, context,
980 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981
Antoine Pitrou480a1242010-04-28 21:37:09 +0000982 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000983 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +0000985 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
986 context.verify_mode = ssl.CERT_REQUIRED
987 context.load_verify_locations(CERTFILE)
988 context.load_cert_chain(CERTFILE)
989 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 flag = threading.Event()
991 server.start(flag)
992 # wait for it to start
993 flag.wait()
994 # try to connect
995 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000996 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000997 s.connect((HOST, server.port))
998 cert = s.getpeercert()
999 self.assertTrue(cert, "Can't get peer certificate.")
1000 cipher = s.cipher()
1001 if support.verbose:
1002 sys.stdout.write(pprint.pformat(cert) + '\n')
1003 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1004 if 'subject' not in cert:
1005 self.fail("No subject field in certificate: %s." %
1006 pprint.pformat(cert))
1007 if ((('organizationName', 'Python Software Foundation'),)
1008 not in cert['subject']):
1009 self.fail(
1010 "Missing or invalid 'organizationName' field in certificate subject; "
1011 "should be 'Python Software Foundation'.")
1012 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001013 finally:
1014 server.stop()
1015 server.join()
1016
Antoine Pitrou480a1242010-04-28 21:37:09 +00001017 def test_empty_cert(self):
1018 """Connecting with an empty cert file"""
1019 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1020 "nullcert.pem"))
1021 def test_malformed_cert(self):
1022 """Connecting with a badly formatted certificate (syntax error)"""
1023 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1024 "badcert.pem"))
1025 def test_nonexisting_cert(self):
1026 """Connecting with a non-existing cert file"""
1027 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1028 "wrongcert.pem"))
1029 def test_malformed_key(self):
1030 """Connecting with a badly formatted key (syntax error)"""
1031 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1032 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001033
Antoine Pitrou480a1242010-04-28 21:37:09 +00001034 def test_rude_shutdown(self):
1035 """A brutal shutdown of an SSL server should raise an IOError
1036 in the client when attempting handshake.
1037 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001038 listener_ready = threading.Event()
1039 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001040
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001041 s = socket.socket()
1042 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001043
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001044 # `listener` runs in a thread. It sits in an accept() until
1045 # the main thread connects. Then it rudely closes the socket,
1046 # and sets Event `listener_gone` to let the main thread know
1047 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001048 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001049 s.listen(5)
1050 listener_ready.set()
1051 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001052 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001053 listener_gone.set()
1054
1055 def connector():
1056 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001057 c = socket.socket()
1058 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001059 listener_gone.wait()
1060 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001061 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001062 except IOError:
1063 pass
1064 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001065 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001066
1067 t = threading.Thread(target=listener)
1068 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001069 try:
1070 connector()
1071 finally:
1072 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001073
Antoine Pitrou23df4832010-08-04 17:14:06 +00001074 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001075 def test_protocol_sslv2(self):
1076 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001077 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001078 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001079 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1080 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1081 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1082 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1083 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1084 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001085 # SSLv23 client with specific SSL options
1086 if no_sslv2_implies_sslv3_hello():
1087 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1088 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1089 client_options=ssl.OP_NO_SSLv2)
1090 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1091 client_options=ssl.OP_NO_SSLv3)
1092 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1093 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001094
Antoine Pitrou23df4832010-08-04 17:14:06 +00001095 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001096 def test_protocol_sslv23(self):
1097 """Connecting to an SSLv23 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")
1100 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001101 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001102 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001103 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001104 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001105 sys.stdout.write(
1106 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1107 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001108 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1109 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1110 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001111
Antoine Pitrou480a1242010-04-28 21:37:09 +00001112 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1113 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1114 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001115
Antoine Pitrou480a1242010-04-28 21:37:09 +00001116 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1117 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1118 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001119
Antoine Pitroub5218772010-05-21 09:56:06 +00001120 # Server with specific SSL options
1121 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1122 server_options=ssl.OP_NO_SSLv3)
1123 # Will choose TLSv1
1124 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1125 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1126 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1127 server_options=ssl.OP_NO_TLSv1)
1128
1129
Antoine Pitrou23df4832010-08-04 17:14:06 +00001130 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001131 def test_protocol_sslv3(self):
1132 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001133 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001134 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001135 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1136 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1137 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1138 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1139 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1140 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001141 if no_sslv2_implies_sslv3_hello():
1142 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1143 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1144 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001145
Antoine Pitrou23df4832010-08-04 17:14:06 +00001146 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001147 def test_protocol_tlsv1(self):
1148 """Connecting to a TLSv1 server with various client options"""
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 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1152 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1153 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1154 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1155 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1156 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001157
Antoine Pitrou480a1242010-04-28 21:37:09 +00001158 def test_starttls(self):
1159 """Switching from clear text to encrypted and back again."""
1160 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 +00001161
Trent Nelson78520002008-04-10 20:54:35 +00001162 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163 ssl_version=ssl.PROTOCOL_TLSv1,
1164 starttls_server=True,
1165 chatty=True,
1166 connectionchatty=True)
1167 flag = threading.Event()
1168 server.start(flag)
1169 # wait for it to start
1170 flag.wait()
1171 # try to connect
1172 wrapped = False
1173 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001174 s = socket.socket()
1175 s.setblocking(1)
1176 s.connect((HOST, server.port))
1177 if support.verbose:
1178 sys.stdout.write("\n")
1179 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001180 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001181 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001183 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001184 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001185 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001186 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001187 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001188 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001189 msg = outdata.strip().lower()
1190 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1191 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001192 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001193 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001194 " client: read %r from server, starting TLS...\n"
1195 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001196 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1197 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001198 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1199 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001200 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001201 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001202 " client: read %r from server, ending TLS...\n"
1203 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001204 s = conn.unwrap()
1205 wrapped = False
1206 else:
1207 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001208 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001209 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001210 if support.verbose:
1211 sys.stdout.write(" client: closing connection.\n")
1212 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001213 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001214 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001215 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001216 if wrapped:
1217 conn.close()
1218 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001219 s.close()
1220 finally:
1221 server.stop()
1222 server.join()
1223
Antoine Pitrou480a1242010-04-28 21:37:09 +00001224 def test_socketserver(self):
1225 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001226 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001227 flag = threading.Event()
1228 server.start(flag)
1229 # wait for it to start
1230 flag.wait()
1231 # try to connect
1232 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001233 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001235 with open(CERTFILE, 'rb') as f:
1236 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001237 d2 = ''
1238 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001239 url = 'https://%s:%d/%s' % (
1240 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001241 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001242 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 if dlen and (int(dlen) > 0):
1244 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001245 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001246 sys.stdout.write(
1247 " client: read %d bytes from remote server '%s'\n"
1248 % (len(d2), server))
1249 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001250 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001251 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001252 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001253 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001254 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001255 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001256 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001257 server.join()
1258
Antoine Pitrou480a1242010-04-28 21:37:09 +00001259 def test_asyncore_server(self):
1260 """Check the example asyncore integration."""
1261 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001262
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001263 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001264 sys.stdout.write("\n")
1265
Antoine Pitrou480a1242010-04-28 21:37:09 +00001266 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001267 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001268 flag = threading.Event()
1269 server.start(flag)
1270 # wait for it to start
1271 flag.wait()
1272 # try to connect
1273 try:
1274 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001275 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001276 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001277 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001278 " client: sending %r...\n" % indata)
1279 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001280 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001281 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001282 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001283 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001284 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001285 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1286 % (outdata[:20], len(outdata),
1287 indata[:20].lower(), len(indata)))
1288 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001289 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001290 sys.stdout.write(" client: closing connection.\n")
1291 s.close()
1292 finally:
1293 server.stop()
1294 server.join()
1295
Antoine Pitrou480a1242010-04-28 21:37:09 +00001296 def test_recv_send(self):
1297 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001298 if support.verbose:
1299 sys.stdout.write("\n")
1300
1301 server = ThreadedEchoServer(CERTFILE,
1302 certreqs=ssl.CERT_NONE,
1303 ssl_version=ssl.PROTOCOL_TLSv1,
1304 cacerts=CERTFILE,
1305 chatty=True,
1306 connectionchatty=False)
1307 flag = threading.Event()
1308 server.start(flag)
1309 # wait for it to start
1310 flag.wait()
1311 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001312 s = ssl.wrap_socket(socket.socket(),
1313 server_side=False,
1314 certfile=CERTFILE,
1315 ca_certs=CERTFILE,
1316 cert_reqs=ssl.CERT_NONE,
1317 ssl_version=ssl.PROTOCOL_TLSv1)
1318 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001319 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001320 # helper methods for standardising recv* method signatures
1321 def _recv_into():
1322 b = bytearray(b"\0"*100)
1323 count = s.recv_into(b)
1324 return b[:count]
1325
1326 def _recvfrom_into():
1327 b = bytearray(b"\0"*100)
1328 count, addr = s.recvfrom_into(b)
1329 return b[:count]
1330
1331 # (name, method, whether to expect success, *args)
1332 send_methods = [
1333 ('send', s.send, True, []),
1334 ('sendto', s.sendto, False, ["some.address"]),
1335 ('sendall', s.sendall, True, []),
1336 ]
1337 recv_methods = [
1338 ('recv', s.recv, True, []),
1339 ('recvfrom', s.recvfrom, False, ["some.address"]),
1340 ('recv_into', _recv_into, True, []),
1341 ('recvfrom_into', _recvfrom_into, False, []),
1342 ]
1343 data_prefix = "PREFIX_"
1344
1345 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001346 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001347 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001348 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001349 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001350 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001351 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001352 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001353 "<<{outdata:r}>> ({nout:d}) received; "
1354 "expected <<{indata:r}>> ({nin:d})\n".format(
1355 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001356 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001358 )
1359 )
1360 except ValueError as e:
1361 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001362 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001363 "Failed to send with method <<{name:s}>>; "
1364 "expected to succeed.\n".format(name=meth_name)
1365 )
1366 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001367 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001368 "Method <<{name:s}>> failed with unexpected "
1369 "exception message: {exp:s}\n".format(
1370 name=meth_name, exp=e
1371 )
1372 )
1373
1374 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001375 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001376 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001377 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001378 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001380 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001381 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001382 "<<{outdata:r}>> ({nout:d}) received; "
1383 "expected <<{indata:r}>> ({nin:d})\n".format(
1384 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001385 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001386 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001387 )
1388 )
1389 except ValueError as e:
1390 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001391 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001392 "Failed to receive with method <<{name:s}>>; "
1393 "expected to succeed.\n".format(name=meth_name)
1394 )
1395 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001396 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001397 "Method <<{name:s}>> failed with unexpected "
1398 "exception message: {exp:s}\n".format(
1399 name=meth_name, exp=e
1400 )
1401 )
1402 # consume data
1403 s.read()
1404
Antoine Pitrou480a1242010-04-28 21:37:09 +00001405 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001406 s.close()
1407 finally:
1408 server.stop()
1409 server.join()
1410
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001411 def test_handshake_timeout(self):
1412 # Issue #5103: SSL handshake must respect the socket timeout
1413 server = socket.socket(socket.AF_INET)
1414 host = "127.0.0.1"
1415 port = support.bind_port(server)
1416 started = threading.Event()
1417 finish = False
1418
1419 def serve():
1420 server.listen(5)
1421 started.set()
1422 conns = []
1423 while not finish:
1424 r, w, e = select.select([server], [], [], 0.1)
1425 if server in r:
1426 # Let the socket hang around rather than having
1427 # it closed by garbage collection.
1428 conns.append(server.accept()[0])
1429
1430 t = threading.Thread(target=serve)
1431 t.start()
1432 started.wait()
1433
1434 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001435 try:
1436 c = socket.socket(socket.AF_INET)
1437 c.settimeout(0.2)
1438 c.connect((host, port))
1439 # Will attempt handshake and time out
1440 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1441 ssl.wrap_socket, c)
1442 finally:
1443 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001444 try:
1445 c = socket.socket(socket.AF_INET)
1446 c = ssl.wrap_socket(c)
1447 c.settimeout(0.2)
1448 # Will attempt handshake and time out
1449 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1450 c.connect, (host, port))
1451 finally:
1452 c.close()
1453 finally:
1454 finish = True
1455 t.join()
1456 server.close()
1457
Bill Janssen58afe4c2008-09-08 16:45:19 +00001458
Thomas Woutersed03b412007-08-28 21:37:11 +00001459def test_main(verbose=False):
1460 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001461 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001462
Antoine Pitrou15cee622010-08-04 16:45:21 +00001463 if support.verbose:
1464 plats = {
1465 'Linux': platform.linux_distribution,
1466 'Mac': platform.mac_ver,
1467 'Windows': platform.win32_ver,
1468 }
1469 for name, func in plats.items():
1470 plat = func()
1471 if plat and plat[0]:
1472 plat = '%s %r' % (name, plat)
1473 break
1474 else:
1475 plat = repr(platform.platform())
1476 print("test_ssl: testing with %r %r" %
1477 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1478 print(" under %s" % plat)
1479
Antoine Pitrou152efa22010-05-16 18:19:27 +00001480 for filename in [
1481 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1482 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1483 BADCERT, BADKEY, EMPTYCERT]:
1484 if not os.path.exists(filename):
1485 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001486
Antoine Pitrou152efa22010-05-16 18:19:27 +00001487 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001488
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001489 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001490 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001491
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001492 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001493 thread_info = support.threading_setup()
1494 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001495 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001496
Antoine Pitrou480a1242010-04-28 21:37:09 +00001497 try:
1498 support.run_unittest(*tests)
1499 finally:
1500 if _have_threads:
1501 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001502
1503if __name__ == "__main__":
1504 test_main()