blob: 9885eaebcaa7848531c969b4239b099d460db841 [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
Christian Heimes9424bb42013-06-17 15:32:57 +02009import datetime
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000010import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000011import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000012import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000013import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000014import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000015import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000016import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000017import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000018import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000019import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000020import functools
Antoine Pitrou242db722013-05-01 20:52:07 +020021from unittest import mock
Thomas Woutersed03b412007-08-28 21:37:11 +000022
Antoine Pitrou05d936d2010-10-13 11:38:36 +000023ssl = support.import_module("ssl")
24
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010025PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000026HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000027
Christian Heimesefff7062013-11-21 03:35:02 +010028def data_file(*name):
29 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000030
Antoine Pitrou81564092010-10-08 23:06:24 +000031# The custom key and certificate files used in test_ssl are generated
32# using Lib/test/make_ssl_certs.py.
33# Other certificates are simply fetched from the Internet servers they
34# are meant to authenticate.
35
Antoine Pitrou152efa22010-05-16 18:19:27 +000036CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000037BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038ONLYCERT = data_file("ssl_cert.pem")
39ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_ONLYCERT = os.fsencode(ONLYCERT)
41BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020042CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
43ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
44KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010047CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
48CAFILE_CACERT = data_file("capath", "5ed36f99.0")
49
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
Christian Heimes22587792013-11-21 23:56:13 +010051# empty CRL
52CRLFILE = data_file("revocation.crl")
53
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010054# Two keys and certs signed by the same CA (for SNI tests)
55SIGNED_CERTFILE = data_file("keycert3.pem")
56SIGNED_CERTFILE2 = data_file("keycert4.pem")
57SIGNING_CA = data_file("pycacert.pem")
58
Antoine Pitrou152efa22010-05-16 18:19:27 +000059SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
60
61EMPTYCERT = data_file("nullcert.pem")
62BADCERT = data_file("badcert.pem")
63WRONGCERT = data_file("XXXnonexisting.pem")
64BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020065NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020066NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000067
Antoine Pitrou0e576f12011-12-22 10:03:38 +010068DHFILE = data_file("dh512.pem")
69BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010071
Thomas Woutersed03b412007-08-28 21:37:11 +000072def handle_error(prefix):
73 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000074 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000075 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000076
Antoine Pitroub5218772010-05-21 09:56:06 +000077def can_clear_options():
78 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020079 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000080
81def no_sslv2_implies_sslv3_hello():
82 # 0.9.7h or higher
83 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
84
Christian Heimes2427b502013-11-23 11:24:32 +010085def have_verify_flags():
86 # 0.9.8 or higher
87 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
88
Christian Heimes9424bb42013-06-17 15:32:57 +020089def asn1time(cert_time):
90 # Some versions of OpenSSL ignore seconds, see #18207
91 # 0.9.8.i
92 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
93 fmt = "%b %d %H:%M:%S %Y GMT"
94 dt = datetime.datetime.strptime(cert_time, fmt)
95 dt = dt.replace(second=0)
96 cert_time = dt.strftime(fmt)
97 # %d adds leading zero but ASN1_TIME_print() uses leading space
98 if cert_time[4] == "0":
99 cert_time = cert_time[:4] + " " + cert_time[5:]
100
101 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000102
Antoine Pitrou23df4832010-08-04 17:14:06 +0000103# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
104def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +0200105 if hasattr(ssl, 'PROTOCOL_SSLv2'):
106 @functools.wraps(func)
107 def f(*args, **kwargs):
108 try:
109 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
110 except ssl.SSLError:
111 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
112 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
113 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
114 return func(*args, **kwargs)
115 return f
116 else:
117 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +0000118
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100119needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
120
Antoine Pitrou23df4832010-08-04 17:14:06 +0000121
Antoine Pitrou152efa22010-05-16 18:19:27 +0000122class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000123
Antoine Pitrou480a1242010-04-28 21:37:09 +0000124 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000125 ssl.CERT_NONE
126 ssl.CERT_OPTIONAL
127 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100128 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100129 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100130 if ssl.HAS_ECDH:
131 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100132 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
133 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000134 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100135 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000136
Antoine Pitrou480a1242010-04-28 21:37:09 +0000137 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000139 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000140 sys.stdout.write("\n RAND_status is %d (%s)\n"
141 % (v, (v and "sufficient randomness") or
142 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200143
144 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
145 self.assertEqual(len(data), 16)
146 self.assertEqual(is_cryptographic, v == 1)
147 if v:
148 data = ssl.RAND_bytes(16)
149 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200150 else:
151 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200152
Victor Stinner1e81a392013-12-19 16:47:04 +0100153 # negative num is invalid
154 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
155 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
156
Jesus Ceac8754a12012-09-11 02:00:58 +0200157 self.assertRaises(TypeError, ssl.RAND_egd, 1)
158 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000159 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000160
Christian Heimesf77b4b22013-08-21 13:26:05 +0200161 @unittest.skipUnless(os.name == 'posix', 'requires posix')
162 def test_random_fork(self):
163 status = ssl.RAND_status()
164 if not status:
165 self.fail("OpenSSL's PRNG has insufficient randomness")
166
167 rfd, wfd = os.pipe()
168 pid = os.fork()
169 if pid == 0:
170 try:
171 os.close(rfd)
172 child_random = ssl.RAND_pseudo_bytes(16)[0]
173 self.assertEqual(len(child_random), 16)
174 os.write(wfd, child_random)
175 os.close(wfd)
176 except BaseException:
177 os._exit(1)
178 else:
179 os._exit(0)
180 else:
181 os.close(wfd)
182 self.addCleanup(os.close, rfd)
183 _, status = os.waitpid(pid, 0)
184 self.assertEqual(status, 0)
185
186 child_random = os.read(rfd, 16)
187 self.assertEqual(len(child_random), 16)
188 parent_random = ssl.RAND_pseudo_bytes(16)[0]
189 self.assertEqual(len(parent_random), 16)
190
191 self.assertNotEqual(child_random, parent_random)
192
Antoine Pitrou480a1242010-04-28 21:37:09 +0000193 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000194 # note that this uses an 'unofficial' function in _ssl.c,
195 # provided solely for this test, to exercise the certificate
196 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000197 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000198 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000199 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200200 self.assertEqual(p['issuer'],
201 ((('countryName', 'XY'),),
202 (('localityName', 'Castle Anthrax'),),
203 (('organizationName', 'Python Software Foundation'),),
204 (('commonName', 'localhost'),))
205 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100206 # Note the next three asserts will fail if the keys are regenerated
Christian Heimes9424bb42013-06-17 15:32:57 +0200207 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
208 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200209 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
210 self.assertEqual(p['subject'],
211 ((('countryName', 'XY'),),
212 (('localityName', 'Castle Anthrax'),),
213 (('organizationName', 'Python Software Foundation'),),
214 (('commonName', 'localhost'),))
215 )
216 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
217 # Issue #13034: the subjectAltName in some certificates
218 # (notably projects.developer.nokia.com:443) wasn't parsed
219 p = ssl._ssl._test_decode_cert(NOKIACERT)
220 if support.verbose:
221 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
222 self.assertEqual(p['subjectAltName'],
223 (('DNS', 'projects.developer.nokia.com'),
224 ('DNS', 'projects.forum.nokia.com'))
225 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100226 # extra OCSP and AIA fields
227 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
228 self.assertEqual(p['caIssuers'],
229 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
230 self.assertEqual(p['crlDistributionPoints'],
231 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000232
Christian Heimes824f7f32013-08-17 00:54:47 +0200233 def test_parse_cert_CVE_2013_4238(self):
234 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
235 if support.verbose:
236 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
237 subject = ((('countryName', 'US'),),
238 (('stateOrProvinceName', 'Oregon'),),
239 (('localityName', 'Beaverton'),),
240 (('organizationName', 'Python Software Foundation'),),
241 (('organizationalUnitName', 'Python Core Development'),),
242 (('commonName', 'null.python.org\x00example.org'),),
243 (('emailAddress', 'python-dev@python.org'),))
244 self.assertEqual(p['subject'], subject)
245 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200246 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
247 san = (('DNS', 'altnull.python.org\x00example.com'),
248 ('email', 'null@python.org\x00user@example.org'),
249 ('URI', 'http://null.python.org\x00http://example.org'),
250 ('IP Address', '192.0.2.1'),
251 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
252 else:
253 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
254 san = (('DNS', 'altnull.python.org\x00example.com'),
255 ('email', 'null@python.org\x00user@example.org'),
256 ('URI', 'http://null.python.org\x00http://example.org'),
257 ('IP Address', '192.0.2.1'),
258 ('IP Address', '<invalid>'))
259
260 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200261
Antoine Pitrou480a1242010-04-28 21:37:09 +0000262 def test_DER_to_PEM(self):
263 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
264 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000265 d1 = ssl.PEM_cert_to_DER_cert(pem)
266 p2 = ssl.DER_cert_to_PEM_cert(d1)
267 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000268 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000269 if not p2.startswith(ssl.PEM_HEADER + '\n'):
270 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
271 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
272 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000273
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000274 def test_openssl_version(self):
275 n = ssl.OPENSSL_VERSION_NUMBER
276 t = ssl.OPENSSL_VERSION_INFO
277 s = ssl.OPENSSL_VERSION
278 self.assertIsInstance(n, int)
279 self.assertIsInstance(t, tuple)
280 self.assertIsInstance(s, str)
281 # Some sanity checks follow
282 # >= 0.9
283 self.assertGreaterEqual(n, 0x900000)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400284 # < 3.0
285 self.assertLess(n, 0x30000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000286 major, minor, fix, patch, status = t
287 self.assertGreaterEqual(major, 0)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400288 self.assertLess(major, 3)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000289 self.assertGreaterEqual(minor, 0)
290 self.assertLess(minor, 256)
291 self.assertGreaterEqual(fix, 0)
292 self.assertLess(fix, 256)
293 self.assertGreaterEqual(patch, 0)
294 self.assertLessEqual(patch, 26)
295 self.assertGreaterEqual(status, 0)
296 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400297 # Version string as returned by {Open,Libre}SSL, the format might change
298 if "LibreSSL" in s:
299 self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
300 (s, t))
301 else:
302 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
303 (s, t))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000304
Antoine Pitrou9d543662010-04-23 23:10:32 +0000305 @support.cpython_only
306 def test_refcycle(self):
307 # Issue #7943: an SSL object doesn't create reference cycles with
308 # itself.
309 s = socket.socket(socket.AF_INET)
310 ss = ssl.wrap_socket(s)
311 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100312 with support.check_warnings(("", ResourceWarning)):
313 del ss
314 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000315
Antoine Pitroua468adc2010-09-14 14:43:44 +0000316 def test_wrapped_unconnected(self):
317 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200318 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000319 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100320 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100321 self.assertRaises(OSError, ss.recv, 1)
322 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
323 self.assertRaises(OSError, ss.recvfrom, 1)
324 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
325 self.assertRaises(OSError, ss.send, b'x')
326 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000327
Antoine Pitrou40f08742010-04-24 22:04:40 +0000328 def test_timeout(self):
329 # Issue #8524: when creating an SSL socket, the timeout of the
330 # original socket should be retained.
331 for timeout in (None, 0.0, 5.0):
332 s = socket.socket(socket.AF_INET)
333 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100334 with ssl.wrap_socket(s) as ss:
335 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000336
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000337 def test_errors(self):
338 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000339 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000340 "certfile must be specified",
341 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000342 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000343 "certfile must be specified for server-side operations",
344 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000345 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000346 "certfile must be specified for server-side operations",
347 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100348 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
349 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
350 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200351 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000352 with socket.socket() as sock:
353 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000354 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200355 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000356 with socket.socket() as sock:
357 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000358 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200359 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000360 with socket.socket() as sock:
361 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000362 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000363
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000364 def test_match_hostname(self):
365 def ok(cert, hostname):
366 ssl.match_hostname(cert, hostname)
367 def fail(cert, hostname):
368 self.assertRaises(ssl.CertificateError,
369 ssl.match_hostname, cert, hostname)
370
371 cert = {'subject': ((('commonName', 'example.com'),),)}
372 ok(cert, 'example.com')
373 ok(cert, 'ExAmple.cOm')
374 fail(cert, 'www.example.com')
375 fail(cert, '.example.com')
376 fail(cert, 'example.org')
377 fail(cert, 'exampleXcom')
378
379 cert = {'subject': ((('commonName', '*.a.com'),),)}
380 ok(cert, 'foo.a.com')
381 fail(cert, 'bar.foo.a.com')
382 fail(cert, 'a.com')
383 fail(cert, 'Xa.com')
384 fail(cert, '.a.com')
385
Georg Brandl72c98d32013-10-27 07:16:53 +0100386 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000387 cert = {'subject': ((('commonName', 'f*.com'),),)}
388 ok(cert, 'foo.com')
389 ok(cert, 'f.com')
390 fail(cert, 'bar.com')
391 fail(cert, 'foo.a.com')
392 fail(cert, 'bar.foo.com')
393
Christian Heimes824f7f32013-08-17 00:54:47 +0200394 # NULL bytes are bad, CVE-2013-4073
395 cert = {'subject': ((('commonName',
396 'null.python.org\x00example.org'),),)}
397 ok(cert, 'null.python.org\x00example.org') # or raise an error?
398 fail(cert, 'example.org')
399 fail(cert, 'null.python.org')
400
Georg Brandl72c98d32013-10-27 07:16:53 +0100401 # error cases with wildcards
402 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
403 fail(cert, 'bar.foo.a.com')
404 fail(cert, 'a.com')
405 fail(cert, 'Xa.com')
406 fail(cert, '.a.com')
407
408 cert = {'subject': ((('commonName', 'a.*.com'),),)}
409 fail(cert, 'a.foo.com')
410 fail(cert, 'a..com')
411 fail(cert, 'a.com')
412
413 # wildcard doesn't match IDNA prefix 'xn--'
414 idna = 'püthon.python.org'.encode("idna").decode("ascii")
415 cert = {'subject': ((('commonName', idna),),)}
416 ok(cert, idna)
417 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
418 fail(cert, idna)
419 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
420 fail(cert, idna)
421
422 # wildcard in first fragment and IDNA A-labels in sequent fragments
423 # are supported.
424 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
425 cert = {'subject': ((('commonName', idna),),)}
426 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
427 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
428 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
429 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
430
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000431 # Slightly fake real-world example
432 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
433 'subject': ((('commonName', 'linuxfrz.org'),),),
434 'subjectAltName': (('DNS', 'linuxfr.org'),
435 ('DNS', 'linuxfr.com'),
436 ('othername', '<unsupported>'))}
437 ok(cert, 'linuxfr.org')
438 ok(cert, 'linuxfr.com')
439 # Not a "DNS" entry
440 fail(cert, '<unsupported>')
441 # When there is a subjectAltName, commonName isn't used
442 fail(cert, 'linuxfrz.org')
443
444 # A pristine real-world example
445 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
446 'subject': ((('countryName', 'US'),),
447 (('stateOrProvinceName', 'California'),),
448 (('localityName', 'Mountain View'),),
449 (('organizationName', 'Google Inc'),),
450 (('commonName', 'mail.google.com'),))}
451 ok(cert, 'mail.google.com')
452 fail(cert, 'gmail.com')
453 # Only commonName is considered
454 fail(cert, 'California')
455
456 # Neither commonName nor subjectAltName
457 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
458 'subject': ((('countryName', 'US'),),
459 (('stateOrProvinceName', 'California'),),
460 (('localityName', 'Mountain View'),),
461 (('organizationName', 'Google Inc'),))}
462 fail(cert, 'mail.google.com')
463
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200464 # No DNS entry in subjectAltName but a commonName
465 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
466 'subject': ((('countryName', 'US'),),
467 (('stateOrProvinceName', 'California'),),
468 (('localityName', 'Mountain View'),),
469 (('commonName', 'mail.google.com'),)),
470 'subjectAltName': (('othername', 'blabla'), )}
471 ok(cert, 'mail.google.com')
472
473 # No DNS entry subjectAltName and no commonName
474 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
475 'subject': ((('countryName', 'US'),),
476 (('stateOrProvinceName', 'California'),),
477 (('localityName', 'Mountain View'),),
478 (('organizationName', 'Google Inc'),)),
479 'subjectAltName': (('othername', 'blabla'),)}
480 fail(cert, 'google.com')
481
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000482 # Empty cert / no cert
483 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
484 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
485
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200486 # Issue #17980: avoid denials of service by refusing more than one
487 # wildcard per fragment.
488 cert = {'subject': ((('commonName', 'a*b.com'),),)}
489 ok(cert, 'axxb.com')
490 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100491 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200492 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
493 with self.assertRaises(ssl.CertificateError) as cm:
494 ssl.match_hostname(cert, 'axxbxxc.com')
495 self.assertIn("too many wildcards", str(cm.exception))
496
Antoine Pitroud5323212010-10-22 18:19:07 +0000497 def test_server_side(self):
498 # server_hostname doesn't work for server sockets
499 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000500 with socket.socket() as sock:
501 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
502 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000503
Antoine Pitroud6494802011-07-21 01:11:30 +0200504 def test_unknown_channel_binding(self):
505 # should raise ValueError for unknown type
506 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100507 with ssl.wrap_socket(s) as ss:
508 with self.assertRaises(ValueError):
509 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200510
511 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
512 "'tls-unique' channel binding not available")
513 def test_tls_unique_channel_binding(self):
514 # unconnected should return None for known type
515 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100516 with ssl.wrap_socket(s) as ss:
517 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200518 # the same for server-side
519 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100520 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
521 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200522
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600523 def test_dealloc_warn(self):
524 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
525 r = repr(ss)
526 with self.assertWarns(ResourceWarning) as cm:
527 ss = None
528 support.gc_collect()
529 self.assertIn(r, str(cm.warning.args[0]))
530
Christian Heimes6d7ad132013-06-09 18:02:55 +0200531 def test_get_default_verify_paths(self):
532 paths = ssl.get_default_verify_paths()
533 self.assertEqual(len(paths), 6)
534 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
535
536 with support.EnvironmentVarGuard() as env:
537 env["SSL_CERT_DIR"] = CAPATH
538 env["SSL_CERT_FILE"] = CERTFILE
539 paths = ssl.get_default_verify_paths()
540 self.assertEqual(paths.cafile, CERTFILE)
541 self.assertEqual(paths.capath, CAPATH)
542
Christian Heimes44109d72013-11-22 01:51:30 +0100543 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
544 def test_enum_certificates(self):
545 self.assertTrue(ssl.enum_certificates("CA"))
546 self.assertTrue(ssl.enum_certificates("ROOT"))
547
548 self.assertRaises(TypeError, ssl.enum_certificates)
549 self.assertRaises(WindowsError, ssl.enum_certificates, "")
550
Christian Heimesc2d65e12013-11-22 16:13:55 +0100551 trust_oids = set()
552 for storename in ("CA", "ROOT"):
553 store = ssl.enum_certificates(storename)
554 self.assertIsInstance(store, list)
555 for element in store:
556 self.assertIsInstance(element, tuple)
557 self.assertEqual(len(element), 3)
558 cert, enc, trust = element
559 self.assertIsInstance(cert, bytes)
560 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
561 self.assertIsInstance(trust, (set, bool))
562 if isinstance(trust, set):
563 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100564
565 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100566 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200567
Christian Heimes46bebee2013-06-09 19:03:31 +0200568 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100569 def test_enum_crls(self):
570 self.assertTrue(ssl.enum_crls("CA"))
571 self.assertRaises(TypeError, ssl.enum_crls)
572 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200573
Christian Heimes44109d72013-11-22 01:51:30 +0100574 crls = ssl.enum_crls("CA")
575 self.assertIsInstance(crls, list)
576 for element in crls:
577 self.assertIsInstance(element, tuple)
578 self.assertEqual(len(element), 2)
579 self.assertIsInstance(element[0], bytes)
580 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200581
Christian Heimes46bebee2013-06-09 19:03:31 +0200582
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100583 def test_asn1object(self):
584 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
585 '1.3.6.1.5.5.7.3.1')
586
587 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
588 self.assertEqual(val, expected)
589 self.assertEqual(val.nid, 129)
590 self.assertEqual(val.shortname, 'serverAuth')
591 self.assertEqual(val.longname, 'TLS Web Server Authentication')
592 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
593 self.assertIsInstance(val, ssl._ASN1Object)
594 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
595
596 val = ssl._ASN1Object.fromnid(129)
597 self.assertEqual(val, expected)
598 self.assertIsInstance(val, ssl._ASN1Object)
599 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100600 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
601 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100602 for i in range(1000):
603 try:
604 obj = ssl._ASN1Object.fromnid(i)
605 except ValueError:
606 pass
607 else:
608 self.assertIsInstance(obj.nid, int)
609 self.assertIsInstance(obj.shortname, str)
610 self.assertIsInstance(obj.longname, str)
611 self.assertIsInstance(obj.oid, (str, type(None)))
612
613 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
614 self.assertEqual(val, expected)
615 self.assertIsInstance(val, ssl._ASN1Object)
616 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
617 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
618 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100619 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
620 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100621
Christian Heimes72d28502013-11-23 13:56:58 +0100622 def test_purpose_enum(self):
623 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
624 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
625 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
626 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
627 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
628 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
629 '1.3.6.1.5.5.7.3.1')
630
631 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
632 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
633 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
634 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
635 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
636 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
637 '1.3.6.1.5.5.7.3.2')
638
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100639 def test_unsupported_dtls(self):
640 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
641 self.addCleanup(s.close)
642 with self.assertRaises(NotImplementedError) as cx:
643 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
644 self.assertEqual(str(cx.exception), "only stream sockets are supported")
645 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
646 with self.assertRaises(NotImplementedError) as cx:
647 ctx.wrap_socket(s)
648 self.assertEqual(str(cx.exception), "only stream sockets are supported")
649
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100650
Antoine Pitrou152efa22010-05-16 18:19:27 +0000651class ContextTests(unittest.TestCase):
652
Antoine Pitrou23df4832010-08-04 17:14:06 +0000653 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000654 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100655 for protocol in PROTOCOLS:
656 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000657 self.assertRaises(TypeError, ssl.SSLContext)
658 self.assertRaises(ValueError, ssl.SSLContext, -1)
659 self.assertRaises(ValueError, ssl.SSLContext, 42)
660
Antoine Pitrou23df4832010-08-04 17:14:06 +0000661 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000662 def test_protocol(self):
663 for proto in PROTOCOLS:
664 ctx = ssl.SSLContext(proto)
665 self.assertEqual(ctx.protocol, proto)
666
667 def test_ciphers(self):
668 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
669 ctx.set_ciphers("ALL")
670 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000671 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000672 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000673
Antoine Pitrou23df4832010-08-04 17:14:06 +0000674 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000675 def test_options(self):
676 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +0100677 # OP_ALL | OP_NO_SSLv2 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000678 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
679 ctx.options)
680 ctx.options |= ssl.OP_NO_SSLv3
681 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
682 ctx.options)
683 if can_clear_options():
684 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
685 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
686 ctx.options)
687 ctx.options = 0
688 self.assertEqual(0, ctx.options)
689 else:
690 with self.assertRaises(ValueError):
691 ctx.options = 0
692
Christian Heimes22587792013-11-21 23:56:13 +0100693 def test_verify_mode(self):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000694 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
695 # Default value
696 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
697 ctx.verify_mode = ssl.CERT_OPTIONAL
698 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
699 ctx.verify_mode = ssl.CERT_REQUIRED
700 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
701 ctx.verify_mode = ssl.CERT_NONE
702 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
703 with self.assertRaises(TypeError):
704 ctx.verify_mode = None
705 with self.assertRaises(ValueError):
706 ctx.verify_mode = 42
707
Christian Heimes2427b502013-11-23 11:24:32 +0100708 @unittest.skipUnless(have_verify_flags(),
709 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +0100710 def test_verify_flags(self):
711 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
712 # default value by OpenSSL
713 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
714 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
715 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
716 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
717 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
718 ctx.verify_flags = ssl.VERIFY_DEFAULT
719 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
720 # supports any value
721 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
722 self.assertEqual(ctx.verify_flags,
723 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
724 with self.assertRaises(TypeError):
725 ctx.verify_flags = None
726
Antoine Pitrou152efa22010-05-16 18:19:27 +0000727 def test_load_cert_chain(self):
728 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
729 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -0500730 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000731 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
732 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200733 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000734 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000735 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000736 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000737 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000738 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000739 ctx.load_cert_chain(EMPTYCERT)
740 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000741 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000742 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
743 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
744 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000745 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000746 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000747 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000748 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000749 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000750 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
751 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000752 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000753 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000754 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200755 # Password protected key and cert
756 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
757 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
758 ctx.load_cert_chain(CERTFILE_PROTECTED,
759 password=bytearray(KEY_PASSWORD.encode()))
760 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
761 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
762 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
763 bytearray(KEY_PASSWORD.encode()))
764 with self.assertRaisesRegex(TypeError, "should be a string"):
765 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
766 with self.assertRaises(ssl.SSLError):
767 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
768 with self.assertRaisesRegex(ValueError, "cannot be longer"):
769 # openssl has a fixed limit on the password buffer.
770 # PEM_BUFSIZE is generally set to 1kb.
771 # Return a string larger than this.
772 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
773 # Password callback
774 def getpass_unicode():
775 return KEY_PASSWORD
776 def getpass_bytes():
777 return KEY_PASSWORD.encode()
778 def getpass_bytearray():
779 return bytearray(KEY_PASSWORD.encode())
780 def getpass_badpass():
781 return "badpass"
782 def getpass_huge():
783 return b'a' * (1024 * 1024)
784 def getpass_bad_type():
785 return 9
786 def getpass_exception():
787 raise Exception('getpass error')
788 class GetPassCallable:
789 def __call__(self):
790 return KEY_PASSWORD
791 def getpass(self):
792 return KEY_PASSWORD
793 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
794 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
795 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
796 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
797 ctx.load_cert_chain(CERTFILE_PROTECTED,
798 password=GetPassCallable().getpass)
799 with self.assertRaises(ssl.SSLError):
800 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
801 with self.assertRaisesRegex(ValueError, "cannot be longer"):
802 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
803 with self.assertRaisesRegex(TypeError, "must return a string"):
804 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
805 with self.assertRaisesRegex(Exception, "getpass error"):
806 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
807 # Make sure the password function isn't called if it isn't needed
808 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000809
810 def test_load_verify_locations(self):
811 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
812 ctx.load_verify_locations(CERTFILE)
813 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
814 ctx.load_verify_locations(BYTES_CERTFILE)
815 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
816 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +0100817 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200818 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000819 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000820 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000821 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000822 ctx.load_verify_locations(BADCERT)
823 ctx.load_verify_locations(CERTFILE, CAPATH)
824 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
825
Victor Stinner80f75e62011-01-29 11:31:20 +0000826 # Issue #10989: crash if the second argument type is invalid
827 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
828
Christian Heimesefff7062013-11-21 03:35:02 +0100829 def test_load_verify_cadata(self):
830 # test cadata
831 with open(CAFILE_CACERT) as f:
832 cacert_pem = f.read()
833 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
834 with open(CAFILE_NEURONIO) as f:
835 neuronio_pem = f.read()
836 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
837
838 # test PEM
839 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
840 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
841 ctx.load_verify_locations(cadata=cacert_pem)
842 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
843 ctx.load_verify_locations(cadata=neuronio_pem)
844 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
845 # cert already in hash table
846 ctx.load_verify_locations(cadata=neuronio_pem)
847 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
848
849 # combined
850 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
851 combined = "\n".join((cacert_pem, neuronio_pem))
852 ctx.load_verify_locations(cadata=combined)
853 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
854
855 # with junk around the certs
856 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
857 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
858 neuronio_pem, "tail"]
859 ctx.load_verify_locations(cadata="\n".join(combined))
860 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
861
862 # test DER
863 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
864 ctx.load_verify_locations(cadata=cacert_der)
865 ctx.load_verify_locations(cadata=neuronio_der)
866 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
867 # cert already in hash table
868 ctx.load_verify_locations(cadata=cacert_der)
869 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
870
871 # combined
872 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
873 combined = b"".join((cacert_der, neuronio_der))
874 ctx.load_verify_locations(cadata=combined)
875 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
876
877 # error cases
878 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
879 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
880
881 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
882 ctx.load_verify_locations(cadata="broken")
883 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
884 ctx.load_verify_locations(cadata=b"broken")
885
886
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100887 def test_load_dh_params(self):
888 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
889 ctx.load_dh_params(DHFILE)
890 if os.name != 'nt':
891 ctx.load_dh_params(BYTES_DHFILE)
892 self.assertRaises(TypeError, ctx.load_dh_params)
893 self.assertRaises(TypeError, ctx.load_dh_params, None)
894 with self.assertRaises(FileNotFoundError) as cm:
895 ctx.load_dh_params(WRONGCERT)
896 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200897 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100898 ctx.load_dh_params(CERTFILE)
899
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000900 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000901 def test_session_stats(self):
902 for proto in PROTOCOLS:
903 ctx = ssl.SSLContext(proto)
904 self.assertEqual(ctx.session_stats(), {
905 'number': 0,
906 'connect': 0,
907 'connect_good': 0,
908 'connect_renegotiate': 0,
909 'accept': 0,
910 'accept_good': 0,
911 'accept_renegotiate': 0,
912 'hits': 0,
913 'misses': 0,
914 'timeouts': 0,
915 'cache_full': 0,
916 })
917
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000918 def test_set_default_verify_paths(self):
919 # There's not much we can do to test that it acts as expected,
920 # so just check it doesn't crash or raise an exception.
921 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
922 ctx.set_default_verify_paths()
923
Antoine Pitrou501da612011-12-21 09:27:41 +0100924 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100925 def test_set_ecdh_curve(self):
926 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
927 ctx.set_ecdh_curve("prime256v1")
928 ctx.set_ecdh_curve(b"prime256v1")
929 self.assertRaises(TypeError, ctx.set_ecdh_curve)
930 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
931 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
932 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
933
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100934 @needs_sni
935 def test_sni_callback(self):
936 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
937
938 # set_servername_callback expects a callable, or None
939 self.assertRaises(TypeError, ctx.set_servername_callback)
940 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
941 self.assertRaises(TypeError, ctx.set_servername_callback, "")
942 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
943
944 def dummycallback(sock, servername, ctx):
945 pass
946 ctx.set_servername_callback(None)
947 ctx.set_servername_callback(dummycallback)
948
949 @needs_sni
950 def test_sni_callback_refcycle(self):
951 # Reference cycles through the servername callback are detected
952 # and cleared.
953 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
954 def dummycallback(sock, servername, ctx, cycle=ctx):
955 pass
956 ctx.set_servername_callback(dummycallback)
957 wr = weakref.ref(ctx)
958 del ctx, dummycallback
959 gc.collect()
960 self.assertIs(wr(), None)
961
Christian Heimes9a5395a2013-06-17 15:44:12 +0200962 def test_cert_store_stats(self):
963 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
964 self.assertEqual(ctx.cert_store_stats(),
965 {'x509_ca': 0, 'crl': 0, 'x509': 0})
966 ctx.load_cert_chain(CERTFILE)
967 self.assertEqual(ctx.cert_store_stats(),
968 {'x509_ca': 0, 'crl': 0, 'x509': 0})
969 ctx.load_verify_locations(CERTFILE)
970 self.assertEqual(ctx.cert_store_stats(),
971 {'x509_ca': 0, 'crl': 0, 'x509': 1})
972 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
973 self.assertEqual(ctx.cert_store_stats(),
974 {'x509_ca': 1, 'crl': 0, 'x509': 2})
975
976 def test_get_ca_certs(self):
977 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
978 self.assertEqual(ctx.get_ca_certs(), [])
979 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
980 ctx.load_verify_locations(CERTFILE)
981 self.assertEqual(ctx.get_ca_certs(), [])
982 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
983 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
984 self.assertEqual(ctx.get_ca_certs(),
985 [{'issuer': ((('organizationName', 'Root CA'),),
986 (('organizationalUnitName', 'http://www.cacert.org'),),
987 (('commonName', 'CA Cert Signing Authority'),),
988 (('emailAddress', 'support@cacert.org'),)),
989 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
990 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
991 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100992 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +0200993 'subject': ((('organizationName', 'Root CA'),),
994 (('organizationalUnitName', 'http://www.cacert.org'),),
995 (('commonName', 'CA Cert Signing Authority'),),
996 (('emailAddress', 'support@cacert.org'),)),
997 'version': 3}])
998
999 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
1000 pem = f.read()
1001 der = ssl.PEM_cert_to_DER_cert(pem)
1002 self.assertEqual(ctx.get_ca_certs(True), [der])
1003
Christian Heimes72d28502013-11-23 13:56:58 +01001004 def test_load_default_certs(self):
1005 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1006 ctx.load_default_certs()
1007
1008 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1009 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1010 ctx.load_default_certs()
1011
1012 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1013 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1014
1015 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1016 self.assertRaises(TypeError, ctx.load_default_certs, None)
1017 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1018
Benjamin Peterson91244e02014-10-03 18:17:15 -04001019 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001020 def test_load_default_certs_env(self):
1021 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1022 with support.EnvironmentVarGuard() as env:
1023 env["SSL_CERT_DIR"] = CAPATH
1024 env["SSL_CERT_FILE"] = CERTFILE
1025 ctx.load_default_certs()
1026 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1027
Benjamin Peterson91244e02014-10-03 18:17:15 -04001028 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1029 def test_load_default_certs_env_windows(self):
1030 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1031 ctx.load_default_certs()
1032 stats = ctx.cert_store_stats()
1033
1034 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1035 with support.EnvironmentVarGuard() as env:
1036 env["SSL_CERT_DIR"] = CAPATH
1037 env["SSL_CERT_FILE"] = CERTFILE
1038 ctx.load_default_certs()
1039 stats["x509"] += 1
1040 self.assertEqual(ctx.cert_store_stats(), stats)
1041
Christian Heimes4c05b472013-11-23 15:58:30 +01001042 def test_create_default_context(self):
1043 ctx = ssl.create_default_context()
Donald Stufft6a2ba942014-03-23 19:05:28 -04001044 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001045 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001046 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001047 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001048 self.assertEqual(
1049 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1050 getattr(ssl, "OP_NO_COMPRESSION", 0),
1051 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001052
1053 with open(SIGNING_CA) as f:
1054 cadata = f.read()
1055 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1056 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001057 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001058 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1059 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001060 self.assertEqual(
1061 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1062 getattr(ssl, "OP_NO_COMPRESSION", 0),
1063 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001064
1065 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001066 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001067 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1068 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001069 self.assertEqual(
1070 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1071 getattr(ssl, "OP_NO_COMPRESSION", 0),
1072 )
1073 self.assertEqual(
1074 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1075 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1076 )
1077 self.assertEqual(
1078 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1079 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1080 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001081
Christian Heimes67986f92013-11-23 22:43:47 +01001082 def test__create_stdlib_context(self):
1083 ctx = ssl._create_stdlib_context()
1084 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1085 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001086 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001087 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1088
1089 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1090 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1091 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1092 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1093
1094 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001095 cert_reqs=ssl.CERT_REQUIRED,
1096 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001097 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1098 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001099 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001100 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1101
1102 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1103 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1104 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1105 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001106
Christian Heimes1aa9a752013-12-02 02:41:19 +01001107 def test_check_hostname(self):
1108 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1109 self.assertFalse(ctx.check_hostname)
1110
1111 # Requires CERT_REQUIRED or CERT_OPTIONAL
1112 with self.assertRaises(ValueError):
1113 ctx.check_hostname = True
1114 ctx.verify_mode = ssl.CERT_REQUIRED
1115 self.assertFalse(ctx.check_hostname)
1116 ctx.check_hostname = True
1117 self.assertTrue(ctx.check_hostname)
1118
1119 ctx.verify_mode = ssl.CERT_OPTIONAL
1120 ctx.check_hostname = True
1121 self.assertTrue(ctx.check_hostname)
1122
1123 # Cannot set CERT_NONE with check_hostname enabled
1124 with self.assertRaises(ValueError):
1125 ctx.verify_mode = ssl.CERT_NONE
1126 ctx.check_hostname = False
1127 self.assertFalse(ctx.check_hostname)
1128
Antoine Pitrou152efa22010-05-16 18:19:27 +00001129
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001130class SSLErrorTests(unittest.TestCase):
1131
1132 def test_str(self):
1133 # The str() of a SSLError doesn't include the errno
1134 e = ssl.SSLError(1, "foo")
1135 self.assertEqual(str(e), "foo")
1136 self.assertEqual(e.errno, 1)
1137 # Same for a subclass
1138 e = ssl.SSLZeroReturnError(1, "foo")
1139 self.assertEqual(str(e), "foo")
1140 self.assertEqual(e.errno, 1)
1141
1142 def test_lib_reason(self):
1143 # Test the library and reason attributes
1144 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1145 with self.assertRaises(ssl.SSLError) as cm:
1146 ctx.load_dh_params(CERTFILE)
1147 self.assertEqual(cm.exception.library, 'PEM')
1148 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1149 s = str(cm.exception)
1150 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1151
1152 def test_subclass(self):
1153 # Check that the appropriate SSLError subclass is raised
1154 # (this only tests one of them)
1155 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1156 with socket.socket() as s:
1157 s.bind(("127.0.0.1", 0))
1158 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001159 c = socket.socket()
1160 c.connect(s.getsockname())
1161 c.setblocking(False)
1162 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001163 with self.assertRaises(ssl.SSLWantReadError) as cm:
1164 c.do_handshake()
1165 s = str(cm.exception)
1166 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1167 # For compatibility
1168 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1169
1170
Bill Janssen6e027db2007-11-15 22:23:56 +00001171class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001172
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001174 with support.transient_internet("svn.python.org"):
1175 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1176 cert_reqs=ssl.CERT_NONE)
1177 try:
1178 s.connect(("svn.python.org", 443))
1179 self.assertEqual({}, s.getpeercert())
1180 finally:
1181 s.close()
1182
1183 # this should fail because we have no verification certs
1184 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1185 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001186 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1187 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001188 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001189
Antoine Pitrou350c7222010-09-09 13:31:46 +00001190 # this should succeed because we specify the root cert
1191 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1192 cert_reqs=ssl.CERT_REQUIRED,
1193 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1194 try:
1195 s.connect(("svn.python.org", 443))
1196 self.assertTrue(s.getpeercert())
1197 finally:
1198 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001199
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001200 def test_connect_ex(self):
1201 # Issue #11326: check connect_ex() implementation
1202 with support.transient_internet("svn.python.org"):
1203 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1204 cert_reqs=ssl.CERT_REQUIRED,
1205 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1206 try:
1207 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
1208 self.assertTrue(s.getpeercert())
1209 finally:
1210 s.close()
1211
1212 def test_non_blocking_connect_ex(self):
1213 # Issue #11326: non-blocking connect_ex() should allow handshake
1214 # to proceed after the socket gets ready.
1215 with support.transient_internet("svn.python.org"):
1216 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1217 cert_reqs=ssl.CERT_REQUIRED,
1218 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1219 do_handshake_on_connect=False)
1220 try:
1221 s.setblocking(False)
1222 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +00001223 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1224 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001225 # Wait for connect to finish
1226 select.select([], [s], [], 5.0)
1227 # Non-blocking handshake
1228 while True:
1229 try:
1230 s.do_handshake()
1231 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001232 except ssl.SSLWantReadError:
1233 select.select([s], [], [], 5.0)
1234 except ssl.SSLWantWriteError:
1235 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001236 # SSL established
1237 self.assertTrue(s.getpeercert())
1238 finally:
1239 s.close()
1240
Antoine Pitroub4410db2011-05-18 18:51:06 +02001241 def test_timeout_connect_ex(self):
1242 # Issue #12065: on a timeout, connect_ex() should return the original
1243 # errno (mimicking the behaviour of non-SSL sockets).
1244 with support.transient_internet("svn.python.org"):
1245 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1246 cert_reqs=ssl.CERT_REQUIRED,
1247 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1248 do_handshake_on_connect=False)
1249 try:
1250 s.settimeout(0.0000001)
1251 rc = s.connect_ex(('svn.python.org', 443))
1252 if rc == 0:
1253 self.skipTest("svn.python.org responded too quickly")
1254 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1255 finally:
1256 s.close()
1257
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001258 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +01001259 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001260 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1261 cert_reqs=ssl.CERT_REQUIRED,
1262 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1263 try:
Christian Heimesde570742013-12-16 21:15:44 +01001264 rc = s.connect_ex(("svn.python.org", 444))
1265 # Issue #19919: Windows machines or VMs hosted on Windows
1266 # machines sometimes return EWOULDBLOCK.
1267 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001268 finally:
1269 s.close()
1270
Antoine Pitrou152efa22010-05-16 18:19:27 +00001271 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001272 with support.transient_internet("svn.python.org"):
1273 # Same as test_connect, but with a separately created context
1274 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1275 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1276 s.connect(("svn.python.org", 443))
1277 try:
1278 self.assertEqual({}, s.getpeercert())
1279 finally:
1280 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +00001281 # Same with a server hostname
1282 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1283 server_hostname="svn.python.org")
Benjamin Peterson7243b572014-11-23 17:04:34 -06001284 s.connect(("svn.python.org", 443))
1285 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001286 # This should fail because we have no verification certs
1287 ctx.verify_mode = ssl.CERT_REQUIRED
1288 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +00001289 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +00001290 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001291 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001292 # This should succeed because we specify the root cert
1293 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1294 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1295 s.connect(("svn.python.org", 443))
1296 try:
1297 cert = s.getpeercert()
1298 self.assertTrue(cert)
1299 finally:
1300 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001301
1302 def test_connect_capath(self):
1303 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001304 # NOTE: the subject hashing algorithm has been changed between
1305 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1306 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001307 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +00001308 with support.transient_internet("svn.python.org"):
1309 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1310 ctx.verify_mode = ssl.CERT_REQUIRED
1311 ctx.load_verify_locations(capath=CAPATH)
1312 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1313 s.connect(("svn.python.org", 443))
1314 try:
1315 cert = s.getpeercert()
1316 self.assertTrue(cert)
1317 finally:
1318 s.close()
1319 # Same with a bytes `capath` argument
1320 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1321 ctx.verify_mode = ssl.CERT_REQUIRED
1322 ctx.load_verify_locations(capath=BYTES_CAPATH)
1323 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1324 s.connect(("svn.python.org", 443))
1325 try:
1326 cert = s.getpeercert()
1327 self.assertTrue(cert)
1328 finally:
1329 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001330
Christian Heimesefff7062013-11-21 03:35:02 +01001331 def test_connect_cadata(self):
1332 with open(CAFILE_CACERT) as f:
1333 pem = f.read()
1334 der = ssl.PEM_cert_to_DER_cert(pem)
1335 with support.transient_internet("svn.python.org"):
1336 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1337 ctx.verify_mode = ssl.CERT_REQUIRED
1338 ctx.load_verify_locations(cadata=pem)
1339 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1340 s.connect(("svn.python.org", 443))
1341 cert = s.getpeercert()
1342 self.assertTrue(cert)
1343
1344 # same with DER
1345 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1346 ctx.verify_mode = ssl.CERT_REQUIRED
1347 ctx.load_verify_locations(cadata=der)
1348 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1349 s.connect(("svn.python.org", 443))
1350 cert = s.getpeercert()
1351 self.assertTrue(cert)
1352
Antoine Pitroue3220242010-04-24 11:13:53 +00001353 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1354 def test_makefile_close(self):
1355 # Issue #5238: creating a file-like object with makefile() shouldn't
1356 # delay closing the underlying "real socket" (here tested with its
1357 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001358 with support.transient_internet("svn.python.org"):
1359 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1360 ss.connect(("svn.python.org", 443))
1361 fd = ss.fileno()
1362 f = ss.makefile()
1363 f.close()
1364 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001365 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001366 # Closing the SSL socket should close the fd too
1367 ss.close()
1368 gc.collect()
1369 with self.assertRaises(OSError) as e:
1370 os.read(fd, 0)
1371 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001372
Antoine Pitrou480a1242010-04-28 21:37:09 +00001373 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001374 with support.transient_internet("svn.python.org"):
1375 s = socket.socket(socket.AF_INET)
1376 s.connect(("svn.python.org", 443))
1377 s.setblocking(False)
1378 s = ssl.wrap_socket(s,
1379 cert_reqs=ssl.CERT_NONE,
1380 do_handshake_on_connect=False)
1381 count = 0
1382 while True:
1383 try:
1384 count += 1
1385 s.do_handshake()
1386 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001387 except ssl.SSLWantReadError:
1388 select.select([s], [], [])
1389 except ssl.SSLWantWriteError:
1390 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001391 s.close()
1392 if support.verbose:
1393 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001394
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001396 def _test_get_server_certificate(host, port, cert=None):
1397 with support.transient_internet(host):
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001398 pem = ssl.get_server_certificate((host, port),
1399 ssl.PROTOCOL_SSLv23)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001400 if not pem:
1401 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001402
Antoine Pitrou15399c32011-04-28 19:23:55 +02001403 try:
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001404 pem = ssl.get_server_certificate((host, port),
1405 ssl.PROTOCOL_SSLv23,
1406 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001407 except ssl.SSLError as x:
1408 #should fail
1409 if support.verbose:
1410 sys.stdout.write("%s\n" % x)
1411 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001412 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1413
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001414 pem = ssl.get_server_certificate((host, port),
1415 ssl.PROTOCOL_SSLv23,
1416 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001417 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001418 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001419 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001420 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001421
Antoine Pitrou15399c32011-04-28 19:23:55 +02001422 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1423 if support.IPV6_ENABLED:
1424 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001425
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001426 def test_ciphers(self):
1427 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001428 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001429 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1430 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1431 s.connect(remote)
1432 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1433 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1434 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001435 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001436 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001437 with socket.socket(socket.AF_INET) as sock:
1438 s = ssl.wrap_socket(sock,
1439 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1440 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001441
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001442 def test_algorithms(self):
1443 # Issue #8484: all algorithms should be available when verifying a
1444 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001445 # SHA256 was added in OpenSSL 0.9.8
1446 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1447 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001448 # sha256.tbs-internet.com needs SNI to use the correct certificate
1449 if not ssl.HAS_SNI:
1450 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001451 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1452 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001453 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001454 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001455 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1456 ctx.verify_mode = ssl.CERT_REQUIRED
1457 ctx.load_verify_locations(sha256_cert)
1458 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1459 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001460 try:
1461 s.connect(remote)
1462 if support.verbose:
1463 sys.stdout.write("\nCipher with %r is %r\n" %
1464 (remote, s.cipher()))
1465 sys.stdout.write("Certificate is:\n%s\n" %
1466 pprint.pformat(s.getpeercert()))
1467 finally:
1468 s.close()
1469
Christian Heimes9a5395a2013-06-17 15:44:12 +02001470 def test_get_ca_certs_capath(self):
1471 # capath certs are loaded on request
1472 with support.transient_internet("svn.python.org"):
1473 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1474 ctx.verify_mode = ssl.CERT_REQUIRED
1475 ctx.load_verify_locations(capath=CAPATH)
1476 self.assertEqual(ctx.get_ca_certs(), [])
1477 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1478 s.connect(("svn.python.org", 443))
1479 try:
1480 cert = s.getpeercert()
1481 self.assertTrue(cert)
1482 finally:
1483 s.close()
1484 self.assertEqual(len(ctx.get_ca_certs()), 1)
1485
Christian Heimes575596e2013-12-15 21:49:17 +01001486 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001487 def test_context_setget(self):
1488 # Check that the context of a connected socket can be replaced.
1489 with support.transient_internet("svn.python.org"):
1490 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1491 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1492 s = socket.socket(socket.AF_INET)
1493 with ctx1.wrap_socket(s) as ss:
1494 ss.connect(("svn.python.org", 443))
1495 self.assertIs(ss.context, ctx1)
1496 self.assertIs(ss._sslobj.context, ctx1)
1497 ss.context = ctx2
1498 self.assertIs(ss.context, ctx2)
1499 self.assertIs(ss._sslobj.context, ctx2)
1500
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001501try:
1502 import threading
1503except ImportError:
1504 _have_threads = False
1505else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001506 _have_threads = True
1507
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001508 from test.ssl_servers import make_https_server
1509
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001510 class ThreadedEchoServer(threading.Thread):
1511
1512 class ConnectionHandler(threading.Thread):
1513
1514 """A mildly complicated class, because we want it to work both
1515 with and without the SSL wrapper around the socket connection, so
1516 that we can test the STARTTLS functionality."""
1517
Bill Janssen6e027db2007-11-15 22:23:56 +00001518 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001519 self.server = server
1520 self.running = False
1521 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001522 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001523 self.sock.setblocking(1)
1524 self.sslconn = None
1525 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001526 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001527
Antoine Pitrou480a1242010-04-28 21:37:09 +00001528 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001529 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001530 self.sslconn = self.server.context.wrap_socket(
1531 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001532 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001533 except (ssl.SSLError, ConnectionResetError) as e:
1534 # We treat ConnectionResetError as though it were an
1535 # SSLError - OpenSSL on Ubuntu abruptly closes the
1536 # connection when asked to use an unsupported protocol.
1537 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001538 # XXX Various errors can have happened here, for example
1539 # a mismatching protocol version, an invalid certificate,
1540 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001541 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001542 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001543 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001544 self.running = False
1545 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001546 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001547 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001548 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001549 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001550 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001551 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001552 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1553 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001554 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001555 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1556 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001557 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001558 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001559 sys.stdout.write(" server: selected protocol is now "
1560 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001561 return True
1562
1563 def read(self):
1564 if self.sslconn:
1565 return self.sslconn.read()
1566 else:
1567 return self.sock.recv(1024)
1568
1569 def write(self, bytes):
1570 if self.sslconn:
1571 return self.sslconn.write(bytes)
1572 else:
1573 return self.sock.send(bytes)
1574
1575 def close(self):
1576 if self.sslconn:
1577 self.sslconn.close()
1578 else:
1579 self.sock.close()
1580
Antoine Pitrou480a1242010-04-28 21:37:09 +00001581 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001582 self.running = True
1583 if not self.server.starttls_server:
1584 if not self.wrap_conn():
1585 return
1586 while self.running:
1587 try:
1588 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001589 stripped = msg.strip()
1590 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001591 # eof, so quit this handler
1592 self.running = False
1593 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001594 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001595 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001596 sys.stdout.write(" server: client closed connection\n")
1597 self.close()
1598 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001599 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001600 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001601 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001602 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001603 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001604 if not self.wrap_conn():
1605 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001606 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001607 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001608 if support.verbose and self.server.connectionchatty:
1609 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001610 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001611 self.sock = self.sslconn.unwrap()
1612 self.sslconn = None
1613 if support.verbose and self.server.connectionchatty:
1614 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001615 elif stripped == b'CB tls-unique':
1616 if support.verbose and self.server.connectionchatty:
1617 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1618 data = self.sslconn.get_channel_binding("tls-unique")
1619 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001620 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001621 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001622 self.server.connectionchatty):
1623 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001624 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1625 % (msg, ctype, msg.lower(), ctype))
1626 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001627 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001628 if self.server.chatty:
1629 handle_error("Test server failure:\n")
1630 self.close()
1631 self.running = False
1632 # normally, we'd just stop here, but for the test
1633 # harness, we want to stop the server
1634 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001635
Antoine Pitroub5218772010-05-21 09:56:06 +00001636 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001637 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001638 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001639 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001640 if context:
1641 self.context = context
1642 else:
1643 self.context = ssl.SSLContext(ssl_version
1644 if ssl_version is not None
1645 else ssl.PROTOCOL_TLSv1)
1646 self.context.verify_mode = (certreqs if certreqs is not None
1647 else ssl.CERT_NONE)
1648 if cacerts:
1649 self.context.load_verify_locations(cacerts)
1650 if certificate:
1651 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001652 if npn_protocols:
1653 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001654 if ciphers:
1655 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001656 self.chatty = chatty
1657 self.connectionchatty = connectionchatty
1658 self.starttls_server = starttls_server
1659 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001660 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001661 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001662 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001663 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001664 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001665 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001666 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001667
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001668 def __enter__(self):
1669 self.start(threading.Event())
1670 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001671 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001672
1673 def __exit__(self, *args):
1674 self.stop()
1675 self.join()
1676
Antoine Pitrou480a1242010-04-28 21:37:09 +00001677 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001678 self.flag = flag
1679 threading.Thread.start(self)
1680
Antoine Pitrou480a1242010-04-28 21:37:09 +00001681 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001682 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001683 self.sock.listen(5)
1684 self.active = True
1685 if self.flag:
1686 # signal an event
1687 self.flag.set()
1688 while self.active:
1689 try:
1690 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001691 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001692 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001693 + repr(connaddr) + '\n')
1694 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001695 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001696 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001697 except socket.timeout:
1698 pass
1699 except KeyboardInterrupt:
1700 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001701 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001702
Antoine Pitrou480a1242010-04-28 21:37:09 +00001703 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001704 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001705
Bill Janssen54cc54c2007-12-14 22:08:56 +00001706 class AsyncoreEchoServer(threading.Thread):
1707
1708 # this one's based on asyncore.dispatcher
1709
1710 class EchoServer (asyncore.dispatcher):
1711
1712 class ConnectionHandler (asyncore.dispatcher_with_send):
1713
1714 def __init__(self, conn, certfile):
1715 self.socket = ssl.wrap_socket(conn, server_side=True,
1716 certfile=certfile,
1717 do_handshake_on_connect=False)
1718 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001719 self._ssl_accepting = True
1720 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001721
1722 def readable(self):
1723 if isinstance(self.socket, ssl.SSLSocket):
1724 while self.socket.pending() > 0:
1725 self.handle_read_event()
1726 return True
1727
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001728 def _do_ssl_handshake(self):
1729 try:
1730 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001731 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1732 return
1733 except ssl.SSLEOFError:
1734 return self.handle_close()
1735 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001736 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001737 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001738 if err.args[0] == errno.ECONNABORTED:
1739 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001740 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001741 self._ssl_accepting = False
1742
1743 def handle_read(self):
1744 if self._ssl_accepting:
1745 self._do_ssl_handshake()
1746 else:
1747 data = self.recv(1024)
1748 if support.verbose:
1749 sys.stdout.write(" server: read %s from client\n" % repr(data))
1750 if not data:
1751 self.close()
1752 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001753 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001754
1755 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001756 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001757 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001758 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1759
1760 def handle_error(self):
1761 raise
1762
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001763 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001764 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001765 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1766 self.port = support.bind_port(sock, '')
1767 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001768 self.listen(5)
1769
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001770 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001771 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001772 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1773 self.ConnectionHandler(sock_obj, self.certfile)
1774
1775 def handle_error(self):
1776 raise
1777
Trent Nelson78520002008-04-10 20:54:35 +00001778 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001779 self.flag = None
1780 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001781 self.server = self.EchoServer(certfile)
1782 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001783 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001784 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001785
1786 def __str__(self):
1787 return "<%s %s>" % (self.__class__.__name__, self.server)
1788
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001789 def __enter__(self):
1790 self.start(threading.Event())
1791 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001792 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001793
1794 def __exit__(self, *args):
1795 if support.verbose:
1796 sys.stdout.write(" cleanup: stopping server.\n")
1797 self.stop()
1798 if support.verbose:
1799 sys.stdout.write(" cleanup: joining server thread.\n")
1800 self.join()
1801 if support.verbose:
1802 sys.stdout.write(" cleanup: successfully joined.\n")
1803
Bill Janssen54cc54c2007-12-14 22:08:56 +00001804 def start (self, flag=None):
1805 self.flag = flag
1806 threading.Thread.start(self)
1807
Antoine Pitrou480a1242010-04-28 21:37:09 +00001808 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001809 self.active = True
1810 if self.flag:
1811 self.flag.set()
1812 while self.active:
1813 try:
1814 asyncore.loop(1)
1815 except:
1816 pass
1817
Antoine Pitrou480a1242010-04-28 21:37:09 +00001818 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001819 self.active = False
1820 self.server.close()
1821
Antoine Pitrou480a1242010-04-28 21:37:09 +00001822 def bad_cert_test(certfile):
1823 """
1824 Launch a server with CERT_REQUIRED, and check that trying to
1825 connect to it with the given client certificate fails.
1826 """
Trent Nelson78520002008-04-10 20:54:35 +00001827 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001828 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001829 cacerts=CERTFILE, chatty=False,
1830 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001831 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001832 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001833 with socket.socket() as sock:
1834 s = ssl.wrap_socket(sock,
1835 certfile=certfile,
1836 ssl_version=ssl.PROTOCOL_TLSv1)
1837 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001838 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001839 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001840 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001841 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001842 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001843 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001844 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001845 if x.errno != errno.ENOENT:
1846 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001847 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001848 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001849 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001850 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001851
Antoine Pitroub5218772010-05-21 09:56:06 +00001852 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001853 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001854 """
1855 Launch a server, connect a client to it and try various reads
1856 and writes.
1857 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001858 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001859 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001860 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001861 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001862 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001863 with client_context.wrap_socket(socket.socket(),
1864 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001865 s.connect((HOST, server.port))
1866 for arg in [indata, bytearray(indata), memoryview(indata)]:
1867 if connectionchatty:
1868 if support.verbose:
1869 sys.stdout.write(
1870 " client: sending %r...\n" % indata)
1871 s.write(arg)
1872 outdata = s.read()
1873 if connectionchatty:
1874 if support.verbose:
1875 sys.stdout.write(" client: read %r\n" % outdata)
1876 if outdata != indata.lower():
1877 raise AssertionError(
1878 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1879 % (outdata[:20], len(outdata),
1880 indata[:20].lower(), len(indata)))
1881 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001882 if connectionchatty:
1883 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001884 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001885 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001886 'compression': s.compression(),
1887 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001888 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001889 'client_npn_protocol': s.selected_npn_protocol()
1890 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001891 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001892 stats['server_npn_protocols'] = server.selected_protocols
1893 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001894
Antoine Pitroub5218772010-05-21 09:56:06 +00001895 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1896 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001897 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001898 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001899 certtype = {
1900 ssl.CERT_NONE: "CERT_NONE",
1901 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1902 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1903 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001904 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001905 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001906 sys.stdout.write(formatstr %
1907 (ssl.get_protocol_name(client_protocol),
1908 ssl.get_protocol_name(server_protocol),
1909 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001910 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001911 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001912 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001913 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001914
1915 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1916 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1917 # starting from OpenSSL 1.0.0 (see issue #8322).
1918 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1919 client_context.set_ciphers("ALL")
1920
Antoine Pitroub5218772010-05-21 09:56:06 +00001921 for ctx in (client_context, server_context):
1922 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001923 ctx.load_cert_chain(CERTFILE)
1924 ctx.load_verify_locations(CERTFILE)
1925 try:
1926 server_params_test(client_context, server_context,
1927 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001928 # Protocol mismatch can result in either an SSLError, or a
1929 # "Connection reset by peer" error.
1930 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001931 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001932 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001933 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001934 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001935 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001936 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001937 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001938 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001939 "Client protocol %s succeeded with server protocol %s!"
1940 % (ssl.get_protocol_name(client_protocol),
1941 ssl.get_protocol_name(server_protocol)))
1942
1943
Bill Janssen6e027db2007-11-15 22:23:56 +00001944 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001945
Antoine Pitrou23df4832010-08-04 17:14:06 +00001946 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001947 def test_echo(self):
1948 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001949 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001950 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001951 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001952 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1953 context = ssl.SSLContext(protocol)
1954 context.load_cert_chain(CERTFILE)
1955 server_params_test(context, context,
1956 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001957
Antoine Pitrou480a1242010-04-28 21:37:09 +00001958 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001959 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001960 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001961 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1962 context.verify_mode = ssl.CERT_REQUIRED
1963 context.load_verify_locations(CERTFILE)
1964 context.load_cert_chain(CERTFILE)
1965 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001966 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001967 s = context.wrap_socket(socket.socket(),
1968 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001969 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001970 # getpeercert() raise ValueError while the handshake isn't
1971 # done.
1972 with self.assertRaises(ValueError):
1973 s.getpeercert()
1974 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001975 cert = s.getpeercert()
1976 self.assertTrue(cert, "Can't get peer certificate.")
1977 cipher = s.cipher()
1978 if support.verbose:
1979 sys.stdout.write(pprint.pformat(cert) + '\n')
1980 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1981 if 'subject' not in cert:
1982 self.fail("No subject field in certificate: %s." %
1983 pprint.pformat(cert))
1984 if ((('organizationName', 'Python Software Foundation'),)
1985 not in cert['subject']):
1986 self.fail(
1987 "Missing or invalid 'organizationName' field in certificate subject; "
1988 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001989 self.assertIn('notBefore', cert)
1990 self.assertIn('notAfter', cert)
1991 before = ssl.cert_time_to_seconds(cert['notBefore'])
1992 after = ssl.cert_time_to_seconds(cert['notAfter'])
1993 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001994 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001995
Christian Heimes2427b502013-11-23 11:24:32 +01001996 @unittest.skipUnless(have_verify_flags(),
1997 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001998 def test_crl_check(self):
1999 if support.verbose:
2000 sys.stdout.write("\n")
2001
2002 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2003 server_context.load_cert_chain(SIGNED_CERTFILE)
2004
2005 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2006 context.verify_mode = ssl.CERT_REQUIRED
2007 context.load_verify_locations(SIGNING_CA)
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002008 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT)
Christian Heimes22587792013-11-21 23:56:13 +01002009
2010 # VERIFY_DEFAULT should pass
2011 server = ThreadedEchoServer(context=server_context, chatty=True)
2012 with server:
2013 with context.wrap_socket(socket.socket()) as s:
2014 s.connect((HOST, server.port))
2015 cert = s.getpeercert()
2016 self.assertTrue(cert, "Can't get peer certificate.")
2017
2018 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002019 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01002020
2021 server = ThreadedEchoServer(context=server_context, chatty=True)
2022 with server:
2023 with context.wrap_socket(socket.socket()) as s:
2024 with self.assertRaisesRegex(ssl.SSLError,
2025 "certificate verify failed"):
2026 s.connect((HOST, server.port))
2027
2028 # now load a CRL file. The CRL file is signed by the CA.
2029 context.load_verify_locations(CRLFILE)
2030
2031 server = ThreadedEchoServer(context=server_context, chatty=True)
2032 with server:
2033 with context.wrap_socket(socket.socket()) as s:
2034 s.connect((HOST, server.port))
2035 cert = s.getpeercert()
2036 self.assertTrue(cert, "Can't get peer certificate.")
2037
Christian Heimes1aa9a752013-12-02 02:41:19 +01002038 def test_check_hostname(self):
2039 if support.verbose:
2040 sys.stdout.write("\n")
2041
2042 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2043 server_context.load_cert_chain(SIGNED_CERTFILE)
2044
2045 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2046 context.verify_mode = ssl.CERT_REQUIRED
2047 context.check_hostname = True
2048 context.load_verify_locations(SIGNING_CA)
2049
2050 # correct hostname should verify
2051 server = ThreadedEchoServer(context=server_context, chatty=True)
2052 with server:
2053 with context.wrap_socket(socket.socket(),
2054 server_hostname="localhost") as s:
2055 s.connect((HOST, server.port))
2056 cert = s.getpeercert()
2057 self.assertTrue(cert, "Can't get peer certificate.")
2058
2059 # incorrect hostname should raise an exception
2060 server = ThreadedEchoServer(context=server_context, chatty=True)
2061 with server:
2062 with context.wrap_socket(socket.socket(),
2063 server_hostname="invalid") as s:
2064 with self.assertRaisesRegex(ssl.CertificateError,
2065 "hostname 'invalid' doesn't match 'localhost'"):
2066 s.connect((HOST, server.port))
2067
2068 # missing server_hostname arg should cause an exception, too
2069 server = ThreadedEchoServer(context=server_context, chatty=True)
2070 with server:
2071 with socket.socket() as s:
2072 with self.assertRaisesRegex(ValueError,
2073 "check_hostname requires server_hostname"):
2074 context.wrap_socket(s)
2075
Antoine Pitrou480a1242010-04-28 21:37:09 +00002076 def test_empty_cert(self):
2077 """Connecting with an empty cert file"""
2078 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2079 "nullcert.pem"))
2080 def test_malformed_cert(self):
2081 """Connecting with a badly formatted certificate (syntax error)"""
2082 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2083 "badcert.pem"))
2084 def test_nonexisting_cert(self):
2085 """Connecting with a non-existing cert file"""
2086 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2087 "wrongcert.pem"))
2088 def test_malformed_key(self):
2089 """Connecting with a badly formatted key (syntax error)"""
2090 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2091 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002092
Antoine Pitrou480a1242010-04-28 21:37:09 +00002093 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002094 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002095 in the client when attempting handshake.
2096 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002097 listener_ready = threading.Event()
2098 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002099
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002100 s = socket.socket()
2101 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002102
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002103 # `listener` runs in a thread. It sits in an accept() until
2104 # the main thread connects. Then it rudely closes the socket,
2105 # and sets Event `listener_gone` to let the main thread know
2106 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002107 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00002108 s.listen(5)
2109 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002110 newsock, addr = s.accept()
2111 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002112 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002113 listener_gone.set()
2114
2115 def connector():
2116 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002117 with socket.socket() as c:
2118 c.connect((HOST, port))
2119 listener_gone.wait()
2120 try:
2121 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002122 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002123 pass
2124 else:
2125 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002126
2127 t = threading.Thread(target=listener)
2128 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002129 try:
2130 connector()
2131 finally:
2132 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002133
Antoine Pitrou23df4832010-08-04 17:14:06 +00002134 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002135 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2136 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002137 def test_protocol_sslv2(self):
2138 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002139 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002140 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002141 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2142 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2143 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002144 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Victor Stinner3f7e0642014-12-12 12:27:08 +01002145 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2146 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002147 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002148 # SSLv23 client with specific SSL options
2149 if no_sslv2_implies_sslv3_hello():
2150 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2151 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2152 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002153 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002154 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002155 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002156 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002157
Antoine Pitrou23df4832010-08-04 17:14:06 +00002158 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002159 def test_protocol_sslv23(self):
2160 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002161 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002162 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002163 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2164 try:
2165 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002166 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002167 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2168 if support.verbose:
2169 sys.stdout.write(
2170 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2171 % str(x))
Benjamin Petersone32467c2014-12-05 21:59:35 -05002172 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2173 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002174 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
2175 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002176
Benjamin Petersone32467c2014-12-05 21:59:35 -05002177 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2178 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002179 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
2180 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002181
Benjamin Petersone32467c2014-12-05 21:59:35 -05002182 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2183 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002184 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
2185 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002186
Antoine Pitroub5218772010-05-21 09:56:06 +00002187 # Server with specific SSL options
Benjamin Petersone32467c2014-12-05 21:59:35 -05002188 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2189 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002190 server_options=ssl.OP_NO_SSLv3)
2191 # Will choose TLSv1
2192 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2193 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2194 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2195 server_options=ssl.OP_NO_TLSv1)
2196
2197
Antoine Pitrou23df4832010-08-04 17:14:06 +00002198 @skip_if_broken_ubuntu_ssl
Benjamin Petersone32467c2014-12-05 21:59:35 -05002199 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2200 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002201 def test_protocol_sslv3(self):
2202 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002203 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002204 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002205 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
2206 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2207 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002208 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2209 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002210 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2211 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002212 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002213 if no_sslv2_implies_sslv3_hello():
2214 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2215 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
2216 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002217
Antoine Pitrou23df4832010-08-04 17:14:06 +00002218 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002219 def test_protocol_tlsv1(self):
2220 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002221 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002222 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002223 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
2224 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
2225 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002226 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2227 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002228 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2229 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002230 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2231 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002232
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002233 @skip_if_broken_ubuntu_ssl
2234 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2235 "TLS version 1.1 not supported.")
2236 def test_protocol_tlsv1_1(self):
2237 """Connecting to a TLSv1.1 server with various client options.
2238 Testing against older TLS versions."""
2239 if support.verbose:
2240 sys.stdout.write("\n")
2241 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
2242 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2243 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002244 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2245 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002246 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2247 client_options=ssl.OP_NO_TLSv1_1)
2248
2249 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
2250 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2251 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2252
2253
2254 @skip_if_broken_ubuntu_ssl
2255 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2256 "TLS version 1.2 not supported.")
2257 def test_protocol_tlsv1_2(self):
2258 """Connecting to a TLSv1.2 server with various client options.
2259 Testing against older TLS versions."""
2260 if support.verbose:
2261 sys.stdout.write("\n")
2262 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
2263 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2264 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2265 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2266 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002267 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2268 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002269 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2270 client_options=ssl.OP_NO_TLSv1_2)
2271
2272 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
2273 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2274 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2275 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2276 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2277
Antoine Pitrou480a1242010-04-28 21:37:09 +00002278 def test_starttls(self):
2279 """Switching from clear text to encrypted and back again."""
2280 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 +00002281
Trent Nelson78520002008-04-10 20:54:35 +00002282 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002283 ssl_version=ssl.PROTOCOL_TLSv1,
2284 starttls_server=True,
2285 chatty=True,
2286 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002287 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002288 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002289 s = socket.socket()
2290 s.setblocking(1)
2291 s.connect((HOST, server.port))
2292 if support.verbose:
2293 sys.stdout.write("\n")
2294 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002295 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002296 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002297 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002298 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002299 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002300 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002301 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002302 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002303 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002304 msg = outdata.strip().lower()
2305 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2306 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002307 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002308 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002309 " client: read %r from server, starting TLS...\n"
2310 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002311 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2312 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002313 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2314 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002315 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002316 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002317 " client: read %r from server, ending TLS...\n"
2318 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002319 s = conn.unwrap()
2320 wrapped = False
2321 else:
2322 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002323 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002324 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002325 if support.verbose:
2326 sys.stdout.write(" client: closing connection.\n")
2327 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002328 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002329 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002330 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002331 if wrapped:
2332 conn.close()
2333 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002334 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002335
Antoine Pitrou480a1242010-04-28 21:37:09 +00002336 def test_socketserver(self):
2337 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002338 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002339 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002340 if support.verbose:
2341 sys.stdout.write('\n')
2342 with open(CERTFILE, 'rb') as f:
2343 d1 = f.read()
2344 d2 = ''
2345 # now fetch the same data from the HTTPS server
Benjamin Peterson4ffb0752014-11-03 14:29:33 -05002346 url = 'https://localhost:%d/%s' % (
2347 server.port, os.path.split(CERTFILE)[1])
2348 context = ssl.create_default_context(cafile=CERTFILE)
2349 f = urllib.request.urlopen(url, context=context)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002350 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002351 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002352 if dlen and (int(dlen) > 0):
2353 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002354 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002355 sys.stdout.write(
2356 " client: read %d bytes from remote server '%s'\n"
2357 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002358 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002359 f.close()
2360 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002361
Antoine Pitrou480a1242010-04-28 21:37:09 +00002362 def test_asyncore_server(self):
2363 """Check the example asyncore integration."""
2364 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002365
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002366 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002367 sys.stdout.write("\n")
2368
Antoine Pitrou480a1242010-04-28 21:37:09 +00002369 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002370 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002371 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002372 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002373 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002374 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002375 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002376 " client: sending %r...\n" % indata)
2377 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002378 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002379 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002380 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002381 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002382 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002383 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2384 % (outdata[:20], len(outdata),
2385 indata[:20].lower(), len(indata)))
2386 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002387 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002388 sys.stdout.write(" client: closing connection.\n")
2389 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002390 if support.verbose:
2391 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002392
Antoine Pitrou480a1242010-04-28 21:37:09 +00002393 def test_recv_send(self):
2394 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002395 if support.verbose:
2396 sys.stdout.write("\n")
2397
2398 server = ThreadedEchoServer(CERTFILE,
2399 certreqs=ssl.CERT_NONE,
2400 ssl_version=ssl.PROTOCOL_TLSv1,
2401 cacerts=CERTFILE,
2402 chatty=True,
2403 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002404 with server:
2405 s = ssl.wrap_socket(socket.socket(),
2406 server_side=False,
2407 certfile=CERTFILE,
2408 ca_certs=CERTFILE,
2409 cert_reqs=ssl.CERT_NONE,
2410 ssl_version=ssl.PROTOCOL_TLSv1)
2411 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002412 # helper methods for standardising recv* method signatures
2413 def _recv_into():
2414 b = bytearray(b"\0"*100)
2415 count = s.recv_into(b)
2416 return b[:count]
2417
2418 def _recvfrom_into():
2419 b = bytearray(b"\0"*100)
2420 count, addr = s.recvfrom_into(b)
2421 return b[:count]
2422
2423 # (name, method, whether to expect success, *args)
2424 send_methods = [
2425 ('send', s.send, True, []),
2426 ('sendto', s.sendto, False, ["some.address"]),
2427 ('sendall', s.sendall, True, []),
2428 ]
2429 recv_methods = [
2430 ('recv', s.recv, True, []),
2431 ('recvfrom', s.recvfrom, False, ["some.address"]),
2432 ('recv_into', _recv_into, True, []),
2433 ('recvfrom_into', _recvfrom_into, False, []),
2434 ]
2435 data_prefix = "PREFIX_"
2436
2437 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002438 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002439 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002440 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002441 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002442 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002443 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002444 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002445 "<<{outdata:r}>> ({nout:d}) received; "
2446 "expected <<{indata:r}>> ({nin:d})\n".format(
2447 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002448 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002449 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002450 )
2451 )
2452 except ValueError as e:
2453 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002454 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002455 "Failed to send with method <<{name:s}>>; "
2456 "expected to succeed.\n".format(name=meth_name)
2457 )
2458 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002459 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002460 "Method <<{name:s}>> failed with unexpected "
2461 "exception message: {exp:s}\n".format(
2462 name=meth_name, exp=e
2463 )
2464 )
2465
2466 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002467 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002468 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002469 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002470 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002471 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002472 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002473 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002474 "<<{outdata:r}>> ({nout:d}) received; "
2475 "expected <<{indata:r}>> ({nin:d})\n".format(
2476 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002477 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002478 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002479 )
2480 )
2481 except ValueError as e:
2482 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002483 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002484 "Failed to receive with method <<{name:s}>>; "
2485 "expected to succeed.\n".format(name=meth_name)
2486 )
2487 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002488 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002489 "Method <<{name:s}>> failed with unexpected "
2490 "exception message: {exp:s}\n".format(
2491 name=meth_name, exp=e
2492 )
2493 )
2494 # consume data
2495 s.read()
2496
Nick Coghlan513886a2011-08-28 00:00:27 +10002497 # Make sure sendmsg et al are disallowed to avoid
2498 # inadvertent disclosure of data and/or corruption
2499 # of the encrypted data stream
2500 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2501 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2502 self.assertRaises(NotImplementedError,
2503 s.recvmsg_into, bytearray(100))
2504
Antoine Pitrou480a1242010-04-28 21:37:09 +00002505 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002506 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002507
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002508 def test_handshake_timeout(self):
2509 # Issue #5103: SSL handshake must respect the socket timeout
2510 server = socket.socket(socket.AF_INET)
2511 host = "127.0.0.1"
2512 port = support.bind_port(server)
2513 started = threading.Event()
2514 finish = False
2515
2516 def serve():
2517 server.listen(5)
2518 started.set()
2519 conns = []
2520 while not finish:
2521 r, w, e = select.select([server], [], [], 0.1)
2522 if server in r:
2523 # Let the socket hang around rather than having
2524 # it closed by garbage collection.
2525 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002526 for sock in conns:
2527 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002528
2529 t = threading.Thread(target=serve)
2530 t.start()
2531 started.wait()
2532
2533 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002534 try:
2535 c = socket.socket(socket.AF_INET)
2536 c.settimeout(0.2)
2537 c.connect((host, port))
2538 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002539 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002540 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002541 finally:
2542 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002543 try:
2544 c = socket.socket(socket.AF_INET)
2545 c = ssl.wrap_socket(c)
2546 c.settimeout(0.2)
2547 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002548 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002549 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002550 finally:
2551 c.close()
2552 finally:
2553 finish = True
2554 t.join()
2555 server.close()
2556
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002557 def test_server_accept(self):
2558 # Issue #16357: accept() on a SSLSocket created through
2559 # SSLContext.wrap_socket().
2560 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2561 context.verify_mode = ssl.CERT_REQUIRED
2562 context.load_verify_locations(CERTFILE)
2563 context.load_cert_chain(CERTFILE)
2564 server = socket.socket(socket.AF_INET)
2565 host = "127.0.0.1"
2566 port = support.bind_port(server)
2567 server = context.wrap_socket(server, server_side=True)
2568
2569 evt = threading.Event()
2570 remote = None
2571 peer = None
2572 def serve():
2573 nonlocal remote, peer
2574 server.listen(5)
2575 # Block on the accept and wait on the connection to close.
2576 evt.set()
2577 remote, peer = server.accept()
2578 remote.recv(1)
2579
2580 t = threading.Thread(target=serve)
2581 t.start()
2582 # Client wait until server setup and perform a connect.
2583 evt.wait()
2584 client = context.wrap_socket(socket.socket())
2585 client.connect((host, port))
2586 client_addr = client.getsockname()
2587 client.close()
2588 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002589 remote.close()
2590 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002591 # Sanity checks.
2592 self.assertIsInstance(remote, ssl.SSLSocket)
2593 self.assertEqual(peer, client_addr)
2594
Antoine Pitrou242db722013-05-01 20:52:07 +02002595 def test_getpeercert_enotconn(self):
2596 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2597 with context.wrap_socket(socket.socket()) as sock:
2598 with self.assertRaises(OSError) as cm:
2599 sock.getpeercert()
2600 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2601
2602 def test_do_handshake_enotconn(self):
2603 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2604 with context.wrap_socket(socket.socket()) as sock:
2605 with self.assertRaises(OSError) as cm:
2606 sock.do_handshake()
2607 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2608
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002609 def test_default_ciphers(self):
2610 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2611 try:
2612 # Force a set of weak ciphers on our client context
2613 context.set_ciphers("DES")
2614 except ssl.SSLError:
2615 self.skipTest("no DES cipher available")
2616 with ThreadedEchoServer(CERTFILE,
2617 ssl_version=ssl.PROTOCOL_SSLv23,
2618 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002619 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002620 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002621 s.connect((HOST, server.port))
2622 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2623
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002624 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2625 def test_default_ecdh_curve(self):
2626 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2627 # should be enabled by default on SSL contexts.
2628 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2629 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02002630 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2631 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2632 # our default cipher list should prefer ECDH-based ciphers
2633 # automatically.
2634 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2635 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002636 with ThreadedEchoServer(context=context) as server:
2637 with context.wrap_socket(socket.socket()) as s:
2638 s.connect((HOST, server.port))
2639 self.assertIn("ECDH", s.cipher()[0])
2640
Antoine Pitroud6494802011-07-21 01:11:30 +02002641 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2642 "'tls-unique' channel binding not available")
2643 def test_tls_unique_channel_binding(self):
2644 """Test tls-unique channel binding."""
2645 if support.verbose:
2646 sys.stdout.write("\n")
2647
2648 server = ThreadedEchoServer(CERTFILE,
2649 certreqs=ssl.CERT_NONE,
2650 ssl_version=ssl.PROTOCOL_TLSv1,
2651 cacerts=CERTFILE,
2652 chatty=True,
2653 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002654 with server:
2655 s = ssl.wrap_socket(socket.socket(),
2656 server_side=False,
2657 certfile=CERTFILE,
2658 ca_certs=CERTFILE,
2659 cert_reqs=ssl.CERT_NONE,
2660 ssl_version=ssl.PROTOCOL_TLSv1)
2661 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002662 # get the data
2663 cb_data = s.get_channel_binding("tls-unique")
2664 if support.verbose:
2665 sys.stdout.write(" got channel binding data: {0!r}\n"
2666 .format(cb_data))
2667
2668 # check if it is sane
2669 self.assertIsNotNone(cb_data)
2670 self.assertEqual(len(cb_data), 12) # True for TLSv1
2671
2672 # and compare with the peers version
2673 s.write(b"CB tls-unique\n")
2674 peer_data_repr = s.read().strip()
2675 self.assertEqual(peer_data_repr,
2676 repr(cb_data).encode("us-ascii"))
2677 s.close()
2678
2679 # now, again
2680 s = ssl.wrap_socket(socket.socket(),
2681 server_side=False,
2682 certfile=CERTFILE,
2683 ca_certs=CERTFILE,
2684 cert_reqs=ssl.CERT_NONE,
2685 ssl_version=ssl.PROTOCOL_TLSv1)
2686 s.connect((HOST, server.port))
2687 new_cb_data = s.get_channel_binding("tls-unique")
2688 if support.verbose:
2689 sys.stdout.write(" got another channel binding data: {0!r}\n"
2690 .format(new_cb_data))
2691 # is it really unique
2692 self.assertNotEqual(cb_data, new_cb_data)
2693 self.assertIsNotNone(cb_data)
2694 self.assertEqual(len(cb_data), 12) # True for TLSv1
2695 s.write(b"CB tls-unique\n")
2696 peer_data_repr = s.read().strip()
2697 self.assertEqual(peer_data_repr,
2698 repr(new_cb_data).encode("us-ascii"))
2699 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002700
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002701 def test_compression(self):
2702 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2703 context.load_cert_chain(CERTFILE)
2704 stats = server_params_test(context, context,
2705 chatty=True, connectionchatty=True)
2706 if support.verbose:
2707 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2708 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2709
2710 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2711 "ssl.OP_NO_COMPRESSION needed for this test")
2712 def test_compression_disabled(self):
2713 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2714 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002715 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002716 stats = server_params_test(context, context,
2717 chatty=True, connectionchatty=True)
2718 self.assertIs(stats['compression'], None)
2719
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002720 def test_dh_params(self):
2721 # Check we can get a connection with ephemeral Diffie-Hellman
2722 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2723 context.load_cert_chain(CERTFILE)
2724 context.load_dh_params(DHFILE)
2725 context.set_ciphers("kEDH")
2726 stats = server_params_test(context, context,
2727 chatty=True, connectionchatty=True)
2728 cipher = stats["cipher"][0]
2729 parts = cipher.split("-")
2730 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2731 self.fail("Non-DH cipher: " + cipher[0])
2732
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002733 def test_selected_npn_protocol(self):
2734 # selected_npn_protocol() is None unless NPN is used
2735 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2736 context.load_cert_chain(CERTFILE)
2737 stats = server_params_test(context, context,
2738 chatty=True, connectionchatty=True)
2739 self.assertIs(stats['client_npn_protocol'], None)
2740
2741 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2742 def test_npn_protocols(self):
2743 server_protocols = ['http/1.1', 'spdy/2']
2744 protocol_tests = [
2745 (['http/1.1', 'spdy/2'], 'http/1.1'),
2746 (['spdy/2', 'http/1.1'], 'http/1.1'),
2747 (['spdy/2', 'test'], 'spdy/2'),
2748 (['abc', 'def'], 'abc')
2749 ]
2750 for client_protocols, expected in protocol_tests:
2751 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2752 server_context.load_cert_chain(CERTFILE)
2753 server_context.set_npn_protocols(server_protocols)
2754 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2755 client_context.load_cert_chain(CERTFILE)
2756 client_context.set_npn_protocols(client_protocols)
2757 stats = server_params_test(client_context, server_context,
2758 chatty=True, connectionchatty=True)
2759
2760 msg = "failed trying %s (s) and %s (c).\n" \
2761 "was expecting %s, but got %%s from the %%s" \
2762 % (str(server_protocols), str(client_protocols),
2763 str(expected))
2764 client_result = stats['client_npn_protocol']
2765 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2766 server_result = stats['server_npn_protocols'][-1] \
2767 if len(stats['server_npn_protocols']) else 'nothing'
2768 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2769
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002770 def sni_contexts(self):
2771 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2772 server_context.load_cert_chain(SIGNED_CERTFILE)
2773 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2774 other_context.load_cert_chain(SIGNED_CERTFILE2)
2775 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2776 client_context.verify_mode = ssl.CERT_REQUIRED
2777 client_context.load_verify_locations(SIGNING_CA)
2778 return server_context, other_context, client_context
2779
2780 def check_common_name(self, stats, name):
2781 cert = stats['peercert']
2782 self.assertIn((('commonName', name),), cert['subject'])
2783
2784 @needs_sni
2785 def test_sni_callback(self):
2786 calls = []
2787 server_context, other_context, client_context = self.sni_contexts()
2788
2789 def servername_cb(ssl_sock, server_name, initial_context):
2790 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002791 if server_name is not None:
2792 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002793 server_context.set_servername_callback(servername_cb)
2794
2795 stats = server_params_test(client_context, server_context,
2796 chatty=True,
2797 sni_name='supermessage')
2798 # The hostname was fetched properly, and the certificate was
2799 # changed for the connection.
2800 self.assertEqual(calls, [("supermessage", server_context)])
2801 # CERTFILE4 was selected
2802 self.check_common_name(stats, 'fakehostname')
2803
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002804 calls = []
2805 # The callback is called with server_name=None
2806 stats = server_params_test(client_context, server_context,
2807 chatty=True,
2808 sni_name=None)
2809 self.assertEqual(calls, [(None, server_context)])
2810 self.check_common_name(stats, 'localhost')
2811
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002812 # Check disabling the callback
2813 calls = []
2814 server_context.set_servername_callback(None)
2815
2816 stats = server_params_test(client_context, server_context,
2817 chatty=True,
2818 sni_name='notfunny')
2819 # Certificate didn't change
2820 self.check_common_name(stats, 'localhost')
2821 self.assertEqual(calls, [])
2822
2823 @needs_sni
2824 def test_sni_callback_alert(self):
2825 # Returning a TLS alert is reflected to the connecting client
2826 server_context, other_context, client_context = self.sni_contexts()
2827
2828 def cb_returning_alert(ssl_sock, server_name, initial_context):
2829 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2830 server_context.set_servername_callback(cb_returning_alert)
2831
2832 with self.assertRaises(ssl.SSLError) as cm:
2833 stats = server_params_test(client_context, server_context,
2834 chatty=False,
2835 sni_name='supermessage')
2836 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2837
2838 @needs_sni
2839 def test_sni_callback_raising(self):
2840 # Raising fails the connection with a TLS handshake failure alert.
2841 server_context, other_context, client_context = self.sni_contexts()
2842
2843 def cb_raising(ssl_sock, server_name, initial_context):
2844 1/0
2845 server_context.set_servername_callback(cb_raising)
2846
2847 with self.assertRaises(ssl.SSLError) as cm, \
2848 support.captured_stderr() as stderr:
2849 stats = server_params_test(client_context, server_context,
2850 chatty=False,
2851 sni_name='supermessage')
2852 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2853 self.assertIn("ZeroDivisionError", stderr.getvalue())
2854
2855 @needs_sni
2856 def test_sni_callback_wrong_return_type(self):
2857 # Returning the wrong return type terminates the TLS connection
2858 # with an internal error alert.
2859 server_context, other_context, client_context = self.sni_contexts()
2860
2861 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2862 return "foo"
2863 server_context.set_servername_callback(cb_wrong_return_type)
2864
2865 with self.assertRaises(ssl.SSLError) as cm, \
2866 support.captured_stderr() as stderr:
2867 stats = server_params_test(client_context, server_context,
2868 chatty=False,
2869 sni_name='supermessage')
2870 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2871 self.assertIn("TypeError", stderr.getvalue())
2872
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002873 def test_read_write_after_close_raises_valuerror(self):
2874 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2875 context.verify_mode = ssl.CERT_REQUIRED
2876 context.load_verify_locations(CERTFILE)
2877 context.load_cert_chain(CERTFILE)
2878 server = ThreadedEchoServer(context=context, chatty=False)
2879
2880 with server:
2881 s = context.wrap_socket(socket.socket())
2882 s.connect((HOST, server.port))
2883 s.close()
2884
2885 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002886 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002887
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002888
Thomas Woutersed03b412007-08-28 21:37:11 +00002889def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002890 if support.verbose:
2891 plats = {
2892 'Linux': platform.linux_distribution,
2893 'Mac': platform.mac_ver,
2894 'Windows': platform.win32_ver,
2895 }
2896 for name, func in plats.items():
2897 plat = func()
2898 if plat and plat[0]:
2899 plat = '%s %r' % (name, plat)
2900 break
2901 else:
2902 plat = repr(platform.platform())
2903 print("test_ssl: testing with %r %r" %
2904 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2905 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002906 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002907 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2908 try:
2909 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2910 except AttributeError:
2911 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002912
Antoine Pitrou152efa22010-05-16 18:19:27 +00002913 for filename in [
2914 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2915 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002916 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002917 BADCERT, BADKEY, EMPTYCERT]:
2918 if not os.path.exists(filename):
2919 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002920
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002921 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002922
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002923 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002924 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002925
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002926 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002927 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002928 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002929 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002930
Antoine Pitrou480a1242010-04-28 21:37:09 +00002931 try:
2932 support.run_unittest(*tests)
2933 finally:
2934 if _have_threads:
2935 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002936
2937if __name__ == "__main__":
2938 test_main()