blob: 67bc01aba4cae0720707720741deb7532f973f52 [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
Antoine Pitroud5323212010-10-22 18:19:07 +000092 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Antoine Pitrou480a1242010-04-28 21:37:09 +000094 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000095 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000096 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 sys.stdout.write("\n RAND_status is %d (%s)\n"
98 % (v, (v and "sufficient randomness") or
99 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000100 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 ssl.RAND_egd(1)
102 except TypeError:
103 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000104 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 print("didn't raise TypeError")
106 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000107
Antoine Pitrou480a1242010-04-28 21:37:09 +0000108 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000109 # note that this uses an 'unofficial' function in _ssl.c,
110 # provided solely for this test, to exercise the certificate
111 # parsing code
112 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000113 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000115
Antoine Pitrou480a1242010-04-28 21:37:09 +0000116 def test_DER_to_PEM(self):
117 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
118 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000119 d1 = ssl.PEM_cert_to_DER_cert(pem)
120 p2 = ssl.DER_cert_to_PEM_cert(d1)
121 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000122 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000123 if not p2.startswith(ssl.PEM_HEADER + '\n'):
124 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
125 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
126 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000128 def test_openssl_version(self):
129 n = ssl.OPENSSL_VERSION_NUMBER
130 t = ssl.OPENSSL_VERSION_INFO
131 s = ssl.OPENSSL_VERSION
132 self.assertIsInstance(n, int)
133 self.assertIsInstance(t, tuple)
134 self.assertIsInstance(s, str)
135 # Some sanity checks follow
136 # >= 0.9
137 self.assertGreaterEqual(n, 0x900000)
138 # < 2.0
139 self.assertLess(n, 0x20000000)
140 major, minor, fix, patch, status = t
141 self.assertGreaterEqual(major, 0)
142 self.assertLess(major, 2)
143 self.assertGreaterEqual(minor, 0)
144 self.assertLess(minor, 256)
145 self.assertGreaterEqual(fix, 0)
146 self.assertLess(fix, 256)
147 self.assertGreaterEqual(patch, 0)
148 self.assertLessEqual(patch, 26)
149 self.assertGreaterEqual(status, 0)
150 self.assertLessEqual(status, 15)
151 # Version string as returned by OpenSSL, the format might change
152 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
153 (s, t))
154
Antoine Pitrou9d543662010-04-23 23:10:32 +0000155 @support.cpython_only
156 def test_refcycle(self):
157 # Issue #7943: an SSL object doesn't create reference cycles with
158 # itself.
159 s = socket.socket(socket.AF_INET)
160 ss = ssl.wrap_socket(s)
161 wr = weakref.ref(ss)
162 del ss
163 self.assertEqual(wr(), None)
164
Antoine Pitroua468adc2010-09-14 14:43:44 +0000165 def test_wrapped_unconnected(self):
166 # Methods on an unconnected SSLSocket propagate the original
167 # socket.error raise by the underlying socket object.
168 s = socket.socket(socket.AF_INET)
169 ss = ssl.wrap_socket(s)
170 self.assertRaises(socket.error, ss.recv, 1)
171 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
172 self.assertRaises(socket.error, ss.recvfrom, 1)
173 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
174 self.assertRaises(socket.error, ss.send, b'x')
175 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
176
Antoine Pitrou40f08742010-04-24 22:04:40 +0000177 def test_timeout(self):
178 # Issue #8524: when creating an SSL socket, the timeout of the
179 # original socket should be retained.
180 for timeout in (None, 0.0, 5.0):
181 s = socket.socket(socket.AF_INET)
182 s.settimeout(timeout)
183 ss = ssl.wrap_socket(s)
184 self.assertEqual(timeout, ss.gettimeout())
185
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000186 def test_errors(self):
187 sock = socket.socket()
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000188 self.assertRaisesRegexp(ValueError,
189 "certfile must be specified",
190 ssl.wrap_socket, sock, keyfile=CERTFILE)
191 self.assertRaisesRegexp(ValueError,
192 "certfile must be specified for server-side operations",
193 ssl.wrap_socket, sock, server_side=True)
194 self.assertRaisesRegexp(ValueError,
195 "certfile must be specified for server-side operations",
196 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000197 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
198 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
199 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000200 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000201 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000202 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000203 with self.assertRaises(IOError) as cm:
204 ssl.wrap_socket(socket.socket(), certfile=CERTFILE, keyfile=WRONGCERT)
205 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000206 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000207 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000208 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000209
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000210 def test_match_hostname(self):
211 def ok(cert, hostname):
212 ssl.match_hostname(cert, hostname)
213 def fail(cert, hostname):
214 self.assertRaises(ssl.CertificateError,
215 ssl.match_hostname, cert, hostname)
216
217 cert = {'subject': ((('commonName', 'example.com'),),)}
218 ok(cert, 'example.com')
219 ok(cert, 'ExAmple.cOm')
220 fail(cert, 'www.example.com')
221 fail(cert, '.example.com')
222 fail(cert, 'example.org')
223 fail(cert, 'exampleXcom')
224
225 cert = {'subject': ((('commonName', '*.a.com'),),)}
226 ok(cert, 'foo.a.com')
227 fail(cert, 'bar.foo.a.com')
228 fail(cert, 'a.com')
229 fail(cert, 'Xa.com')
230 fail(cert, '.a.com')
231
232 cert = {'subject': ((('commonName', 'a.*.com'),),)}
233 ok(cert, 'a.foo.com')
234 fail(cert, 'a..com')
235 fail(cert, 'a.com')
236
237 cert = {'subject': ((('commonName', 'f*.com'),),)}
238 ok(cert, 'foo.com')
239 ok(cert, 'f.com')
240 fail(cert, 'bar.com')
241 fail(cert, 'foo.a.com')
242 fail(cert, 'bar.foo.com')
243
244 # Slightly fake real-world example
245 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
246 'subject': ((('commonName', 'linuxfrz.org'),),),
247 'subjectAltName': (('DNS', 'linuxfr.org'),
248 ('DNS', 'linuxfr.com'),
249 ('othername', '<unsupported>'))}
250 ok(cert, 'linuxfr.org')
251 ok(cert, 'linuxfr.com')
252 # Not a "DNS" entry
253 fail(cert, '<unsupported>')
254 # When there is a subjectAltName, commonName isn't used
255 fail(cert, 'linuxfrz.org')
256
257 # A pristine real-world example
258 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
259 'subject': ((('countryName', 'US'),),
260 (('stateOrProvinceName', 'California'),),
261 (('localityName', 'Mountain View'),),
262 (('organizationName', 'Google Inc'),),
263 (('commonName', 'mail.google.com'),))}
264 ok(cert, 'mail.google.com')
265 fail(cert, 'gmail.com')
266 # Only commonName is considered
267 fail(cert, 'California')
268
269 # Neither commonName nor subjectAltName
270 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
271 'subject': ((('countryName', 'US'),),
272 (('stateOrProvinceName', 'California'),),
273 (('localityName', 'Mountain View'),),
274 (('organizationName', 'Google Inc'),))}
275 fail(cert, 'mail.google.com')
276
277 # Empty cert / no cert
278 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
279 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
280
Antoine Pitroud5323212010-10-22 18:19:07 +0000281 def test_server_side(self):
282 # server_hostname doesn't work for server sockets
283 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
284 sock = socket.socket()
285 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
286 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000287
Antoine Pitrou152efa22010-05-16 18:19:27 +0000288class ContextTests(unittest.TestCase):
289
Antoine Pitrou23df4832010-08-04 17:14:06 +0000290 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000291 def test_constructor(self):
292 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
293 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
294 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
295 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
296 self.assertRaises(TypeError, ssl.SSLContext)
297 self.assertRaises(ValueError, ssl.SSLContext, -1)
298 self.assertRaises(ValueError, ssl.SSLContext, 42)
299
Antoine Pitrou23df4832010-08-04 17:14:06 +0000300 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000301 def test_protocol(self):
302 for proto in PROTOCOLS:
303 ctx = ssl.SSLContext(proto)
304 self.assertEqual(ctx.protocol, proto)
305
306 def test_ciphers(self):
307 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
308 ctx.set_ciphers("ALL")
309 ctx.set_ciphers("DEFAULT")
310 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000311 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000312
Antoine Pitrou23df4832010-08-04 17:14:06 +0000313 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000314 def test_options(self):
315 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
316 # OP_ALL is the default value
317 self.assertEqual(ssl.OP_ALL, ctx.options)
318 ctx.options |= ssl.OP_NO_SSLv2
319 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
320 ctx.options)
321 ctx.options |= ssl.OP_NO_SSLv3
322 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
323 ctx.options)
324 if can_clear_options():
325 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
326 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
327 ctx.options)
328 ctx.options = 0
329 self.assertEqual(0, ctx.options)
330 else:
331 with self.assertRaises(ValueError):
332 ctx.options = 0
333
Antoine Pitrou152efa22010-05-16 18:19:27 +0000334 def test_verify(self):
335 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
336 # Default value
337 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
338 ctx.verify_mode = ssl.CERT_OPTIONAL
339 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
340 ctx.verify_mode = ssl.CERT_REQUIRED
341 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
342 ctx.verify_mode = ssl.CERT_NONE
343 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
344 with self.assertRaises(TypeError):
345 ctx.verify_mode = None
346 with self.assertRaises(ValueError):
347 ctx.verify_mode = 42
348
349 def test_load_cert_chain(self):
350 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
351 # Combined key and cert in a single file
352 ctx.load_cert_chain(CERTFILE)
353 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
354 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000355 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000356 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000357 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000358 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
359 ctx.load_cert_chain(BADCERT)
360 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
361 ctx.load_cert_chain(EMPTYCERT)
362 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000363 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000364 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
365 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
366 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
367 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
368 ctx.load_cert_chain(ONLYCERT)
369 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
370 ctx.load_cert_chain(ONLYKEY)
371 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
372 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
373 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000374 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000375 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000376 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000377
378 def test_load_verify_locations(self):
379 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
380 ctx.load_verify_locations(CERTFILE)
381 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
382 ctx.load_verify_locations(BYTES_CERTFILE)
383 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
384 self.assertRaises(TypeError, ctx.load_verify_locations)
385 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000386 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000387 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000388 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000389 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
390 ctx.load_verify_locations(BADCERT)
391 ctx.load_verify_locations(CERTFILE, CAPATH)
392 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
393
Antoine Pitroub0182c82010-10-12 20:09:02 +0000394 def test_session_stats(self):
395 for proto in PROTOCOLS:
396 ctx = ssl.SSLContext(proto)
397 self.assertEqual(ctx.session_stats(), {
398 'number': 0,
399 'connect': 0,
400 'connect_good': 0,
401 'connect_renegotiate': 0,
402 'accept': 0,
403 'accept_good': 0,
404 'accept_renegotiate': 0,
405 'hits': 0,
406 'misses': 0,
407 'timeouts': 0,
408 'cache_full': 0,
409 })
410
Antoine Pitrou152efa22010-05-16 18:19:27 +0000411
Bill Janssen6e027db2007-11-15 22:23:56 +0000412class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000413
Antoine Pitrou480a1242010-04-28 21:37:09 +0000414 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000415 with support.transient_internet("svn.python.org"):
416 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
417 cert_reqs=ssl.CERT_NONE)
418 try:
419 s.connect(("svn.python.org", 443))
420 self.assertEqual({}, s.getpeercert())
421 finally:
422 s.close()
423
424 # this should fail because we have no verification certs
425 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
426 cert_reqs=ssl.CERT_REQUIRED)
427 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
428 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000429 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000430
Antoine Pitrou350c7222010-09-09 13:31:46 +0000431 # this should succeed because we specify the root cert
432 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
433 cert_reqs=ssl.CERT_REQUIRED,
434 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
435 try:
436 s.connect(("svn.python.org", 443))
437 self.assertTrue(s.getpeercert())
438 finally:
439 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000440
441 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000442 with support.transient_internet("svn.python.org"):
443 # Same as test_connect, but with a separately created context
444 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
445 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
446 s.connect(("svn.python.org", 443))
447 try:
448 self.assertEqual({}, s.getpeercert())
449 finally:
450 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000451 # Same with a server hostname
452 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
453 server_hostname="svn.python.org")
454 if ssl.HAS_SNI:
455 s.connect(("svn.python.org", 443))
456 s.close()
457 else:
458 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000459 # This should fail because we have no verification certs
460 ctx.verify_mode = ssl.CERT_REQUIRED
461 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
462 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
463 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000464 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000465 # This should succeed because we specify the root cert
466 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
467 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
468 s.connect(("svn.python.org", 443))
469 try:
470 cert = s.getpeercert()
471 self.assertTrue(cert)
472 finally:
473 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000474
475 def test_connect_capath(self):
476 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000477 # NOTE: the subject hashing algorithm has been changed between
478 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
479 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000480 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000481 with support.transient_internet("svn.python.org"):
482 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
483 ctx.verify_mode = ssl.CERT_REQUIRED
484 ctx.load_verify_locations(capath=CAPATH)
485 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
486 s.connect(("svn.python.org", 443))
487 try:
488 cert = s.getpeercert()
489 self.assertTrue(cert)
490 finally:
491 s.close()
492 # Same with a bytes `capath` argument
493 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
494 ctx.verify_mode = ssl.CERT_REQUIRED
495 ctx.load_verify_locations(capath=BYTES_CAPATH)
496 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
497 s.connect(("svn.python.org", 443))
498 try:
499 cert = s.getpeercert()
500 self.assertTrue(cert)
501 finally:
502 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000503
Antoine Pitroue3220242010-04-24 11:13:53 +0000504 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
505 def test_makefile_close(self):
506 # Issue #5238: creating a file-like object with makefile() shouldn't
507 # delay closing the underlying "real socket" (here tested with its
508 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000509 with support.transient_internet("svn.python.org"):
510 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
511 ss.connect(("svn.python.org", 443))
512 fd = ss.fileno()
513 f = ss.makefile()
514 f.close()
515 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000516 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000517 # Closing the SSL socket should close the fd too
518 ss.close()
519 gc.collect()
520 with self.assertRaises(OSError) as e:
521 os.read(fd, 0)
522 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000523
Antoine Pitrou480a1242010-04-28 21:37:09 +0000524 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000525 with support.transient_internet("svn.python.org"):
526 s = socket.socket(socket.AF_INET)
527 s.connect(("svn.python.org", 443))
528 s.setblocking(False)
529 s = ssl.wrap_socket(s,
530 cert_reqs=ssl.CERT_NONE,
531 do_handshake_on_connect=False)
532 count = 0
533 while True:
534 try:
535 count += 1
536 s.do_handshake()
537 break
538 except ssl.SSLError as err:
539 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
540 select.select([s], [], [])
541 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
542 select.select([], [s], [])
543 else:
544 raise
545 s.close()
546 if support.verbose:
547 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000548
Antoine Pitrou480a1242010-04-28 21:37:09 +0000549 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000550 with support.transient_internet("svn.python.org"):
551 pem = ssl.get_server_certificate(("svn.python.org", 443))
552 if not pem:
553 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000554
Antoine Pitrou350c7222010-09-09 13:31:46 +0000555 try:
556 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
557 except ssl.SSLError as x:
558 #should fail
559 if support.verbose:
560 sys.stdout.write("%s\n" % x)
561 else:
562 self.fail("Got server certificate %s for svn.python.org!" % pem)
563
564 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
565 if not pem:
566 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000567 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000568 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000569
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000570 def test_ciphers(self):
571 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000572 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000573 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000574 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000575 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000576 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
577 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
578 s.connect(remote)
579 # Error checking can happen at instantiation or when connecting
580 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
581 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
582 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
583 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000584
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000585 def test_algorithms(self):
586 # Issue #8484: all algorithms should be available when verifying a
587 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000588 # SHA256 was added in OpenSSL 0.9.8
589 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
590 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000591 # NOTE: https://sha256.tbs-internet.com is another possible test host
592 remote = ("sha2.hboeck.de", 443)
593 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000594 with support.transient_internet("sha2.hboeck.de"):
595 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
596 cert_reqs=ssl.CERT_REQUIRED,
597 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000598 try:
599 s.connect(remote)
600 if support.verbose:
601 sys.stdout.write("\nCipher with %r is %r\n" %
602 (remote, s.cipher()))
603 sys.stdout.write("Certificate is:\n%s\n" %
604 pprint.pformat(s.getpeercert()))
605 finally:
606 s.close()
607
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000608
609try:
610 import threading
611except ImportError:
612 _have_threads = False
613else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000614 _have_threads = True
615
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000616 from test.ssl_servers import make_https_server
617
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000618 class ThreadedEchoServer(threading.Thread):
619
620 class ConnectionHandler(threading.Thread):
621
622 """A mildly complicated class, because we want it to work both
623 with and without the SSL wrapper around the socket connection, so
624 that we can test the STARTTLS functionality."""
625
Bill Janssen6e027db2007-11-15 22:23:56 +0000626 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627 self.server = server
628 self.running = False
629 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000630 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000631 self.sock.setblocking(1)
632 self.sslconn = None
633 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000634 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000635
Antoine Pitrou480a1242010-04-28 21:37:09 +0000636 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000637 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000638 self.sslconn = self.server.context.wrap_socket(
639 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000640 except ssl.SSLError:
641 # XXX Various errors can have happened here, for example
642 # a mismatching protocol version, an invalid certificate,
643 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000644 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000645 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000646 self.running = False
647 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000648 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000649 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000651 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000652 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000653 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000654 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
655 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000656 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
658 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000659 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000660 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
661 return True
662
663 def read(self):
664 if self.sslconn:
665 return self.sslconn.read()
666 else:
667 return self.sock.recv(1024)
668
669 def write(self, bytes):
670 if self.sslconn:
671 return self.sslconn.write(bytes)
672 else:
673 return self.sock.send(bytes)
674
675 def close(self):
676 if self.sslconn:
677 self.sslconn.close()
678 else:
679 self.sock.close()
680
Antoine Pitrou480a1242010-04-28 21:37:09 +0000681 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000682 self.running = True
683 if not self.server.starttls_server:
684 if not self.wrap_conn():
685 return
686 while self.running:
687 try:
688 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000689 stripped = msg.strip()
690 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000691 # eof, so quit this handler
692 self.running = False
693 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000694 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000695 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000696 sys.stdout.write(" server: client closed connection\n")
697 self.close()
698 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000699 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000700 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000701 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000702 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000703 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000704 if not self.wrap_conn():
705 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000706 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000707 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000708 if support.verbose and self.server.connectionchatty:
709 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000710 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000711 self.sock = self.sslconn.unwrap()
712 self.sslconn = None
713 if support.verbose and self.server.connectionchatty:
714 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000715 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000716 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000717 self.server.connectionchatty):
718 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000719 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
720 % (msg, ctype, msg.lower(), ctype))
721 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000722 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000723 if self.server.chatty:
724 handle_error("Test server failure:\n")
725 self.close()
726 self.running = False
727 # normally, we'd just stop here, but for the test
728 # harness, we want to stop the server
729 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000730
Antoine Pitroub5218772010-05-21 09:56:06 +0000731 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000732 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000733 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000734 ciphers=None, context=None):
735 if context:
736 self.context = context
737 else:
738 self.context = ssl.SSLContext(ssl_version
739 if ssl_version is not None
740 else ssl.PROTOCOL_TLSv1)
741 self.context.verify_mode = (certreqs if certreqs is not None
742 else ssl.CERT_NONE)
743 if cacerts:
744 self.context.load_verify_locations(cacerts)
745 if certificate:
746 self.context.load_cert_chain(certificate)
747 if ciphers:
748 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000749 self.chatty = chatty
750 self.connectionchatty = connectionchatty
751 self.starttls_server = starttls_server
752 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000753 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000754 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000755 self.active = False
756 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000757 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000758
Antoine Pitrou480a1242010-04-28 21:37:09 +0000759 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000760 self.flag = flag
761 threading.Thread.start(self)
762
Antoine Pitrou480a1242010-04-28 21:37:09 +0000763 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000764 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000765 self.sock.listen(5)
766 self.active = True
767 if self.flag:
768 # signal an event
769 self.flag.set()
770 while self.active:
771 try:
772 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000773 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000774 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000775 + repr(connaddr) + '\n')
776 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000777 handler.start()
778 except socket.timeout:
779 pass
780 except KeyboardInterrupt:
781 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000782 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783
Antoine Pitrou480a1242010-04-28 21:37:09 +0000784 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000785 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000786
Bill Janssen54cc54c2007-12-14 22:08:56 +0000787 class AsyncoreEchoServer(threading.Thread):
788
789 # this one's based on asyncore.dispatcher
790
791 class EchoServer (asyncore.dispatcher):
792
793 class ConnectionHandler (asyncore.dispatcher_with_send):
794
795 def __init__(self, conn, certfile):
796 self.socket = ssl.wrap_socket(conn, server_side=True,
797 certfile=certfile,
798 do_handshake_on_connect=False)
799 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000800 self._ssl_accepting = True
801 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000802
803 def readable(self):
804 if isinstance(self.socket, ssl.SSLSocket):
805 while self.socket.pending() > 0:
806 self.handle_read_event()
807 return True
808
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000809 def _do_ssl_handshake(self):
810 try:
811 self.socket.do_handshake()
812 except ssl.SSLError as err:
813 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
814 ssl.SSL_ERROR_WANT_WRITE):
815 return
816 elif err.args[0] == ssl.SSL_ERROR_EOF:
817 return self.handle_close()
818 raise
819 except socket.error as err:
820 if err.args[0] == errno.ECONNABORTED:
821 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000822 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000823 self._ssl_accepting = False
824
825 def handle_read(self):
826 if self._ssl_accepting:
827 self._do_ssl_handshake()
828 else:
829 data = self.recv(1024)
830 if support.verbose:
831 sys.stdout.write(" server: read %s from client\n" % repr(data))
832 if not data:
833 self.close()
834 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000835 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000836
837 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000838 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000839 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000840 sys.stdout.write(" server: closed connection %s\n" % self.socket)
841
842 def handle_error(self):
843 raise
844
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000845 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000846 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000847 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
848 self.port = support.bind_port(sock, '')
849 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000850 self.listen(5)
851
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000852 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000853 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000854 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
855 self.ConnectionHandler(sock_obj, self.certfile)
856
857 def handle_error(self):
858 raise
859
Trent Nelson78520002008-04-10 20:54:35 +0000860 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000861 self.flag = None
862 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000863 self.server = self.EchoServer(certfile)
864 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000865 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000866 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000867
868 def __str__(self):
869 return "<%s %s>" % (self.__class__.__name__, self.server)
870
871 def start (self, flag=None):
872 self.flag = flag
873 threading.Thread.start(self)
874
Antoine Pitrou480a1242010-04-28 21:37:09 +0000875 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000876 self.active = True
877 if self.flag:
878 self.flag.set()
879 while self.active:
880 try:
881 asyncore.loop(1)
882 except:
883 pass
884
Antoine Pitrou480a1242010-04-28 21:37:09 +0000885 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000886 self.active = False
887 self.server.close()
888
Antoine Pitrou480a1242010-04-28 21:37:09 +0000889 def bad_cert_test(certfile):
890 """
891 Launch a server with CERT_REQUIRED, and check that trying to
892 connect to it with the given client certificate fails.
893 """
Trent Nelson78520002008-04-10 20:54:35 +0000894 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000896 cacerts=CERTFILE, chatty=False,
897 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 flag = threading.Event()
899 server.start(flag)
900 # wait for it to start
901 flag.wait()
902 # try to connect
903 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000904 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905 s = ssl.wrap_socket(socket.socket(),
906 certfile=certfile,
907 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000908 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000910 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000911 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000912 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000913 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000914 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000915 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000916 if x.errno != errno.ENOENT:
917 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000918 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000919 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000920 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000921 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 finally:
923 server.stop()
924 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000925
Antoine Pitroub5218772010-05-21 09:56:06 +0000926 def server_params_test(client_context, server_context, indata=b"FOO\n",
927 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000928 """
929 Launch a server, connect a client to it and try various reads
930 and writes.
931 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000932 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000934 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 flag = threading.Event()
936 server.start(flag)
937 # wait for it to start
938 flag.wait()
939 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000940 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000941 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000942 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000943 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000944 if connectionchatty:
945 if support.verbose:
946 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000947 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000948 s.write(arg)
949 outdata = s.read()
950 if connectionchatty:
951 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000952 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000953 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000954 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000955 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
956 % (outdata[:20], len(outdata),
957 indata[:20].lower(), len(indata)))
958 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000959 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000960 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000961 sys.stdout.write(" client: closing connection.\n")
962 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963 finally:
964 server.stop()
965 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000966
Antoine Pitroub5218772010-05-21 09:56:06 +0000967 def try_protocol_combo(server_protocol, client_protocol, expect_success,
968 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000969 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000971 certtype = {
972 ssl.CERT_NONE: "CERT_NONE",
973 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
974 ssl.CERT_REQUIRED: "CERT_REQUIRED",
975 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000976 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000977 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 sys.stdout.write(formatstr %
979 (ssl.get_protocol_name(client_protocol),
980 ssl.get_protocol_name(server_protocol),
981 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000982 client_context = ssl.SSLContext(client_protocol)
983 client_context.options = ssl.OP_ALL | client_options
984 server_context = ssl.SSLContext(server_protocol)
985 server_context.options = ssl.OP_ALL | server_options
986 for ctx in (client_context, server_context):
987 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000988 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
989 # will send an SSLv3 hello (rather than SSLv2) starting from
990 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000991 ctx.set_ciphers("ALL")
992 ctx.load_cert_chain(CERTFILE)
993 ctx.load_verify_locations(CERTFILE)
994 try:
995 server_params_test(client_context, server_context,
996 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000997 # Protocol mismatch can result in either an SSLError, or a
998 # "Connection reset by peer" error.
999 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001000 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001002 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001003 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001004 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001005 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001006 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001007 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001008 "Client protocol %s succeeded with server protocol %s!"
1009 % (ssl.get_protocol_name(client_protocol),
1010 ssl.get_protocol_name(server_protocol)))
1011
1012
Bill Janssen6e027db2007-11-15 22:23:56 +00001013 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014
Antoine Pitrou23df4832010-08-04 17:14:06 +00001015 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001016 def test_echo(self):
1017 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001018 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001019 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001020 for protocol in PROTOCOLS:
1021 context = ssl.SSLContext(protocol)
1022 context.load_cert_chain(CERTFILE)
1023 server_params_test(context, context,
1024 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001025
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001027 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001028 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001029 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1030 context.verify_mode = ssl.CERT_REQUIRED
1031 context.load_verify_locations(CERTFILE)
1032 context.load_cert_chain(CERTFILE)
1033 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 flag = threading.Event()
1035 server.start(flag)
1036 # wait for it to start
1037 flag.wait()
1038 # try to connect
1039 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001040 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001041 s.connect((HOST, server.port))
1042 cert = s.getpeercert()
1043 self.assertTrue(cert, "Can't get peer certificate.")
1044 cipher = s.cipher()
1045 if support.verbose:
1046 sys.stdout.write(pprint.pformat(cert) + '\n')
1047 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1048 if 'subject' not in cert:
1049 self.fail("No subject field in certificate: %s." %
1050 pprint.pformat(cert))
1051 if ((('organizationName', 'Python Software Foundation'),)
1052 not in cert['subject']):
1053 self.fail(
1054 "Missing or invalid 'organizationName' field in certificate subject; "
1055 "should be 'Python Software Foundation'.")
1056 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001057 finally:
1058 server.stop()
1059 server.join()
1060
Antoine Pitrou480a1242010-04-28 21:37:09 +00001061 def test_empty_cert(self):
1062 """Connecting with an empty cert file"""
1063 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1064 "nullcert.pem"))
1065 def test_malformed_cert(self):
1066 """Connecting with a badly formatted certificate (syntax error)"""
1067 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1068 "badcert.pem"))
1069 def test_nonexisting_cert(self):
1070 """Connecting with a non-existing cert file"""
1071 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1072 "wrongcert.pem"))
1073 def test_malformed_key(self):
1074 """Connecting with a badly formatted key (syntax error)"""
1075 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1076 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077
Antoine Pitrou480a1242010-04-28 21:37:09 +00001078 def test_rude_shutdown(self):
1079 """A brutal shutdown of an SSL server should raise an IOError
1080 in the client when attempting handshake.
1081 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001082 listener_ready = threading.Event()
1083 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001084
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001085 s = socket.socket()
1086 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001087
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001088 # `listener` runs in a thread. It sits in an accept() until
1089 # the main thread connects. Then it rudely closes the socket,
1090 # and sets Event `listener_gone` to let the main thread know
1091 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001092 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001093 s.listen(5)
1094 listener_ready.set()
1095 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001096 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001097 listener_gone.set()
1098
1099 def connector():
1100 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001101 c = socket.socket()
1102 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001103 listener_gone.wait()
1104 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001105 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001106 except IOError:
1107 pass
1108 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001109 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001110
1111 t = threading.Thread(target=listener)
1112 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001113 try:
1114 connector()
1115 finally:
1116 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001117
Antoine Pitrou23df4832010-08-04 17:14:06 +00001118 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001119 def test_protocol_sslv2(self):
1120 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001121 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001122 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001123 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1124 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1125 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1126 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1127 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1128 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001129 # SSLv23 client with specific SSL options
1130 if no_sslv2_implies_sslv3_hello():
1131 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1132 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1133 client_options=ssl.OP_NO_SSLv2)
1134 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1135 client_options=ssl.OP_NO_SSLv3)
1136 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1137 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001138
Antoine Pitrou23df4832010-08-04 17:14:06 +00001139 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001140 def test_protocol_sslv23(self):
1141 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001142 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001143 sys.stdout.write("\n")
1144 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001146 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001148 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001149 sys.stdout.write(
1150 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1151 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1153 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1154 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001155
Antoine Pitrou480a1242010-04-28 21:37:09 +00001156 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1157 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1158 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001159
Antoine Pitrou480a1242010-04-28 21:37:09 +00001160 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1161 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1162 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163
Antoine Pitroub5218772010-05-21 09:56:06 +00001164 # Server with specific SSL options
1165 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1166 server_options=ssl.OP_NO_SSLv3)
1167 # Will choose TLSv1
1168 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1169 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1170 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1171 server_options=ssl.OP_NO_TLSv1)
1172
1173
Antoine Pitrou23df4832010-08-04 17:14:06 +00001174 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001175 def test_protocol_sslv3(self):
1176 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001177 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001178 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001179 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1180 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1181 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1182 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1183 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1184 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001185 if no_sslv2_implies_sslv3_hello():
1186 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1187 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1188 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001189
Antoine Pitrou23df4832010-08-04 17:14:06 +00001190 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001191 def test_protocol_tlsv1(self):
1192 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001193 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001194 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001195 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1196 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1197 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1198 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1199 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1200 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001201
Antoine Pitrou480a1242010-04-28 21:37:09 +00001202 def test_starttls(self):
1203 """Switching from clear text to encrypted and back again."""
1204 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 +00001205
Trent Nelson78520002008-04-10 20:54:35 +00001206 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001207 ssl_version=ssl.PROTOCOL_TLSv1,
1208 starttls_server=True,
1209 chatty=True,
1210 connectionchatty=True)
1211 flag = threading.Event()
1212 server.start(flag)
1213 # wait for it to start
1214 flag.wait()
1215 # try to connect
1216 wrapped = False
1217 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001218 s = socket.socket()
1219 s.setblocking(1)
1220 s.connect((HOST, server.port))
1221 if support.verbose:
1222 sys.stdout.write("\n")
1223 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001224 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001225 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001226 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001227 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001228 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001229 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001230 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001232 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001233 msg = outdata.strip().lower()
1234 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1235 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001236 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, starting TLS...\n"
1239 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001240 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1241 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1243 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001244 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001245 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001246 " client: read %r from server, ending TLS...\n"
1247 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001248 s = conn.unwrap()
1249 wrapped = False
1250 else:
1251 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001252 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001253 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001254 if support.verbose:
1255 sys.stdout.write(" client: closing connection.\n")
1256 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001257 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001258 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001259 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001260 if wrapped:
1261 conn.close()
1262 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001263 s.close()
1264 finally:
1265 server.stop()
1266 server.join()
1267
Antoine Pitrou480a1242010-04-28 21:37:09 +00001268 def test_socketserver(self):
1269 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001270 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001271 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001272 if support.verbose:
1273 sys.stdout.write('\n')
1274 with open(CERTFILE, 'rb') as f:
1275 d1 = f.read()
1276 d2 = ''
1277 # now fetch the same data from the HTTPS server
1278 url = 'https://%s:%d/%s' % (
1279 HOST, server.port, os.path.split(CERTFILE)[1])
1280 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001281 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001282 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001283 if dlen and (int(dlen) > 0):
1284 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001285 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001286 sys.stdout.write(
1287 " client: read %d bytes from remote server '%s'\n"
1288 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001289 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001290 f.close()
1291 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001292
Antoine Pitrou480a1242010-04-28 21:37:09 +00001293 def test_asyncore_server(self):
1294 """Check the example asyncore integration."""
1295 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001296
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001297 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001298 sys.stdout.write("\n")
1299
Antoine Pitrou480a1242010-04-28 21:37:09 +00001300 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001301 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001302 flag = threading.Event()
1303 server.start(flag)
1304 # wait for it to start
1305 flag.wait()
1306 # try to connect
1307 try:
1308 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001309 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001310 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001311 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001312 " client: sending %r...\n" % indata)
1313 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001314 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001315 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001316 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001317 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001318 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001319 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1320 % (outdata[:20], len(outdata),
1321 indata[:20].lower(), len(indata)))
1322 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001323 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001324 sys.stdout.write(" client: closing connection.\n")
1325 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001326 if support.verbose:
1327 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001328 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001329 if support.verbose:
1330 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001331 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001332 if support.verbose:
1333 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001334 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001335 if support.verbose:
1336 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001337
Antoine Pitrou480a1242010-04-28 21:37:09 +00001338 def test_recv_send(self):
1339 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001340 if support.verbose:
1341 sys.stdout.write("\n")
1342
1343 server = ThreadedEchoServer(CERTFILE,
1344 certreqs=ssl.CERT_NONE,
1345 ssl_version=ssl.PROTOCOL_TLSv1,
1346 cacerts=CERTFILE,
1347 chatty=True,
1348 connectionchatty=False)
1349 flag = threading.Event()
1350 server.start(flag)
1351 # wait for it to start
1352 flag.wait()
1353 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001354 s = ssl.wrap_socket(socket.socket(),
1355 server_side=False,
1356 certfile=CERTFILE,
1357 ca_certs=CERTFILE,
1358 cert_reqs=ssl.CERT_NONE,
1359 ssl_version=ssl.PROTOCOL_TLSv1)
1360 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001361 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001362 # helper methods for standardising recv* method signatures
1363 def _recv_into():
1364 b = bytearray(b"\0"*100)
1365 count = s.recv_into(b)
1366 return b[:count]
1367
1368 def _recvfrom_into():
1369 b = bytearray(b"\0"*100)
1370 count, addr = s.recvfrom_into(b)
1371 return b[:count]
1372
1373 # (name, method, whether to expect success, *args)
1374 send_methods = [
1375 ('send', s.send, True, []),
1376 ('sendto', s.sendto, False, ["some.address"]),
1377 ('sendall', s.sendall, True, []),
1378 ]
1379 recv_methods = [
1380 ('recv', s.recv, True, []),
1381 ('recvfrom', s.recvfrom, False, ["some.address"]),
1382 ('recv_into', _recv_into, True, []),
1383 ('recvfrom_into', _recvfrom_into, False, []),
1384 ]
1385 data_prefix = "PREFIX_"
1386
1387 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001388 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001389 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001390 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001391 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001392 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001393 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001394 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395 "<<{outdata:r}>> ({nout:d}) received; "
1396 "expected <<{indata:r}>> ({nin:d})\n".format(
1397 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001398 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001399 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001400 )
1401 )
1402 except ValueError as e:
1403 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001404 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001405 "Failed to send with method <<{name:s}>>; "
1406 "expected to succeed.\n".format(name=meth_name)
1407 )
1408 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001409 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001410 "Method <<{name:s}>> failed with unexpected "
1411 "exception message: {exp:s}\n".format(
1412 name=meth_name, exp=e
1413 )
1414 )
1415
1416 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001417 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001418 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001419 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001420 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001421 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001422 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001423 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001424 "<<{outdata:r}>> ({nout:d}) received; "
1425 "expected <<{indata:r}>> ({nin:d})\n".format(
1426 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001427 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001428 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001429 )
1430 )
1431 except ValueError as e:
1432 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001433 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001434 "Failed to receive with method <<{name:s}>>; "
1435 "expected to succeed.\n".format(name=meth_name)
1436 )
1437 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001438 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001439 "Method <<{name:s}>> failed with unexpected "
1440 "exception message: {exp:s}\n".format(
1441 name=meth_name, exp=e
1442 )
1443 )
1444 # consume data
1445 s.read()
1446
Antoine Pitrou480a1242010-04-28 21:37:09 +00001447 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001448 s.close()
1449 finally:
1450 server.stop()
1451 server.join()
1452
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001453 def test_handshake_timeout(self):
1454 # Issue #5103: SSL handshake must respect the socket timeout
1455 server = socket.socket(socket.AF_INET)
1456 host = "127.0.0.1"
1457 port = support.bind_port(server)
1458 started = threading.Event()
1459 finish = False
1460
1461 def serve():
1462 server.listen(5)
1463 started.set()
1464 conns = []
1465 while not finish:
1466 r, w, e = select.select([server], [], [], 0.1)
1467 if server in r:
1468 # Let the socket hang around rather than having
1469 # it closed by garbage collection.
1470 conns.append(server.accept()[0])
1471
1472 t = threading.Thread(target=serve)
1473 t.start()
1474 started.wait()
1475
1476 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001477 try:
1478 c = socket.socket(socket.AF_INET)
1479 c.settimeout(0.2)
1480 c.connect((host, port))
1481 # Will attempt handshake and time out
1482 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1483 ssl.wrap_socket, c)
1484 finally:
1485 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001486 try:
1487 c = socket.socket(socket.AF_INET)
1488 c = ssl.wrap_socket(c)
1489 c.settimeout(0.2)
1490 # Will attempt handshake and time out
1491 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1492 c.connect, (host, port))
1493 finally:
1494 c.close()
1495 finally:
1496 finish = True
1497 t.join()
1498 server.close()
1499
Bill Janssen58afe4c2008-09-08 16:45:19 +00001500
Thomas Woutersed03b412007-08-28 21:37:11 +00001501def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001502 if support.verbose:
1503 plats = {
1504 'Linux': platform.linux_distribution,
1505 'Mac': platform.mac_ver,
1506 'Windows': platform.win32_ver,
1507 }
1508 for name, func in plats.items():
1509 plat = func()
1510 if plat and plat[0]:
1511 plat = '%s %r' % (name, plat)
1512 break
1513 else:
1514 plat = repr(platform.platform())
1515 print("test_ssl: testing with %r %r" %
1516 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1517 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001518 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001519
Antoine Pitrou152efa22010-05-16 18:19:27 +00001520 for filename in [
1521 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1522 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1523 BADCERT, BADKEY, EMPTYCERT]:
1524 if not os.path.exists(filename):
1525 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001526
Antoine Pitrou152efa22010-05-16 18:19:27 +00001527 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001528
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001529 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001530 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001531
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001532 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001533 thread_info = support.threading_setup()
1534 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001535 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001536
Antoine Pitrou480a1242010-04-28 21:37:09 +00001537 try:
1538 support.run_unittest(*tests)
1539 finally:
1540 if _have_threads:
1541 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001542
1543if __name__ == "__main__":
1544 test_main()