blob: a44054cc75dcb4b050afaef5be3245e0969c66d0 [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
Thomas Woutersed03b412007-08-28 21:37:11 +000021
Antoine Pitrou05d936d2010-10-13 11:38:36 +000022ssl = support.import_module("ssl")
23
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010024PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000025HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000026
Christian Heimesefff7062013-11-21 03:35:02 +010027def data_file(*name):
28 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000029
Antoine Pitrou81564092010-10-08 23:06:24 +000030# The custom key and certificate files used in test_ssl are generated
31# using Lib/test/make_ssl_certs.py.
32# Other certificates are simply fetched from the Internet servers they
33# are meant to authenticate.
34
Antoine Pitrou152efa22010-05-16 18:19:27 +000035CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000036BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000037ONLYCERT = data_file("ssl_cert.pem")
38ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000039BYTES_ONLYCERT = os.fsencode(ONLYCERT)
40BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020041CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
42ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
43KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000044CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000045BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010046CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
47CAFILE_CACERT = data_file("capath", "5ed36f99.0")
48
Antoine Pitrou152efa22010-05-16 18:19:27 +000049
Christian Heimes22587792013-11-21 23:56:13 +010050# empty CRL
51CRLFILE = data_file("revocation.crl")
52
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010053# Two keys and certs signed by the same CA (for SNI tests)
54SIGNED_CERTFILE = data_file("keycert3.pem")
55SIGNED_CERTFILE2 = data_file("keycert4.pem")
56SIGNING_CA = data_file("pycacert.pem")
57
Antoine Pitrou152efa22010-05-16 18:19:27 +000058SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
59
60EMPTYCERT = data_file("nullcert.pem")
61BADCERT = data_file("badcert.pem")
62WRONGCERT = data_file("XXXnonexisting.pem")
63BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020064NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020065NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000066
Benjamin Petersona7eaf562015-04-02 00:04:06 -040067DHFILE = data_file("dh1024.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +010068BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010070
Thomas Woutersed03b412007-08-28 21:37:11 +000071def handle_error(prefix):
72 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000073 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000074 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000075
Antoine Pitroub5218772010-05-21 09:56:06 +000076def can_clear_options():
77 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020078 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000079
80def no_sslv2_implies_sslv3_hello():
81 # 0.9.7h or higher
82 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
83
Christian Heimes2427b502013-11-23 11:24:32 +010084def have_verify_flags():
85 # 0.9.8 or higher
86 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
87
Christian Heimes9424bb42013-06-17 15:32:57 +020088def asn1time(cert_time):
89 # Some versions of OpenSSL ignore seconds, see #18207
90 # 0.9.8.i
91 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
92 fmt = "%b %d %H:%M:%S %Y GMT"
93 dt = datetime.datetime.strptime(cert_time, fmt)
94 dt = dt.replace(second=0)
95 cert_time = dt.strftime(fmt)
96 # %d adds leading zero but ASN1_TIME_print() uses leading space
97 if cert_time[4] == "0":
98 cert_time = cert_time[:4] + " " + cert_time[5:]
99
100 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000101
Antoine Pitrou23df4832010-08-04 17:14:06 +0000102# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
103def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +0200104 if hasattr(ssl, 'PROTOCOL_SSLv2'):
105 @functools.wraps(func)
106 def f(*args, **kwargs):
107 try:
108 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
109 except ssl.SSLError:
110 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
111 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
112 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
113 return func(*args, **kwargs)
114 return f
115 else:
116 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +0000117
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100118needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
119
Antoine Pitrou23df4832010-08-04 17:14:06 +0000120
Antoine Pitrou152efa22010-05-16 18:19:27 +0000121class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000122
Antoine Pitrou480a1242010-04-28 21:37:09 +0000123 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000124 ssl.CERT_NONE
125 ssl.CERT_OPTIONAL
126 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100127 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100128 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100129 if ssl.HAS_ECDH:
130 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100131 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
132 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000133 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100134 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000135
Antoine Pitrou480a1242010-04-28 21:37:09 +0000136 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000137 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000138 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000139 sys.stdout.write("\n RAND_status is %d (%s)\n"
140 % (v, (v and "sufficient randomness") or
141 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200142
143 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
144 self.assertEqual(len(data), 16)
145 self.assertEqual(is_cryptographic, v == 1)
146 if v:
147 data = ssl.RAND_bytes(16)
148 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200149 else:
150 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200151
Victor Stinner1e81a392013-12-19 16:47:04 +0100152 # negative num is invalid
153 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
154 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
155
Victor Stinnerfcfed192015-01-06 13:54:58 +0100156 if hasattr(ssl, 'RAND_egd'):
157 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)
Ned Deily05784a72015-02-05 17:20:13 +1100294 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000295 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)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -0800677 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000678 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
679 ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -0800680 ctx.options |= ssl.OP_NO_TLSv1
681 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1,
682 ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +0000683 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)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -0500712 # default value
713 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
714 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +0100715 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
716 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
717 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
718 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
719 ctx.verify_flags = ssl.VERIFY_DEFAULT
720 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
721 # supports any value
722 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
723 self.assertEqual(ctx.verify_flags,
724 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
725 with self.assertRaises(TypeError):
726 ctx.verify_flags = None
727
Antoine Pitrou152efa22010-05-16 18:19:27 +0000728 def test_load_cert_chain(self):
729 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
730 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -0500731 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000732 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
733 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200734 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000735 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000736 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000737 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000738 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000739 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000740 ctx.load_cert_chain(EMPTYCERT)
741 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000742 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000743 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
744 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
745 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000746 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000747 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000748 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000749 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000750 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000751 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
752 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000753 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000754 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000755 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200756 # Password protected key and cert
757 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
758 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
759 ctx.load_cert_chain(CERTFILE_PROTECTED,
760 password=bytearray(KEY_PASSWORD.encode()))
761 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
762 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
763 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
764 bytearray(KEY_PASSWORD.encode()))
765 with self.assertRaisesRegex(TypeError, "should be a string"):
766 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
767 with self.assertRaises(ssl.SSLError):
768 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
769 with self.assertRaisesRegex(ValueError, "cannot be longer"):
770 # openssl has a fixed limit on the password buffer.
771 # PEM_BUFSIZE is generally set to 1kb.
772 # Return a string larger than this.
773 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
774 # Password callback
775 def getpass_unicode():
776 return KEY_PASSWORD
777 def getpass_bytes():
778 return KEY_PASSWORD.encode()
779 def getpass_bytearray():
780 return bytearray(KEY_PASSWORD.encode())
781 def getpass_badpass():
782 return "badpass"
783 def getpass_huge():
784 return b'a' * (1024 * 1024)
785 def getpass_bad_type():
786 return 9
787 def getpass_exception():
788 raise Exception('getpass error')
789 class GetPassCallable:
790 def __call__(self):
791 return KEY_PASSWORD
792 def getpass(self):
793 return KEY_PASSWORD
794 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
795 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
796 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
797 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
798 ctx.load_cert_chain(CERTFILE_PROTECTED,
799 password=GetPassCallable().getpass)
800 with self.assertRaises(ssl.SSLError):
801 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
802 with self.assertRaisesRegex(ValueError, "cannot be longer"):
803 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
804 with self.assertRaisesRegex(TypeError, "must return a string"):
805 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
806 with self.assertRaisesRegex(Exception, "getpass error"):
807 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
808 # Make sure the password function isn't called if it isn't needed
809 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000810
811 def test_load_verify_locations(self):
812 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
813 ctx.load_verify_locations(CERTFILE)
814 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
815 ctx.load_verify_locations(BYTES_CERTFILE)
816 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
817 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +0100818 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200819 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000820 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000821 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000822 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000823 ctx.load_verify_locations(BADCERT)
824 ctx.load_verify_locations(CERTFILE, CAPATH)
825 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
826
Victor Stinner80f75e62011-01-29 11:31:20 +0000827 # Issue #10989: crash if the second argument type is invalid
828 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
829
Christian Heimesefff7062013-11-21 03:35:02 +0100830 def test_load_verify_cadata(self):
831 # test cadata
832 with open(CAFILE_CACERT) as f:
833 cacert_pem = f.read()
834 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
835 with open(CAFILE_NEURONIO) as f:
836 neuronio_pem = f.read()
837 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
838
839 # test PEM
840 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
841 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
842 ctx.load_verify_locations(cadata=cacert_pem)
843 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
844 ctx.load_verify_locations(cadata=neuronio_pem)
845 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
846 # cert already in hash table
847 ctx.load_verify_locations(cadata=neuronio_pem)
848 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
849
850 # combined
851 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
852 combined = "\n".join((cacert_pem, neuronio_pem))
853 ctx.load_verify_locations(cadata=combined)
854 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
855
856 # with junk around the certs
857 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
858 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
859 neuronio_pem, "tail"]
860 ctx.load_verify_locations(cadata="\n".join(combined))
861 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
862
863 # test DER
864 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
865 ctx.load_verify_locations(cadata=cacert_der)
866 ctx.load_verify_locations(cadata=neuronio_der)
867 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
868 # cert already in hash table
869 ctx.load_verify_locations(cadata=cacert_der)
870 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
871
872 # combined
873 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
874 combined = b"".join((cacert_der, neuronio_der))
875 ctx.load_verify_locations(cadata=combined)
876 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
877
878 # error cases
879 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
880 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
881
882 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
883 ctx.load_verify_locations(cadata="broken")
884 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
885 ctx.load_verify_locations(cadata=b"broken")
886
887
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100888 def test_load_dh_params(self):
889 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
890 ctx.load_dh_params(DHFILE)
891 if os.name != 'nt':
892 ctx.load_dh_params(BYTES_DHFILE)
893 self.assertRaises(TypeError, ctx.load_dh_params)
894 self.assertRaises(TypeError, ctx.load_dh_params, None)
895 with self.assertRaises(FileNotFoundError) as cm:
896 ctx.load_dh_params(WRONGCERT)
897 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200898 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100899 ctx.load_dh_params(CERTFILE)
900
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000901 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000902 def test_session_stats(self):
903 for proto in PROTOCOLS:
904 ctx = ssl.SSLContext(proto)
905 self.assertEqual(ctx.session_stats(), {
906 'number': 0,
907 'connect': 0,
908 'connect_good': 0,
909 'connect_renegotiate': 0,
910 'accept': 0,
911 'accept_good': 0,
912 'accept_renegotiate': 0,
913 'hits': 0,
914 'misses': 0,
915 'timeouts': 0,
916 'cache_full': 0,
917 })
918
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000919 def test_set_default_verify_paths(self):
920 # There's not much we can do to test that it acts as expected,
921 # so just check it doesn't crash or raise an exception.
922 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
923 ctx.set_default_verify_paths()
924
Antoine Pitrou501da612011-12-21 09:27:41 +0100925 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100926 def test_set_ecdh_curve(self):
927 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
928 ctx.set_ecdh_curve("prime256v1")
929 ctx.set_ecdh_curve(b"prime256v1")
930 self.assertRaises(TypeError, ctx.set_ecdh_curve)
931 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
932 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
933 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
934
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100935 @needs_sni
936 def test_sni_callback(self):
937 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
938
939 # set_servername_callback expects a callable, or None
940 self.assertRaises(TypeError, ctx.set_servername_callback)
941 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
942 self.assertRaises(TypeError, ctx.set_servername_callback, "")
943 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
944
945 def dummycallback(sock, servername, ctx):
946 pass
947 ctx.set_servername_callback(None)
948 ctx.set_servername_callback(dummycallback)
949
950 @needs_sni
951 def test_sni_callback_refcycle(self):
952 # Reference cycles through the servername callback are detected
953 # and cleared.
954 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
955 def dummycallback(sock, servername, ctx, cycle=ctx):
956 pass
957 ctx.set_servername_callback(dummycallback)
958 wr = weakref.ref(ctx)
959 del ctx, dummycallback
960 gc.collect()
961 self.assertIs(wr(), None)
962
Christian Heimes9a5395a2013-06-17 15:44:12 +0200963 def test_cert_store_stats(self):
964 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
965 self.assertEqual(ctx.cert_store_stats(),
966 {'x509_ca': 0, 'crl': 0, 'x509': 0})
967 ctx.load_cert_chain(CERTFILE)
968 self.assertEqual(ctx.cert_store_stats(),
969 {'x509_ca': 0, 'crl': 0, 'x509': 0})
970 ctx.load_verify_locations(CERTFILE)
971 self.assertEqual(ctx.cert_store_stats(),
972 {'x509_ca': 0, 'crl': 0, 'x509': 1})
973 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
974 self.assertEqual(ctx.cert_store_stats(),
975 {'x509_ca': 1, 'crl': 0, 'x509': 2})
976
977 def test_get_ca_certs(self):
978 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
979 self.assertEqual(ctx.get_ca_certs(), [])
980 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
981 ctx.load_verify_locations(CERTFILE)
982 self.assertEqual(ctx.get_ca_certs(), [])
983 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
984 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
985 self.assertEqual(ctx.get_ca_certs(),
986 [{'issuer': ((('organizationName', 'Root CA'),),
987 (('organizationalUnitName', 'http://www.cacert.org'),),
988 (('commonName', 'CA Cert Signing Authority'),),
989 (('emailAddress', 'support@cacert.org'),)),
990 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
991 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
992 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100993 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +0200994 'subject': ((('organizationName', 'Root CA'),),
995 (('organizationalUnitName', 'http://www.cacert.org'),),
996 (('commonName', 'CA Cert Signing Authority'),),
997 (('emailAddress', 'support@cacert.org'),)),
998 'version': 3}])
999
1000 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
1001 pem = f.read()
1002 der = ssl.PEM_cert_to_DER_cert(pem)
1003 self.assertEqual(ctx.get_ca_certs(True), [der])
1004
Christian Heimes72d28502013-11-23 13:56:58 +01001005 def test_load_default_certs(self):
1006 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1007 ctx.load_default_certs()
1008
1009 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1010 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1011 ctx.load_default_certs()
1012
1013 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1014 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1015
1016 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1017 self.assertRaises(TypeError, ctx.load_default_certs, None)
1018 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1019
Benjamin Peterson91244e02014-10-03 18:17:15 -04001020 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001021 def test_load_default_certs_env(self):
1022 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1023 with support.EnvironmentVarGuard() as env:
1024 env["SSL_CERT_DIR"] = CAPATH
1025 env["SSL_CERT_FILE"] = CERTFILE
1026 ctx.load_default_certs()
1027 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1028
Benjamin Peterson91244e02014-10-03 18:17:15 -04001029 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1030 def test_load_default_certs_env_windows(self):
1031 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1032 ctx.load_default_certs()
1033 stats = ctx.cert_store_stats()
1034
1035 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1036 with support.EnvironmentVarGuard() as env:
1037 env["SSL_CERT_DIR"] = CAPATH
1038 env["SSL_CERT_FILE"] = CERTFILE
1039 ctx.load_default_certs()
1040 stats["x509"] += 1
1041 self.assertEqual(ctx.cert_store_stats(), stats)
1042
Christian Heimes4c05b472013-11-23 15:58:30 +01001043 def test_create_default_context(self):
1044 ctx = ssl.create_default_context()
Donald Stufft6a2ba942014-03-23 19:05:28 -04001045 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001046 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001047 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001048 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001049 self.assertEqual(
1050 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1051 getattr(ssl, "OP_NO_COMPRESSION", 0),
1052 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001053
1054 with open(SIGNING_CA) as f:
1055 cadata = f.read()
1056 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1057 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001058 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001059 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1060 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001061 self.assertEqual(
1062 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1063 getattr(ssl, "OP_NO_COMPRESSION", 0),
1064 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001065
1066 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001067 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001068 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1069 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001070 self.assertEqual(
1071 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1072 getattr(ssl, "OP_NO_COMPRESSION", 0),
1073 )
1074 self.assertEqual(
1075 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1076 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1077 )
1078 self.assertEqual(
1079 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1080 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1081 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001082
Christian Heimes67986f92013-11-23 22:43:47 +01001083 def test__create_stdlib_context(self):
1084 ctx = ssl._create_stdlib_context()
1085 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1086 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001087 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001088 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1089
1090 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1091 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1092 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1093 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1094
1095 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001096 cert_reqs=ssl.CERT_REQUIRED,
1097 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001098 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1099 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001100 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001101 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1102
1103 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1104 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1105 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1106 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001107
Christian Heimes1aa9a752013-12-02 02:41:19 +01001108 def test_check_hostname(self):
1109 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1110 self.assertFalse(ctx.check_hostname)
1111
1112 # Requires CERT_REQUIRED or CERT_OPTIONAL
1113 with self.assertRaises(ValueError):
1114 ctx.check_hostname = True
1115 ctx.verify_mode = ssl.CERT_REQUIRED
1116 self.assertFalse(ctx.check_hostname)
1117 ctx.check_hostname = True
1118 self.assertTrue(ctx.check_hostname)
1119
1120 ctx.verify_mode = ssl.CERT_OPTIONAL
1121 ctx.check_hostname = True
1122 self.assertTrue(ctx.check_hostname)
1123
1124 # Cannot set CERT_NONE with check_hostname enabled
1125 with self.assertRaises(ValueError):
1126 ctx.verify_mode = ssl.CERT_NONE
1127 ctx.check_hostname = False
1128 self.assertFalse(ctx.check_hostname)
1129
Antoine Pitrou152efa22010-05-16 18:19:27 +00001130
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001131class SSLErrorTests(unittest.TestCase):
1132
1133 def test_str(self):
1134 # The str() of a SSLError doesn't include the errno
1135 e = ssl.SSLError(1, "foo")
1136 self.assertEqual(str(e), "foo")
1137 self.assertEqual(e.errno, 1)
1138 # Same for a subclass
1139 e = ssl.SSLZeroReturnError(1, "foo")
1140 self.assertEqual(str(e), "foo")
1141 self.assertEqual(e.errno, 1)
1142
1143 def test_lib_reason(self):
1144 # Test the library and reason attributes
1145 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1146 with self.assertRaises(ssl.SSLError) as cm:
1147 ctx.load_dh_params(CERTFILE)
1148 self.assertEqual(cm.exception.library, 'PEM')
1149 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1150 s = str(cm.exception)
1151 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1152
1153 def test_subclass(self):
1154 # Check that the appropriate SSLError subclass is raised
1155 # (this only tests one of them)
1156 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1157 with socket.socket() as s:
1158 s.bind(("127.0.0.1", 0))
1159 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001160 c = socket.socket()
1161 c.connect(s.getsockname())
1162 c.setblocking(False)
1163 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001164 with self.assertRaises(ssl.SSLWantReadError) as cm:
1165 c.do_handshake()
1166 s = str(cm.exception)
1167 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1168 # For compatibility
1169 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1170
1171
Bill Janssen6e027db2007-11-15 22:23:56 +00001172class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001173
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001175 with support.transient_internet("svn.python.org"):
1176 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1177 cert_reqs=ssl.CERT_NONE)
1178 try:
1179 s.connect(("svn.python.org", 443))
1180 self.assertEqual({}, s.getpeercert())
1181 finally:
1182 s.close()
1183
1184 # this should fail because we have no verification certs
1185 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1186 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001187 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1188 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001189 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001190
Antoine Pitrou350c7222010-09-09 13:31:46 +00001191 # this should succeed because we specify the root cert
1192 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1193 cert_reqs=ssl.CERT_REQUIRED,
1194 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1195 try:
1196 s.connect(("svn.python.org", 443))
1197 self.assertTrue(s.getpeercert())
1198 finally:
1199 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001200
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001201 def test_connect_ex(self):
1202 # Issue #11326: check connect_ex() implementation
1203 with support.transient_internet("svn.python.org"):
1204 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1205 cert_reqs=ssl.CERT_REQUIRED,
1206 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1207 try:
1208 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
1209 self.assertTrue(s.getpeercert())
1210 finally:
1211 s.close()
1212
1213 def test_non_blocking_connect_ex(self):
1214 # Issue #11326: non-blocking connect_ex() should allow handshake
1215 # to proceed after the socket gets ready.
1216 with support.transient_internet("svn.python.org"):
1217 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1218 cert_reqs=ssl.CERT_REQUIRED,
1219 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1220 do_handshake_on_connect=False)
1221 try:
1222 s.setblocking(False)
1223 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +00001224 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1225 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001226 # Wait for connect to finish
1227 select.select([], [s], [], 5.0)
1228 # Non-blocking handshake
1229 while True:
1230 try:
1231 s.do_handshake()
1232 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001233 except ssl.SSLWantReadError:
1234 select.select([s], [], [], 5.0)
1235 except ssl.SSLWantWriteError:
1236 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001237 # SSL established
1238 self.assertTrue(s.getpeercert())
1239 finally:
1240 s.close()
1241
Antoine Pitroub4410db2011-05-18 18:51:06 +02001242 def test_timeout_connect_ex(self):
1243 # Issue #12065: on a timeout, connect_ex() should return the original
1244 # errno (mimicking the behaviour of non-SSL sockets).
1245 with support.transient_internet("svn.python.org"):
1246 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1247 cert_reqs=ssl.CERT_REQUIRED,
1248 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1249 do_handshake_on_connect=False)
1250 try:
1251 s.settimeout(0.0000001)
1252 rc = s.connect_ex(('svn.python.org', 443))
1253 if rc == 0:
1254 self.skipTest("svn.python.org responded too quickly")
1255 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1256 finally:
1257 s.close()
1258
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001259 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +01001260 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001261 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1262 cert_reqs=ssl.CERT_REQUIRED,
1263 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1264 try:
Christian Heimesde570742013-12-16 21:15:44 +01001265 rc = s.connect_ex(("svn.python.org", 444))
1266 # Issue #19919: Windows machines or VMs hosted on Windows
1267 # machines sometimes return EWOULDBLOCK.
1268 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001269 finally:
1270 s.close()
1271
Antoine Pitrou152efa22010-05-16 18:19:27 +00001272 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001273 with support.transient_internet("svn.python.org"):
1274 # Same as test_connect, but with a separately created context
1275 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1276 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1277 s.connect(("svn.python.org", 443))
1278 try:
1279 self.assertEqual({}, s.getpeercert())
1280 finally:
1281 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +00001282 # Same with a server hostname
1283 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1284 server_hostname="svn.python.org")
Benjamin Peterson7243b572014-11-23 17:04:34 -06001285 s.connect(("svn.python.org", 443))
1286 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001287 # This should fail because we have no verification certs
1288 ctx.verify_mode = ssl.CERT_REQUIRED
1289 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +00001290 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +00001291 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001292 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001293 # This should succeed because we specify the root cert
1294 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1295 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1296 s.connect(("svn.python.org", 443))
1297 try:
1298 cert = s.getpeercert()
1299 self.assertTrue(cert)
1300 finally:
1301 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001302
1303 def test_connect_capath(self):
1304 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001305 # NOTE: the subject hashing algorithm has been changed between
1306 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1307 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001308 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +00001309 with support.transient_internet("svn.python.org"):
1310 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1311 ctx.verify_mode = ssl.CERT_REQUIRED
1312 ctx.load_verify_locations(capath=CAPATH)
1313 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1314 s.connect(("svn.python.org", 443))
1315 try:
1316 cert = s.getpeercert()
1317 self.assertTrue(cert)
1318 finally:
1319 s.close()
1320 # Same with a bytes `capath` argument
1321 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1322 ctx.verify_mode = ssl.CERT_REQUIRED
1323 ctx.load_verify_locations(capath=BYTES_CAPATH)
1324 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1325 s.connect(("svn.python.org", 443))
1326 try:
1327 cert = s.getpeercert()
1328 self.assertTrue(cert)
1329 finally:
1330 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001331
Christian Heimesefff7062013-11-21 03:35:02 +01001332 def test_connect_cadata(self):
1333 with open(CAFILE_CACERT) as f:
1334 pem = f.read()
1335 der = ssl.PEM_cert_to_DER_cert(pem)
1336 with support.transient_internet("svn.python.org"):
1337 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1338 ctx.verify_mode = ssl.CERT_REQUIRED
1339 ctx.load_verify_locations(cadata=pem)
1340 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1341 s.connect(("svn.python.org", 443))
1342 cert = s.getpeercert()
1343 self.assertTrue(cert)
1344
1345 # same with DER
1346 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1347 ctx.verify_mode = ssl.CERT_REQUIRED
1348 ctx.load_verify_locations(cadata=der)
1349 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1350 s.connect(("svn.python.org", 443))
1351 cert = s.getpeercert()
1352 self.assertTrue(cert)
1353
Antoine Pitroue3220242010-04-24 11:13:53 +00001354 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1355 def test_makefile_close(self):
1356 # Issue #5238: creating a file-like object with makefile() shouldn't
1357 # delay closing the underlying "real socket" (here tested with its
1358 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001359 with support.transient_internet("svn.python.org"):
1360 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1361 ss.connect(("svn.python.org", 443))
1362 fd = ss.fileno()
1363 f = ss.makefile()
1364 f.close()
1365 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001366 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001367 # Closing the SSL socket should close the fd too
1368 ss.close()
1369 gc.collect()
1370 with self.assertRaises(OSError) as e:
1371 os.read(fd, 0)
1372 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001373
Antoine Pitrou480a1242010-04-28 21:37:09 +00001374 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001375 with support.transient_internet("svn.python.org"):
1376 s = socket.socket(socket.AF_INET)
1377 s.connect(("svn.python.org", 443))
1378 s.setblocking(False)
1379 s = ssl.wrap_socket(s,
1380 cert_reqs=ssl.CERT_NONE,
1381 do_handshake_on_connect=False)
1382 count = 0
1383 while True:
1384 try:
1385 count += 1
1386 s.do_handshake()
1387 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001388 except ssl.SSLWantReadError:
1389 select.select([s], [], [])
1390 except ssl.SSLWantWriteError:
1391 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001392 s.close()
1393 if support.verbose:
1394 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001397 def _test_get_server_certificate(host, port, cert=None):
1398 with support.transient_internet(host):
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001399 pem = ssl.get_server_certificate((host, port),
1400 ssl.PROTOCOL_SSLv23)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001401 if not pem:
1402 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001403
Antoine Pitrou15399c32011-04-28 19:23:55 +02001404 try:
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001405 pem = ssl.get_server_certificate((host, port),
1406 ssl.PROTOCOL_SSLv23,
1407 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001408 except ssl.SSLError as x:
1409 #should fail
1410 if support.verbose:
1411 sys.stdout.write("%s\n" % x)
1412 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001413 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1414
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001415 pem = ssl.get_server_certificate((host, port),
1416 ssl.PROTOCOL_SSLv23,
1417 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001418 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001419 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001420 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001421 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001422
Antoine Pitrou15399c32011-04-28 19:23:55 +02001423 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1424 if support.IPV6_ENABLED:
1425 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001426
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001427 def test_ciphers(self):
1428 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001429 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001430 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1431 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1432 s.connect(remote)
1433 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1434 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1435 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001436 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001437 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001438 with socket.socket(socket.AF_INET) as sock:
1439 s = ssl.wrap_socket(sock,
1440 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1441 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001442
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001443 def test_algorithms(self):
1444 # Issue #8484: all algorithms should be available when verifying a
1445 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001446 # SHA256 was added in OpenSSL 0.9.8
1447 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1448 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001449 # sha256.tbs-internet.com needs SNI to use the correct certificate
1450 if not ssl.HAS_SNI:
1451 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001452 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1453 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001454 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001455 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001456 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1457 ctx.verify_mode = ssl.CERT_REQUIRED
1458 ctx.load_verify_locations(sha256_cert)
1459 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1460 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001461 try:
1462 s.connect(remote)
1463 if support.verbose:
1464 sys.stdout.write("\nCipher with %r is %r\n" %
1465 (remote, s.cipher()))
1466 sys.stdout.write("Certificate is:\n%s\n" %
1467 pprint.pformat(s.getpeercert()))
1468 finally:
1469 s.close()
1470
Christian Heimes9a5395a2013-06-17 15:44:12 +02001471 def test_get_ca_certs_capath(self):
1472 # capath certs are loaded on request
1473 with support.transient_internet("svn.python.org"):
1474 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1475 ctx.verify_mode = ssl.CERT_REQUIRED
1476 ctx.load_verify_locations(capath=CAPATH)
1477 self.assertEqual(ctx.get_ca_certs(), [])
1478 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1479 s.connect(("svn.python.org", 443))
1480 try:
1481 cert = s.getpeercert()
1482 self.assertTrue(cert)
1483 finally:
1484 s.close()
1485 self.assertEqual(len(ctx.get_ca_certs()), 1)
1486
Christian Heimes575596e2013-12-15 21:49:17 +01001487 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001488 def test_context_setget(self):
1489 # Check that the context of a connected socket can be replaced.
1490 with support.transient_internet("svn.python.org"):
1491 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1492 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1493 s = socket.socket(socket.AF_INET)
1494 with ctx1.wrap_socket(s) as ss:
1495 ss.connect(("svn.python.org", 443))
1496 self.assertIs(ss.context, ctx1)
1497 self.assertIs(ss._sslobj.context, ctx1)
1498 ss.context = ctx2
1499 self.assertIs(ss.context, ctx2)
1500 self.assertIs(ss._sslobj.context, ctx2)
1501
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001502try:
1503 import threading
1504except ImportError:
1505 _have_threads = False
1506else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001507 _have_threads = True
1508
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001509 from test.ssl_servers import make_https_server
1510
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001511 class ThreadedEchoServer(threading.Thread):
1512
1513 class ConnectionHandler(threading.Thread):
1514
1515 """A mildly complicated class, because we want it to work both
1516 with and without the SSL wrapper around the socket connection, so
1517 that we can test the STARTTLS functionality."""
1518
Bill Janssen6e027db2007-11-15 22:23:56 +00001519 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001520 self.server = server
1521 self.running = False
1522 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001523 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001524 self.sock.setblocking(1)
1525 self.sslconn = None
1526 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001527 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001528
Antoine Pitrou480a1242010-04-28 21:37:09 +00001529 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001531 self.sslconn = self.server.context.wrap_socket(
1532 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001533 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001534 except (ssl.SSLError, ConnectionResetError) as e:
1535 # We treat ConnectionResetError as though it were an
1536 # SSLError - OpenSSL on Ubuntu abruptly closes the
1537 # connection when asked to use an unsupported protocol.
1538 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001539 # XXX Various errors can have happened here, for example
1540 # a mismatching protocol version, an invalid certificate,
1541 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001542 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001543 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001544 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001545 self.running = False
1546 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001547 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001548 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001549 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001550 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001551 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001552 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001553 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1554 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001555 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001556 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1557 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001558 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001559 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001560 sys.stdout.write(" server: selected protocol is now "
1561 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001562 return True
1563
1564 def read(self):
1565 if self.sslconn:
1566 return self.sslconn.read()
1567 else:
1568 return self.sock.recv(1024)
1569
1570 def write(self, bytes):
1571 if self.sslconn:
1572 return self.sslconn.write(bytes)
1573 else:
1574 return self.sock.send(bytes)
1575
1576 def close(self):
1577 if self.sslconn:
1578 self.sslconn.close()
1579 else:
1580 self.sock.close()
1581
Antoine Pitrou480a1242010-04-28 21:37:09 +00001582 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001583 self.running = True
1584 if not self.server.starttls_server:
1585 if not self.wrap_conn():
1586 return
1587 while self.running:
1588 try:
1589 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001590 stripped = msg.strip()
1591 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001592 # eof, so quit this handler
1593 self.running = False
1594 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001595 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001596 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001597 sys.stdout.write(" server: client closed connection\n")
1598 self.close()
1599 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001600 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001601 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001602 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001603 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001604 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001605 if not self.wrap_conn():
1606 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001607 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001608 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001609 if support.verbose and self.server.connectionchatty:
1610 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001611 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001612 self.sock = self.sslconn.unwrap()
1613 self.sslconn = None
1614 if support.verbose and self.server.connectionchatty:
1615 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001616 elif stripped == b'CB tls-unique':
1617 if support.verbose and self.server.connectionchatty:
1618 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1619 data = self.sslconn.get_channel_binding("tls-unique")
1620 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001621 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001622 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001623 self.server.connectionchatty):
1624 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001625 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1626 % (msg, ctype, msg.lower(), ctype))
1627 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001628 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001629 if self.server.chatty:
1630 handle_error("Test server failure:\n")
1631 self.close()
1632 self.running = False
1633 # normally, we'd just stop here, but for the test
1634 # harness, we want to stop the server
1635 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636
Antoine Pitroub5218772010-05-21 09:56:06 +00001637 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001638 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001639 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001640 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001641 if context:
1642 self.context = context
1643 else:
1644 self.context = ssl.SSLContext(ssl_version
1645 if ssl_version is not None
1646 else ssl.PROTOCOL_TLSv1)
1647 self.context.verify_mode = (certreqs if certreqs is not None
1648 else ssl.CERT_NONE)
1649 if cacerts:
1650 self.context.load_verify_locations(cacerts)
1651 if certificate:
1652 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001653 if npn_protocols:
1654 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001655 if ciphers:
1656 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001657 self.chatty = chatty
1658 self.connectionchatty = connectionchatty
1659 self.starttls_server = starttls_server
1660 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001661 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001662 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001663 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001664 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001665 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001666 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001667 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001668
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001669 def __enter__(self):
1670 self.start(threading.Event())
1671 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001672 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001673
1674 def __exit__(self, *args):
1675 self.stop()
1676 self.join()
1677
Antoine Pitrou480a1242010-04-28 21:37:09 +00001678 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001679 self.flag = flag
1680 threading.Thread.start(self)
1681
Antoine Pitrou480a1242010-04-28 21:37:09 +00001682 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001683 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001684 self.sock.listen(5)
1685 self.active = True
1686 if self.flag:
1687 # signal an event
1688 self.flag.set()
1689 while self.active:
1690 try:
1691 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001692 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001693 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001694 + repr(connaddr) + '\n')
1695 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001696 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001697 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001698 except socket.timeout:
1699 pass
1700 except KeyboardInterrupt:
1701 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001702 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001703
Antoine Pitrou480a1242010-04-28 21:37:09 +00001704 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001705 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001706
Bill Janssen54cc54c2007-12-14 22:08:56 +00001707 class AsyncoreEchoServer(threading.Thread):
1708
1709 # this one's based on asyncore.dispatcher
1710
1711 class EchoServer (asyncore.dispatcher):
1712
1713 class ConnectionHandler (asyncore.dispatcher_with_send):
1714
1715 def __init__(self, conn, certfile):
1716 self.socket = ssl.wrap_socket(conn, server_side=True,
1717 certfile=certfile,
1718 do_handshake_on_connect=False)
1719 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001720 self._ssl_accepting = True
1721 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001722
1723 def readable(self):
1724 if isinstance(self.socket, ssl.SSLSocket):
1725 while self.socket.pending() > 0:
1726 self.handle_read_event()
1727 return True
1728
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001729 def _do_ssl_handshake(self):
1730 try:
1731 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001732 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1733 return
1734 except ssl.SSLEOFError:
1735 return self.handle_close()
1736 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001737 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001738 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001739 if err.args[0] == errno.ECONNABORTED:
1740 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001741 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001742 self._ssl_accepting = False
1743
1744 def handle_read(self):
1745 if self._ssl_accepting:
1746 self._do_ssl_handshake()
1747 else:
1748 data = self.recv(1024)
1749 if support.verbose:
1750 sys.stdout.write(" server: read %s from client\n" % repr(data))
1751 if not data:
1752 self.close()
1753 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001754 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001755
1756 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001757 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001758 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001759 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1760
1761 def handle_error(self):
1762 raise
1763
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001764 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001765 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001766 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1767 self.port = support.bind_port(sock, '')
1768 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001769 self.listen(5)
1770
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001771 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001772 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001773 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1774 self.ConnectionHandler(sock_obj, self.certfile)
1775
1776 def handle_error(self):
1777 raise
1778
Trent Nelson78520002008-04-10 20:54:35 +00001779 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001780 self.flag = None
1781 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001782 self.server = self.EchoServer(certfile)
1783 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001784 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001785 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001786
1787 def __str__(self):
1788 return "<%s %s>" % (self.__class__.__name__, self.server)
1789
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001790 def __enter__(self):
1791 self.start(threading.Event())
1792 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001793 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001794
1795 def __exit__(self, *args):
1796 if support.verbose:
1797 sys.stdout.write(" cleanup: stopping server.\n")
1798 self.stop()
1799 if support.verbose:
1800 sys.stdout.write(" cleanup: joining server thread.\n")
1801 self.join()
1802 if support.verbose:
1803 sys.stdout.write(" cleanup: successfully joined.\n")
1804
Bill Janssen54cc54c2007-12-14 22:08:56 +00001805 def start (self, flag=None):
1806 self.flag = flag
1807 threading.Thread.start(self)
1808
Antoine Pitrou480a1242010-04-28 21:37:09 +00001809 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001810 self.active = True
1811 if self.flag:
1812 self.flag.set()
1813 while self.active:
1814 try:
1815 asyncore.loop(1)
1816 except:
1817 pass
1818
Antoine Pitrou480a1242010-04-28 21:37:09 +00001819 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001820 self.active = False
1821 self.server.close()
1822
Antoine Pitrou480a1242010-04-28 21:37:09 +00001823 def bad_cert_test(certfile):
1824 """
1825 Launch a server with CERT_REQUIRED, and check that trying to
1826 connect to it with the given client certificate fails.
1827 """
Trent Nelson78520002008-04-10 20:54:35 +00001828 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001829 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001830 cacerts=CERTFILE, chatty=False,
1831 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001832 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001833 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001834 with socket.socket() as sock:
1835 s = ssl.wrap_socket(sock,
1836 certfile=certfile,
1837 ssl_version=ssl.PROTOCOL_TLSv1)
1838 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001839 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001840 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001841 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001842 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001843 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001844 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001845 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001846 if x.errno != errno.ENOENT:
1847 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001848 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001849 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001850 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001851 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001852
Antoine Pitroub5218772010-05-21 09:56:06 +00001853 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001854 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001855 """
1856 Launch a server, connect a client to it and try various reads
1857 and writes.
1858 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001859 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001860 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001861 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001862 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001863 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001864 with client_context.wrap_socket(socket.socket(),
1865 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001866 s.connect((HOST, server.port))
1867 for arg in [indata, bytearray(indata), memoryview(indata)]:
1868 if connectionchatty:
1869 if support.verbose:
1870 sys.stdout.write(
1871 " client: sending %r...\n" % indata)
1872 s.write(arg)
1873 outdata = s.read()
1874 if connectionchatty:
1875 if support.verbose:
1876 sys.stdout.write(" client: read %r\n" % outdata)
1877 if outdata != indata.lower():
1878 raise AssertionError(
1879 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1880 % (outdata[:20], len(outdata),
1881 indata[:20].lower(), len(indata)))
1882 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001883 if connectionchatty:
1884 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001885 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001886 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001887 'compression': s.compression(),
1888 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001889 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001890 'client_npn_protocol': s.selected_npn_protocol()
1891 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001892 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001893 stats['server_npn_protocols'] = server.selected_protocols
1894 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001895
Antoine Pitroub5218772010-05-21 09:56:06 +00001896 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1897 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001898 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001899 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001900 certtype = {
1901 ssl.CERT_NONE: "CERT_NONE",
1902 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1903 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1904 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001905 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001906 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001907 sys.stdout.write(formatstr %
1908 (ssl.get_protocol_name(client_protocol),
1909 ssl.get_protocol_name(server_protocol),
1910 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001911 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001912 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001913 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001914 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001915
1916 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1917 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1918 # starting from OpenSSL 1.0.0 (see issue #8322).
1919 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1920 client_context.set_ciphers("ALL")
1921
Antoine Pitroub5218772010-05-21 09:56:06 +00001922 for ctx in (client_context, server_context):
1923 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001924 ctx.load_cert_chain(CERTFILE)
1925 ctx.load_verify_locations(CERTFILE)
1926 try:
1927 server_params_test(client_context, server_context,
1928 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001929 # Protocol mismatch can result in either an SSLError, or a
1930 # "Connection reset by peer" error.
1931 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001932 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001933 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001934 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001935 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001936 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001937 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001938 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001939 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001940 "Client protocol %s succeeded with server protocol %s!"
1941 % (ssl.get_protocol_name(client_protocol),
1942 ssl.get_protocol_name(server_protocol)))
1943
1944
Bill Janssen6e027db2007-11-15 22:23:56 +00001945 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001946
Antoine Pitrou23df4832010-08-04 17:14:06 +00001947 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001948 def test_echo(self):
1949 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001950 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001951 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001952 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001953 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1954 context = ssl.SSLContext(protocol)
1955 context.load_cert_chain(CERTFILE)
1956 server_params_test(context, context,
1957 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001958
Antoine Pitrou480a1242010-04-28 21:37:09 +00001959 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001960 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001961 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001962 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1963 context.verify_mode = ssl.CERT_REQUIRED
1964 context.load_verify_locations(CERTFILE)
1965 context.load_cert_chain(CERTFILE)
1966 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001967 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001968 s = context.wrap_socket(socket.socket(),
1969 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001970 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001971 # getpeercert() raise ValueError while the handshake isn't
1972 # done.
1973 with self.assertRaises(ValueError):
1974 s.getpeercert()
1975 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001976 cert = s.getpeercert()
1977 self.assertTrue(cert, "Can't get peer certificate.")
1978 cipher = s.cipher()
1979 if support.verbose:
1980 sys.stdout.write(pprint.pformat(cert) + '\n')
1981 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1982 if 'subject' not in cert:
1983 self.fail("No subject field in certificate: %s." %
1984 pprint.pformat(cert))
1985 if ((('organizationName', 'Python Software Foundation'),)
1986 not in cert['subject']):
1987 self.fail(
1988 "Missing or invalid 'organizationName' field in certificate subject; "
1989 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001990 self.assertIn('notBefore', cert)
1991 self.assertIn('notAfter', cert)
1992 before = ssl.cert_time_to_seconds(cert['notBefore'])
1993 after = ssl.cert_time_to_seconds(cert['notAfter'])
1994 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001995 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001996
Christian Heimes2427b502013-11-23 11:24:32 +01001997 @unittest.skipUnless(have_verify_flags(),
1998 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001999 def test_crl_check(self):
2000 if support.verbose:
2001 sys.stdout.write("\n")
2002
2003 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2004 server_context.load_cert_chain(SIGNED_CERTFILE)
2005
2006 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2007 context.verify_mode = ssl.CERT_REQUIRED
2008 context.load_verify_locations(SIGNING_CA)
Benjamin Petersonc3d9c5c2015-03-04 23:18:48 -05002009 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2010 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01002011
2012 # VERIFY_DEFAULT should pass
2013 server = ThreadedEchoServer(context=server_context, chatty=True)
2014 with server:
2015 with context.wrap_socket(socket.socket()) as s:
2016 s.connect((HOST, server.port))
2017 cert = s.getpeercert()
2018 self.assertTrue(cert, "Can't get peer certificate.")
2019
2020 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002021 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01002022
2023 server = ThreadedEchoServer(context=server_context, chatty=True)
2024 with server:
2025 with context.wrap_socket(socket.socket()) as s:
2026 with self.assertRaisesRegex(ssl.SSLError,
2027 "certificate verify failed"):
2028 s.connect((HOST, server.port))
2029
2030 # now load a CRL file. The CRL file is signed by the CA.
2031 context.load_verify_locations(CRLFILE)
2032
2033 server = ThreadedEchoServer(context=server_context, chatty=True)
2034 with server:
2035 with context.wrap_socket(socket.socket()) as s:
2036 s.connect((HOST, server.port))
2037 cert = s.getpeercert()
2038 self.assertTrue(cert, "Can't get peer certificate.")
2039
Christian Heimes1aa9a752013-12-02 02:41:19 +01002040 def test_check_hostname(self):
2041 if support.verbose:
2042 sys.stdout.write("\n")
2043
2044 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2045 server_context.load_cert_chain(SIGNED_CERTFILE)
2046
2047 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2048 context.verify_mode = ssl.CERT_REQUIRED
2049 context.check_hostname = True
2050 context.load_verify_locations(SIGNING_CA)
2051
2052 # correct hostname should verify
2053 server = ThreadedEchoServer(context=server_context, chatty=True)
2054 with server:
2055 with context.wrap_socket(socket.socket(),
2056 server_hostname="localhost") as s:
2057 s.connect((HOST, server.port))
2058 cert = s.getpeercert()
2059 self.assertTrue(cert, "Can't get peer certificate.")
2060
2061 # incorrect hostname should raise an exception
2062 server = ThreadedEchoServer(context=server_context, chatty=True)
2063 with server:
2064 with context.wrap_socket(socket.socket(),
2065 server_hostname="invalid") as s:
2066 with self.assertRaisesRegex(ssl.CertificateError,
2067 "hostname 'invalid' doesn't match 'localhost'"):
2068 s.connect((HOST, server.port))
2069
2070 # missing server_hostname arg should cause an exception, too
2071 server = ThreadedEchoServer(context=server_context, chatty=True)
2072 with server:
2073 with socket.socket() as s:
2074 with self.assertRaisesRegex(ValueError,
2075 "check_hostname requires server_hostname"):
2076 context.wrap_socket(s)
2077
Antoine Pitrou480a1242010-04-28 21:37:09 +00002078 def test_empty_cert(self):
2079 """Connecting with an empty cert file"""
2080 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2081 "nullcert.pem"))
2082 def test_malformed_cert(self):
2083 """Connecting with a badly formatted certificate (syntax error)"""
2084 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2085 "badcert.pem"))
2086 def test_nonexisting_cert(self):
2087 """Connecting with a non-existing cert file"""
2088 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2089 "wrongcert.pem"))
2090 def test_malformed_key(self):
2091 """Connecting with a badly formatted key (syntax error)"""
2092 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2093 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002094
Antoine Pitrou480a1242010-04-28 21:37:09 +00002095 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002096 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002097 in the client when attempting handshake.
2098 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002099 listener_ready = threading.Event()
2100 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002101
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002102 s = socket.socket()
2103 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002104
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002105 # `listener` runs in a thread. It sits in an accept() until
2106 # the main thread connects. Then it rudely closes the socket,
2107 # and sets Event `listener_gone` to let the main thread know
2108 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002109 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00002110 s.listen(5)
2111 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002112 newsock, addr = s.accept()
2113 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002114 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002115 listener_gone.set()
2116
2117 def connector():
2118 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002119 with socket.socket() as c:
2120 c.connect((HOST, port))
2121 listener_gone.wait()
2122 try:
2123 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002124 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002125 pass
2126 else:
2127 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002128
2129 t = threading.Thread(target=listener)
2130 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002131 try:
2132 connector()
2133 finally:
2134 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002135
Antoine Pitrou23df4832010-08-04 17:14:06 +00002136 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002137 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2138 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002139 def test_protocol_sslv2(self):
2140 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002141 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002142 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002143 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2144 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2145 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002146 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Victor Stinner3f7e0642014-12-12 12:27:08 +01002147 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2148 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002149 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002150 # SSLv23 client with specific SSL options
2151 if no_sslv2_implies_sslv3_hello():
2152 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2153 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2154 client_options=ssl.OP_NO_SSLv2)
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_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002157 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002158 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002159
Antoine Pitrou23df4832010-08-04 17:14:06 +00002160 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002161 def test_protocol_sslv23(self):
2162 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002163 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002164 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002165 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2166 try:
2167 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002168 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002169 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2170 if support.verbose:
2171 sys.stdout.write(
2172 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2173 % str(x))
Benjamin Petersone32467c2014-12-05 21:59:35 -05002174 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002175 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002176 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
2177 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002178
Benjamin Petersone32467c2014-12-05 21:59:35 -05002179 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002180 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002181 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
2182 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002183
Benjamin Petersone32467c2014-12-05 21:59:35 -05002184 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002185 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002186 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
2187 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002188
Antoine Pitroub5218772010-05-21 09:56:06 +00002189 # Server with specific SSL options
Benjamin Petersone32467c2014-12-05 21:59:35 -05002190 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2191 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002192 server_options=ssl.OP_NO_SSLv3)
2193 # Will choose TLSv1
2194 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2195 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2196 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2197 server_options=ssl.OP_NO_TLSv1)
2198
2199
Antoine Pitrou23df4832010-08-04 17:14:06 +00002200 @skip_if_broken_ubuntu_ssl
Benjamin Petersone32467c2014-12-05 21:59:35 -05002201 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2202 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002203 def test_protocol_sslv3(self):
2204 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002205 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002206 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002207 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
2208 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2209 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002210 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2211 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002212 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2213 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002214 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002215 if no_sslv2_implies_sslv3_hello():
2216 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002217 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2218 False, client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002219
Antoine Pitrou23df4832010-08-04 17:14:06 +00002220 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002221 def test_protocol_tlsv1(self):
2222 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002223 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002224 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002225 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
2226 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
2227 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002228 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2229 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002230 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2231 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002232 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2233 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002234
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002235 @skip_if_broken_ubuntu_ssl
2236 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2237 "TLS version 1.1 not supported.")
2238 def test_protocol_tlsv1_1(self):
2239 """Connecting to a TLSv1.1 server with various client options.
2240 Testing against older TLS versions."""
2241 if support.verbose:
2242 sys.stdout.write("\n")
2243 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
2244 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2245 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002246 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2247 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002248 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2249 client_options=ssl.OP_NO_TLSv1_1)
2250
2251 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
2252 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2253 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2254
2255
2256 @skip_if_broken_ubuntu_ssl
2257 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2258 "TLS version 1.2 not supported.")
2259 def test_protocol_tlsv1_2(self):
2260 """Connecting to a TLSv1.2 server with various client options.
2261 Testing against older TLS versions."""
2262 if support.verbose:
2263 sys.stdout.write("\n")
2264 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
2265 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2266 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2267 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2268 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002269 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2270 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002271 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2272 client_options=ssl.OP_NO_TLSv1_2)
2273
2274 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
2275 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2276 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2277 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2278 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2279
Antoine Pitrou480a1242010-04-28 21:37:09 +00002280 def test_starttls(self):
2281 """Switching from clear text to encrypted and back again."""
2282 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 +00002283
Trent Nelson78520002008-04-10 20:54:35 +00002284 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002285 ssl_version=ssl.PROTOCOL_TLSv1,
2286 starttls_server=True,
2287 chatty=True,
2288 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002289 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002290 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002291 s = socket.socket()
2292 s.setblocking(1)
2293 s.connect((HOST, server.port))
2294 if support.verbose:
2295 sys.stdout.write("\n")
2296 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002297 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002298 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002299 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002300 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002301 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002302 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002303 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002304 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002305 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002306 msg = outdata.strip().lower()
2307 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2308 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002309 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002310 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002311 " client: read %r from server, starting TLS...\n"
2312 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002313 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2314 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002315 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2316 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002317 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002318 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002319 " client: read %r from server, ending TLS...\n"
2320 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002321 s = conn.unwrap()
2322 wrapped = False
2323 else:
2324 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002325 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002326 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002327 if support.verbose:
2328 sys.stdout.write(" client: closing connection.\n")
2329 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002330 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002331 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002332 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002333 if wrapped:
2334 conn.close()
2335 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002336 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002337
Antoine Pitrou480a1242010-04-28 21:37:09 +00002338 def test_socketserver(self):
2339 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002340 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002341 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002342 if support.verbose:
2343 sys.stdout.write('\n')
2344 with open(CERTFILE, 'rb') as f:
2345 d1 = f.read()
2346 d2 = ''
2347 # now fetch the same data from the HTTPS server
Benjamin Peterson4ffb0752014-11-03 14:29:33 -05002348 url = 'https://localhost:%d/%s' % (
2349 server.port, os.path.split(CERTFILE)[1])
2350 context = ssl.create_default_context(cafile=CERTFILE)
2351 f = urllib.request.urlopen(url, context=context)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002352 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002353 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002354 if dlen and (int(dlen) > 0):
2355 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002356 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002357 sys.stdout.write(
2358 " client: read %d bytes from remote server '%s'\n"
2359 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002360 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002361 f.close()
2362 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002363
Antoine Pitrou480a1242010-04-28 21:37:09 +00002364 def test_asyncore_server(self):
2365 """Check the example asyncore integration."""
2366 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002367
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002368 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002369 sys.stdout.write("\n")
2370
Antoine Pitrou480a1242010-04-28 21:37:09 +00002371 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002372 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002373 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002374 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002375 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002376 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002377 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002378 " client: sending %r...\n" % indata)
2379 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002380 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002381 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002382 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002383 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002384 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002385 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2386 % (outdata[:20], len(outdata),
2387 indata[:20].lower(), len(indata)))
2388 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002389 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002390 sys.stdout.write(" client: closing connection.\n")
2391 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002392 if support.verbose:
2393 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002394
Antoine Pitrou480a1242010-04-28 21:37:09 +00002395 def test_recv_send(self):
2396 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002397 if support.verbose:
2398 sys.stdout.write("\n")
2399
2400 server = ThreadedEchoServer(CERTFILE,
2401 certreqs=ssl.CERT_NONE,
2402 ssl_version=ssl.PROTOCOL_TLSv1,
2403 cacerts=CERTFILE,
2404 chatty=True,
2405 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002406 with server:
2407 s = ssl.wrap_socket(socket.socket(),
2408 server_side=False,
2409 certfile=CERTFILE,
2410 ca_certs=CERTFILE,
2411 cert_reqs=ssl.CERT_NONE,
2412 ssl_version=ssl.PROTOCOL_TLSv1)
2413 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002414 # helper methods for standardising recv* method signatures
2415 def _recv_into():
2416 b = bytearray(b"\0"*100)
2417 count = s.recv_into(b)
2418 return b[:count]
2419
2420 def _recvfrom_into():
2421 b = bytearray(b"\0"*100)
2422 count, addr = s.recvfrom_into(b)
2423 return b[:count]
2424
2425 # (name, method, whether to expect success, *args)
2426 send_methods = [
2427 ('send', s.send, True, []),
2428 ('sendto', s.sendto, False, ["some.address"]),
2429 ('sendall', s.sendall, True, []),
2430 ]
2431 recv_methods = [
2432 ('recv', s.recv, True, []),
2433 ('recvfrom', s.recvfrom, False, ["some.address"]),
2434 ('recv_into', _recv_into, True, []),
2435 ('recvfrom_into', _recvfrom_into, False, []),
2436 ]
2437 data_prefix = "PREFIX_"
2438
2439 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002440 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002441 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002442 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002443 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002444 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002445 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002446 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002447 "<<{outdata:r}>> ({nout:d}) received; "
2448 "expected <<{indata:r}>> ({nin:d})\n".format(
2449 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002450 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002451 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002452 )
2453 )
2454 except ValueError as e:
2455 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002456 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002457 "Failed to send with method <<{name:s}>>; "
2458 "expected to succeed.\n".format(name=meth_name)
2459 )
2460 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002461 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002462 "Method <<{name:s}>> failed with unexpected "
2463 "exception message: {exp:s}\n".format(
2464 name=meth_name, exp=e
2465 )
2466 )
2467
2468 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002469 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002470 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002471 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002472 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002473 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002474 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002475 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002476 "<<{outdata:r}>> ({nout:d}) received; "
2477 "expected <<{indata:r}>> ({nin:d})\n".format(
2478 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002479 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002480 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002481 )
2482 )
2483 except ValueError as e:
2484 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002485 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002486 "Failed to receive with method <<{name:s}>>; "
2487 "expected to succeed.\n".format(name=meth_name)
2488 )
2489 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002490 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002491 "Method <<{name:s}>> failed with unexpected "
2492 "exception message: {exp:s}\n".format(
2493 name=meth_name, exp=e
2494 )
2495 )
2496 # consume data
2497 s.read()
2498
Nick Coghlan513886a2011-08-28 00:00:27 +10002499 # Make sure sendmsg et al are disallowed to avoid
2500 # inadvertent disclosure of data and/or corruption
2501 # of the encrypted data stream
2502 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2503 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2504 self.assertRaises(NotImplementedError,
2505 s.recvmsg_into, bytearray(100))
2506
Antoine Pitrou480a1242010-04-28 21:37:09 +00002507 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002508 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002509
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002510 def test_handshake_timeout(self):
2511 # Issue #5103: SSL handshake must respect the socket timeout
2512 server = socket.socket(socket.AF_INET)
2513 host = "127.0.0.1"
2514 port = support.bind_port(server)
2515 started = threading.Event()
2516 finish = False
2517
2518 def serve():
2519 server.listen(5)
2520 started.set()
2521 conns = []
2522 while not finish:
2523 r, w, e = select.select([server], [], [], 0.1)
2524 if server in r:
2525 # Let the socket hang around rather than having
2526 # it closed by garbage collection.
2527 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002528 for sock in conns:
2529 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002530
2531 t = threading.Thread(target=serve)
2532 t.start()
2533 started.wait()
2534
2535 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002536 try:
2537 c = socket.socket(socket.AF_INET)
2538 c.settimeout(0.2)
2539 c.connect((host, port))
2540 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002541 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002542 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002543 finally:
2544 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002545 try:
2546 c = socket.socket(socket.AF_INET)
2547 c = ssl.wrap_socket(c)
2548 c.settimeout(0.2)
2549 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002550 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002551 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002552 finally:
2553 c.close()
2554 finally:
2555 finish = True
2556 t.join()
2557 server.close()
2558
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002559 def test_server_accept(self):
2560 # Issue #16357: accept() on a SSLSocket created through
2561 # SSLContext.wrap_socket().
2562 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2563 context.verify_mode = ssl.CERT_REQUIRED
2564 context.load_verify_locations(CERTFILE)
2565 context.load_cert_chain(CERTFILE)
2566 server = socket.socket(socket.AF_INET)
2567 host = "127.0.0.1"
2568 port = support.bind_port(server)
2569 server = context.wrap_socket(server, server_side=True)
2570
2571 evt = threading.Event()
2572 remote = None
2573 peer = None
2574 def serve():
2575 nonlocal remote, peer
2576 server.listen(5)
2577 # Block on the accept and wait on the connection to close.
2578 evt.set()
2579 remote, peer = server.accept()
2580 remote.recv(1)
2581
2582 t = threading.Thread(target=serve)
2583 t.start()
2584 # Client wait until server setup and perform a connect.
2585 evt.wait()
2586 client = context.wrap_socket(socket.socket())
2587 client.connect((host, port))
2588 client_addr = client.getsockname()
2589 client.close()
2590 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002591 remote.close()
2592 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002593 # Sanity checks.
2594 self.assertIsInstance(remote, ssl.SSLSocket)
2595 self.assertEqual(peer, client_addr)
2596
Antoine Pitrou242db722013-05-01 20:52:07 +02002597 def test_getpeercert_enotconn(self):
2598 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2599 with context.wrap_socket(socket.socket()) as sock:
2600 with self.assertRaises(OSError) as cm:
2601 sock.getpeercert()
2602 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2603
2604 def test_do_handshake_enotconn(self):
2605 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2606 with context.wrap_socket(socket.socket()) as sock:
2607 with self.assertRaises(OSError) as cm:
2608 sock.do_handshake()
2609 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2610
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002611 def test_default_ciphers(self):
2612 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2613 try:
2614 # Force a set of weak ciphers on our client context
2615 context.set_ciphers("DES")
2616 except ssl.SSLError:
2617 self.skipTest("no DES cipher available")
2618 with ThreadedEchoServer(CERTFILE,
2619 ssl_version=ssl.PROTOCOL_SSLv23,
2620 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002621 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002622 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002623 s.connect((HOST, server.port))
2624 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2625
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002626 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2627 def test_default_ecdh_curve(self):
2628 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2629 # should be enabled by default on SSL contexts.
2630 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2631 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02002632 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2633 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2634 # our default cipher list should prefer ECDH-based ciphers
2635 # automatically.
2636 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2637 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002638 with ThreadedEchoServer(context=context) as server:
2639 with context.wrap_socket(socket.socket()) as s:
2640 s.connect((HOST, server.port))
2641 self.assertIn("ECDH", s.cipher()[0])
2642
Antoine Pitroud6494802011-07-21 01:11:30 +02002643 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2644 "'tls-unique' channel binding not available")
2645 def test_tls_unique_channel_binding(self):
2646 """Test tls-unique channel binding."""
2647 if support.verbose:
2648 sys.stdout.write("\n")
2649
2650 server = ThreadedEchoServer(CERTFILE,
2651 certreqs=ssl.CERT_NONE,
2652 ssl_version=ssl.PROTOCOL_TLSv1,
2653 cacerts=CERTFILE,
2654 chatty=True,
2655 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002656 with server:
2657 s = ssl.wrap_socket(socket.socket(),
2658 server_side=False,
2659 certfile=CERTFILE,
2660 ca_certs=CERTFILE,
2661 cert_reqs=ssl.CERT_NONE,
2662 ssl_version=ssl.PROTOCOL_TLSv1)
2663 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002664 # get the data
2665 cb_data = s.get_channel_binding("tls-unique")
2666 if support.verbose:
2667 sys.stdout.write(" got channel binding data: {0!r}\n"
2668 .format(cb_data))
2669
2670 # check if it is sane
2671 self.assertIsNotNone(cb_data)
2672 self.assertEqual(len(cb_data), 12) # True for TLSv1
2673
2674 # and compare with the peers version
2675 s.write(b"CB tls-unique\n")
2676 peer_data_repr = s.read().strip()
2677 self.assertEqual(peer_data_repr,
2678 repr(cb_data).encode("us-ascii"))
2679 s.close()
2680
2681 # now, again
2682 s = ssl.wrap_socket(socket.socket(),
2683 server_side=False,
2684 certfile=CERTFILE,
2685 ca_certs=CERTFILE,
2686 cert_reqs=ssl.CERT_NONE,
2687 ssl_version=ssl.PROTOCOL_TLSv1)
2688 s.connect((HOST, server.port))
2689 new_cb_data = s.get_channel_binding("tls-unique")
2690 if support.verbose:
2691 sys.stdout.write(" got another channel binding data: {0!r}\n"
2692 .format(new_cb_data))
2693 # is it really unique
2694 self.assertNotEqual(cb_data, new_cb_data)
2695 self.assertIsNotNone(cb_data)
2696 self.assertEqual(len(cb_data), 12) # True for TLSv1
2697 s.write(b"CB tls-unique\n")
2698 peer_data_repr = s.read().strip()
2699 self.assertEqual(peer_data_repr,
2700 repr(new_cb_data).encode("us-ascii"))
2701 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002702
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002703 def test_compression(self):
2704 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2705 context.load_cert_chain(CERTFILE)
2706 stats = server_params_test(context, context,
2707 chatty=True, connectionchatty=True)
2708 if support.verbose:
2709 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2710 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2711
2712 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2713 "ssl.OP_NO_COMPRESSION needed for this test")
2714 def test_compression_disabled(self):
2715 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2716 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002717 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002718 stats = server_params_test(context, context,
2719 chatty=True, connectionchatty=True)
2720 self.assertIs(stats['compression'], None)
2721
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002722 def test_dh_params(self):
2723 # Check we can get a connection with ephemeral Diffie-Hellman
2724 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2725 context.load_cert_chain(CERTFILE)
2726 context.load_dh_params(DHFILE)
2727 context.set_ciphers("kEDH")
2728 stats = server_params_test(context, context,
2729 chatty=True, connectionchatty=True)
2730 cipher = stats["cipher"][0]
2731 parts = cipher.split("-")
2732 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2733 self.fail("Non-DH cipher: " + cipher[0])
2734
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002735 def test_selected_npn_protocol(self):
2736 # selected_npn_protocol() is None unless NPN is used
2737 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2738 context.load_cert_chain(CERTFILE)
2739 stats = server_params_test(context, context,
2740 chatty=True, connectionchatty=True)
2741 self.assertIs(stats['client_npn_protocol'], None)
2742
2743 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2744 def test_npn_protocols(self):
2745 server_protocols = ['http/1.1', 'spdy/2']
2746 protocol_tests = [
2747 (['http/1.1', 'spdy/2'], 'http/1.1'),
2748 (['spdy/2', 'http/1.1'], 'http/1.1'),
2749 (['spdy/2', 'test'], 'spdy/2'),
2750 (['abc', 'def'], 'abc')
2751 ]
2752 for client_protocols, expected in protocol_tests:
2753 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2754 server_context.load_cert_chain(CERTFILE)
2755 server_context.set_npn_protocols(server_protocols)
2756 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2757 client_context.load_cert_chain(CERTFILE)
2758 client_context.set_npn_protocols(client_protocols)
2759 stats = server_params_test(client_context, server_context,
2760 chatty=True, connectionchatty=True)
2761
2762 msg = "failed trying %s (s) and %s (c).\n" \
2763 "was expecting %s, but got %%s from the %%s" \
2764 % (str(server_protocols), str(client_protocols),
2765 str(expected))
2766 client_result = stats['client_npn_protocol']
2767 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2768 server_result = stats['server_npn_protocols'][-1] \
2769 if len(stats['server_npn_protocols']) else 'nothing'
2770 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2771
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002772 def sni_contexts(self):
2773 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2774 server_context.load_cert_chain(SIGNED_CERTFILE)
2775 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2776 other_context.load_cert_chain(SIGNED_CERTFILE2)
2777 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2778 client_context.verify_mode = ssl.CERT_REQUIRED
2779 client_context.load_verify_locations(SIGNING_CA)
2780 return server_context, other_context, client_context
2781
2782 def check_common_name(self, stats, name):
2783 cert = stats['peercert']
2784 self.assertIn((('commonName', name),), cert['subject'])
2785
2786 @needs_sni
2787 def test_sni_callback(self):
2788 calls = []
2789 server_context, other_context, client_context = self.sni_contexts()
2790
2791 def servername_cb(ssl_sock, server_name, initial_context):
2792 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002793 if server_name is not None:
2794 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002795 server_context.set_servername_callback(servername_cb)
2796
2797 stats = server_params_test(client_context, server_context,
2798 chatty=True,
2799 sni_name='supermessage')
2800 # The hostname was fetched properly, and the certificate was
2801 # changed for the connection.
2802 self.assertEqual(calls, [("supermessage", server_context)])
2803 # CERTFILE4 was selected
2804 self.check_common_name(stats, 'fakehostname')
2805
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002806 calls = []
2807 # The callback is called with server_name=None
2808 stats = server_params_test(client_context, server_context,
2809 chatty=True,
2810 sni_name=None)
2811 self.assertEqual(calls, [(None, server_context)])
2812 self.check_common_name(stats, 'localhost')
2813
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002814 # Check disabling the callback
2815 calls = []
2816 server_context.set_servername_callback(None)
2817
2818 stats = server_params_test(client_context, server_context,
2819 chatty=True,
2820 sni_name='notfunny')
2821 # Certificate didn't change
2822 self.check_common_name(stats, 'localhost')
2823 self.assertEqual(calls, [])
2824
2825 @needs_sni
2826 def test_sni_callback_alert(self):
2827 # Returning a TLS alert is reflected to the connecting client
2828 server_context, other_context, client_context = self.sni_contexts()
2829
2830 def cb_returning_alert(ssl_sock, server_name, initial_context):
2831 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2832 server_context.set_servername_callback(cb_returning_alert)
2833
2834 with self.assertRaises(ssl.SSLError) as cm:
2835 stats = server_params_test(client_context, server_context,
2836 chatty=False,
2837 sni_name='supermessage')
2838 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2839
2840 @needs_sni
2841 def test_sni_callback_raising(self):
2842 # Raising fails the connection with a TLS handshake failure alert.
2843 server_context, other_context, client_context = self.sni_contexts()
2844
2845 def cb_raising(ssl_sock, server_name, initial_context):
2846 1/0
2847 server_context.set_servername_callback(cb_raising)
2848
2849 with self.assertRaises(ssl.SSLError) as cm, \
2850 support.captured_stderr() as stderr:
2851 stats = server_params_test(client_context, server_context,
2852 chatty=False,
2853 sni_name='supermessage')
2854 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2855 self.assertIn("ZeroDivisionError", stderr.getvalue())
2856
2857 @needs_sni
2858 def test_sni_callback_wrong_return_type(self):
2859 # Returning the wrong return type terminates the TLS connection
2860 # with an internal error alert.
2861 server_context, other_context, client_context = self.sni_contexts()
2862
2863 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2864 return "foo"
2865 server_context.set_servername_callback(cb_wrong_return_type)
2866
2867 with self.assertRaises(ssl.SSLError) as cm, \
2868 support.captured_stderr() as stderr:
2869 stats = server_params_test(client_context, server_context,
2870 chatty=False,
2871 sni_name='supermessage')
2872 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2873 self.assertIn("TypeError", stderr.getvalue())
2874
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002875 def test_read_write_after_close_raises_valuerror(self):
2876 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2877 context.verify_mode = ssl.CERT_REQUIRED
2878 context.load_verify_locations(CERTFILE)
2879 context.load_cert_chain(CERTFILE)
2880 server = ThreadedEchoServer(context=context, chatty=False)
2881
2882 with server:
2883 s = context.wrap_socket(socket.socket())
2884 s.connect((HOST, server.port))
2885 s.close()
2886
2887 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002888 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002889
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002890
Thomas Woutersed03b412007-08-28 21:37:11 +00002891def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002892 if support.verbose:
2893 plats = {
2894 'Linux': platform.linux_distribution,
2895 'Mac': platform.mac_ver,
2896 'Windows': platform.win32_ver,
2897 }
2898 for name, func in plats.items():
2899 plat = func()
2900 if plat and plat[0]:
2901 plat = '%s %r' % (name, plat)
2902 break
2903 else:
2904 plat = repr(platform.platform())
2905 print("test_ssl: testing with %r %r" %
2906 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2907 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002908 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002909 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2910 try:
2911 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2912 except AttributeError:
2913 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002914
Antoine Pitrou152efa22010-05-16 18:19:27 +00002915 for filename in [
2916 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2917 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002918 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002919 BADCERT, BADKEY, EMPTYCERT]:
2920 if not os.path.exists(filename):
2921 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002922
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002923 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002924
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002925 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002926 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002927
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002928 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002929 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002930 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002931 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002932
Antoine Pitrou480a1242010-04-28 21:37:09 +00002933 try:
2934 support.run_unittest(*tests)
2935 finally:
2936 if _have_threads:
2937 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002938
2939if __name__ == "__main__":
2940 test_main()