blob: 0c8a8e63b297f72b33a4dcc801a2916e020f1091 [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
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import 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
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
23PROTOCOLS = [
24 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
25 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Thomas Woutersed03b412007-08-28 21:37:11 +000027
Benjamin Petersonee8712c2008-05-20 21:35:26 +000028HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000029
30data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
Antoine Pitrou81564092010-10-08 23:06:24 +000032# The custom key and certificate files used in test_ssl are generated
33# using Lib/test/make_ssl_certs.py.
34# Other certificates are simply fetched from the Internet servers they
35# are meant to authenticate.
36
Antoine Pitrou152efa22010-05-16 18:19:27 +000037CERTFILE = 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 Pitrou23df4832010-08-04 17:14:06 +000068# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
69def skip_if_broken_ubuntu_ssl(func):
70 @functools.wraps(func)
71 def f(*args, **kwargs):
72 try:
73 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
74 except ssl.SSLError:
75 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
76 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
77 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
78 return func(*args, **kwargs)
79 return f
80
81
Antoine Pitrou152efa22010-05-16 18:19:27 +000082class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000083
Antoine Pitrou480a1242010-04-28 21:37:09 +000084 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000085 ssl.PROTOCOL_SSLv2
86 ssl.PROTOCOL_SSLv23
87 ssl.PROTOCOL_SSLv3
88 ssl.PROTOCOL_TLSv1
89 ssl.CERT_NONE
90 ssl.CERT_OPTIONAL
91 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000092
Antoine Pitrou480a1242010-04-28 21:37:09 +000093 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000094 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000095 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 sys.stdout.write("\n RAND_status is %d (%s)\n"
97 % (v, (v and "sufficient randomness") or
98 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000099 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000100 ssl.RAND_egd(1)
101 except TypeError:
102 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000103 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000104 print("didn't raise TypeError")
105 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000106
Antoine Pitrou480a1242010-04-28 21:37:09 +0000107 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000108 # note that this uses an 'unofficial' function in _ssl.c,
109 # provided solely for this test, to exercise the certificate
110 # parsing code
111 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000112 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000114
Antoine Pitrou480a1242010-04-28 21:37:09 +0000115 def test_DER_to_PEM(self):
116 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
117 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000118 d1 = ssl.PEM_cert_to_DER_cert(pem)
119 p2 = ssl.DER_cert_to_PEM_cert(d1)
120 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000121 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000122 if not p2.startswith(ssl.PEM_HEADER + '\n'):
123 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
124 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
125 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000126
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000127 def test_openssl_version(self):
128 n = ssl.OPENSSL_VERSION_NUMBER
129 t = ssl.OPENSSL_VERSION_INFO
130 s = ssl.OPENSSL_VERSION
131 self.assertIsInstance(n, int)
132 self.assertIsInstance(t, tuple)
133 self.assertIsInstance(s, str)
134 # Some sanity checks follow
135 # >= 0.9
136 self.assertGreaterEqual(n, 0x900000)
137 # < 2.0
138 self.assertLess(n, 0x20000000)
139 major, minor, fix, patch, status = t
140 self.assertGreaterEqual(major, 0)
141 self.assertLess(major, 2)
142 self.assertGreaterEqual(minor, 0)
143 self.assertLess(minor, 256)
144 self.assertGreaterEqual(fix, 0)
145 self.assertLess(fix, 256)
146 self.assertGreaterEqual(patch, 0)
147 self.assertLessEqual(patch, 26)
148 self.assertGreaterEqual(status, 0)
149 self.assertLessEqual(status, 15)
150 # Version string as returned by OpenSSL, the format might change
151 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
152 (s, t))
153
Antoine Pitrou9d543662010-04-23 23:10:32 +0000154 @support.cpython_only
155 def test_refcycle(self):
156 # Issue #7943: an SSL object doesn't create reference cycles with
157 # itself.
158 s = socket.socket(socket.AF_INET)
159 ss = ssl.wrap_socket(s)
160 wr = weakref.ref(ss)
161 del ss
162 self.assertEqual(wr(), None)
163
Antoine Pitroua468adc2010-09-14 14:43:44 +0000164 def test_wrapped_unconnected(self):
165 # Methods on an unconnected SSLSocket propagate the original
166 # socket.error raise by the underlying socket object.
167 s = socket.socket(socket.AF_INET)
168 ss = ssl.wrap_socket(s)
169 self.assertRaises(socket.error, ss.recv, 1)
170 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
171 self.assertRaises(socket.error, ss.recvfrom, 1)
172 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
173 self.assertRaises(socket.error, ss.send, b'x')
174 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
175
Antoine Pitrou40f08742010-04-24 22:04:40 +0000176 def test_timeout(self):
177 # Issue #8524: when creating an SSL socket, the timeout of the
178 # original socket should be retained.
179 for timeout in (None, 0.0, 5.0):
180 s = socket.socket(socket.AF_INET)
181 s.settimeout(timeout)
182 ss = ssl.wrap_socket(s)
183 self.assertEqual(timeout, ss.gettimeout())
184
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000185 def test_errors(self):
186 sock = socket.socket()
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000187 self.assertRaisesRegexp(ValueError,
188 "certfile must be specified",
189 ssl.wrap_socket, sock, keyfile=CERTFILE)
190 self.assertRaisesRegexp(ValueError,
191 "certfile must be specified for server-side operations",
192 ssl.wrap_socket, sock, server_side=True)
193 self.assertRaisesRegexp(ValueError,
194 "certfile must be specified for server-side operations",
195 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000196 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
197 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
198 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000199 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000200 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000201 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000202 with self.assertRaises(IOError) as cm:
203 ssl.wrap_socket(socket.socket(), certfile=CERTFILE, keyfile=WRONGCERT)
204 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000205 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000206 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000207 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000208
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000209 def test_match_hostname(self):
210 def ok(cert, hostname):
211 ssl.match_hostname(cert, hostname)
212 def fail(cert, hostname):
213 self.assertRaises(ssl.CertificateError,
214 ssl.match_hostname, cert, hostname)
215
216 cert = {'subject': ((('commonName', 'example.com'),),)}
217 ok(cert, 'example.com')
218 ok(cert, 'ExAmple.cOm')
219 fail(cert, 'www.example.com')
220 fail(cert, '.example.com')
221 fail(cert, 'example.org')
222 fail(cert, 'exampleXcom')
223
224 cert = {'subject': ((('commonName', '*.a.com'),),)}
225 ok(cert, 'foo.a.com')
226 fail(cert, 'bar.foo.a.com')
227 fail(cert, 'a.com')
228 fail(cert, 'Xa.com')
229 fail(cert, '.a.com')
230
231 cert = {'subject': ((('commonName', 'a.*.com'),),)}
232 ok(cert, 'a.foo.com')
233 fail(cert, 'a..com')
234 fail(cert, 'a.com')
235
236 cert = {'subject': ((('commonName', 'f*.com'),),)}
237 ok(cert, 'foo.com')
238 ok(cert, 'f.com')
239 fail(cert, 'bar.com')
240 fail(cert, 'foo.a.com')
241 fail(cert, 'bar.foo.com')
242
243 # Slightly fake real-world example
244 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
245 'subject': ((('commonName', 'linuxfrz.org'),),),
246 'subjectAltName': (('DNS', 'linuxfr.org'),
247 ('DNS', 'linuxfr.com'),
248 ('othername', '<unsupported>'))}
249 ok(cert, 'linuxfr.org')
250 ok(cert, 'linuxfr.com')
251 # Not a "DNS" entry
252 fail(cert, '<unsupported>')
253 # When there is a subjectAltName, commonName isn't used
254 fail(cert, 'linuxfrz.org')
255
256 # A pristine real-world example
257 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
258 'subject': ((('countryName', 'US'),),
259 (('stateOrProvinceName', 'California'),),
260 (('localityName', 'Mountain View'),),
261 (('organizationName', 'Google Inc'),),
262 (('commonName', 'mail.google.com'),))}
263 ok(cert, 'mail.google.com')
264 fail(cert, 'gmail.com')
265 # Only commonName is considered
266 fail(cert, 'California')
267
268 # Neither commonName nor subjectAltName
269 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
270 'subject': ((('countryName', 'US'),),
271 (('stateOrProvinceName', 'California'),),
272 (('localityName', 'Mountain View'),),
273 (('organizationName', 'Google Inc'),))}
274 fail(cert, 'mail.google.com')
275
276 # Empty cert / no cert
277 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
278 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
279
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000280
Antoine Pitrou152efa22010-05-16 18:19:27 +0000281class ContextTests(unittest.TestCase):
282
Antoine Pitrou23df4832010-08-04 17:14:06 +0000283 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000284 def test_constructor(self):
285 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
286 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
287 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
288 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
289 self.assertRaises(TypeError, ssl.SSLContext)
290 self.assertRaises(ValueError, ssl.SSLContext, -1)
291 self.assertRaises(ValueError, ssl.SSLContext, 42)
292
Antoine Pitrou23df4832010-08-04 17:14:06 +0000293 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000294 def test_protocol(self):
295 for proto in PROTOCOLS:
296 ctx = ssl.SSLContext(proto)
297 self.assertEqual(ctx.protocol, proto)
298
299 def test_ciphers(self):
300 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
301 ctx.set_ciphers("ALL")
302 ctx.set_ciphers("DEFAULT")
303 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000304 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000305
Antoine Pitrou23df4832010-08-04 17:14:06 +0000306 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000307 def test_options(self):
308 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
309 # OP_ALL is the default value
310 self.assertEqual(ssl.OP_ALL, ctx.options)
311 ctx.options |= ssl.OP_NO_SSLv2
312 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
313 ctx.options)
314 ctx.options |= ssl.OP_NO_SSLv3
315 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
316 ctx.options)
317 if can_clear_options():
318 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
319 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
320 ctx.options)
321 ctx.options = 0
322 self.assertEqual(0, ctx.options)
323 else:
324 with self.assertRaises(ValueError):
325 ctx.options = 0
326
Antoine Pitrou152efa22010-05-16 18:19:27 +0000327 def test_verify(self):
328 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
329 # Default value
330 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
331 ctx.verify_mode = ssl.CERT_OPTIONAL
332 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
333 ctx.verify_mode = ssl.CERT_REQUIRED
334 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
335 ctx.verify_mode = ssl.CERT_NONE
336 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
337 with self.assertRaises(TypeError):
338 ctx.verify_mode = None
339 with self.assertRaises(ValueError):
340 ctx.verify_mode = 42
341
342 def test_load_cert_chain(self):
343 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
344 # Combined key and cert in a single file
345 ctx.load_cert_chain(CERTFILE)
346 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
347 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000348 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000349 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000350 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000351 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
352 ctx.load_cert_chain(BADCERT)
353 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
354 ctx.load_cert_chain(EMPTYCERT)
355 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000356 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000357 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
358 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
359 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
360 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
361 ctx.load_cert_chain(ONLYCERT)
362 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
363 ctx.load_cert_chain(ONLYKEY)
364 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
365 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
366 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000367 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000368 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000369 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000370
371 def test_load_verify_locations(self):
372 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
373 ctx.load_verify_locations(CERTFILE)
374 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
375 ctx.load_verify_locations(BYTES_CERTFILE)
376 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
377 self.assertRaises(TypeError, ctx.load_verify_locations)
378 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000379 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000380 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000381 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000382 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
383 ctx.load_verify_locations(BADCERT)
384 ctx.load_verify_locations(CERTFILE, CAPATH)
385 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
386
Antoine Pitroub0182c82010-10-12 20:09:02 +0000387 def test_session_stats(self):
388 for proto in PROTOCOLS:
389 ctx = ssl.SSLContext(proto)
390 self.assertEqual(ctx.session_stats(), {
391 'number': 0,
392 'connect': 0,
393 'connect_good': 0,
394 'connect_renegotiate': 0,
395 'accept': 0,
396 'accept_good': 0,
397 'accept_renegotiate': 0,
398 'hits': 0,
399 'misses': 0,
400 'timeouts': 0,
401 'cache_full': 0,
402 })
403
Antoine Pitrou152efa22010-05-16 18:19:27 +0000404
Bill Janssen6e027db2007-11-15 22:23:56 +0000405class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000406
Antoine Pitrou480a1242010-04-28 21:37:09 +0000407 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000408 with support.transient_internet("svn.python.org"):
409 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
410 cert_reqs=ssl.CERT_NONE)
411 try:
412 s.connect(("svn.python.org", 443))
413 self.assertEqual({}, s.getpeercert())
414 finally:
415 s.close()
416
417 # this should fail because we have no verification certs
418 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
419 cert_reqs=ssl.CERT_REQUIRED)
420 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
421 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000422 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000423
Antoine Pitrou350c7222010-09-09 13:31:46 +0000424 # this should succeed because we specify the root cert
425 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
426 cert_reqs=ssl.CERT_REQUIRED,
427 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
428 try:
429 s.connect(("svn.python.org", 443))
430 self.assertTrue(s.getpeercert())
431 finally:
432 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000433
434 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000435 with support.transient_internet("svn.python.org"):
436 # Same as test_connect, but with a separately created context
437 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
438 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
439 s.connect(("svn.python.org", 443))
440 try:
441 self.assertEqual({}, s.getpeercert())
442 finally:
443 s.close()
444 # This should fail because we have no verification certs
445 ctx.verify_mode = ssl.CERT_REQUIRED
446 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
447 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
448 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000449 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000450 # This should succeed because we specify the root cert
451 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
452 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
453 s.connect(("svn.python.org", 443))
454 try:
455 cert = s.getpeercert()
456 self.assertTrue(cert)
457 finally:
458 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000459
460 def test_connect_capath(self):
461 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000462 # NOTE: the subject hashing algorithm has been changed between
463 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
464 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000465 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000466 with support.transient_internet("svn.python.org"):
467 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
468 ctx.verify_mode = ssl.CERT_REQUIRED
469 ctx.load_verify_locations(capath=CAPATH)
470 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
471 s.connect(("svn.python.org", 443))
472 try:
473 cert = s.getpeercert()
474 self.assertTrue(cert)
475 finally:
476 s.close()
477 # Same with a bytes `capath` argument
478 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
479 ctx.verify_mode = ssl.CERT_REQUIRED
480 ctx.load_verify_locations(capath=BYTES_CAPATH)
481 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
482 s.connect(("svn.python.org", 443))
483 try:
484 cert = s.getpeercert()
485 self.assertTrue(cert)
486 finally:
487 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000488
Antoine Pitroue3220242010-04-24 11:13:53 +0000489 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
490 def test_makefile_close(self):
491 # Issue #5238: creating a file-like object with makefile() shouldn't
492 # delay closing the underlying "real socket" (here tested with its
493 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000494 with support.transient_internet("svn.python.org"):
495 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
496 ss.connect(("svn.python.org", 443))
497 fd = ss.fileno()
498 f = ss.makefile()
499 f.close()
500 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000501 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000502 # Closing the SSL socket should close the fd too
503 ss.close()
504 gc.collect()
505 with self.assertRaises(OSError) as e:
506 os.read(fd, 0)
507 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000508
Antoine Pitrou480a1242010-04-28 21:37:09 +0000509 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000510 with support.transient_internet("svn.python.org"):
511 s = socket.socket(socket.AF_INET)
512 s.connect(("svn.python.org", 443))
513 s.setblocking(False)
514 s = ssl.wrap_socket(s,
515 cert_reqs=ssl.CERT_NONE,
516 do_handshake_on_connect=False)
517 count = 0
518 while True:
519 try:
520 count += 1
521 s.do_handshake()
522 break
523 except ssl.SSLError as err:
524 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
525 select.select([s], [], [])
526 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
527 select.select([], [s], [])
528 else:
529 raise
530 s.close()
531 if support.verbose:
532 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000533
Antoine Pitrou480a1242010-04-28 21:37:09 +0000534 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000535 with support.transient_internet("svn.python.org"):
536 pem = ssl.get_server_certificate(("svn.python.org", 443))
537 if not pem:
538 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000539
Antoine Pitrou350c7222010-09-09 13:31:46 +0000540 try:
541 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
542 except ssl.SSLError as x:
543 #should fail
544 if support.verbose:
545 sys.stdout.write("%s\n" % x)
546 else:
547 self.fail("Got server certificate %s for svn.python.org!" % pem)
548
549 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
550 if not pem:
551 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000552 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000553 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000554
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000555 def test_ciphers(self):
556 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000557 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000558 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000559 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000560 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000561 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
562 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
563 s.connect(remote)
564 # Error checking can happen at instantiation or when connecting
565 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
566 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
567 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
568 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000569
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000570 def test_algorithms(self):
571 # Issue #8484: all algorithms should be available when verifying a
572 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000573 # SHA256 was added in OpenSSL 0.9.8
574 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
575 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000576 # NOTE: https://sha256.tbs-internet.com is another possible test host
577 remote = ("sha2.hboeck.de", 443)
578 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000579 with support.transient_internet("sha2.hboeck.de"):
580 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
581 cert_reqs=ssl.CERT_REQUIRED,
582 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000583 try:
584 s.connect(remote)
585 if support.verbose:
586 sys.stdout.write("\nCipher with %r is %r\n" %
587 (remote, s.cipher()))
588 sys.stdout.write("Certificate is:\n%s\n" %
589 pprint.pformat(s.getpeercert()))
590 finally:
591 s.close()
592
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000593
594try:
595 import threading
596except ImportError:
597 _have_threads = False
598else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000599 _have_threads = True
600
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000601 from test.ssl_servers import make_https_server
602
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000603 class ThreadedEchoServer(threading.Thread):
604
605 class ConnectionHandler(threading.Thread):
606
607 """A mildly complicated class, because we want it to work both
608 with and without the SSL wrapper around the socket connection, so
609 that we can test the STARTTLS functionality."""
610
Bill Janssen6e027db2007-11-15 22:23:56 +0000611 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000612 self.server = server
613 self.running = False
614 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000615 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000616 self.sock.setblocking(1)
617 self.sslconn = None
618 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000619 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000620
Antoine Pitrou480a1242010-04-28 21:37:09 +0000621 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000622 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000623 self.sslconn = self.server.context.wrap_socket(
624 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000625 except ssl.SSLError:
626 # XXX Various errors can have happened here, for example
627 # a mismatching protocol version, an invalid certificate,
628 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000629 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000630 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000631 self.running = False
632 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000633 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000635 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000636 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000637 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000638 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
640 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000641 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000642 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
643 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000644 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
646 return True
647
648 def read(self):
649 if self.sslconn:
650 return self.sslconn.read()
651 else:
652 return self.sock.recv(1024)
653
654 def write(self, bytes):
655 if self.sslconn:
656 return self.sslconn.write(bytes)
657 else:
658 return self.sock.send(bytes)
659
660 def close(self):
661 if self.sslconn:
662 self.sslconn.close()
663 else:
664 self.sock.close()
665
Antoine Pitrou480a1242010-04-28 21:37:09 +0000666 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000667 self.running = True
668 if not self.server.starttls_server:
669 if not self.wrap_conn():
670 return
671 while self.running:
672 try:
673 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000674 stripped = msg.strip()
675 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000676 # eof, so quit this handler
677 self.running = False
678 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000679 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000680 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000681 sys.stdout.write(" server: client closed connection\n")
682 self.close()
683 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000684 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000685 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000686 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000687 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000688 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000689 if not self.wrap_conn():
690 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000691 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000692 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000693 if support.verbose and self.server.connectionchatty:
694 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000695 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000696 self.sock = self.sslconn.unwrap()
697 self.sslconn = None
698 if support.verbose and self.server.connectionchatty:
699 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000700 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000701 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000702 self.server.connectionchatty):
703 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000704 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
705 % (msg, ctype, msg.lower(), ctype))
706 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000707 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000708 if self.server.chatty:
709 handle_error("Test server failure:\n")
710 self.close()
711 self.running = False
712 # normally, we'd just stop here, but for the test
713 # harness, we want to stop the server
714 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000715
Antoine Pitroub5218772010-05-21 09:56:06 +0000716 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000717 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000718 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000719 ciphers=None, context=None):
720 if context:
721 self.context = context
722 else:
723 self.context = ssl.SSLContext(ssl_version
724 if ssl_version is not None
725 else ssl.PROTOCOL_TLSv1)
726 self.context.verify_mode = (certreqs if certreqs is not None
727 else ssl.CERT_NONE)
728 if cacerts:
729 self.context.load_verify_locations(cacerts)
730 if certificate:
731 self.context.load_cert_chain(certificate)
732 if ciphers:
733 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000734 self.chatty = chatty
735 self.connectionchatty = connectionchatty
736 self.starttls_server = starttls_server
737 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000738 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000740 self.active = False
741 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000742 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000743
Antoine Pitrou480a1242010-04-28 21:37:09 +0000744 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000745 self.flag = flag
746 threading.Thread.start(self)
747
Antoine Pitrou480a1242010-04-28 21:37:09 +0000748 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000749 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750 self.sock.listen(5)
751 self.active = True
752 if self.flag:
753 # signal an event
754 self.flag.set()
755 while self.active:
756 try:
757 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000758 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000759 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000760 + repr(connaddr) + '\n')
761 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000762 handler.start()
763 except socket.timeout:
764 pass
765 except KeyboardInterrupt:
766 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000767 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000768
Antoine Pitrou480a1242010-04-28 21:37:09 +0000769 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000770 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000771
Bill Janssen54cc54c2007-12-14 22:08:56 +0000772 class AsyncoreEchoServer(threading.Thread):
773
774 # this one's based on asyncore.dispatcher
775
776 class EchoServer (asyncore.dispatcher):
777
778 class ConnectionHandler (asyncore.dispatcher_with_send):
779
780 def __init__(self, conn, certfile):
781 self.socket = ssl.wrap_socket(conn, server_side=True,
782 certfile=certfile,
783 do_handshake_on_connect=False)
784 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000785 self._ssl_accepting = True
786 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000787
788 def readable(self):
789 if isinstance(self.socket, ssl.SSLSocket):
790 while self.socket.pending() > 0:
791 self.handle_read_event()
792 return True
793
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000794 def _do_ssl_handshake(self):
795 try:
796 self.socket.do_handshake()
797 except ssl.SSLError as err:
798 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
799 ssl.SSL_ERROR_WANT_WRITE):
800 return
801 elif err.args[0] == ssl.SSL_ERROR_EOF:
802 return self.handle_close()
803 raise
804 except socket.error as err:
805 if err.args[0] == errno.ECONNABORTED:
806 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000807 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000808 self._ssl_accepting = False
809
810 def handle_read(self):
811 if self._ssl_accepting:
812 self._do_ssl_handshake()
813 else:
814 data = self.recv(1024)
815 if support.verbose:
816 sys.stdout.write(" server: read %s from client\n" % repr(data))
817 if not data:
818 self.close()
819 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000820 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000821
822 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000823 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000824 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000825 sys.stdout.write(" server: closed connection %s\n" % self.socket)
826
827 def handle_error(self):
828 raise
829
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000830 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000831 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000832 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
833 self.port = support.bind_port(sock, '')
834 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000835 self.listen(5)
836
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000837 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000838 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000839 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
840 self.ConnectionHandler(sock_obj, self.certfile)
841
842 def handle_error(self):
843 raise
844
Trent Nelson78520002008-04-10 20:54:35 +0000845 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000846 self.flag = None
847 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000848 self.server = self.EchoServer(certfile)
849 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000850 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000851 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000852
853 def __str__(self):
854 return "<%s %s>" % (self.__class__.__name__, self.server)
855
856 def start (self, flag=None):
857 self.flag = flag
858 threading.Thread.start(self)
859
Antoine Pitrou480a1242010-04-28 21:37:09 +0000860 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000861 self.active = True
862 if self.flag:
863 self.flag.set()
864 while self.active:
865 try:
866 asyncore.loop(1)
867 except:
868 pass
869
Antoine Pitrou480a1242010-04-28 21:37:09 +0000870 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000871 self.active = False
872 self.server.close()
873
Antoine Pitrou480a1242010-04-28 21:37:09 +0000874 def bad_cert_test(certfile):
875 """
876 Launch a server with CERT_REQUIRED, and check that trying to
877 connect to it with the given client certificate fails.
878 """
Trent Nelson78520002008-04-10 20:54:35 +0000879 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000880 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000881 cacerts=CERTFILE, chatty=False,
882 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000883 flag = threading.Event()
884 server.start(flag)
885 # wait for it to start
886 flag.wait()
887 # try to connect
888 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000889 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000890 s = ssl.wrap_socket(socket.socket(),
891 certfile=certfile,
892 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000893 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000894 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000895 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000896 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000897 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000898 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000899 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000900 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000901 if x.errno != errno.ENOENT:
902 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000903 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000904 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000906 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 finally:
908 server.stop()
909 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000910
Antoine Pitroub5218772010-05-21 09:56:06 +0000911 def server_params_test(client_context, server_context, indata=b"FOO\n",
912 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000913 """
914 Launch a server, connect a client to it and try various reads
915 and writes.
916 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000917 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000919 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000920 flag = threading.Event()
921 server.start(flag)
922 # wait for it to start
923 flag.wait()
924 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000926 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000927 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000928 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000929 if connectionchatty:
930 if support.verbose:
931 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000932 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000933 s.write(arg)
934 outdata = s.read()
935 if connectionchatty:
936 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000937 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000938 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000939 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000940 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
941 % (outdata[:20], len(outdata),
942 indata[:20].lower(), len(indata)))
943 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000944 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000945 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000946 sys.stdout.write(" client: closing connection.\n")
947 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000948 finally:
949 server.stop()
950 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000951
Antoine Pitroub5218772010-05-21 09:56:06 +0000952 def try_protocol_combo(server_protocol, client_protocol, expect_success,
953 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000954 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000956 certtype = {
957 ssl.CERT_NONE: "CERT_NONE",
958 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
959 ssl.CERT_REQUIRED: "CERT_REQUIRED",
960 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000961 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000962 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963 sys.stdout.write(formatstr %
964 (ssl.get_protocol_name(client_protocol),
965 ssl.get_protocol_name(server_protocol),
966 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000967 client_context = ssl.SSLContext(client_protocol)
968 client_context.options = ssl.OP_ALL | client_options
969 server_context = ssl.SSLContext(server_protocol)
970 server_context.options = ssl.OP_ALL | server_options
971 for ctx in (client_context, server_context):
972 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000973 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
974 # will send an SSLv3 hello (rather than SSLv2) starting from
975 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000976 ctx.set_ciphers("ALL")
977 ctx.load_cert_chain(CERTFILE)
978 ctx.load_verify_locations(CERTFILE)
979 try:
980 server_params_test(client_context, server_context,
981 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000982 # Protocol mismatch can result in either an SSLError, or a
983 # "Connection reset by peer" error.
984 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000985 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000987 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000988 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000989 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000991 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000992 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000993 "Client protocol %s succeeded with server protocol %s!"
994 % (ssl.get_protocol_name(client_protocol),
995 ssl.get_protocol_name(server_protocol)))
996
997
Bill Janssen6e027db2007-11-15 22:23:56 +0000998 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000999
Antoine Pitrou23df4832010-08-04 17:14:06 +00001000 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 def test_echo(self):
1002 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001003 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001005 for protocol in PROTOCOLS:
1006 context = ssl.SSLContext(protocol)
1007 context.load_cert_chain(CERTFILE)
1008 server_params_test(context, context,
1009 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001010
Antoine Pitrou480a1242010-04-28 21:37:09 +00001011 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001012 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001013 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001014 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1015 context.verify_mode = ssl.CERT_REQUIRED
1016 context.load_verify_locations(CERTFILE)
1017 context.load_cert_chain(CERTFILE)
1018 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001019 flag = threading.Event()
1020 server.start(flag)
1021 # wait for it to start
1022 flag.wait()
1023 # try to connect
1024 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001025 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001026 s.connect((HOST, server.port))
1027 cert = s.getpeercert()
1028 self.assertTrue(cert, "Can't get peer certificate.")
1029 cipher = s.cipher()
1030 if support.verbose:
1031 sys.stdout.write(pprint.pformat(cert) + '\n')
1032 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1033 if 'subject' not in cert:
1034 self.fail("No subject field in certificate: %s." %
1035 pprint.pformat(cert))
1036 if ((('organizationName', 'Python Software Foundation'),)
1037 not in cert['subject']):
1038 self.fail(
1039 "Missing or invalid 'organizationName' field in certificate subject; "
1040 "should be 'Python Software Foundation'.")
1041 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001042 finally:
1043 server.stop()
1044 server.join()
1045
Antoine Pitrou480a1242010-04-28 21:37:09 +00001046 def test_empty_cert(self):
1047 """Connecting with an empty cert file"""
1048 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1049 "nullcert.pem"))
1050 def test_malformed_cert(self):
1051 """Connecting with a badly formatted certificate (syntax error)"""
1052 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1053 "badcert.pem"))
1054 def test_nonexisting_cert(self):
1055 """Connecting with a non-existing cert file"""
1056 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1057 "wrongcert.pem"))
1058 def test_malformed_key(self):
1059 """Connecting with a badly formatted key (syntax error)"""
1060 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1061 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001062
Antoine Pitrou480a1242010-04-28 21:37:09 +00001063 def test_rude_shutdown(self):
1064 """A brutal shutdown of an SSL server should raise an IOError
1065 in the client when attempting handshake.
1066 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001067 listener_ready = threading.Event()
1068 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001069
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001070 s = socket.socket()
1071 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001072
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001073 # `listener` runs in a thread. It sits in an accept() until
1074 # the main thread connects. Then it rudely closes the socket,
1075 # and sets Event `listener_gone` to let the main thread know
1076 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001077 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001078 s.listen(5)
1079 listener_ready.set()
1080 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001081 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001082 listener_gone.set()
1083
1084 def connector():
1085 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001086 c = socket.socket()
1087 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001088 listener_gone.wait()
1089 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001090 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001091 except IOError:
1092 pass
1093 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001094 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001095
1096 t = threading.Thread(target=listener)
1097 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001098 try:
1099 connector()
1100 finally:
1101 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001102
Antoine Pitrou23df4832010-08-04 17:14:06 +00001103 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 def test_protocol_sslv2(self):
1105 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001106 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001108 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1109 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1110 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1111 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1112 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1113 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001114 # SSLv23 client with specific SSL options
1115 if no_sslv2_implies_sslv3_hello():
1116 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1117 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1118 client_options=ssl.OP_NO_SSLv2)
1119 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1120 client_options=ssl.OP_NO_SSLv3)
1121 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1122 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001123
Antoine Pitrou23df4832010-08-04 17:14:06 +00001124 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001125 def test_protocol_sslv23(self):
1126 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001127 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001128 sys.stdout.write("\n")
1129 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001130 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001131 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001132 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001133 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001134 sys.stdout.write(
1135 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1136 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001137 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1138 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1139 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1142 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1143 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1146 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1147 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148
Antoine Pitroub5218772010-05-21 09:56:06 +00001149 # Server with specific SSL options
1150 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1151 server_options=ssl.OP_NO_SSLv3)
1152 # Will choose TLSv1
1153 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1154 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1155 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1156 server_options=ssl.OP_NO_TLSv1)
1157
1158
Antoine Pitrou23df4832010-08-04 17:14:06 +00001159 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001160 def test_protocol_sslv3(self):
1161 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001162 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001164 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1165 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1166 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1167 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1168 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1169 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001170 if no_sslv2_implies_sslv3_hello():
1171 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1172 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1173 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174
Antoine Pitrou23df4832010-08-04 17:14:06 +00001175 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001176 def test_protocol_tlsv1(self):
1177 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001178 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1181 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1182 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1183 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1184 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1185 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001186
Antoine Pitrou480a1242010-04-28 21:37:09 +00001187 def test_starttls(self):
1188 """Switching from clear text to encrypted and back again."""
1189 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 +00001190
Trent Nelson78520002008-04-10 20:54:35 +00001191 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001192 ssl_version=ssl.PROTOCOL_TLSv1,
1193 starttls_server=True,
1194 chatty=True,
1195 connectionchatty=True)
1196 flag = threading.Event()
1197 server.start(flag)
1198 # wait for it to start
1199 flag.wait()
1200 # try to connect
1201 wrapped = False
1202 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001203 s = socket.socket()
1204 s.setblocking(1)
1205 s.connect((HOST, server.port))
1206 if support.verbose:
1207 sys.stdout.write("\n")
1208 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001209 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001210 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001211 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001212 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001213 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001214 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001215 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001217 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001218 msg = outdata.strip().lower()
1219 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1220 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001221 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001222 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001223 " client: read %r from server, starting TLS...\n"
1224 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001225 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1226 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001227 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1228 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001229 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001230 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 " client: read %r from server, ending TLS...\n"
1232 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001233 s = conn.unwrap()
1234 wrapped = False
1235 else:
1236 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001237 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001238 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001239 if support.verbose:
1240 sys.stdout.write(" client: closing connection.\n")
1241 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001243 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001244 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001245 if wrapped:
1246 conn.close()
1247 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001248 s.close()
1249 finally:
1250 server.stop()
1251 server.join()
1252
Antoine Pitrou480a1242010-04-28 21:37:09 +00001253 def test_socketserver(self):
1254 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001255 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001256 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001257 if support.verbose:
1258 sys.stdout.write('\n')
1259 with open(CERTFILE, 'rb') as f:
1260 d1 = f.read()
1261 d2 = ''
1262 # now fetch the same data from the HTTPS server
1263 url = 'https://%s:%d/%s' % (
1264 HOST, server.port, os.path.split(CERTFILE)[1])
1265 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001266 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001267 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001268 if dlen and (int(dlen) > 0):
1269 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001270 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001271 sys.stdout.write(
1272 " client: read %d bytes from remote server '%s'\n"
1273 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001274 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001275 f.close()
1276 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001277
Antoine Pitrou480a1242010-04-28 21:37:09 +00001278 def test_asyncore_server(self):
1279 """Check the example asyncore integration."""
1280 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001281
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001282 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001283 sys.stdout.write("\n")
1284
Antoine Pitrou480a1242010-04-28 21:37:09 +00001285 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001286 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001287 flag = threading.Event()
1288 server.start(flag)
1289 # wait for it to start
1290 flag.wait()
1291 # try to connect
1292 try:
1293 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001294 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001295 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001296 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001297 " client: sending %r...\n" % indata)
1298 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001299 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001300 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001301 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001302 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001303 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001304 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1305 % (outdata[:20], len(outdata),
1306 indata[:20].lower(), len(indata)))
1307 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001308 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001309 sys.stdout.write(" client: closing connection.\n")
1310 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001311 if support.verbose:
1312 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001313 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001314 if support.verbose:
1315 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001316 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001317 if support.verbose:
1318 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001319 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001320 if support.verbose:
1321 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001322
Antoine Pitrou480a1242010-04-28 21:37:09 +00001323 def test_recv_send(self):
1324 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001325 if support.verbose:
1326 sys.stdout.write("\n")
1327
1328 server = ThreadedEchoServer(CERTFILE,
1329 certreqs=ssl.CERT_NONE,
1330 ssl_version=ssl.PROTOCOL_TLSv1,
1331 cacerts=CERTFILE,
1332 chatty=True,
1333 connectionchatty=False)
1334 flag = threading.Event()
1335 server.start(flag)
1336 # wait for it to start
1337 flag.wait()
1338 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001339 s = ssl.wrap_socket(socket.socket(),
1340 server_side=False,
1341 certfile=CERTFILE,
1342 ca_certs=CERTFILE,
1343 cert_reqs=ssl.CERT_NONE,
1344 ssl_version=ssl.PROTOCOL_TLSv1)
1345 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001346 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001347 # helper methods for standardising recv* method signatures
1348 def _recv_into():
1349 b = bytearray(b"\0"*100)
1350 count = s.recv_into(b)
1351 return b[:count]
1352
1353 def _recvfrom_into():
1354 b = bytearray(b"\0"*100)
1355 count, addr = s.recvfrom_into(b)
1356 return b[:count]
1357
1358 # (name, method, whether to expect success, *args)
1359 send_methods = [
1360 ('send', s.send, True, []),
1361 ('sendto', s.sendto, False, ["some.address"]),
1362 ('sendall', s.sendall, True, []),
1363 ]
1364 recv_methods = [
1365 ('recv', s.recv, True, []),
1366 ('recvfrom', s.recvfrom, False, ["some.address"]),
1367 ('recv_into', _recv_into, True, []),
1368 ('recvfrom_into', _recvfrom_into, False, []),
1369 ]
1370 data_prefix = "PREFIX_"
1371
1372 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001373 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001374 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001375 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001376 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001377 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001378 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 "<<{outdata:r}>> ({nout:d}) received; "
1381 "expected <<{indata:r}>> ({nin:d})\n".format(
1382 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001383 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001384 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001385 )
1386 )
1387 except ValueError as e:
1388 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001389 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001390 "Failed to send with method <<{name:s}>>; "
1391 "expected to succeed.\n".format(name=meth_name)
1392 )
1393 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001394 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001395 "Method <<{name:s}>> failed with unexpected "
1396 "exception message: {exp:s}\n".format(
1397 name=meth_name, exp=e
1398 )
1399 )
1400
1401 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001402 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001403 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001404 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001405 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001406 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001407 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001408 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001409 "<<{outdata:r}>> ({nout:d}) received; "
1410 "expected <<{indata:r}>> ({nin:d})\n".format(
1411 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001412 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001413 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001414 )
1415 )
1416 except ValueError as e:
1417 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001418 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001419 "Failed to receive with method <<{name:s}>>; "
1420 "expected to succeed.\n".format(name=meth_name)
1421 )
1422 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001423 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001424 "Method <<{name:s}>> failed with unexpected "
1425 "exception message: {exp:s}\n".format(
1426 name=meth_name, exp=e
1427 )
1428 )
1429 # consume data
1430 s.read()
1431
Antoine Pitrou480a1242010-04-28 21:37:09 +00001432 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001433 s.close()
1434 finally:
1435 server.stop()
1436 server.join()
1437
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001438 def test_handshake_timeout(self):
1439 # Issue #5103: SSL handshake must respect the socket timeout
1440 server = socket.socket(socket.AF_INET)
1441 host = "127.0.0.1"
1442 port = support.bind_port(server)
1443 started = threading.Event()
1444 finish = False
1445
1446 def serve():
1447 server.listen(5)
1448 started.set()
1449 conns = []
1450 while not finish:
1451 r, w, e = select.select([server], [], [], 0.1)
1452 if server in r:
1453 # Let the socket hang around rather than having
1454 # it closed by garbage collection.
1455 conns.append(server.accept()[0])
1456
1457 t = threading.Thread(target=serve)
1458 t.start()
1459 started.wait()
1460
1461 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001462 try:
1463 c = socket.socket(socket.AF_INET)
1464 c.settimeout(0.2)
1465 c.connect((host, port))
1466 # Will attempt handshake and time out
1467 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1468 ssl.wrap_socket, c)
1469 finally:
1470 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001471 try:
1472 c = socket.socket(socket.AF_INET)
1473 c = ssl.wrap_socket(c)
1474 c.settimeout(0.2)
1475 # Will attempt handshake and time out
1476 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1477 c.connect, (host, port))
1478 finally:
1479 c.close()
1480 finally:
1481 finish = True
1482 t.join()
1483 server.close()
1484
Bill Janssen58afe4c2008-09-08 16:45:19 +00001485
Thomas Woutersed03b412007-08-28 21:37:11 +00001486def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001487 if support.verbose:
1488 plats = {
1489 'Linux': platform.linux_distribution,
1490 'Mac': platform.mac_ver,
1491 'Windows': platform.win32_ver,
1492 }
1493 for name, func in plats.items():
1494 plat = func()
1495 if plat and plat[0]:
1496 plat = '%s %r' % (name, plat)
1497 break
1498 else:
1499 plat = repr(platform.platform())
1500 print("test_ssl: testing with %r %r" %
1501 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1502 print(" under %s" % plat)
1503
Antoine Pitrou152efa22010-05-16 18:19:27 +00001504 for filename in [
1505 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1506 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1507 BADCERT, BADKEY, EMPTYCERT]:
1508 if not os.path.exists(filename):
1509 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001510
Antoine Pitrou152efa22010-05-16 18:19:27 +00001511 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001512
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001513 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001514 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001515
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001516 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001517 thread_info = support.threading_setup()
1518 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001519 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001520
Antoine Pitrou480a1242010-04-28 21:37:09 +00001521 try:
1522 support.run_unittest(*tests)
1523 finally:
1524 if _have_threads:
1525 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001526
1527if __name__ == "__main__":
1528 test_main()