blob: 08a07bab80f40b2ebccd1ea18bfd623ebb2908c0 [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
Antoine Pitrou242db722013-05-01 20:52:07 +020020from unittest import mock
Thomas Woutersed03b412007-08-28 21:37:11 +000021
Antoine Pitrou05d936d2010-10-13 11:38:36 +000022ssl = support.import_module("ssl")
23
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010024PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000025HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000026
27data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000028
Antoine Pitrou81564092010-10-08 23:06:24 +000029# The custom key and certificate files used in test_ssl are generated
30# using Lib/test/make_ssl_certs.py.
31# Other certificates are simply fetched from the Internet servers they
32# are meant to authenticate.
33
Antoine Pitrou152efa22010-05-16 18:19:27 +000034CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000035BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000036ONLYCERT = data_file("ssl_cert.pem")
37ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000038BYTES_ONLYCERT = os.fsencode(ONLYCERT)
39BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020040CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
41ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
42KEY_PASSWORD = "somepass"
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
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010046# Two keys and certs signed by the same CA (for SNI tests)
47SIGNED_CERTFILE = data_file("keycert3.pem")
48SIGNED_CERTFILE2 = data_file("keycert4.pem")
49SIGNING_CA = data_file("pycacert.pem")
50
Antoine Pitrou152efa22010-05-16 18:19:27 +000051SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
52
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020057NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000058
Antoine Pitrou0e576f12011-12-22 10:03:38 +010059DHFILE = data_file("dh512.pem")
60BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000061
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010062
Thomas Woutersed03b412007-08-28 21:37:11 +000063def handle_error(prefix):
64 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000065 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000066 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000067
Antoine Pitroub5218772010-05-21 09:56:06 +000068def can_clear_options():
69 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020070 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000071
72def no_sslv2_implies_sslv3_hello():
73 # 0.9.7h or higher
74 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
75
Thomas Woutersed03b412007-08-28 21:37:11 +000076
Antoine Pitrou23df4832010-08-04 17:14:06 +000077# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
78def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020079 if hasattr(ssl, 'PROTOCOL_SSLv2'):
80 @functools.wraps(func)
81 def f(*args, **kwargs):
82 try:
83 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
84 except ssl.SSLError:
85 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
86 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
87 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
88 return func(*args, **kwargs)
89 return f
90 else:
91 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000092
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010093needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
94
Antoine Pitrou23df4832010-08-04 17:14:06 +000095
Antoine Pitrou152efa22010-05-16 18:19:27 +000096class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000097
Antoine Pitrou480a1242010-04-28 21:37:09 +000098 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000099 ssl.CERT_NONE
100 ssl.CERT_OPTIONAL
101 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100102 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100103 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100104 if ssl.HAS_ECDH:
105 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100106 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
107 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000108 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100109 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000110
Antoine Pitrou480a1242010-04-28 21:37:09 +0000111 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000112 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000113 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 sys.stdout.write("\n RAND_status is %d (%s)\n"
115 % (v, (v and "sufficient randomness") or
116 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200117
118 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
119 self.assertEqual(len(data), 16)
120 self.assertEqual(is_cryptographic, v == 1)
121 if v:
122 data = ssl.RAND_bytes(16)
123 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200124 else:
125 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200126
Jesus Ceac8754a12012-09-11 02:00:58 +0200127 self.assertRaises(TypeError, ssl.RAND_egd, 1)
128 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000130
Antoine Pitrou480a1242010-04-28 21:37:09 +0000131 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132 # note that this uses an 'unofficial' function in _ssl.c,
133 # provided solely for this test, to exercise the certificate
134 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000135 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000136 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000137 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200138 self.assertEqual(p['issuer'],
139 ((('countryName', 'XY'),),
140 (('localityName', 'Castle Anthrax'),),
141 (('organizationName', 'Python Software Foundation'),),
142 (('commonName', 'localhost'),))
143 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100144 # Note the next three asserts will fail if the keys are regenerated
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200145 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
146 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
147 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
148 self.assertEqual(p['subject'],
149 ((('countryName', 'XY'),),
150 (('localityName', 'Castle Anthrax'),),
151 (('organizationName', 'Python Software Foundation'),),
152 (('commonName', 'localhost'),))
153 )
154 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
155 # Issue #13034: the subjectAltName in some certificates
156 # (notably projects.developer.nokia.com:443) wasn't parsed
157 p = ssl._ssl._test_decode_cert(NOKIACERT)
158 if support.verbose:
159 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
160 self.assertEqual(p['subjectAltName'],
161 (('DNS', 'projects.developer.nokia.com'),
162 ('DNS', 'projects.forum.nokia.com'))
163 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000164
Antoine Pitrou480a1242010-04-28 21:37:09 +0000165 def test_DER_to_PEM(self):
166 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
167 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000168 d1 = ssl.PEM_cert_to_DER_cert(pem)
169 p2 = ssl.DER_cert_to_PEM_cert(d1)
170 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000171 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000172 if not p2.startswith(ssl.PEM_HEADER + '\n'):
173 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
174 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
175 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000176
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000177 def test_openssl_version(self):
178 n = ssl.OPENSSL_VERSION_NUMBER
179 t = ssl.OPENSSL_VERSION_INFO
180 s = ssl.OPENSSL_VERSION
181 self.assertIsInstance(n, int)
182 self.assertIsInstance(t, tuple)
183 self.assertIsInstance(s, str)
184 # Some sanity checks follow
185 # >= 0.9
186 self.assertGreaterEqual(n, 0x900000)
187 # < 2.0
188 self.assertLess(n, 0x20000000)
189 major, minor, fix, patch, status = t
190 self.assertGreaterEqual(major, 0)
191 self.assertLess(major, 2)
192 self.assertGreaterEqual(minor, 0)
193 self.assertLess(minor, 256)
194 self.assertGreaterEqual(fix, 0)
195 self.assertLess(fix, 256)
196 self.assertGreaterEqual(patch, 0)
197 self.assertLessEqual(patch, 26)
198 self.assertGreaterEqual(status, 0)
199 self.assertLessEqual(status, 15)
200 # Version string as returned by OpenSSL, the format might change
201 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
202 (s, t))
203
Antoine Pitrou9d543662010-04-23 23:10:32 +0000204 @support.cpython_only
205 def test_refcycle(self):
206 # Issue #7943: an SSL object doesn't create reference cycles with
207 # itself.
208 s = socket.socket(socket.AF_INET)
209 ss = ssl.wrap_socket(s)
210 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100211 with support.check_warnings(("", ResourceWarning)):
212 del ss
213 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000214
Antoine Pitroua468adc2010-09-14 14:43:44 +0000215 def test_wrapped_unconnected(self):
216 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200217 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000218 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100219 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100220 self.assertRaises(OSError, ss.recv, 1)
221 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
222 self.assertRaises(OSError, ss.recvfrom, 1)
223 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
224 self.assertRaises(OSError, ss.send, b'x')
225 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000226
Antoine Pitrou40f08742010-04-24 22:04:40 +0000227 def test_timeout(self):
228 # Issue #8524: when creating an SSL socket, the timeout of the
229 # original socket should be retained.
230 for timeout in (None, 0.0, 5.0):
231 s = socket.socket(socket.AF_INET)
232 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100233 with ssl.wrap_socket(s) as ss:
234 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000235
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000236 def test_errors(self):
237 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000238 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000239 "certfile must be specified",
240 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000241 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000242 "certfile must be specified for server-side operations",
243 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000244 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000245 "certfile must be specified for server-side operations",
246 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100247 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
248 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
249 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200250 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000251 with socket.socket() as sock:
252 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000253 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200254 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000255 with socket.socket() as sock:
256 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000257 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200258 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000259 with socket.socket() as sock:
260 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000261 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000262
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000263 def test_match_hostname(self):
264 def ok(cert, hostname):
265 ssl.match_hostname(cert, hostname)
266 def fail(cert, hostname):
267 self.assertRaises(ssl.CertificateError,
268 ssl.match_hostname, cert, hostname)
269
270 cert = {'subject': ((('commonName', 'example.com'),),)}
271 ok(cert, 'example.com')
272 ok(cert, 'ExAmple.cOm')
273 fail(cert, 'www.example.com')
274 fail(cert, '.example.com')
275 fail(cert, 'example.org')
276 fail(cert, 'exampleXcom')
277
278 cert = {'subject': ((('commonName', '*.a.com'),),)}
279 ok(cert, 'foo.a.com')
280 fail(cert, 'bar.foo.a.com')
281 fail(cert, 'a.com')
282 fail(cert, 'Xa.com')
283 fail(cert, '.a.com')
284
285 cert = {'subject': ((('commonName', 'a.*.com'),),)}
286 ok(cert, 'a.foo.com')
287 fail(cert, 'a..com')
288 fail(cert, 'a.com')
289
290 cert = {'subject': ((('commonName', 'f*.com'),),)}
291 ok(cert, 'foo.com')
292 ok(cert, 'f.com')
293 fail(cert, 'bar.com')
294 fail(cert, 'foo.a.com')
295 fail(cert, 'bar.foo.com')
296
297 # Slightly fake real-world example
298 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
299 'subject': ((('commonName', 'linuxfrz.org'),),),
300 'subjectAltName': (('DNS', 'linuxfr.org'),
301 ('DNS', 'linuxfr.com'),
302 ('othername', '<unsupported>'))}
303 ok(cert, 'linuxfr.org')
304 ok(cert, 'linuxfr.com')
305 # Not a "DNS" entry
306 fail(cert, '<unsupported>')
307 # When there is a subjectAltName, commonName isn't used
308 fail(cert, 'linuxfrz.org')
309
310 # A pristine real-world example
311 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
312 'subject': ((('countryName', 'US'),),
313 (('stateOrProvinceName', 'California'),),
314 (('localityName', 'Mountain View'),),
315 (('organizationName', 'Google Inc'),),
316 (('commonName', 'mail.google.com'),))}
317 ok(cert, 'mail.google.com')
318 fail(cert, 'gmail.com')
319 # Only commonName is considered
320 fail(cert, 'California')
321
322 # Neither commonName nor subjectAltName
323 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
324 'subject': ((('countryName', 'US'),),
325 (('stateOrProvinceName', 'California'),),
326 (('localityName', 'Mountain View'),),
327 (('organizationName', 'Google Inc'),))}
328 fail(cert, 'mail.google.com')
329
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200330 # No DNS entry in subjectAltName but a commonName
331 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
332 'subject': ((('countryName', 'US'),),
333 (('stateOrProvinceName', 'California'),),
334 (('localityName', 'Mountain View'),),
335 (('commonName', 'mail.google.com'),)),
336 'subjectAltName': (('othername', 'blabla'), )}
337 ok(cert, 'mail.google.com')
338
339 # No DNS entry subjectAltName and no commonName
340 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
341 'subject': ((('countryName', 'US'),),
342 (('stateOrProvinceName', 'California'),),
343 (('localityName', 'Mountain View'),),
344 (('organizationName', 'Google Inc'),)),
345 'subjectAltName': (('othername', 'blabla'),)}
346 fail(cert, 'google.com')
347
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000348 # Empty cert / no cert
349 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
350 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
351
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200352 # Issue #17980: avoid denials of service by refusing more than one
353 # wildcard per fragment.
354 cert = {'subject': ((('commonName', 'a*b.com'),),)}
355 ok(cert, 'axxb.com')
356 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
357 ok(cert, 'axxb.com')
358 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
359 with self.assertRaises(ssl.CertificateError) as cm:
360 ssl.match_hostname(cert, 'axxbxxc.com')
361 self.assertIn("too many wildcards", str(cm.exception))
362
Antoine Pitroud5323212010-10-22 18:19:07 +0000363 def test_server_side(self):
364 # server_hostname doesn't work for server sockets
365 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000366 with socket.socket() as sock:
367 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
368 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000369
Antoine Pitroud6494802011-07-21 01:11:30 +0200370 def test_unknown_channel_binding(self):
371 # should raise ValueError for unknown type
372 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100373 with ssl.wrap_socket(s) as ss:
374 with self.assertRaises(ValueError):
375 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200376
377 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
378 "'tls-unique' channel binding not available")
379 def test_tls_unique_channel_binding(self):
380 # unconnected should return None for known type
381 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100382 with ssl.wrap_socket(s) as ss:
383 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200384 # the same for server-side
385 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100386 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
387 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200388
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600389 def test_dealloc_warn(self):
390 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
391 r = repr(ss)
392 with self.assertWarns(ResourceWarning) as cm:
393 ss = None
394 support.gc_collect()
395 self.assertIn(r, str(cm.warning.args[0]))
396
Christian Heimes6d7ad132013-06-09 18:02:55 +0200397 def test_get_default_verify_paths(self):
398 paths = ssl.get_default_verify_paths()
399 self.assertEqual(len(paths), 6)
400 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
401
402 with support.EnvironmentVarGuard() as env:
403 env["SSL_CERT_DIR"] = CAPATH
404 env["SSL_CERT_FILE"] = CERTFILE
405 paths = ssl.get_default_verify_paths()
406 self.assertEqual(paths.cafile, CERTFILE)
407 self.assertEqual(paths.capath, CAPATH)
408
409
Christian Heimes46bebee2013-06-09 19:03:31 +0200410 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
411 def test_enum_cert_store(self):
412 self.assertEqual(ssl.X509_ASN_ENCODING, 1)
413 self.assertEqual(ssl.PKCS_7_ASN_ENCODING, 0x00010000)
414
415 self.assertEqual(ssl.enum_cert_store("CA"),
416 ssl.enum_cert_store("CA", "certificate"))
417 ssl.enum_cert_store("CA", "crl")
418 self.assertEqual(ssl.enum_cert_store("ROOT"),
419 ssl.enum_cert_store("ROOT", "certificate"))
420 ssl.enum_cert_store("ROOT", "crl")
421
422 self.assertRaises(TypeError, ssl.enum_cert_store)
423 self.assertRaises(WindowsError, ssl.enum_cert_store, "")
424 self.assertRaises(ValueError, ssl.enum_cert_store, "CA", "wrong")
425
426 ca = ssl.enum_cert_store("CA")
427 self.assertIsInstance(ca, list)
428 self.assertIsInstance(ca[0], tuple)
429 self.assertEqual(len(ca[0]), 2)
430 self.assertIsInstance(ca[0][0], bytes)
431 self.assertIsInstance(ca[0][1], int)
432
Antoine Pitrou152efa22010-05-16 18:19:27 +0000433class ContextTests(unittest.TestCase):
434
Antoine Pitrou23df4832010-08-04 17:14:06 +0000435 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000436 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100437 for protocol in PROTOCOLS:
438 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000439 self.assertRaises(TypeError, ssl.SSLContext)
440 self.assertRaises(ValueError, ssl.SSLContext, -1)
441 self.assertRaises(ValueError, ssl.SSLContext, 42)
442
Antoine Pitrou23df4832010-08-04 17:14:06 +0000443 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000444 def test_protocol(self):
445 for proto in PROTOCOLS:
446 ctx = ssl.SSLContext(proto)
447 self.assertEqual(ctx.protocol, proto)
448
449 def test_ciphers(self):
450 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
451 ctx.set_ciphers("ALL")
452 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000453 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000454 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000455
Antoine Pitrou23df4832010-08-04 17:14:06 +0000456 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000457 def test_options(self):
458 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
459 # OP_ALL is the default value
460 self.assertEqual(ssl.OP_ALL, ctx.options)
461 ctx.options |= ssl.OP_NO_SSLv2
462 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
463 ctx.options)
464 ctx.options |= ssl.OP_NO_SSLv3
465 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
466 ctx.options)
467 if can_clear_options():
468 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
469 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
470 ctx.options)
471 ctx.options = 0
472 self.assertEqual(0, ctx.options)
473 else:
474 with self.assertRaises(ValueError):
475 ctx.options = 0
476
Antoine Pitrou152efa22010-05-16 18:19:27 +0000477 def test_verify(self):
478 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
479 # Default value
480 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
481 ctx.verify_mode = ssl.CERT_OPTIONAL
482 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
483 ctx.verify_mode = ssl.CERT_REQUIRED
484 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
485 ctx.verify_mode = ssl.CERT_NONE
486 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
487 with self.assertRaises(TypeError):
488 ctx.verify_mode = None
489 with self.assertRaises(ValueError):
490 ctx.verify_mode = 42
491
492 def test_load_cert_chain(self):
493 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
494 # Combined key and cert in a single file
495 ctx.load_cert_chain(CERTFILE)
496 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
497 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200498 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000499 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000500 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000501 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000502 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000503 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000504 ctx.load_cert_chain(EMPTYCERT)
505 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000506 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000507 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
508 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
509 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000510 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000511 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000512 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000513 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000514 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000515 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
516 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000517 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000518 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000519 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200520 # Password protected key and cert
521 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
522 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
523 ctx.load_cert_chain(CERTFILE_PROTECTED,
524 password=bytearray(KEY_PASSWORD.encode()))
525 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
526 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
527 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
528 bytearray(KEY_PASSWORD.encode()))
529 with self.assertRaisesRegex(TypeError, "should be a string"):
530 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
531 with self.assertRaises(ssl.SSLError):
532 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
533 with self.assertRaisesRegex(ValueError, "cannot be longer"):
534 # openssl has a fixed limit on the password buffer.
535 # PEM_BUFSIZE is generally set to 1kb.
536 # Return a string larger than this.
537 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
538 # Password callback
539 def getpass_unicode():
540 return KEY_PASSWORD
541 def getpass_bytes():
542 return KEY_PASSWORD.encode()
543 def getpass_bytearray():
544 return bytearray(KEY_PASSWORD.encode())
545 def getpass_badpass():
546 return "badpass"
547 def getpass_huge():
548 return b'a' * (1024 * 1024)
549 def getpass_bad_type():
550 return 9
551 def getpass_exception():
552 raise Exception('getpass error')
553 class GetPassCallable:
554 def __call__(self):
555 return KEY_PASSWORD
556 def getpass(self):
557 return KEY_PASSWORD
558 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
559 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
560 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
561 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
562 ctx.load_cert_chain(CERTFILE_PROTECTED,
563 password=GetPassCallable().getpass)
564 with self.assertRaises(ssl.SSLError):
565 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
566 with self.assertRaisesRegex(ValueError, "cannot be longer"):
567 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
568 with self.assertRaisesRegex(TypeError, "must return a string"):
569 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
570 with self.assertRaisesRegex(Exception, "getpass error"):
571 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
572 # Make sure the password function isn't called if it isn't needed
573 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000574
575 def test_load_verify_locations(self):
576 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
577 ctx.load_verify_locations(CERTFILE)
578 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
579 ctx.load_verify_locations(BYTES_CERTFILE)
580 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
581 self.assertRaises(TypeError, ctx.load_verify_locations)
582 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200583 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000584 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000585 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000586 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000587 ctx.load_verify_locations(BADCERT)
588 ctx.load_verify_locations(CERTFILE, CAPATH)
589 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
590
Victor Stinner80f75e62011-01-29 11:31:20 +0000591 # Issue #10989: crash if the second argument type is invalid
592 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
593
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100594 def test_load_dh_params(self):
595 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
596 ctx.load_dh_params(DHFILE)
597 if os.name != 'nt':
598 ctx.load_dh_params(BYTES_DHFILE)
599 self.assertRaises(TypeError, ctx.load_dh_params)
600 self.assertRaises(TypeError, ctx.load_dh_params, None)
601 with self.assertRaises(FileNotFoundError) as cm:
602 ctx.load_dh_params(WRONGCERT)
603 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200604 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100605 ctx.load_dh_params(CERTFILE)
606
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000607 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000608 def test_session_stats(self):
609 for proto in PROTOCOLS:
610 ctx = ssl.SSLContext(proto)
611 self.assertEqual(ctx.session_stats(), {
612 'number': 0,
613 'connect': 0,
614 'connect_good': 0,
615 'connect_renegotiate': 0,
616 'accept': 0,
617 'accept_good': 0,
618 'accept_renegotiate': 0,
619 'hits': 0,
620 'misses': 0,
621 'timeouts': 0,
622 'cache_full': 0,
623 })
624
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000625 def test_set_default_verify_paths(self):
626 # There's not much we can do to test that it acts as expected,
627 # so just check it doesn't crash or raise an exception.
628 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
629 ctx.set_default_verify_paths()
630
Antoine Pitrou501da612011-12-21 09:27:41 +0100631 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100632 def test_set_ecdh_curve(self):
633 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
634 ctx.set_ecdh_curve("prime256v1")
635 ctx.set_ecdh_curve(b"prime256v1")
636 self.assertRaises(TypeError, ctx.set_ecdh_curve)
637 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
638 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
639 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
640
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100641 @needs_sni
642 def test_sni_callback(self):
643 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
644
645 # set_servername_callback expects a callable, or None
646 self.assertRaises(TypeError, ctx.set_servername_callback)
647 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
648 self.assertRaises(TypeError, ctx.set_servername_callback, "")
649 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
650
651 def dummycallback(sock, servername, ctx):
652 pass
653 ctx.set_servername_callback(None)
654 ctx.set_servername_callback(dummycallback)
655
656 @needs_sni
657 def test_sni_callback_refcycle(self):
658 # Reference cycles through the servername callback are detected
659 # and cleared.
660 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
661 def dummycallback(sock, servername, ctx, cycle=ctx):
662 pass
663 ctx.set_servername_callback(dummycallback)
664 wr = weakref.ref(ctx)
665 del ctx, dummycallback
666 gc.collect()
667 self.assertIs(wr(), None)
668
Antoine Pitrou152efa22010-05-16 18:19:27 +0000669
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200670class SSLErrorTests(unittest.TestCase):
671
672 def test_str(self):
673 # The str() of a SSLError doesn't include the errno
674 e = ssl.SSLError(1, "foo")
675 self.assertEqual(str(e), "foo")
676 self.assertEqual(e.errno, 1)
677 # Same for a subclass
678 e = ssl.SSLZeroReturnError(1, "foo")
679 self.assertEqual(str(e), "foo")
680 self.assertEqual(e.errno, 1)
681
682 def test_lib_reason(self):
683 # Test the library and reason attributes
684 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
685 with self.assertRaises(ssl.SSLError) as cm:
686 ctx.load_dh_params(CERTFILE)
687 self.assertEqual(cm.exception.library, 'PEM')
688 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
689 s = str(cm.exception)
690 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
691
692 def test_subclass(self):
693 # Check that the appropriate SSLError subclass is raised
694 # (this only tests one of them)
695 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
696 with socket.socket() as s:
697 s.bind(("127.0.0.1", 0))
698 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100699 c = socket.socket()
700 c.connect(s.getsockname())
701 c.setblocking(False)
702 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200703 with self.assertRaises(ssl.SSLWantReadError) as cm:
704 c.do_handshake()
705 s = str(cm.exception)
706 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
707 # For compatibility
708 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
709
710
Bill Janssen6e027db2007-11-15 22:23:56 +0000711class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000712
Antoine Pitrou480a1242010-04-28 21:37:09 +0000713 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000714 with support.transient_internet("svn.python.org"):
715 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
716 cert_reqs=ssl.CERT_NONE)
717 try:
718 s.connect(("svn.python.org", 443))
719 self.assertEqual({}, s.getpeercert())
720 finally:
721 s.close()
722
723 # this should fail because we have no verification certs
724 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
725 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000726 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
727 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000728 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000729
Antoine Pitrou350c7222010-09-09 13:31:46 +0000730 # this should succeed because we specify the root cert
731 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
732 cert_reqs=ssl.CERT_REQUIRED,
733 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
734 try:
735 s.connect(("svn.python.org", 443))
736 self.assertTrue(s.getpeercert())
737 finally:
738 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000739
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000740 def test_connect_ex(self):
741 # Issue #11326: check connect_ex() implementation
742 with support.transient_internet("svn.python.org"):
743 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
744 cert_reqs=ssl.CERT_REQUIRED,
745 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
746 try:
747 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
748 self.assertTrue(s.getpeercert())
749 finally:
750 s.close()
751
752 def test_non_blocking_connect_ex(self):
753 # Issue #11326: non-blocking connect_ex() should allow handshake
754 # to proceed after the socket gets ready.
755 with support.transient_internet("svn.python.org"):
756 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
757 cert_reqs=ssl.CERT_REQUIRED,
758 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
759 do_handshake_on_connect=False)
760 try:
761 s.setblocking(False)
762 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000763 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
764 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000765 # Wait for connect to finish
766 select.select([], [s], [], 5.0)
767 # Non-blocking handshake
768 while True:
769 try:
770 s.do_handshake()
771 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200772 except ssl.SSLWantReadError:
773 select.select([s], [], [], 5.0)
774 except ssl.SSLWantWriteError:
775 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000776 # SSL established
777 self.assertTrue(s.getpeercert())
778 finally:
779 s.close()
780
Antoine Pitroub4410db2011-05-18 18:51:06 +0200781 def test_timeout_connect_ex(self):
782 # Issue #12065: on a timeout, connect_ex() should return the original
783 # errno (mimicking the behaviour of non-SSL sockets).
784 with support.transient_internet("svn.python.org"):
785 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
786 cert_reqs=ssl.CERT_REQUIRED,
787 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
788 do_handshake_on_connect=False)
789 try:
790 s.settimeout(0.0000001)
791 rc = s.connect_ex(('svn.python.org', 443))
792 if rc == 0:
793 self.skipTest("svn.python.org responded too quickly")
794 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
795 finally:
796 s.close()
797
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100798 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100799 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100800 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
801 cert_reqs=ssl.CERT_REQUIRED,
802 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
803 try:
804 self.assertEqual(errno.ECONNREFUSED,
805 s.connect_ex(("svn.python.org", 444)))
806 finally:
807 s.close()
808
Antoine Pitrou152efa22010-05-16 18:19:27 +0000809 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000810 with support.transient_internet("svn.python.org"):
811 # Same as test_connect, but with a separately created context
812 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
813 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
814 s.connect(("svn.python.org", 443))
815 try:
816 self.assertEqual({}, s.getpeercert())
817 finally:
818 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000819 # Same with a server hostname
820 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
821 server_hostname="svn.python.org")
822 if ssl.HAS_SNI:
823 s.connect(("svn.python.org", 443))
824 s.close()
825 else:
826 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000827 # This should fail because we have no verification certs
828 ctx.verify_mode = ssl.CERT_REQUIRED
829 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000830 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000831 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000832 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000833 # This should succeed because we specify the root cert
834 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
835 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
836 s.connect(("svn.python.org", 443))
837 try:
838 cert = s.getpeercert()
839 self.assertTrue(cert)
840 finally:
841 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000842
843 def test_connect_capath(self):
844 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000845 # NOTE: the subject hashing algorithm has been changed between
846 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
847 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000848 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000849 with support.transient_internet("svn.python.org"):
850 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
851 ctx.verify_mode = ssl.CERT_REQUIRED
852 ctx.load_verify_locations(capath=CAPATH)
853 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
854 s.connect(("svn.python.org", 443))
855 try:
856 cert = s.getpeercert()
857 self.assertTrue(cert)
858 finally:
859 s.close()
860 # Same with a bytes `capath` argument
861 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
862 ctx.verify_mode = ssl.CERT_REQUIRED
863 ctx.load_verify_locations(capath=BYTES_CAPATH)
864 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
865 s.connect(("svn.python.org", 443))
866 try:
867 cert = s.getpeercert()
868 self.assertTrue(cert)
869 finally:
870 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000871
Antoine Pitroue3220242010-04-24 11:13:53 +0000872 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
873 def test_makefile_close(self):
874 # Issue #5238: creating a file-like object with makefile() shouldn't
875 # delay closing the underlying "real socket" (here tested with its
876 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000877 with support.transient_internet("svn.python.org"):
878 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
879 ss.connect(("svn.python.org", 443))
880 fd = ss.fileno()
881 f = ss.makefile()
882 f.close()
883 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000884 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000885 # Closing the SSL socket should close the fd too
886 ss.close()
887 gc.collect()
888 with self.assertRaises(OSError) as e:
889 os.read(fd, 0)
890 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000891
Antoine Pitrou480a1242010-04-28 21:37:09 +0000892 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000893 with support.transient_internet("svn.python.org"):
894 s = socket.socket(socket.AF_INET)
895 s.connect(("svn.python.org", 443))
896 s.setblocking(False)
897 s = ssl.wrap_socket(s,
898 cert_reqs=ssl.CERT_NONE,
899 do_handshake_on_connect=False)
900 count = 0
901 while True:
902 try:
903 count += 1
904 s.do_handshake()
905 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200906 except ssl.SSLWantReadError:
907 select.select([s], [], [])
908 except ssl.SSLWantWriteError:
909 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000910 s.close()
911 if support.verbose:
912 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000913
Antoine Pitrou480a1242010-04-28 21:37:09 +0000914 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200915 def _test_get_server_certificate(host, port, cert=None):
916 with support.transient_internet(host):
917 pem = ssl.get_server_certificate((host, port))
918 if not pem:
919 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200920
Antoine Pitrou15399c32011-04-28 19:23:55 +0200921 try:
922 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
923 except ssl.SSLError as x:
924 #should fail
925 if support.verbose:
926 sys.stdout.write("%s\n" % x)
927 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200928 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
929
Antoine Pitrou15399c32011-04-28 19:23:55 +0200930 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
931 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200932 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000933 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200934 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000935
Antoine Pitrou15399c32011-04-28 19:23:55 +0200936 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
937 if support.IPV6_ENABLED:
938 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000939
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000940 def test_ciphers(self):
941 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000942 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100943 with ssl.wrap_socket(socket.socket(socket.AF_INET),
944 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
945 s.connect(remote)
946 with ssl.wrap_socket(socket.socket(socket.AF_INET),
947 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
948 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000949 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000950 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000951 with socket.socket(socket.AF_INET) as sock:
952 s = ssl.wrap_socket(sock,
953 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
954 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000955
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000956 def test_algorithms(self):
957 # Issue #8484: all algorithms should be available when verifying a
958 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000959 # SHA256 was added in OpenSSL 0.9.8
960 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
961 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200962 # sha256.tbs-internet.com needs SNI to use the correct certificate
963 if not ssl.HAS_SNI:
964 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000965 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
966 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000967 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000968 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200969 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
970 ctx.verify_mode = ssl.CERT_REQUIRED
971 ctx.load_verify_locations(sha256_cert)
972 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
973 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000974 try:
975 s.connect(remote)
976 if support.verbose:
977 sys.stdout.write("\nCipher with %r is %r\n" %
978 (remote, s.cipher()))
979 sys.stdout.write("Certificate is:\n%s\n" %
980 pprint.pformat(s.getpeercert()))
981 finally:
982 s.close()
983
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984
985try:
986 import threading
987except ImportError:
988 _have_threads = False
989else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 _have_threads = True
991
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000992 from test.ssl_servers import make_https_server
993
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000994 class ThreadedEchoServer(threading.Thread):
995
996 class ConnectionHandler(threading.Thread):
997
998 """A mildly complicated class, because we want it to work both
999 with and without the SSL wrapper around the socket connection, so
1000 that we can test the STARTTLS functionality."""
1001
Bill Janssen6e027db2007-11-15 22:23:56 +00001002 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 self.server = server
1004 self.running = False
1005 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001006 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007 self.sock.setblocking(1)
1008 self.sslconn = None
1009 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001010 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001011
Antoine Pitrou480a1242010-04-28 21:37:09 +00001012 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001013 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001014 self.sslconn = self.server.context.wrap_socket(
1015 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001016 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001017 except (ssl.SSLError, ConnectionResetError) as e:
1018 # We treat ConnectionResetError as though it were an
1019 # SSLError - OpenSSL on Ubuntu abruptly closes the
1020 # connection when asked to use an unsupported protocol.
1021 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001022 # XXX Various errors can have happened here, for example
1023 # a mismatching protocol version, an invalid certificate,
1024 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001025 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001026 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001027 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001028 self.running = False
1029 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001030 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001031 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001032 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001033 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001035 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001036 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1037 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001038 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001039 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1040 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001041 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001042 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001043 sys.stdout.write(" server: selected protocol is now "
1044 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001045 return True
1046
1047 def read(self):
1048 if self.sslconn:
1049 return self.sslconn.read()
1050 else:
1051 return self.sock.recv(1024)
1052
1053 def write(self, bytes):
1054 if self.sslconn:
1055 return self.sslconn.write(bytes)
1056 else:
1057 return self.sock.send(bytes)
1058
1059 def close(self):
1060 if self.sslconn:
1061 self.sslconn.close()
1062 else:
1063 self.sock.close()
1064
Antoine Pitrou480a1242010-04-28 21:37:09 +00001065 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 self.running = True
1067 if not self.server.starttls_server:
1068 if not self.wrap_conn():
1069 return
1070 while self.running:
1071 try:
1072 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001073 stripped = msg.strip()
1074 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001075 # eof, so quit this handler
1076 self.running = False
1077 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001078 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001079 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001080 sys.stdout.write(" server: client closed connection\n")
1081 self.close()
1082 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001083 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001084 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001085 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001087 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001088 if not self.wrap_conn():
1089 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001090 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001091 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001092 if support.verbose and self.server.connectionchatty:
1093 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001094 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001095 self.sock = self.sslconn.unwrap()
1096 self.sslconn = None
1097 if support.verbose and self.server.connectionchatty:
1098 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001099 elif stripped == b'CB tls-unique':
1100 if support.verbose and self.server.connectionchatty:
1101 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1102 data = self.sslconn.get_channel_binding("tls-unique")
1103 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001104 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001105 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001106 self.server.connectionchatty):
1107 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001108 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1109 % (msg, ctype, msg.lower(), ctype))
1110 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001111 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112 if self.server.chatty:
1113 handle_error("Test server failure:\n")
1114 self.close()
1115 self.running = False
1116 # normally, we'd just stop here, but for the test
1117 # harness, we want to stop the server
1118 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001119
Antoine Pitroub5218772010-05-21 09:56:06 +00001120 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001121 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001122 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001123 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001124 if context:
1125 self.context = context
1126 else:
1127 self.context = ssl.SSLContext(ssl_version
1128 if ssl_version is not None
1129 else ssl.PROTOCOL_TLSv1)
1130 self.context.verify_mode = (certreqs if certreqs is not None
1131 else ssl.CERT_NONE)
1132 if cacerts:
1133 self.context.load_verify_locations(cacerts)
1134 if certificate:
1135 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001136 if npn_protocols:
1137 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001138 if ciphers:
1139 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140 self.chatty = chatty
1141 self.connectionchatty = connectionchatty
1142 self.starttls_server = starttls_server
1143 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001144 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001145 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001146 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001147 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001148 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001149 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001150 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001151
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001152 def __enter__(self):
1153 self.start(threading.Event())
1154 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001155 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001156
1157 def __exit__(self, *args):
1158 self.stop()
1159 self.join()
1160
Antoine Pitrou480a1242010-04-28 21:37:09 +00001161 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001162 self.flag = flag
1163 threading.Thread.start(self)
1164
Antoine Pitrou480a1242010-04-28 21:37:09 +00001165 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001166 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167 self.sock.listen(5)
1168 self.active = True
1169 if self.flag:
1170 # signal an event
1171 self.flag.set()
1172 while self.active:
1173 try:
1174 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001175 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001176 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001177 + repr(connaddr) + '\n')
1178 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001180 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001181 except socket.timeout:
1182 pass
1183 except KeyboardInterrupt:
1184 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001185 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001186
Antoine Pitrou480a1242010-04-28 21:37:09 +00001187 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001188 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001189
Bill Janssen54cc54c2007-12-14 22:08:56 +00001190 class AsyncoreEchoServer(threading.Thread):
1191
1192 # this one's based on asyncore.dispatcher
1193
1194 class EchoServer (asyncore.dispatcher):
1195
1196 class ConnectionHandler (asyncore.dispatcher_with_send):
1197
1198 def __init__(self, conn, certfile):
1199 self.socket = ssl.wrap_socket(conn, server_side=True,
1200 certfile=certfile,
1201 do_handshake_on_connect=False)
1202 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001203 self._ssl_accepting = True
1204 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001205
1206 def readable(self):
1207 if isinstance(self.socket, ssl.SSLSocket):
1208 while self.socket.pending() > 0:
1209 self.handle_read_event()
1210 return True
1211
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001212 def _do_ssl_handshake(self):
1213 try:
1214 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001215 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1216 return
1217 except ssl.SSLEOFError:
1218 return self.handle_close()
1219 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001220 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001221 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001222 if err.args[0] == errno.ECONNABORTED:
1223 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001224 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001225 self._ssl_accepting = False
1226
1227 def handle_read(self):
1228 if self._ssl_accepting:
1229 self._do_ssl_handshake()
1230 else:
1231 data = self.recv(1024)
1232 if support.verbose:
1233 sys.stdout.write(" server: read %s from client\n" % repr(data))
1234 if not data:
1235 self.close()
1236 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001237 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001238
1239 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001240 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001241 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001242 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1243
1244 def handle_error(self):
1245 raise
1246
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001247 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001248 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001249 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1250 self.port = support.bind_port(sock, '')
1251 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001252 self.listen(5)
1253
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001254 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001255 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001256 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1257 self.ConnectionHandler(sock_obj, self.certfile)
1258
1259 def handle_error(self):
1260 raise
1261
Trent Nelson78520002008-04-10 20:54:35 +00001262 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001263 self.flag = None
1264 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001265 self.server = self.EchoServer(certfile)
1266 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001267 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001268 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001269
1270 def __str__(self):
1271 return "<%s %s>" % (self.__class__.__name__, self.server)
1272
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001273 def __enter__(self):
1274 self.start(threading.Event())
1275 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001276 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001277
1278 def __exit__(self, *args):
1279 if support.verbose:
1280 sys.stdout.write(" cleanup: stopping server.\n")
1281 self.stop()
1282 if support.verbose:
1283 sys.stdout.write(" cleanup: joining server thread.\n")
1284 self.join()
1285 if support.verbose:
1286 sys.stdout.write(" cleanup: successfully joined.\n")
1287
Bill Janssen54cc54c2007-12-14 22:08:56 +00001288 def start (self, flag=None):
1289 self.flag = flag
1290 threading.Thread.start(self)
1291
Antoine Pitrou480a1242010-04-28 21:37:09 +00001292 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001293 self.active = True
1294 if self.flag:
1295 self.flag.set()
1296 while self.active:
1297 try:
1298 asyncore.loop(1)
1299 except:
1300 pass
1301
Antoine Pitrou480a1242010-04-28 21:37:09 +00001302 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001303 self.active = False
1304 self.server.close()
1305
Antoine Pitrou480a1242010-04-28 21:37:09 +00001306 def bad_cert_test(certfile):
1307 """
1308 Launch a server with CERT_REQUIRED, and check that trying to
1309 connect to it with the given client certificate fails.
1310 """
Trent Nelson78520002008-04-10 20:54:35 +00001311 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001312 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001313 cacerts=CERTFILE, chatty=False,
1314 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001315 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001316 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001317 with socket.socket() as sock:
1318 s = ssl.wrap_socket(sock,
1319 certfile=certfile,
1320 ssl_version=ssl.PROTOCOL_TLSv1)
1321 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001322 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001323 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001324 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001325 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001327 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001328 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001329 if x.errno != errno.ENOENT:
1330 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001331 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001332 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001333 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001334 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001335
Antoine Pitroub5218772010-05-21 09:56:06 +00001336 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001337 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001338 """
1339 Launch a server, connect a client to it and try various reads
1340 and writes.
1341 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001342 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001343 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001344 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001345 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001346 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001347 with client_context.wrap_socket(socket.socket(),
1348 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001349 s.connect((HOST, server.port))
1350 for arg in [indata, bytearray(indata), memoryview(indata)]:
1351 if connectionchatty:
1352 if support.verbose:
1353 sys.stdout.write(
1354 " client: sending %r...\n" % indata)
1355 s.write(arg)
1356 outdata = s.read()
1357 if connectionchatty:
1358 if support.verbose:
1359 sys.stdout.write(" client: read %r\n" % outdata)
1360 if outdata != indata.lower():
1361 raise AssertionError(
1362 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1363 % (outdata[:20], len(outdata),
1364 indata[:20].lower(), len(indata)))
1365 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001366 if connectionchatty:
1367 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001368 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001369 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001370 'compression': s.compression(),
1371 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001372 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001373 'client_npn_protocol': s.selected_npn_protocol()
1374 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001375 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001376 stats['server_npn_protocols'] = server.selected_protocols
1377 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001378
Antoine Pitroub5218772010-05-21 09:56:06 +00001379 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1380 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001381 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001382 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 certtype = {
1384 ssl.CERT_NONE: "CERT_NONE",
1385 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1386 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1387 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001388 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001390 sys.stdout.write(formatstr %
1391 (ssl.get_protocol_name(client_protocol),
1392 ssl.get_protocol_name(server_protocol),
1393 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001394 client_context = ssl.SSLContext(client_protocol)
1395 client_context.options = ssl.OP_ALL | client_options
1396 server_context = ssl.SSLContext(server_protocol)
1397 server_context.options = ssl.OP_ALL | server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001398
1399 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1400 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1401 # starting from OpenSSL 1.0.0 (see issue #8322).
1402 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1403 client_context.set_ciphers("ALL")
1404
Antoine Pitroub5218772010-05-21 09:56:06 +00001405 for ctx in (client_context, server_context):
1406 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001407 ctx.load_cert_chain(CERTFILE)
1408 ctx.load_verify_locations(CERTFILE)
1409 try:
1410 server_params_test(client_context, server_context,
1411 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001412 # Protocol mismatch can result in either an SSLError, or a
1413 # "Connection reset by peer" error.
1414 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001415 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001416 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001417 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001419 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001420 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001421 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001422 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001423 "Client protocol %s succeeded with server protocol %s!"
1424 % (ssl.get_protocol_name(client_protocol),
1425 ssl.get_protocol_name(server_protocol)))
1426
1427
Bill Janssen6e027db2007-11-15 22:23:56 +00001428 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001429
Antoine Pitrou23df4832010-08-04 17:14:06 +00001430 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001431 def test_echo(self):
1432 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001433 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001435 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001436 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1437 context = ssl.SSLContext(protocol)
1438 context.load_cert_chain(CERTFILE)
1439 server_params_test(context, context,
1440 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001441
Antoine Pitrou480a1242010-04-28 21:37:09 +00001442 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001443 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001444 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001445 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1446 context.verify_mode = ssl.CERT_REQUIRED
1447 context.load_verify_locations(CERTFILE)
1448 context.load_cert_chain(CERTFILE)
1449 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001450 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001451 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001452 s.connect((HOST, server.port))
1453 cert = s.getpeercert()
1454 self.assertTrue(cert, "Can't get peer certificate.")
1455 cipher = s.cipher()
1456 if support.verbose:
1457 sys.stdout.write(pprint.pformat(cert) + '\n')
1458 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1459 if 'subject' not in cert:
1460 self.fail("No subject field in certificate: %s." %
1461 pprint.pformat(cert))
1462 if ((('organizationName', 'Python Software Foundation'),)
1463 not in cert['subject']):
1464 self.fail(
1465 "Missing or invalid 'organizationName' field in certificate subject; "
1466 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001467 self.assertIn('notBefore', cert)
1468 self.assertIn('notAfter', cert)
1469 before = ssl.cert_time_to_seconds(cert['notBefore'])
1470 after = ssl.cert_time_to_seconds(cert['notAfter'])
1471 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001472 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001473
Antoine Pitrou480a1242010-04-28 21:37:09 +00001474 def test_empty_cert(self):
1475 """Connecting with an empty cert file"""
1476 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1477 "nullcert.pem"))
1478 def test_malformed_cert(self):
1479 """Connecting with a badly formatted certificate (syntax error)"""
1480 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1481 "badcert.pem"))
1482 def test_nonexisting_cert(self):
1483 """Connecting with a non-existing cert file"""
1484 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1485 "wrongcert.pem"))
1486 def test_malformed_key(self):
1487 """Connecting with a badly formatted key (syntax error)"""
1488 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1489 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001490
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001492 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00001493 in the client when attempting handshake.
1494 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001495 listener_ready = threading.Event()
1496 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001497
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001498 s = socket.socket()
1499 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001500
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001501 # `listener` runs in a thread. It sits in an accept() until
1502 # the main thread connects. Then it rudely closes the socket,
1503 # and sets Event `listener_gone` to let the main thread know
1504 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001505 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001506 s.listen(5)
1507 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001508 newsock, addr = s.accept()
1509 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001510 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001511 listener_gone.set()
1512
1513 def connector():
1514 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001515 with socket.socket() as c:
1516 c.connect((HOST, port))
1517 listener_gone.wait()
1518 try:
1519 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001520 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001521 pass
1522 else:
1523 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001524
1525 t = threading.Thread(target=listener)
1526 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001527 try:
1528 connector()
1529 finally:
1530 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001531
Antoine Pitrou23df4832010-08-04 17:14:06 +00001532 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001533 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1534 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001535 def test_protocol_sslv2(self):
1536 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001537 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001538 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001539 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1540 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1541 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1542 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1543 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1544 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001545 # SSLv23 client with specific SSL options
1546 if no_sslv2_implies_sslv3_hello():
1547 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1548 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1549 client_options=ssl.OP_NO_SSLv2)
1550 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1551 client_options=ssl.OP_NO_SSLv3)
1552 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1553 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001554
Antoine Pitrou23df4832010-08-04 17:14:06 +00001555 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001556 def test_protocol_sslv23(self):
1557 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001558 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001559 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001560 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1561 try:
1562 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02001563 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02001564 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1565 if support.verbose:
1566 sys.stdout.write(
1567 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1568 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001569 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1570 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1571 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001572
Antoine Pitrou480a1242010-04-28 21:37:09 +00001573 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1574 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1575 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001576
Antoine Pitrou480a1242010-04-28 21:37:09 +00001577 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1578 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1579 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001580
Antoine Pitroub5218772010-05-21 09:56:06 +00001581 # Server with specific SSL options
1582 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1583 server_options=ssl.OP_NO_SSLv3)
1584 # Will choose TLSv1
1585 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1586 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1587 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1588 server_options=ssl.OP_NO_TLSv1)
1589
1590
Antoine Pitrou23df4832010-08-04 17:14:06 +00001591 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001592 def test_protocol_sslv3(self):
1593 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001594 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001595 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001596 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1597 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1598 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001599 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1600 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001601 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1602 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001603 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001604 if no_sslv2_implies_sslv3_hello():
1605 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1606 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1607 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001608
Antoine Pitrou23df4832010-08-04 17:14:06 +00001609 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001610 def test_protocol_tlsv1(self):
1611 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001612 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001613 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001614 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1615 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1616 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001617 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1618 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001619 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001620 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1621 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001622
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001623 @skip_if_broken_ubuntu_ssl
1624 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
1625 "TLS version 1.1 not supported.")
1626 def test_protocol_tlsv1_1(self):
1627 """Connecting to a TLSv1.1 server with various client options.
1628 Testing against older TLS versions."""
1629 if support.verbose:
1630 sys.stdout.write("\n")
1631 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
1632 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1633 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
1634 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
1635 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
1636 client_options=ssl.OP_NO_TLSv1_1)
1637
1638 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
1639 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
1640 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
1641
1642
1643 @skip_if_broken_ubuntu_ssl
1644 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
1645 "TLS version 1.2 not supported.")
1646 def test_protocol_tlsv1_2(self):
1647 """Connecting to a TLSv1.2 server with various client options.
1648 Testing against older TLS versions."""
1649 if support.verbose:
1650 sys.stdout.write("\n")
1651 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
1652 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
1653 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
1654 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1655 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
1656 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
1657 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
1658 client_options=ssl.OP_NO_TLSv1_2)
1659
1660 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
1661 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
1662 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
1663 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
1664 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
1665
Antoine Pitrou480a1242010-04-28 21:37:09 +00001666 def test_starttls(self):
1667 """Switching from clear text to encrypted and back again."""
1668 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 +00001669
Trent Nelson78520002008-04-10 20:54:35 +00001670 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001671 ssl_version=ssl.PROTOCOL_TLSv1,
1672 starttls_server=True,
1673 chatty=True,
1674 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001675 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001676 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001677 s = socket.socket()
1678 s.setblocking(1)
1679 s.connect((HOST, server.port))
1680 if support.verbose:
1681 sys.stdout.write("\n")
1682 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001683 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001684 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001685 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001686 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001687 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001688 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001689 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001690 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001691 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001692 msg = outdata.strip().lower()
1693 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1694 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001695 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001696 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001697 " client: read %r from server, starting TLS...\n"
1698 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001699 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1700 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001701 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1702 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001703 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001704 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001705 " client: read %r from server, ending TLS...\n"
1706 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001707 s = conn.unwrap()
1708 wrapped = False
1709 else:
1710 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001711 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001712 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001713 if support.verbose:
1714 sys.stdout.write(" client: closing connection.\n")
1715 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001716 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001717 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001718 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001719 if wrapped:
1720 conn.close()
1721 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001722 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001723
Antoine Pitrou480a1242010-04-28 21:37:09 +00001724 def test_socketserver(self):
1725 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01001726 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001727 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001728 if support.verbose:
1729 sys.stdout.write('\n')
1730 with open(CERTFILE, 'rb') as f:
1731 d1 = f.read()
1732 d2 = ''
1733 # now fetch the same data from the HTTPS server
1734 url = 'https://%s:%d/%s' % (
1735 HOST, server.port, os.path.split(CERTFILE)[1])
1736 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001737 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001738 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001739 if dlen and (int(dlen) > 0):
1740 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001741 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001742 sys.stdout.write(
1743 " client: read %d bytes from remote server '%s'\n"
1744 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001745 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001746 f.close()
1747 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001748
Antoine Pitrou480a1242010-04-28 21:37:09 +00001749 def test_asyncore_server(self):
1750 """Check the example asyncore integration."""
1751 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001752
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001753 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001754 sys.stdout.write("\n")
1755
Antoine Pitrou480a1242010-04-28 21:37:09 +00001756 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001757 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001758 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001759 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001760 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001761 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001762 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001763 " client: sending %r...\n" % indata)
1764 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001765 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001766 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001767 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001768 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001769 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001770 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1771 % (outdata[:20], len(outdata),
1772 indata[:20].lower(), len(indata)))
1773 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001774 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001775 sys.stdout.write(" client: closing connection.\n")
1776 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001777 if support.verbose:
1778 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001779
Antoine Pitrou480a1242010-04-28 21:37:09 +00001780 def test_recv_send(self):
1781 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001782 if support.verbose:
1783 sys.stdout.write("\n")
1784
1785 server = ThreadedEchoServer(CERTFILE,
1786 certreqs=ssl.CERT_NONE,
1787 ssl_version=ssl.PROTOCOL_TLSv1,
1788 cacerts=CERTFILE,
1789 chatty=True,
1790 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001791 with server:
1792 s = ssl.wrap_socket(socket.socket(),
1793 server_side=False,
1794 certfile=CERTFILE,
1795 ca_certs=CERTFILE,
1796 cert_reqs=ssl.CERT_NONE,
1797 ssl_version=ssl.PROTOCOL_TLSv1)
1798 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001799 # helper methods for standardising recv* method signatures
1800 def _recv_into():
1801 b = bytearray(b"\0"*100)
1802 count = s.recv_into(b)
1803 return b[:count]
1804
1805 def _recvfrom_into():
1806 b = bytearray(b"\0"*100)
1807 count, addr = s.recvfrom_into(b)
1808 return b[:count]
1809
1810 # (name, method, whether to expect success, *args)
1811 send_methods = [
1812 ('send', s.send, True, []),
1813 ('sendto', s.sendto, False, ["some.address"]),
1814 ('sendall', s.sendall, True, []),
1815 ]
1816 recv_methods = [
1817 ('recv', s.recv, True, []),
1818 ('recvfrom', s.recvfrom, False, ["some.address"]),
1819 ('recv_into', _recv_into, True, []),
1820 ('recvfrom_into', _recvfrom_into, False, []),
1821 ]
1822 data_prefix = "PREFIX_"
1823
1824 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001825 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001826 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001827 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001828 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001829 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001830 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001831 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001832 "<<{outdata:r}>> ({nout:d}) received; "
1833 "expected <<{indata:r}>> ({nin:d})\n".format(
1834 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001835 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001836 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001837 )
1838 )
1839 except ValueError as e:
1840 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001841 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001842 "Failed to send with method <<{name:s}>>; "
1843 "expected to succeed.\n".format(name=meth_name)
1844 )
1845 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001846 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001847 "Method <<{name:s}>> failed with unexpected "
1848 "exception message: {exp:s}\n".format(
1849 name=meth_name, exp=e
1850 )
1851 )
1852
1853 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001854 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001855 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001856 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001857 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001858 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001859 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001860 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001861 "<<{outdata:r}>> ({nout:d}) received; "
1862 "expected <<{indata:r}>> ({nin:d})\n".format(
1863 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001864 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001865 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001866 )
1867 )
1868 except ValueError as e:
1869 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001870 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001871 "Failed to receive with method <<{name:s}>>; "
1872 "expected to succeed.\n".format(name=meth_name)
1873 )
1874 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001875 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001876 "Method <<{name:s}>> failed with unexpected "
1877 "exception message: {exp:s}\n".format(
1878 name=meth_name, exp=e
1879 )
1880 )
1881 # consume data
1882 s.read()
1883
Nick Coghlan513886a2011-08-28 00:00:27 +10001884 # Make sure sendmsg et al are disallowed to avoid
1885 # inadvertent disclosure of data and/or corruption
1886 # of the encrypted data stream
1887 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1888 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1889 self.assertRaises(NotImplementedError,
1890 s.recvmsg_into, bytearray(100))
1891
Antoine Pitrou480a1242010-04-28 21:37:09 +00001892 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001893 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001894
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001895 def test_handshake_timeout(self):
1896 # Issue #5103: SSL handshake must respect the socket timeout
1897 server = socket.socket(socket.AF_INET)
1898 host = "127.0.0.1"
1899 port = support.bind_port(server)
1900 started = threading.Event()
1901 finish = False
1902
1903 def serve():
1904 server.listen(5)
1905 started.set()
1906 conns = []
1907 while not finish:
1908 r, w, e = select.select([server], [], [], 0.1)
1909 if server in r:
1910 # Let the socket hang around rather than having
1911 # it closed by garbage collection.
1912 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001913 for sock in conns:
1914 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001915
1916 t = threading.Thread(target=serve)
1917 t.start()
1918 started.wait()
1919
1920 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001921 try:
1922 c = socket.socket(socket.AF_INET)
1923 c.settimeout(0.2)
1924 c.connect((host, port))
1925 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001926 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001927 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001928 finally:
1929 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001930 try:
1931 c = socket.socket(socket.AF_INET)
1932 c = ssl.wrap_socket(c)
1933 c.settimeout(0.2)
1934 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001935 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001936 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001937 finally:
1938 c.close()
1939 finally:
1940 finish = True
1941 t.join()
1942 server.close()
1943
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001944 def test_server_accept(self):
1945 # Issue #16357: accept() on a SSLSocket created through
1946 # SSLContext.wrap_socket().
1947 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1948 context.verify_mode = ssl.CERT_REQUIRED
1949 context.load_verify_locations(CERTFILE)
1950 context.load_cert_chain(CERTFILE)
1951 server = socket.socket(socket.AF_INET)
1952 host = "127.0.0.1"
1953 port = support.bind_port(server)
1954 server = context.wrap_socket(server, server_side=True)
1955
1956 evt = threading.Event()
1957 remote = None
1958 peer = None
1959 def serve():
1960 nonlocal remote, peer
1961 server.listen(5)
1962 # Block on the accept and wait on the connection to close.
1963 evt.set()
1964 remote, peer = server.accept()
1965 remote.recv(1)
1966
1967 t = threading.Thread(target=serve)
1968 t.start()
1969 # Client wait until server setup and perform a connect.
1970 evt.wait()
1971 client = context.wrap_socket(socket.socket())
1972 client.connect((host, port))
1973 client_addr = client.getsockname()
1974 client.close()
1975 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001976 remote.close()
1977 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001978 # Sanity checks.
1979 self.assertIsInstance(remote, ssl.SSLSocket)
1980 self.assertEqual(peer, client_addr)
1981
Antoine Pitrou242db722013-05-01 20:52:07 +02001982 def test_getpeercert_enotconn(self):
1983 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1984 with context.wrap_socket(socket.socket()) as sock:
1985 with self.assertRaises(OSError) as cm:
1986 sock.getpeercert()
1987 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
1988
1989 def test_do_handshake_enotconn(self):
1990 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1991 with context.wrap_socket(socket.socket()) as sock:
1992 with self.assertRaises(OSError) as cm:
1993 sock.do_handshake()
1994 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
1995
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001996 def test_default_ciphers(self):
1997 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1998 try:
1999 # Force a set of weak ciphers on our client context
2000 context.set_ciphers("DES")
2001 except ssl.SSLError:
2002 self.skipTest("no DES cipher available")
2003 with ThreadedEchoServer(CERTFILE,
2004 ssl_version=ssl.PROTOCOL_SSLv23,
2005 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002006 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002007 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002008 s.connect((HOST, server.port))
2009 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2010
Antoine Pitroud6494802011-07-21 01:11:30 +02002011 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2012 "'tls-unique' channel binding not available")
2013 def test_tls_unique_channel_binding(self):
2014 """Test tls-unique channel binding."""
2015 if support.verbose:
2016 sys.stdout.write("\n")
2017
2018 server = ThreadedEchoServer(CERTFILE,
2019 certreqs=ssl.CERT_NONE,
2020 ssl_version=ssl.PROTOCOL_TLSv1,
2021 cacerts=CERTFILE,
2022 chatty=True,
2023 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002024 with server:
2025 s = ssl.wrap_socket(socket.socket(),
2026 server_side=False,
2027 certfile=CERTFILE,
2028 ca_certs=CERTFILE,
2029 cert_reqs=ssl.CERT_NONE,
2030 ssl_version=ssl.PROTOCOL_TLSv1)
2031 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002032 # get the data
2033 cb_data = s.get_channel_binding("tls-unique")
2034 if support.verbose:
2035 sys.stdout.write(" got channel binding data: {0!r}\n"
2036 .format(cb_data))
2037
2038 # check if it is sane
2039 self.assertIsNotNone(cb_data)
2040 self.assertEqual(len(cb_data), 12) # True for TLSv1
2041
2042 # and compare with the peers version
2043 s.write(b"CB tls-unique\n")
2044 peer_data_repr = s.read().strip()
2045 self.assertEqual(peer_data_repr,
2046 repr(cb_data).encode("us-ascii"))
2047 s.close()
2048
2049 # now, again
2050 s = ssl.wrap_socket(socket.socket(),
2051 server_side=False,
2052 certfile=CERTFILE,
2053 ca_certs=CERTFILE,
2054 cert_reqs=ssl.CERT_NONE,
2055 ssl_version=ssl.PROTOCOL_TLSv1)
2056 s.connect((HOST, server.port))
2057 new_cb_data = s.get_channel_binding("tls-unique")
2058 if support.verbose:
2059 sys.stdout.write(" got another channel binding data: {0!r}\n"
2060 .format(new_cb_data))
2061 # is it really unique
2062 self.assertNotEqual(cb_data, new_cb_data)
2063 self.assertIsNotNone(cb_data)
2064 self.assertEqual(len(cb_data), 12) # True for TLSv1
2065 s.write(b"CB tls-unique\n")
2066 peer_data_repr = s.read().strip()
2067 self.assertEqual(peer_data_repr,
2068 repr(new_cb_data).encode("us-ascii"))
2069 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002070
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002071 def test_compression(self):
2072 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2073 context.load_cert_chain(CERTFILE)
2074 stats = server_params_test(context, context,
2075 chatty=True, connectionchatty=True)
2076 if support.verbose:
2077 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2078 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2079
2080 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2081 "ssl.OP_NO_COMPRESSION needed for this test")
2082 def test_compression_disabled(self):
2083 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2084 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002085 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002086 stats = server_params_test(context, context,
2087 chatty=True, connectionchatty=True)
2088 self.assertIs(stats['compression'], None)
2089
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002090 def test_dh_params(self):
2091 # Check we can get a connection with ephemeral Diffie-Hellman
2092 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2093 context.load_cert_chain(CERTFILE)
2094 context.load_dh_params(DHFILE)
2095 context.set_ciphers("kEDH")
2096 stats = server_params_test(context, context,
2097 chatty=True, connectionchatty=True)
2098 cipher = stats["cipher"][0]
2099 parts = cipher.split("-")
2100 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2101 self.fail("Non-DH cipher: " + cipher[0])
2102
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002103 def test_selected_npn_protocol(self):
2104 # selected_npn_protocol() is None unless NPN is used
2105 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2106 context.load_cert_chain(CERTFILE)
2107 stats = server_params_test(context, context,
2108 chatty=True, connectionchatty=True)
2109 self.assertIs(stats['client_npn_protocol'], None)
2110
2111 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2112 def test_npn_protocols(self):
2113 server_protocols = ['http/1.1', 'spdy/2']
2114 protocol_tests = [
2115 (['http/1.1', 'spdy/2'], 'http/1.1'),
2116 (['spdy/2', 'http/1.1'], 'http/1.1'),
2117 (['spdy/2', 'test'], 'spdy/2'),
2118 (['abc', 'def'], 'abc')
2119 ]
2120 for client_protocols, expected in protocol_tests:
2121 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2122 server_context.load_cert_chain(CERTFILE)
2123 server_context.set_npn_protocols(server_protocols)
2124 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2125 client_context.load_cert_chain(CERTFILE)
2126 client_context.set_npn_protocols(client_protocols)
2127 stats = server_params_test(client_context, server_context,
2128 chatty=True, connectionchatty=True)
2129
2130 msg = "failed trying %s (s) and %s (c).\n" \
2131 "was expecting %s, but got %%s from the %%s" \
2132 % (str(server_protocols), str(client_protocols),
2133 str(expected))
2134 client_result = stats['client_npn_protocol']
2135 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2136 server_result = stats['server_npn_protocols'][-1] \
2137 if len(stats['server_npn_protocols']) else 'nothing'
2138 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2139
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002140 def sni_contexts(self):
2141 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2142 server_context.load_cert_chain(SIGNED_CERTFILE)
2143 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2144 other_context.load_cert_chain(SIGNED_CERTFILE2)
2145 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2146 client_context.verify_mode = ssl.CERT_REQUIRED
2147 client_context.load_verify_locations(SIGNING_CA)
2148 return server_context, other_context, client_context
2149
2150 def check_common_name(self, stats, name):
2151 cert = stats['peercert']
2152 self.assertIn((('commonName', name),), cert['subject'])
2153
2154 @needs_sni
2155 def test_sni_callback(self):
2156 calls = []
2157 server_context, other_context, client_context = self.sni_contexts()
2158
2159 def servername_cb(ssl_sock, server_name, initial_context):
2160 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002161 if server_name is not None:
2162 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002163 server_context.set_servername_callback(servername_cb)
2164
2165 stats = server_params_test(client_context, server_context,
2166 chatty=True,
2167 sni_name='supermessage')
2168 # The hostname was fetched properly, and the certificate was
2169 # changed for the connection.
2170 self.assertEqual(calls, [("supermessage", server_context)])
2171 # CERTFILE4 was selected
2172 self.check_common_name(stats, 'fakehostname')
2173
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002174 calls = []
2175 # The callback is called with server_name=None
2176 stats = server_params_test(client_context, server_context,
2177 chatty=True,
2178 sni_name=None)
2179 self.assertEqual(calls, [(None, server_context)])
2180 self.check_common_name(stats, 'localhost')
2181
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002182 # Check disabling the callback
2183 calls = []
2184 server_context.set_servername_callback(None)
2185
2186 stats = server_params_test(client_context, server_context,
2187 chatty=True,
2188 sni_name='notfunny')
2189 # Certificate didn't change
2190 self.check_common_name(stats, 'localhost')
2191 self.assertEqual(calls, [])
2192
2193 @needs_sni
2194 def test_sni_callback_alert(self):
2195 # Returning a TLS alert is reflected to the connecting client
2196 server_context, other_context, client_context = self.sni_contexts()
2197
2198 def cb_returning_alert(ssl_sock, server_name, initial_context):
2199 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2200 server_context.set_servername_callback(cb_returning_alert)
2201
2202 with self.assertRaises(ssl.SSLError) as cm:
2203 stats = server_params_test(client_context, server_context,
2204 chatty=False,
2205 sni_name='supermessage')
2206 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2207
2208 @needs_sni
2209 def test_sni_callback_raising(self):
2210 # Raising fails the connection with a TLS handshake failure alert.
2211 server_context, other_context, client_context = self.sni_contexts()
2212
2213 def cb_raising(ssl_sock, server_name, initial_context):
2214 1/0
2215 server_context.set_servername_callback(cb_raising)
2216
2217 with self.assertRaises(ssl.SSLError) as cm, \
2218 support.captured_stderr() as stderr:
2219 stats = server_params_test(client_context, server_context,
2220 chatty=False,
2221 sni_name='supermessage')
2222 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2223 self.assertIn("ZeroDivisionError", stderr.getvalue())
2224
2225 @needs_sni
2226 def test_sni_callback_wrong_return_type(self):
2227 # Returning the wrong return type terminates the TLS connection
2228 # with an internal error alert.
2229 server_context, other_context, client_context = self.sni_contexts()
2230
2231 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2232 return "foo"
2233 server_context.set_servername_callback(cb_wrong_return_type)
2234
2235 with self.assertRaises(ssl.SSLError) as cm, \
2236 support.captured_stderr() as stderr:
2237 stats = server_params_test(client_context, server_context,
2238 chatty=False,
2239 sni_name='supermessage')
2240 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2241 self.assertIn("TypeError", stderr.getvalue())
2242
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002243
Thomas Woutersed03b412007-08-28 21:37:11 +00002244def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002245 if support.verbose:
2246 plats = {
2247 'Linux': platform.linux_distribution,
2248 'Mac': platform.mac_ver,
2249 'Windows': platform.win32_ver,
2250 }
2251 for name, func in plats.items():
2252 plat = func()
2253 if plat and plat[0]:
2254 plat = '%s %r' % (name, plat)
2255 break
2256 else:
2257 plat = repr(platform.platform())
2258 print("test_ssl: testing with %r %r" %
2259 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2260 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002261 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002262 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2263 try:
2264 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2265 except AttributeError:
2266 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002267
Antoine Pitrou152efa22010-05-16 18:19:27 +00002268 for filename in [
2269 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2270 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002271 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002272 BADCERT, BADKEY, EMPTYCERT]:
2273 if not os.path.exists(filename):
2274 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002275
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002276 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002277
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002278 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002279 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002280
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002281 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002282 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002283 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002284 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002285
Antoine Pitrou480a1242010-04-28 21:37:09 +00002286 try:
2287 support.run_unittest(*tests)
2288 finally:
2289 if _have_threads:
2290 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002291
2292if __name__ == "__main__":
2293 test_main()