blob: 0dc04c08eaefb887b0135bbf4d81510e34d8b56c [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Christian Heimes9424bb42013-06-17 15:32:57 +02009import datetime
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000010import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000011import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000012import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000013import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000014import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000015import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000016import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000017import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000018import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000019import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000020import functools
Antoine Pitrou242db722013-05-01 20:52:07 +020021from unittest import mock
Thomas Woutersed03b412007-08-28 21:37:11 +000022
Antoine Pitrou05d936d2010-10-13 11:38:36 +000023ssl = support.import_module("ssl")
24
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010025PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000026HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000027
Christian Heimesefff7062013-11-21 03:35:02 +010028def data_file(*name):
29 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000030
Antoine Pitrou81564092010-10-08 23:06:24 +000031# The custom key and certificate files used in test_ssl are generated
32# using Lib/test/make_ssl_certs.py.
33# Other certificates are simply fetched from the Internet servers they
34# are meant to authenticate.
35
Antoine Pitrou152efa22010-05-16 18:19:27 +000036CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000037BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038ONLYCERT = data_file("ssl_cert.pem")
39ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_ONLYCERT = os.fsencode(ONLYCERT)
41BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020042CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
43ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
44KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010047CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
48CAFILE_CACERT = data_file("capath", "5ed36f99.0")
49
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
Christian Heimes22587792013-11-21 23:56:13 +010051# empty CRL
52CRLFILE = data_file("revocation.crl")
53
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010054# Two keys and certs signed by the same CA (for SNI tests)
55SIGNED_CERTFILE = data_file("keycert3.pem")
56SIGNED_CERTFILE2 = data_file("keycert4.pem")
57SIGNING_CA = data_file("pycacert.pem")
58
Antoine Pitrou152efa22010-05-16 18:19:27 +000059SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
60
61EMPTYCERT = data_file("nullcert.pem")
62BADCERT = data_file("badcert.pem")
63WRONGCERT = data_file("XXXnonexisting.pem")
64BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020065NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020066NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000067
Antoine Pitrou0e576f12011-12-22 10:03:38 +010068DHFILE = data_file("dh512.pem")
69BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010071
Thomas Woutersed03b412007-08-28 21:37:11 +000072def handle_error(prefix):
73 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000074 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000075 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000076
Antoine Pitroub5218772010-05-21 09:56:06 +000077def can_clear_options():
78 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020079 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000080
81def no_sslv2_implies_sslv3_hello():
82 # 0.9.7h or higher
83 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
84
Christian Heimes2427b502013-11-23 11:24:32 +010085def have_verify_flags():
86 # 0.9.8 or higher
87 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
88
Christian Heimes9424bb42013-06-17 15:32:57 +020089def asn1time(cert_time):
90 # Some versions of OpenSSL ignore seconds, see #18207
91 # 0.9.8.i
92 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
93 fmt = "%b %d %H:%M:%S %Y GMT"
94 dt = datetime.datetime.strptime(cert_time, fmt)
95 dt = dt.replace(second=0)
96 cert_time = dt.strftime(fmt)
97 # %d adds leading zero but ASN1_TIME_print() uses leading space
98 if cert_time[4] == "0":
99 cert_time = cert_time[:4] + " " + cert_time[5:]
100
101 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000102
Antoine Pitrou23df4832010-08-04 17:14:06 +0000103# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
104def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +0200105 if hasattr(ssl, 'PROTOCOL_SSLv2'):
106 @functools.wraps(func)
107 def f(*args, **kwargs):
108 try:
109 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
110 except ssl.SSLError:
111 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
112 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
113 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
114 return func(*args, **kwargs)
115 return f
116 else:
117 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +0000118
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100119needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
120
Antoine Pitrou23df4832010-08-04 17:14:06 +0000121
Antoine Pitrou152efa22010-05-16 18:19:27 +0000122class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000123
Antoine Pitrou480a1242010-04-28 21:37:09 +0000124 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000125 ssl.CERT_NONE
126 ssl.CERT_OPTIONAL
127 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100128 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100129 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100130 if ssl.HAS_ECDH:
131 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100132 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
133 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000134 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100135 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000136
Antoine Pitrou480a1242010-04-28 21:37:09 +0000137 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000139 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000140 sys.stdout.write("\n RAND_status is %d (%s)\n"
141 % (v, (v and "sufficient randomness") or
142 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200143
144 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
145 self.assertEqual(len(data), 16)
146 self.assertEqual(is_cryptographic, v == 1)
147 if v:
148 data = ssl.RAND_bytes(16)
149 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200150 else:
151 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200152
Victor Stinner1e81a392013-12-19 16:47:04 +0100153 # negative num is invalid
154 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
155 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
156
Jesus Ceac8754a12012-09-11 02:00:58 +0200157 self.assertRaises(TypeError, ssl.RAND_egd, 1)
158 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000159 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000160
Christian Heimesf77b4b22013-08-21 13:26:05 +0200161 @unittest.skipUnless(os.name == 'posix', 'requires posix')
162 def test_random_fork(self):
163 status = ssl.RAND_status()
164 if not status:
165 self.fail("OpenSSL's PRNG has insufficient randomness")
166
167 rfd, wfd = os.pipe()
168 pid = os.fork()
169 if pid == 0:
170 try:
171 os.close(rfd)
172 child_random = ssl.RAND_pseudo_bytes(16)[0]
173 self.assertEqual(len(child_random), 16)
174 os.write(wfd, child_random)
175 os.close(wfd)
176 except BaseException:
177 os._exit(1)
178 else:
179 os._exit(0)
180 else:
181 os.close(wfd)
182 self.addCleanup(os.close, rfd)
183 _, status = os.waitpid(pid, 0)
184 self.assertEqual(status, 0)
185
186 child_random = os.read(rfd, 16)
187 self.assertEqual(len(child_random), 16)
188 parent_random = ssl.RAND_pseudo_bytes(16)[0]
189 self.assertEqual(len(parent_random), 16)
190
191 self.assertNotEqual(child_random, parent_random)
192
Antoine Pitrou480a1242010-04-28 21:37:09 +0000193 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000194 # note that this uses an 'unofficial' function in _ssl.c,
195 # provided solely for this test, to exercise the certificate
196 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000197 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000198 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000199 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200200 self.assertEqual(p['issuer'],
201 ((('countryName', 'XY'),),
202 (('localityName', 'Castle Anthrax'),),
203 (('organizationName', 'Python Software Foundation'),),
204 (('commonName', 'localhost'),))
205 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100206 # Note the next three asserts will fail if the keys are regenerated
Christian Heimes9424bb42013-06-17 15:32:57 +0200207 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
208 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200209 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
210 self.assertEqual(p['subject'],
211 ((('countryName', 'XY'),),
212 (('localityName', 'Castle Anthrax'),),
213 (('organizationName', 'Python Software Foundation'),),
214 (('commonName', 'localhost'),))
215 )
216 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
217 # Issue #13034: the subjectAltName in some certificates
218 # (notably projects.developer.nokia.com:443) wasn't parsed
219 p = ssl._ssl._test_decode_cert(NOKIACERT)
220 if support.verbose:
221 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
222 self.assertEqual(p['subjectAltName'],
223 (('DNS', 'projects.developer.nokia.com'),
224 ('DNS', 'projects.forum.nokia.com'))
225 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100226 # extra OCSP and AIA fields
227 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
228 self.assertEqual(p['caIssuers'],
229 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
230 self.assertEqual(p['crlDistributionPoints'],
231 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000232
Christian Heimes824f7f32013-08-17 00:54:47 +0200233 def test_parse_cert_CVE_2013_4238(self):
234 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
235 if support.verbose:
236 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
237 subject = ((('countryName', 'US'),),
238 (('stateOrProvinceName', 'Oregon'),),
239 (('localityName', 'Beaverton'),),
240 (('organizationName', 'Python Software Foundation'),),
241 (('organizationalUnitName', 'Python Core Development'),),
242 (('commonName', 'null.python.org\x00example.org'),),
243 (('emailAddress', 'python-dev@python.org'),))
244 self.assertEqual(p['subject'], subject)
245 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200246 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
247 san = (('DNS', 'altnull.python.org\x00example.com'),
248 ('email', 'null@python.org\x00user@example.org'),
249 ('URI', 'http://null.python.org\x00http://example.org'),
250 ('IP Address', '192.0.2.1'),
251 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
252 else:
253 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
254 san = (('DNS', 'altnull.python.org\x00example.com'),
255 ('email', 'null@python.org\x00user@example.org'),
256 ('URI', 'http://null.python.org\x00http://example.org'),
257 ('IP Address', '192.0.2.1'),
258 ('IP Address', '<invalid>'))
259
260 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200261
Antoine Pitrou480a1242010-04-28 21:37:09 +0000262 def test_DER_to_PEM(self):
263 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
264 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000265 d1 = ssl.PEM_cert_to_DER_cert(pem)
266 p2 = ssl.DER_cert_to_PEM_cert(d1)
267 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000268 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000269 if not p2.startswith(ssl.PEM_HEADER + '\n'):
270 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
271 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
272 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000273
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000274 def test_openssl_version(self):
275 n = ssl.OPENSSL_VERSION_NUMBER
276 t = ssl.OPENSSL_VERSION_INFO
277 s = ssl.OPENSSL_VERSION
278 self.assertIsInstance(n, int)
279 self.assertIsInstance(t, tuple)
280 self.assertIsInstance(s, str)
281 # Some sanity checks follow
282 # >= 0.9
283 self.assertGreaterEqual(n, 0x900000)
284 # < 2.0
285 self.assertLess(n, 0x20000000)
286 major, minor, fix, patch, status = t
287 self.assertGreaterEqual(major, 0)
288 self.assertLess(major, 2)
289 self.assertGreaterEqual(minor, 0)
290 self.assertLess(minor, 256)
291 self.assertGreaterEqual(fix, 0)
292 self.assertLess(fix, 256)
293 self.assertGreaterEqual(patch, 0)
294 self.assertLessEqual(patch, 26)
295 self.assertGreaterEqual(status, 0)
296 self.assertLessEqual(status, 15)
297 # Version string as returned by OpenSSL, the format might change
298 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
299 (s, t))
300
Antoine Pitrou9d543662010-04-23 23:10:32 +0000301 @support.cpython_only
302 def test_refcycle(self):
303 # Issue #7943: an SSL object doesn't create reference cycles with
304 # itself.
305 s = socket.socket(socket.AF_INET)
306 ss = ssl.wrap_socket(s)
307 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100308 with support.check_warnings(("", ResourceWarning)):
309 del ss
310 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000311
Antoine Pitroua468adc2010-09-14 14:43:44 +0000312 def test_wrapped_unconnected(self):
313 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200314 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000315 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100316 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100317 self.assertRaises(OSError, ss.recv, 1)
318 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
319 self.assertRaises(OSError, ss.recvfrom, 1)
320 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
321 self.assertRaises(OSError, ss.send, b'x')
322 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000323
Antoine Pitrou40f08742010-04-24 22:04:40 +0000324 def test_timeout(self):
325 # Issue #8524: when creating an SSL socket, the timeout of the
326 # original socket should be retained.
327 for timeout in (None, 0.0, 5.0):
328 s = socket.socket(socket.AF_INET)
329 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100330 with ssl.wrap_socket(s) as ss:
331 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000332
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000333 def test_errors(self):
334 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000335 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000336 "certfile must be specified",
337 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000338 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000339 "certfile must be specified for server-side operations",
340 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000341 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000342 "certfile must be specified for server-side operations",
343 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100344 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
345 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
346 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200347 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000348 with socket.socket() as sock:
349 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000350 self.assertEqual(cm.exception.errno, errno.ENOENT)
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=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +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=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000358 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000359
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000360 def test_match_hostname(self):
361 def ok(cert, hostname):
362 ssl.match_hostname(cert, hostname)
363 def fail(cert, hostname):
364 self.assertRaises(ssl.CertificateError,
365 ssl.match_hostname, cert, hostname)
366
367 cert = {'subject': ((('commonName', 'example.com'),),)}
368 ok(cert, 'example.com')
369 ok(cert, 'ExAmple.cOm')
370 fail(cert, 'www.example.com')
371 fail(cert, '.example.com')
372 fail(cert, 'example.org')
373 fail(cert, 'exampleXcom')
374
375 cert = {'subject': ((('commonName', '*.a.com'),),)}
376 ok(cert, 'foo.a.com')
377 fail(cert, 'bar.foo.a.com')
378 fail(cert, 'a.com')
379 fail(cert, 'Xa.com')
380 fail(cert, '.a.com')
381
Georg Brandl72c98d32013-10-27 07:16:53 +0100382 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000383 cert = {'subject': ((('commonName', 'f*.com'),),)}
384 ok(cert, 'foo.com')
385 ok(cert, 'f.com')
386 fail(cert, 'bar.com')
387 fail(cert, 'foo.a.com')
388 fail(cert, 'bar.foo.com')
389
Christian Heimes824f7f32013-08-17 00:54:47 +0200390 # NULL bytes are bad, CVE-2013-4073
391 cert = {'subject': ((('commonName',
392 'null.python.org\x00example.org'),),)}
393 ok(cert, 'null.python.org\x00example.org') # or raise an error?
394 fail(cert, 'example.org')
395 fail(cert, 'null.python.org')
396
Georg Brandl72c98d32013-10-27 07:16:53 +0100397 # error cases with wildcards
398 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
399 fail(cert, 'bar.foo.a.com')
400 fail(cert, 'a.com')
401 fail(cert, 'Xa.com')
402 fail(cert, '.a.com')
403
404 cert = {'subject': ((('commonName', 'a.*.com'),),)}
405 fail(cert, 'a.foo.com')
406 fail(cert, 'a..com')
407 fail(cert, 'a.com')
408
409 # wildcard doesn't match IDNA prefix 'xn--'
410 idna = 'püthon.python.org'.encode("idna").decode("ascii")
411 cert = {'subject': ((('commonName', idna),),)}
412 ok(cert, idna)
413 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
414 fail(cert, idna)
415 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
416 fail(cert, idna)
417
418 # wildcard in first fragment and IDNA A-labels in sequent fragments
419 # are supported.
420 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
421 cert = {'subject': ((('commonName', idna),),)}
422 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
423 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
424 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
425 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
426
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000427 # Slightly fake real-world example
428 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
429 'subject': ((('commonName', 'linuxfrz.org'),),),
430 'subjectAltName': (('DNS', 'linuxfr.org'),
431 ('DNS', 'linuxfr.com'),
432 ('othername', '<unsupported>'))}
433 ok(cert, 'linuxfr.org')
434 ok(cert, 'linuxfr.com')
435 # Not a "DNS" entry
436 fail(cert, '<unsupported>')
437 # When there is a subjectAltName, commonName isn't used
438 fail(cert, 'linuxfrz.org')
439
440 # A pristine real-world example
441 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
442 'subject': ((('countryName', 'US'),),
443 (('stateOrProvinceName', 'California'),),
444 (('localityName', 'Mountain View'),),
445 (('organizationName', 'Google Inc'),),
446 (('commonName', 'mail.google.com'),))}
447 ok(cert, 'mail.google.com')
448 fail(cert, 'gmail.com')
449 # Only commonName is considered
450 fail(cert, 'California')
451
452 # Neither commonName nor subjectAltName
453 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
454 'subject': ((('countryName', 'US'),),
455 (('stateOrProvinceName', 'California'),),
456 (('localityName', 'Mountain View'),),
457 (('organizationName', 'Google Inc'),))}
458 fail(cert, 'mail.google.com')
459
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200460 # No DNS entry in subjectAltName but a commonName
461 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
462 'subject': ((('countryName', 'US'),),
463 (('stateOrProvinceName', 'California'),),
464 (('localityName', 'Mountain View'),),
465 (('commonName', 'mail.google.com'),)),
466 'subjectAltName': (('othername', 'blabla'), )}
467 ok(cert, 'mail.google.com')
468
469 # No DNS entry subjectAltName and no commonName
470 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
471 'subject': ((('countryName', 'US'),),
472 (('stateOrProvinceName', 'California'),),
473 (('localityName', 'Mountain View'),),
474 (('organizationName', 'Google Inc'),)),
475 'subjectAltName': (('othername', 'blabla'),)}
476 fail(cert, 'google.com')
477
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000478 # Empty cert / no cert
479 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
480 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
481
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200482 # Issue #17980: avoid denials of service by refusing more than one
483 # wildcard per fragment.
484 cert = {'subject': ((('commonName', 'a*b.com'),),)}
485 ok(cert, 'axxb.com')
486 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100487 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200488 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
489 with self.assertRaises(ssl.CertificateError) as cm:
490 ssl.match_hostname(cert, 'axxbxxc.com')
491 self.assertIn("too many wildcards", str(cm.exception))
492
Antoine Pitroud5323212010-10-22 18:19:07 +0000493 def test_server_side(self):
494 # server_hostname doesn't work for server sockets
495 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000496 with socket.socket() as sock:
497 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
498 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000499
Antoine Pitroud6494802011-07-21 01:11:30 +0200500 def test_unknown_channel_binding(self):
501 # should raise ValueError for unknown type
502 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100503 with ssl.wrap_socket(s) as ss:
504 with self.assertRaises(ValueError):
505 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200506
507 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
508 "'tls-unique' channel binding not available")
509 def test_tls_unique_channel_binding(self):
510 # unconnected should return None for known type
511 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100512 with ssl.wrap_socket(s) as ss:
513 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200514 # the same for server-side
515 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100516 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
517 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200518
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600519 def test_dealloc_warn(self):
520 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
521 r = repr(ss)
522 with self.assertWarns(ResourceWarning) as cm:
523 ss = None
524 support.gc_collect()
525 self.assertIn(r, str(cm.warning.args[0]))
526
Christian Heimes6d7ad132013-06-09 18:02:55 +0200527 def test_get_default_verify_paths(self):
528 paths = ssl.get_default_verify_paths()
529 self.assertEqual(len(paths), 6)
530 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
531
532 with support.EnvironmentVarGuard() as env:
533 env["SSL_CERT_DIR"] = CAPATH
534 env["SSL_CERT_FILE"] = CERTFILE
535 paths = ssl.get_default_verify_paths()
536 self.assertEqual(paths.cafile, CERTFILE)
537 self.assertEqual(paths.capath, CAPATH)
538
Christian Heimes44109d72013-11-22 01:51:30 +0100539 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
540 def test_enum_certificates(self):
541 self.assertTrue(ssl.enum_certificates("CA"))
542 self.assertTrue(ssl.enum_certificates("ROOT"))
543
544 self.assertRaises(TypeError, ssl.enum_certificates)
545 self.assertRaises(WindowsError, ssl.enum_certificates, "")
546
Christian Heimesc2d65e12013-11-22 16:13:55 +0100547 trust_oids = set()
548 for storename in ("CA", "ROOT"):
549 store = ssl.enum_certificates(storename)
550 self.assertIsInstance(store, list)
551 for element in store:
552 self.assertIsInstance(element, tuple)
553 self.assertEqual(len(element), 3)
554 cert, enc, trust = element
555 self.assertIsInstance(cert, bytes)
556 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
557 self.assertIsInstance(trust, (set, bool))
558 if isinstance(trust, set):
559 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100560
561 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100562 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200563
Christian Heimes46bebee2013-06-09 19:03:31 +0200564 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100565 def test_enum_crls(self):
566 self.assertTrue(ssl.enum_crls("CA"))
567 self.assertRaises(TypeError, ssl.enum_crls)
568 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200569
Christian Heimes44109d72013-11-22 01:51:30 +0100570 crls = ssl.enum_crls("CA")
571 self.assertIsInstance(crls, list)
572 for element in crls:
573 self.assertIsInstance(element, tuple)
574 self.assertEqual(len(element), 2)
575 self.assertIsInstance(element[0], bytes)
576 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200577
Christian Heimes46bebee2013-06-09 19:03:31 +0200578
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100579 def test_asn1object(self):
580 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
581 '1.3.6.1.5.5.7.3.1')
582
583 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
584 self.assertEqual(val, expected)
585 self.assertEqual(val.nid, 129)
586 self.assertEqual(val.shortname, 'serverAuth')
587 self.assertEqual(val.longname, 'TLS Web Server Authentication')
588 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
589 self.assertIsInstance(val, ssl._ASN1Object)
590 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
591
592 val = ssl._ASN1Object.fromnid(129)
593 self.assertEqual(val, expected)
594 self.assertIsInstance(val, ssl._ASN1Object)
595 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100596 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
597 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100598 for i in range(1000):
599 try:
600 obj = ssl._ASN1Object.fromnid(i)
601 except ValueError:
602 pass
603 else:
604 self.assertIsInstance(obj.nid, int)
605 self.assertIsInstance(obj.shortname, str)
606 self.assertIsInstance(obj.longname, str)
607 self.assertIsInstance(obj.oid, (str, type(None)))
608
609 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
610 self.assertEqual(val, expected)
611 self.assertIsInstance(val, ssl._ASN1Object)
612 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
613 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
614 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100615 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
616 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100617
Christian Heimes72d28502013-11-23 13:56:58 +0100618 def test_purpose_enum(self):
619 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
620 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
621 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
622 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
623 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
624 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
625 '1.3.6.1.5.5.7.3.1')
626
627 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
628 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
629 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
630 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
631 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
632 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
633 '1.3.6.1.5.5.7.3.2')
634
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100635 def test_unsupported_dtls(self):
636 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
637 self.addCleanup(s.close)
638 with self.assertRaises(NotImplementedError) as cx:
639 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
640 self.assertEqual(str(cx.exception), "only stream sockets are supported")
641 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
642 with self.assertRaises(NotImplementedError) as cx:
643 ctx.wrap_socket(s)
644 self.assertEqual(str(cx.exception), "only stream sockets are supported")
645
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100646
Antoine Pitrou152efa22010-05-16 18:19:27 +0000647class ContextTests(unittest.TestCase):
648
Antoine Pitrou23df4832010-08-04 17:14:06 +0000649 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000650 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100651 for protocol in PROTOCOLS:
652 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000653 self.assertRaises(TypeError, ssl.SSLContext)
654 self.assertRaises(ValueError, ssl.SSLContext, -1)
655 self.assertRaises(ValueError, ssl.SSLContext, 42)
656
Antoine Pitrou23df4832010-08-04 17:14:06 +0000657 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000658 def test_protocol(self):
659 for proto in PROTOCOLS:
660 ctx = ssl.SSLContext(proto)
661 self.assertEqual(ctx.protocol, proto)
662
663 def test_ciphers(self):
664 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
665 ctx.set_ciphers("ALL")
666 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000667 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000668 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000669
Antoine Pitrou23df4832010-08-04 17:14:06 +0000670 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000671 def test_options(self):
672 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +0100673 # OP_ALL | OP_NO_SSLv2 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000674 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
675 ctx.options)
676 ctx.options |= ssl.OP_NO_SSLv3
677 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
678 ctx.options)
679 if can_clear_options():
680 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
681 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
682 ctx.options)
683 ctx.options = 0
684 self.assertEqual(0, ctx.options)
685 else:
686 with self.assertRaises(ValueError):
687 ctx.options = 0
688
Christian Heimes22587792013-11-21 23:56:13 +0100689 def test_verify_mode(self):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000690 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
691 # Default value
692 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
693 ctx.verify_mode = ssl.CERT_OPTIONAL
694 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
695 ctx.verify_mode = ssl.CERT_REQUIRED
696 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
697 ctx.verify_mode = ssl.CERT_NONE
698 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
699 with self.assertRaises(TypeError):
700 ctx.verify_mode = None
701 with self.assertRaises(ValueError):
702 ctx.verify_mode = 42
703
Christian Heimes2427b502013-11-23 11:24:32 +0100704 @unittest.skipUnless(have_verify_flags(),
705 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +0100706 def test_verify_flags(self):
707 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
708 # default value by OpenSSL
709 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
710 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
711 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
712 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
713 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
714 ctx.verify_flags = ssl.VERIFY_DEFAULT
715 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
716 # supports any value
717 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
718 self.assertEqual(ctx.verify_flags,
719 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
720 with self.assertRaises(TypeError):
721 ctx.verify_flags = None
722
Antoine Pitrou152efa22010-05-16 18:19:27 +0000723 def test_load_cert_chain(self):
724 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
725 # Combined key and cert in a single file
726 ctx.load_cert_chain(CERTFILE)
727 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
728 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200729 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000730 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000731 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000732 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000733 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000734 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000735 ctx.load_cert_chain(EMPTYCERT)
736 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000737 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000738 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
739 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
740 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000741 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000742 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000743 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000744 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000745 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000746 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
747 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000748 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000749 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000750 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200751 # Password protected key and cert
752 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
753 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
754 ctx.load_cert_chain(CERTFILE_PROTECTED,
755 password=bytearray(KEY_PASSWORD.encode()))
756 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
757 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
758 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
759 bytearray(KEY_PASSWORD.encode()))
760 with self.assertRaisesRegex(TypeError, "should be a string"):
761 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
762 with self.assertRaises(ssl.SSLError):
763 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
764 with self.assertRaisesRegex(ValueError, "cannot be longer"):
765 # openssl has a fixed limit on the password buffer.
766 # PEM_BUFSIZE is generally set to 1kb.
767 # Return a string larger than this.
768 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
769 # Password callback
770 def getpass_unicode():
771 return KEY_PASSWORD
772 def getpass_bytes():
773 return KEY_PASSWORD.encode()
774 def getpass_bytearray():
775 return bytearray(KEY_PASSWORD.encode())
776 def getpass_badpass():
777 return "badpass"
778 def getpass_huge():
779 return b'a' * (1024 * 1024)
780 def getpass_bad_type():
781 return 9
782 def getpass_exception():
783 raise Exception('getpass error')
784 class GetPassCallable:
785 def __call__(self):
786 return KEY_PASSWORD
787 def getpass(self):
788 return KEY_PASSWORD
789 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
790 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
791 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
792 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
793 ctx.load_cert_chain(CERTFILE_PROTECTED,
794 password=GetPassCallable().getpass)
795 with self.assertRaises(ssl.SSLError):
796 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
797 with self.assertRaisesRegex(ValueError, "cannot be longer"):
798 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
799 with self.assertRaisesRegex(TypeError, "must return a string"):
800 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
801 with self.assertRaisesRegex(Exception, "getpass error"):
802 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
803 # Make sure the password function isn't called if it isn't needed
804 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000805
806 def test_load_verify_locations(self):
807 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
808 ctx.load_verify_locations(CERTFILE)
809 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
810 ctx.load_verify_locations(BYTES_CERTFILE)
811 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
812 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +0100813 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200814 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000815 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000816 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000817 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000818 ctx.load_verify_locations(BADCERT)
819 ctx.load_verify_locations(CERTFILE, CAPATH)
820 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
821
Victor Stinner80f75e62011-01-29 11:31:20 +0000822 # Issue #10989: crash if the second argument type is invalid
823 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
824
Christian Heimesefff7062013-11-21 03:35:02 +0100825 def test_load_verify_cadata(self):
826 # test cadata
827 with open(CAFILE_CACERT) as f:
828 cacert_pem = f.read()
829 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
830 with open(CAFILE_NEURONIO) as f:
831 neuronio_pem = f.read()
832 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
833
834 # test PEM
835 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
836 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
837 ctx.load_verify_locations(cadata=cacert_pem)
838 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
839 ctx.load_verify_locations(cadata=neuronio_pem)
840 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
841 # cert already in hash table
842 ctx.load_verify_locations(cadata=neuronio_pem)
843 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
844
845 # combined
846 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
847 combined = "\n".join((cacert_pem, neuronio_pem))
848 ctx.load_verify_locations(cadata=combined)
849 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
850
851 # with junk around the certs
852 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
853 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
854 neuronio_pem, "tail"]
855 ctx.load_verify_locations(cadata="\n".join(combined))
856 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
857
858 # test DER
859 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
860 ctx.load_verify_locations(cadata=cacert_der)
861 ctx.load_verify_locations(cadata=neuronio_der)
862 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
863 # cert already in hash table
864 ctx.load_verify_locations(cadata=cacert_der)
865 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
866
867 # combined
868 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
869 combined = b"".join((cacert_der, neuronio_der))
870 ctx.load_verify_locations(cadata=combined)
871 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
872
873 # error cases
874 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
875 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
876
877 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
878 ctx.load_verify_locations(cadata="broken")
879 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
880 ctx.load_verify_locations(cadata=b"broken")
881
882
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100883 def test_load_dh_params(self):
884 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
885 ctx.load_dh_params(DHFILE)
886 if os.name != 'nt':
887 ctx.load_dh_params(BYTES_DHFILE)
888 self.assertRaises(TypeError, ctx.load_dh_params)
889 self.assertRaises(TypeError, ctx.load_dh_params, None)
890 with self.assertRaises(FileNotFoundError) as cm:
891 ctx.load_dh_params(WRONGCERT)
892 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200893 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100894 ctx.load_dh_params(CERTFILE)
895
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000896 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000897 def test_session_stats(self):
898 for proto in PROTOCOLS:
899 ctx = ssl.SSLContext(proto)
900 self.assertEqual(ctx.session_stats(), {
901 'number': 0,
902 'connect': 0,
903 'connect_good': 0,
904 'connect_renegotiate': 0,
905 'accept': 0,
906 'accept_good': 0,
907 'accept_renegotiate': 0,
908 'hits': 0,
909 'misses': 0,
910 'timeouts': 0,
911 'cache_full': 0,
912 })
913
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000914 def test_set_default_verify_paths(self):
915 # There's not much we can do to test that it acts as expected,
916 # so just check it doesn't crash or raise an exception.
917 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
918 ctx.set_default_verify_paths()
919
Antoine Pitrou501da612011-12-21 09:27:41 +0100920 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100921 def test_set_ecdh_curve(self):
922 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
923 ctx.set_ecdh_curve("prime256v1")
924 ctx.set_ecdh_curve(b"prime256v1")
925 self.assertRaises(TypeError, ctx.set_ecdh_curve)
926 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
927 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
928 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
929
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100930 @needs_sni
931 def test_sni_callback(self):
932 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
933
934 # set_servername_callback expects a callable, or None
935 self.assertRaises(TypeError, ctx.set_servername_callback)
936 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
937 self.assertRaises(TypeError, ctx.set_servername_callback, "")
938 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
939
940 def dummycallback(sock, servername, ctx):
941 pass
942 ctx.set_servername_callback(None)
943 ctx.set_servername_callback(dummycallback)
944
945 @needs_sni
946 def test_sni_callback_refcycle(self):
947 # Reference cycles through the servername callback are detected
948 # and cleared.
949 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
950 def dummycallback(sock, servername, ctx, cycle=ctx):
951 pass
952 ctx.set_servername_callback(dummycallback)
953 wr = weakref.ref(ctx)
954 del ctx, dummycallback
955 gc.collect()
956 self.assertIs(wr(), None)
957
Christian Heimes9a5395a2013-06-17 15:44:12 +0200958 def test_cert_store_stats(self):
959 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
960 self.assertEqual(ctx.cert_store_stats(),
961 {'x509_ca': 0, 'crl': 0, 'x509': 0})
962 ctx.load_cert_chain(CERTFILE)
963 self.assertEqual(ctx.cert_store_stats(),
964 {'x509_ca': 0, 'crl': 0, 'x509': 0})
965 ctx.load_verify_locations(CERTFILE)
966 self.assertEqual(ctx.cert_store_stats(),
967 {'x509_ca': 0, 'crl': 0, 'x509': 1})
968 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
969 self.assertEqual(ctx.cert_store_stats(),
970 {'x509_ca': 1, 'crl': 0, 'x509': 2})
971
972 def test_get_ca_certs(self):
973 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
974 self.assertEqual(ctx.get_ca_certs(), [])
975 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
976 ctx.load_verify_locations(CERTFILE)
977 self.assertEqual(ctx.get_ca_certs(), [])
978 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
979 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
980 self.assertEqual(ctx.get_ca_certs(),
981 [{'issuer': ((('organizationName', 'Root CA'),),
982 (('organizationalUnitName', 'http://www.cacert.org'),),
983 (('commonName', 'CA Cert Signing Authority'),),
984 (('emailAddress', 'support@cacert.org'),)),
985 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
986 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
987 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100988 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +0200989 'subject': ((('organizationName', 'Root CA'),),
990 (('organizationalUnitName', 'http://www.cacert.org'),),
991 (('commonName', 'CA Cert Signing Authority'),),
992 (('emailAddress', 'support@cacert.org'),)),
993 'version': 3}])
994
995 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
996 pem = f.read()
997 der = ssl.PEM_cert_to_DER_cert(pem)
998 self.assertEqual(ctx.get_ca_certs(True), [der])
999
Christian Heimes72d28502013-11-23 13:56:58 +01001000 def test_load_default_certs(self):
1001 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1002 ctx.load_default_certs()
1003
1004 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1005 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1006 ctx.load_default_certs()
1007
1008 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1009 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1010
1011 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1012 self.assertRaises(TypeError, ctx.load_default_certs, None)
1013 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1014
Christian Heimes4c05b472013-11-23 15:58:30 +01001015 def test_create_default_context(self):
1016 ctx = ssl.create_default_context()
1017 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1018 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001019 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001020 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1021
1022 with open(SIGNING_CA) as f:
1023 cadata = f.read()
1024 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1025 cadata=cadata)
1026 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1027 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1028 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1029
1030 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
1031 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1032 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1033 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1034
Christian Heimes67986f92013-11-23 22:43:47 +01001035 def test__create_stdlib_context(self):
1036 ctx = ssl._create_stdlib_context()
1037 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1038 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001039 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001040 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1041
1042 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1043 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1044 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1045 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1046
1047 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001048 cert_reqs=ssl.CERT_REQUIRED,
1049 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001050 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1051 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001052 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001053 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1054
1055 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1056 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1057 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1058 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001059
Christian Heimes1aa9a752013-12-02 02:41:19 +01001060 def test_check_hostname(self):
1061 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1062 self.assertFalse(ctx.check_hostname)
1063
1064 # Requires CERT_REQUIRED or CERT_OPTIONAL
1065 with self.assertRaises(ValueError):
1066 ctx.check_hostname = True
1067 ctx.verify_mode = ssl.CERT_REQUIRED
1068 self.assertFalse(ctx.check_hostname)
1069 ctx.check_hostname = True
1070 self.assertTrue(ctx.check_hostname)
1071
1072 ctx.verify_mode = ssl.CERT_OPTIONAL
1073 ctx.check_hostname = True
1074 self.assertTrue(ctx.check_hostname)
1075
1076 # Cannot set CERT_NONE with check_hostname enabled
1077 with self.assertRaises(ValueError):
1078 ctx.verify_mode = ssl.CERT_NONE
1079 ctx.check_hostname = False
1080 self.assertFalse(ctx.check_hostname)
1081
Antoine Pitrou152efa22010-05-16 18:19:27 +00001082
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001083class SSLErrorTests(unittest.TestCase):
1084
1085 def test_str(self):
1086 # The str() of a SSLError doesn't include the errno
1087 e = ssl.SSLError(1, "foo")
1088 self.assertEqual(str(e), "foo")
1089 self.assertEqual(e.errno, 1)
1090 # Same for a subclass
1091 e = ssl.SSLZeroReturnError(1, "foo")
1092 self.assertEqual(str(e), "foo")
1093 self.assertEqual(e.errno, 1)
1094
1095 def test_lib_reason(self):
1096 # Test the library and reason attributes
1097 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1098 with self.assertRaises(ssl.SSLError) as cm:
1099 ctx.load_dh_params(CERTFILE)
1100 self.assertEqual(cm.exception.library, 'PEM')
1101 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1102 s = str(cm.exception)
1103 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1104
1105 def test_subclass(self):
1106 # Check that the appropriate SSLError subclass is raised
1107 # (this only tests one of them)
1108 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1109 with socket.socket() as s:
1110 s.bind(("127.0.0.1", 0))
1111 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001112 c = socket.socket()
1113 c.connect(s.getsockname())
1114 c.setblocking(False)
1115 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001116 with self.assertRaises(ssl.SSLWantReadError) as cm:
1117 c.do_handshake()
1118 s = str(cm.exception)
1119 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1120 # For compatibility
1121 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1122
1123
Bill Janssen6e027db2007-11-15 22:23:56 +00001124class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125
Antoine Pitrou480a1242010-04-28 21:37:09 +00001126 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001127 with support.transient_internet("svn.python.org"):
1128 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1129 cert_reqs=ssl.CERT_NONE)
1130 try:
1131 s.connect(("svn.python.org", 443))
1132 self.assertEqual({}, s.getpeercert())
1133 finally:
1134 s.close()
1135
1136 # this should fail because we have no verification certs
1137 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1138 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001139 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1140 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001141 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001142
Antoine Pitrou350c7222010-09-09 13:31:46 +00001143 # this should succeed because we specify the root cert
1144 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1145 cert_reqs=ssl.CERT_REQUIRED,
1146 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1147 try:
1148 s.connect(("svn.python.org", 443))
1149 self.assertTrue(s.getpeercert())
1150 finally:
1151 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001152
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001153 def test_connect_ex(self):
1154 # Issue #11326: check connect_ex() implementation
1155 with support.transient_internet("svn.python.org"):
1156 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1157 cert_reqs=ssl.CERT_REQUIRED,
1158 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1159 try:
1160 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
1161 self.assertTrue(s.getpeercert())
1162 finally:
1163 s.close()
1164
1165 def test_non_blocking_connect_ex(self):
1166 # Issue #11326: non-blocking connect_ex() should allow handshake
1167 # to proceed after the socket gets ready.
1168 with support.transient_internet("svn.python.org"):
1169 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1170 cert_reqs=ssl.CERT_REQUIRED,
1171 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1172 do_handshake_on_connect=False)
1173 try:
1174 s.setblocking(False)
1175 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +00001176 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1177 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001178 # Wait for connect to finish
1179 select.select([], [s], [], 5.0)
1180 # Non-blocking handshake
1181 while True:
1182 try:
1183 s.do_handshake()
1184 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001185 except ssl.SSLWantReadError:
1186 select.select([s], [], [], 5.0)
1187 except ssl.SSLWantWriteError:
1188 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001189 # SSL established
1190 self.assertTrue(s.getpeercert())
1191 finally:
1192 s.close()
1193
Antoine Pitroub4410db2011-05-18 18:51:06 +02001194 def test_timeout_connect_ex(self):
1195 # Issue #12065: on a timeout, connect_ex() should return the original
1196 # errno (mimicking the behaviour of non-SSL sockets).
1197 with support.transient_internet("svn.python.org"):
1198 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1199 cert_reqs=ssl.CERT_REQUIRED,
1200 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1201 do_handshake_on_connect=False)
1202 try:
1203 s.settimeout(0.0000001)
1204 rc = s.connect_ex(('svn.python.org', 443))
1205 if rc == 0:
1206 self.skipTest("svn.python.org responded too quickly")
1207 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1208 finally:
1209 s.close()
1210
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001211 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +01001212 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001213 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1214 cert_reqs=ssl.CERT_REQUIRED,
1215 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1216 try:
Christian Heimesde570742013-12-16 21:15:44 +01001217 rc = s.connect_ex(("svn.python.org", 444))
1218 # Issue #19919: Windows machines or VMs hosted on Windows
1219 # machines sometimes return EWOULDBLOCK.
1220 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001221 finally:
1222 s.close()
1223
Antoine Pitrou152efa22010-05-16 18:19:27 +00001224 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001225 with support.transient_internet("svn.python.org"):
1226 # Same as test_connect, but with a separately created context
1227 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1228 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1229 s.connect(("svn.python.org", 443))
1230 try:
1231 self.assertEqual({}, s.getpeercert())
1232 finally:
1233 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +00001234 # Same with a server hostname
1235 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1236 server_hostname="svn.python.org")
1237 if ssl.HAS_SNI:
1238 s.connect(("svn.python.org", 443))
1239 s.close()
1240 else:
1241 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001242 # This should fail because we have no verification certs
1243 ctx.verify_mode = ssl.CERT_REQUIRED
1244 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +00001245 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +00001246 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001247 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001248 # This should succeed because we specify the root cert
1249 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1250 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1251 s.connect(("svn.python.org", 443))
1252 try:
1253 cert = s.getpeercert()
1254 self.assertTrue(cert)
1255 finally:
1256 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001257
1258 def test_connect_capath(self):
1259 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001260 # NOTE: the subject hashing algorithm has been changed between
1261 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1262 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001263 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +00001264 with support.transient_internet("svn.python.org"):
1265 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1266 ctx.verify_mode = ssl.CERT_REQUIRED
1267 ctx.load_verify_locations(capath=CAPATH)
1268 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1269 s.connect(("svn.python.org", 443))
1270 try:
1271 cert = s.getpeercert()
1272 self.assertTrue(cert)
1273 finally:
1274 s.close()
1275 # Same with a bytes `capath` argument
1276 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1277 ctx.verify_mode = ssl.CERT_REQUIRED
1278 ctx.load_verify_locations(capath=BYTES_CAPATH)
1279 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1280 s.connect(("svn.python.org", 443))
1281 try:
1282 cert = s.getpeercert()
1283 self.assertTrue(cert)
1284 finally:
1285 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001286
Christian Heimesefff7062013-11-21 03:35:02 +01001287 def test_connect_cadata(self):
1288 with open(CAFILE_CACERT) as f:
1289 pem = f.read()
1290 der = ssl.PEM_cert_to_DER_cert(pem)
1291 with support.transient_internet("svn.python.org"):
1292 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1293 ctx.verify_mode = ssl.CERT_REQUIRED
1294 ctx.load_verify_locations(cadata=pem)
1295 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1296 s.connect(("svn.python.org", 443))
1297 cert = s.getpeercert()
1298 self.assertTrue(cert)
1299
1300 # same with DER
1301 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1302 ctx.verify_mode = ssl.CERT_REQUIRED
1303 ctx.load_verify_locations(cadata=der)
1304 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1305 s.connect(("svn.python.org", 443))
1306 cert = s.getpeercert()
1307 self.assertTrue(cert)
1308
Antoine Pitroue3220242010-04-24 11:13:53 +00001309 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1310 def test_makefile_close(self):
1311 # Issue #5238: creating a file-like object with makefile() shouldn't
1312 # delay closing the underlying "real socket" (here tested with its
1313 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001314 with support.transient_internet("svn.python.org"):
1315 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1316 ss.connect(("svn.python.org", 443))
1317 fd = ss.fileno()
1318 f = ss.makefile()
1319 f.close()
1320 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001321 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001322 # Closing the SSL socket should close the fd too
1323 ss.close()
1324 gc.collect()
1325 with self.assertRaises(OSError) as e:
1326 os.read(fd, 0)
1327 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001328
Antoine Pitrou480a1242010-04-28 21:37:09 +00001329 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001330 with support.transient_internet("svn.python.org"):
1331 s = socket.socket(socket.AF_INET)
1332 s.connect(("svn.python.org", 443))
1333 s.setblocking(False)
1334 s = ssl.wrap_socket(s,
1335 cert_reqs=ssl.CERT_NONE,
1336 do_handshake_on_connect=False)
1337 count = 0
1338 while True:
1339 try:
1340 count += 1
1341 s.do_handshake()
1342 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001343 except ssl.SSLWantReadError:
1344 select.select([s], [], [])
1345 except ssl.SSLWantWriteError:
1346 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001347 s.close()
1348 if support.verbose:
1349 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001350
Antoine Pitrou480a1242010-04-28 21:37:09 +00001351 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001352 def _test_get_server_certificate(host, port, cert=None):
1353 with support.transient_internet(host):
1354 pem = ssl.get_server_certificate((host, port))
1355 if not pem:
1356 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001357
Antoine Pitrou15399c32011-04-28 19:23:55 +02001358 try:
1359 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
1360 except ssl.SSLError as x:
1361 #should fail
1362 if support.verbose:
1363 sys.stdout.write("%s\n" % x)
1364 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001365 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1366
Antoine Pitrou15399c32011-04-28 19:23:55 +02001367 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
1368 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001369 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001370 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001371 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001372
Antoine Pitrou15399c32011-04-28 19:23:55 +02001373 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1374 if support.IPV6_ENABLED:
1375 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001376
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001377 def test_ciphers(self):
1378 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001379 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001380 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1381 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1382 s.connect(remote)
1383 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1384 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1385 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001386 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001387 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001388 with socket.socket(socket.AF_INET) as sock:
1389 s = ssl.wrap_socket(sock,
1390 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1391 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001392
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001393 def test_algorithms(self):
1394 # Issue #8484: all algorithms should be available when verifying a
1395 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001396 # SHA256 was added in OpenSSL 0.9.8
1397 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1398 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001399 # sha256.tbs-internet.com needs SNI to use the correct certificate
1400 if not ssl.HAS_SNI:
1401 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001402 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1403 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001404 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001405 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001406 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1407 ctx.verify_mode = ssl.CERT_REQUIRED
1408 ctx.load_verify_locations(sha256_cert)
1409 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1410 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001411 try:
1412 s.connect(remote)
1413 if support.verbose:
1414 sys.stdout.write("\nCipher with %r is %r\n" %
1415 (remote, s.cipher()))
1416 sys.stdout.write("Certificate is:\n%s\n" %
1417 pprint.pformat(s.getpeercert()))
1418 finally:
1419 s.close()
1420
Christian Heimes9a5395a2013-06-17 15:44:12 +02001421 def test_get_ca_certs_capath(self):
1422 # capath certs are loaded on request
1423 with support.transient_internet("svn.python.org"):
1424 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1425 ctx.verify_mode = ssl.CERT_REQUIRED
1426 ctx.load_verify_locations(capath=CAPATH)
1427 self.assertEqual(ctx.get_ca_certs(), [])
1428 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1429 s.connect(("svn.python.org", 443))
1430 try:
1431 cert = s.getpeercert()
1432 self.assertTrue(cert)
1433 finally:
1434 s.close()
1435 self.assertEqual(len(ctx.get_ca_certs()), 1)
1436
Christian Heimes575596e2013-12-15 21:49:17 +01001437 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001438 def test_context_setget(self):
1439 # Check that the context of a connected socket can be replaced.
1440 with support.transient_internet("svn.python.org"):
1441 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1442 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1443 s = socket.socket(socket.AF_INET)
1444 with ctx1.wrap_socket(s) as ss:
1445 ss.connect(("svn.python.org", 443))
1446 self.assertIs(ss.context, ctx1)
1447 self.assertIs(ss._sslobj.context, ctx1)
1448 ss.context = ctx2
1449 self.assertIs(ss.context, ctx2)
1450 self.assertIs(ss._sslobj.context, ctx2)
1451
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001452try:
1453 import threading
1454except ImportError:
1455 _have_threads = False
1456else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001457 _have_threads = True
1458
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001459 from test.ssl_servers import make_https_server
1460
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001461 class ThreadedEchoServer(threading.Thread):
1462
1463 class ConnectionHandler(threading.Thread):
1464
1465 """A mildly complicated class, because we want it to work both
1466 with and without the SSL wrapper around the socket connection, so
1467 that we can test the STARTTLS functionality."""
1468
Bill Janssen6e027db2007-11-15 22:23:56 +00001469 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001470 self.server = server
1471 self.running = False
1472 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001473 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001474 self.sock.setblocking(1)
1475 self.sslconn = None
1476 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001477 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478
Antoine Pitrou480a1242010-04-28 21:37:09 +00001479 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001480 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001481 self.sslconn = self.server.context.wrap_socket(
1482 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001483 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001484 except (ssl.SSLError, ConnectionResetError) as e:
1485 # We treat ConnectionResetError as though it were an
1486 # SSLError - OpenSSL on Ubuntu abruptly closes the
1487 # connection when asked to use an unsupported protocol.
1488 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001489 # XXX Various errors can have happened here, for example
1490 # a mismatching protocol version, an invalid certificate,
1491 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001492 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001493 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001494 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001495 self.running = False
1496 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001497 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001498 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001499 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001500 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001501 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001502 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001503 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1504 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001505 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001506 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1507 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001508 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001509 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001510 sys.stdout.write(" server: selected protocol is now "
1511 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001512 return True
1513
1514 def read(self):
1515 if self.sslconn:
1516 return self.sslconn.read()
1517 else:
1518 return self.sock.recv(1024)
1519
1520 def write(self, bytes):
1521 if self.sslconn:
1522 return self.sslconn.write(bytes)
1523 else:
1524 return self.sock.send(bytes)
1525
1526 def close(self):
1527 if self.sslconn:
1528 self.sslconn.close()
1529 else:
1530 self.sock.close()
1531
Antoine Pitrou480a1242010-04-28 21:37:09 +00001532 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001533 self.running = True
1534 if not self.server.starttls_server:
1535 if not self.wrap_conn():
1536 return
1537 while self.running:
1538 try:
1539 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001540 stripped = msg.strip()
1541 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001542 # eof, so quit this handler
1543 self.running = False
1544 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001546 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001547 sys.stdout.write(" server: client closed connection\n")
1548 self.close()
1549 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001550 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001551 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001552 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001553 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001554 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001555 if not self.wrap_conn():
1556 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001557 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001558 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001559 if support.verbose and self.server.connectionchatty:
1560 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001561 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001562 self.sock = self.sslconn.unwrap()
1563 self.sslconn = None
1564 if support.verbose and self.server.connectionchatty:
1565 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001566 elif stripped == b'CB tls-unique':
1567 if support.verbose and self.server.connectionchatty:
1568 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1569 data = self.sslconn.get_channel_binding("tls-unique")
1570 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001571 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001572 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001573 self.server.connectionchatty):
1574 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001575 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1576 % (msg, ctype, msg.lower(), ctype))
1577 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001578 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001579 if self.server.chatty:
1580 handle_error("Test server failure:\n")
1581 self.close()
1582 self.running = False
1583 # normally, we'd just stop here, but for the test
1584 # harness, we want to stop the server
1585 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001586
Antoine Pitroub5218772010-05-21 09:56:06 +00001587 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001588 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001589 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001590 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001591 if context:
1592 self.context = context
1593 else:
1594 self.context = ssl.SSLContext(ssl_version
1595 if ssl_version is not None
1596 else ssl.PROTOCOL_TLSv1)
1597 self.context.verify_mode = (certreqs if certreqs is not None
1598 else ssl.CERT_NONE)
1599 if cacerts:
1600 self.context.load_verify_locations(cacerts)
1601 if certificate:
1602 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001603 if npn_protocols:
1604 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001605 if ciphers:
1606 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001607 self.chatty = chatty
1608 self.connectionchatty = connectionchatty
1609 self.starttls_server = starttls_server
1610 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001611 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001612 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001613 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001614 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001615 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001616 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001617 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001618
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001619 def __enter__(self):
1620 self.start(threading.Event())
1621 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001622 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001623
1624 def __exit__(self, *args):
1625 self.stop()
1626 self.join()
1627
Antoine Pitrou480a1242010-04-28 21:37:09 +00001628 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001629 self.flag = flag
1630 threading.Thread.start(self)
1631
Antoine Pitrou480a1242010-04-28 21:37:09 +00001632 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001633 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001634 self.sock.listen(5)
1635 self.active = True
1636 if self.flag:
1637 # signal an event
1638 self.flag.set()
1639 while self.active:
1640 try:
1641 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001642 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001643 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001644 + repr(connaddr) + '\n')
1645 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001646 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001647 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001648 except socket.timeout:
1649 pass
1650 except KeyboardInterrupt:
1651 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001652 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001653
Antoine Pitrou480a1242010-04-28 21:37:09 +00001654 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001655 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001656
Bill Janssen54cc54c2007-12-14 22:08:56 +00001657 class AsyncoreEchoServer(threading.Thread):
1658
1659 # this one's based on asyncore.dispatcher
1660
1661 class EchoServer (asyncore.dispatcher):
1662
1663 class ConnectionHandler (asyncore.dispatcher_with_send):
1664
1665 def __init__(self, conn, certfile):
1666 self.socket = ssl.wrap_socket(conn, server_side=True,
1667 certfile=certfile,
1668 do_handshake_on_connect=False)
1669 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001670 self._ssl_accepting = True
1671 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001672
1673 def readable(self):
1674 if isinstance(self.socket, ssl.SSLSocket):
1675 while self.socket.pending() > 0:
1676 self.handle_read_event()
1677 return True
1678
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001679 def _do_ssl_handshake(self):
1680 try:
1681 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001682 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1683 return
1684 except ssl.SSLEOFError:
1685 return self.handle_close()
1686 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001687 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001688 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001689 if err.args[0] == errno.ECONNABORTED:
1690 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001691 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001692 self._ssl_accepting = False
1693
1694 def handle_read(self):
1695 if self._ssl_accepting:
1696 self._do_ssl_handshake()
1697 else:
1698 data = self.recv(1024)
1699 if support.verbose:
1700 sys.stdout.write(" server: read %s from client\n" % repr(data))
1701 if not data:
1702 self.close()
1703 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001704 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001705
1706 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001707 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001708 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001709 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1710
1711 def handle_error(self):
1712 raise
1713
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001714 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001715 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001716 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1717 self.port = support.bind_port(sock, '')
1718 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001719 self.listen(5)
1720
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001721 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001722 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001723 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1724 self.ConnectionHandler(sock_obj, self.certfile)
1725
1726 def handle_error(self):
1727 raise
1728
Trent Nelson78520002008-04-10 20:54:35 +00001729 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001730 self.flag = None
1731 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001732 self.server = self.EchoServer(certfile)
1733 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001734 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001735 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001736
1737 def __str__(self):
1738 return "<%s %s>" % (self.__class__.__name__, self.server)
1739
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001740 def __enter__(self):
1741 self.start(threading.Event())
1742 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001743 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001744
1745 def __exit__(self, *args):
1746 if support.verbose:
1747 sys.stdout.write(" cleanup: stopping server.\n")
1748 self.stop()
1749 if support.verbose:
1750 sys.stdout.write(" cleanup: joining server thread.\n")
1751 self.join()
1752 if support.verbose:
1753 sys.stdout.write(" cleanup: successfully joined.\n")
1754
Bill Janssen54cc54c2007-12-14 22:08:56 +00001755 def start (self, flag=None):
1756 self.flag = flag
1757 threading.Thread.start(self)
1758
Antoine Pitrou480a1242010-04-28 21:37:09 +00001759 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001760 self.active = True
1761 if self.flag:
1762 self.flag.set()
1763 while self.active:
1764 try:
1765 asyncore.loop(1)
1766 except:
1767 pass
1768
Antoine Pitrou480a1242010-04-28 21:37:09 +00001769 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001770 self.active = False
1771 self.server.close()
1772
Antoine Pitrou480a1242010-04-28 21:37:09 +00001773 def bad_cert_test(certfile):
1774 """
1775 Launch a server with CERT_REQUIRED, and check that trying to
1776 connect to it with the given client certificate fails.
1777 """
Trent Nelson78520002008-04-10 20:54:35 +00001778 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001779 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001780 cacerts=CERTFILE, chatty=False,
1781 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001782 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001783 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001784 with socket.socket() as sock:
1785 s = ssl.wrap_socket(sock,
1786 certfile=certfile,
1787 ssl_version=ssl.PROTOCOL_TLSv1)
1788 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001789 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001790 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001791 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001792 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001793 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001794 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001795 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001796 if x.errno != errno.ENOENT:
1797 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001798 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001799 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001800 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001801 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001802
Antoine Pitroub5218772010-05-21 09:56:06 +00001803 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001804 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001805 """
1806 Launch a server, connect a client to it and try various reads
1807 and writes.
1808 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001809 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001810 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001811 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001812 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001813 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001814 with client_context.wrap_socket(socket.socket(),
1815 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001816 s.connect((HOST, server.port))
1817 for arg in [indata, bytearray(indata), memoryview(indata)]:
1818 if connectionchatty:
1819 if support.verbose:
1820 sys.stdout.write(
1821 " client: sending %r...\n" % indata)
1822 s.write(arg)
1823 outdata = s.read()
1824 if connectionchatty:
1825 if support.verbose:
1826 sys.stdout.write(" client: read %r\n" % outdata)
1827 if outdata != indata.lower():
1828 raise AssertionError(
1829 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1830 % (outdata[:20], len(outdata),
1831 indata[:20].lower(), len(indata)))
1832 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001833 if connectionchatty:
1834 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001835 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001836 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001837 'compression': s.compression(),
1838 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001839 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001840 'client_npn_protocol': s.selected_npn_protocol()
1841 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001842 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001843 stats['server_npn_protocols'] = server.selected_protocols
1844 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001845
Antoine Pitroub5218772010-05-21 09:56:06 +00001846 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1847 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001848 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001849 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001850 certtype = {
1851 ssl.CERT_NONE: "CERT_NONE",
1852 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1853 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1854 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001855 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001856 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001857 sys.stdout.write(formatstr %
1858 (ssl.get_protocol_name(client_protocol),
1859 ssl.get_protocol_name(server_protocol),
1860 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001861 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001862 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001863 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001864 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001865
1866 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1867 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1868 # starting from OpenSSL 1.0.0 (see issue #8322).
1869 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1870 client_context.set_ciphers("ALL")
1871
Antoine Pitroub5218772010-05-21 09:56:06 +00001872 for ctx in (client_context, server_context):
1873 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001874 ctx.load_cert_chain(CERTFILE)
1875 ctx.load_verify_locations(CERTFILE)
1876 try:
1877 server_params_test(client_context, server_context,
1878 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001879 # Protocol mismatch can result in either an SSLError, or a
1880 # "Connection reset by peer" error.
1881 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001882 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001883 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001884 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001885 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001886 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001887 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001888 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001889 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001890 "Client protocol %s succeeded with server protocol %s!"
1891 % (ssl.get_protocol_name(client_protocol),
1892 ssl.get_protocol_name(server_protocol)))
1893
1894
Bill Janssen6e027db2007-11-15 22:23:56 +00001895 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001896
Antoine Pitrou23df4832010-08-04 17:14:06 +00001897 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001898 def test_echo(self):
1899 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001900 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001901 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001902 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001903 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1904 context = ssl.SSLContext(protocol)
1905 context.load_cert_chain(CERTFILE)
1906 server_params_test(context, context,
1907 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001908
Antoine Pitrou480a1242010-04-28 21:37:09 +00001909 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001910 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001911 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001912 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1913 context.verify_mode = ssl.CERT_REQUIRED
1914 context.load_verify_locations(CERTFILE)
1915 context.load_cert_chain(CERTFILE)
1916 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001917 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001918 s = context.wrap_socket(socket.socket(),
1919 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001920 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001921 # getpeercert() raise ValueError while the handshake isn't
1922 # done.
1923 with self.assertRaises(ValueError):
1924 s.getpeercert()
1925 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001926 cert = s.getpeercert()
1927 self.assertTrue(cert, "Can't get peer certificate.")
1928 cipher = s.cipher()
1929 if support.verbose:
1930 sys.stdout.write(pprint.pformat(cert) + '\n')
1931 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1932 if 'subject' not in cert:
1933 self.fail("No subject field in certificate: %s." %
1934 pprint.pformat(cert))
1935 if ((('organizationName', 'Python Software Foundation'),)
1936 not in cert['subject']):
1937 self.fail(
1938 "Missing or invalid 'organizationName' field in certificate subject; "
1939 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001940 self.assertIn('notBefore', cert)
1941 self.assertIn('notAfter', cert)
1942 before = ssl.cert_time_to_seconds(cert['notBefore'])
1943 after = ssl.cert_time_to_seconds(cert['notAfter'])
1944 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001945 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001946
Christian Heimes2427b502013-11-23 11:24:32 +01001947 @unittest.skipUnless(have_verify_flags(),
1948 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001949 def test_crl_check(self):
1950 if support.verbose:
1951 sys.stdout.write("\n")
1952
1953 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1954 server_context.load_cert_chain(SIGNED_CERTFILE)
1955
1956 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1957 context.verify_mode = ssl.CERT_REQUIRED
1958 context.load_verify_locations(SIGNING_CA)
Christian Heimes32f0c7a2013-11-22 03:43:48 +01001959 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT)
Christian Heimes22587792013-11-21 23:56:13 +01001960
1961 # VERIFY_DEFAULT should pass
1962 server = ThreadedEchoServer(context=server_context, chatty=True)
1963 with server:
1964 with context.wrap_socket(socket.socket()) as s:
1965 s.connect((HOST, server.port))
1966 cert = s.getpeercert()
1967 self.assertTrue(cert, "Can't get peer certificate.")
1968
1969 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01001970 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01001971
1972 server = ThreadedEchoServer(context=server_context, chatty=True)
1973 with server:
1974 with context.wrap_socket(socket.socket()) as s:
1975 with self.assertRaisesRegex(ssl.SSLError,
1976 "certificate verify failed"):
1977 s.connect((HOST, server.port))
1978
1979 # now load a CRL file. The CRL file is signed by the CA.
1980 context.load_verify_locations(CRLFILE)
1981
1982 server = ThreadedEchoServer(context=server_context, chatty=True)
1983 with server:
1984 with context.wrap_socket(socket.socket()) as s:
1985 s.connect((HOST, server.port))
1986 cert = s.getpeercert()
1987 self.assertTrue(cert, "Can't get peer certificate.")
1988
Christian Heimes575596e2013-12-15 21:49:17 +01001989 @needs_sni
Christian Heimes1aa9a752013-12-02 02:41:19 +01001990 def test_check_hostname(self):
1991 if support.verbose:
1992 sys.stdout.write("\n")
1993
1994 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1995 server_context.load_cert_chain(SIGNED_CERTFILE)
1996
1997 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1998 context.verify_mode = ssl.CERT_REQUIRED
1999 context.check_hostname = True
2000 context.load_verify_locations(SIGNING_CA)
2001
2002 # correct hostname should verify
2003 server = ThreadedEchoServer(context=server_context, chatty=True)
2004 with server:
2005 with context.wrap_socket(socket.socket(),
2006 server_hostname="localhost") as s:
2007 s.connect((HOST, server.port))
2008 cert = s.getpeercert()
2009 self.assertTrue(cert, "Can't get peer certificate.")
2010
2011 # incorrect hostname should raise an exception
2012 server = ThreadedEchoServer(context=server_context, chatty=True)
2013 with server:
2014 with context.wrap_socket(socket.socket(),
2015 server_hostname="invalid") as s:
2016 with self.assertRaisesRegex(ssl.CertificateError,
2017 "hostname 'invalid' doesn't match 'localhost'"):
2018 s.connect((HOST, server.port))
2019
2020 # missing server_hostname arg should cause an exception, too
2021 server = ThreadedEchoServer(context=server_context, chatty=True)
2022 with server:
2023 with socket.socket() as s:
2024 with self.assertRaisesRegex(ValueError,
2025 "check_hostname requires server_hostname"):
2026 context.wrap_socket(s)
2027
Antoine Pitrou480a1242010-04-28 21:37:09 +00002028 def test_empty_cert(self):
2029 """Connecting with an empty cert file"""
2030 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2031 "nullcert.pem"))
2032 def test_malformed_cert(self):
2033 """Connecting with a badly formatted certificate (syntax error)"""
2034 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2035 "badcert.pem"))
2036 def test_nonexisting_cert(self):
2037 """Connecting with a non-existing cert file"""
2038 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2039 "wrongcert.pem"))
2040 def test_malformed_key(self):
2041 """Connecting with a badly formatted key (syntax error)"""
2042 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2043 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002044
Antoine Pitrou480a1242010-04-28 21:37:09 +00002045 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002046 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002047 in the client when attempting handshake.
2048 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002049 listener_ready = threading.Event()
2050 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002051
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002052 s = socket.socket()
2053 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002054
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002055 # `listener` runs in a thread. It sits in an accept() until
2056 # the main thread connects. Then it rudely closes the socket,
2057 # and sets Event `listener_gone` to let the main thread know
2058 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002059 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00002060 s.listen(5)
2061 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002062 newsock, addr = s.accept()
2063 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002064 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002065 listener_gone.set()
2066
2067 def connector():
2068 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002069 with socket.socket() as c:
2070 c.connect((HOST, port))
2071 listener_gone.wait()
2072 try:
2073 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002074 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002075 pass
2076 else:
2077 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002078
2079 t = threading.Thread(target=listener)
2080 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002081 try:
2082 connector()
2083 finally:
2084 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002085
Antoine Pitrou23df4832010-08-04 17:14:06 +00002086 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002087 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2088 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002089 def test_protocol_sslv2(self):
2090 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002091 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002092 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002093 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2094 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2095 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002096 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002097 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2098 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002099 # SSLv23 client with specific SSL options
2100 if no_sslv2_implies_sslv3_hello():
2101 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2102 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2103 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002104 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002105 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002106 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002107 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002108
Antoine Pitrou23df4832010-08-04 17:14:06 +00002109 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002110 def test_protocol_sslv23(self):
2111 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002112 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002113 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002114 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2115 try:
2116 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002117 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002118 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2119 if support.verbose:
2120 sys.stdout.write(
2121 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2122 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00002123 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
2124 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
2125 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002126
Antoine Pitrou480a1242010-04-28 21:37:09 +00002127 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2128 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
2129 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002130
Antoine Pitrou480a1242010-04-28 21:37:09 +00002131 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
2132 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
2133 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002134
Antoine Pitroub5218772010-05-21 09:56:06 +00002135 # Server with specific SSL options
2136 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
2137 server_options=ssl.OP_NO_SSLv3)
2138 # Will choose TLSv1
2139 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2140 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2141 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2142 server_options=ssl.OP_NO_TLSv1)
2143
2144
Antoine Pitrou23df4832010-08-04 17:14:06 +00002145 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002146 def test_protocol_sslv3(self):
2147 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002148 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002149 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002150 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
2151 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2152 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002153 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2154 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002155 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2156 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002157 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002158 if no_sslv2_implies_sslv3_hello():
2159 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2160 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
2161 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002162
Antoine Pitrou23df4832010-08-04 17:14:06 +00002163 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002164 def test_protocol_tlsv1(self):
2165 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002166 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002167 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002168 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
2169 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
2170 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002171 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2172 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002173 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002174 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2175 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002176
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002177 @skip_if_broken_ubuntu_ssl
2178 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2179 "TLS version 1.1 not supported.")
2180 def test_protocol_tlsv1_1(self):
2181 """Connecting to a TLSv1.1 server with various client options.
2182 Testing against older TLS versions."""
2183 if support.verbose:
2184 sys.stdout.write("\n")
2185 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
2186 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2187 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
2188 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
2189 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2190 client_options=ssl.OP_NO_TLSv1_1)
2191
2192 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
2193 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2194 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2195
2196
2197 @skip_if_broken_ubuntu_ssl
2198 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2199 "TLS version 1.2 not supported.")
2200 def test_protocol_tlsv1_2(self):
2201 """Connecting to a TLSv1.2 server with various client options.
2202 Testing against older TLS versions."""
2203 if support.verbose:
2204 sys.stdout.write("\n")
2205 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
2206 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2207 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2208 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2209 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
2210 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
2211 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2212 client_options=ssl.OP_NO_TLSv1_2)
2213
2214 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
2215 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2216 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2217 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2218 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2219
Antoine Pitrou480a1242010-04-28 21:37:09 +00002220 def test_starttls(self):
2221 """Switching from clear text to encrypted and back again."""
2222 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 +00002223
Trent Nelson78520002008-04-10 20:54:35 +00002224 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002225 ssl_version=ssl.PROTOCOL_TLSv1,
2226 starttls_server=True,
2227 chatty=True,
2228 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002229 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002230 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002231 s = socket.socket()
2232 s.setblocking(1)
2233 s.connect((HOST, server.port))
2234 if support.verbose:
2235 sys.stdout.write("\n")
2236 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002237 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002238 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002239 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002240 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002241 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002242 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002243 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002244 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002245 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002246 msg = outdata.strip().lower()
2247 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2248 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002249 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002250 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002251 " client: read %r from server, starting TLS...\n"
2252 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002253 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2254 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002255 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2256 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002257 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002258 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002259 " client: read %r from server, ending TLS...\n"
2260 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002261 s = conn.unwrap()
2262 wrapped = False
2263 else:
2264 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002265 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002266 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002267 if support.verbose:
2268 sys.stdout.write(" client: closing connection.\n")
2269 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002270 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002271 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002272 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002273 if wrapped:
2274 conn.close()
2275 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002276 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002277
Antoine Pitrou480a1242010-04-28 21:37:09 +00002278 def test_socketserver(self):
2279 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002280 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002281 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002282 if support.verbose:
2283 sys.stdout.write('\n')
2284 with open(CERTFILE, 'rb') as f:
2285 d1 = f.read()
2286 d2 = ''
2287 # now fetch the same data from the HTTPS server
2288 url = 'https://%s:%d/%s' % (
2289 HOST, server.port, os.path.split(CERTFILE)[1])
2290 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002291 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002292 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002293 if dlen and (int(dlen) > 0):
2294 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002295 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002296 sys.stdout.write(
2297 " client: read %d bytes from remote server '%s'\n"
2298 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002299 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002300 f.close()
2301 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002302
Antoine Pitrou480a1242010-04-28 21:37:09 +00002303 def test_asyncore_server(self):
2304 """Check the example asyncore integration."""
2305 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002306
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002307 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002308 sys.stdout.write("\n")
2309
Antoine Pitrou480a1242010-04-28 21:37:09 +00002310 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002311 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002312 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002313 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002314 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002315 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002316 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002317 " client: sending %r...\n" % indata)
2318 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002319 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002320 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002321 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002322 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002323 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002324 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2325 % (outdata[:20], len(outdata),
2326 indata[:20].lower(), len(indata)))
2327 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002328 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002329 sys.stdout.write(" client: closing connection.\n")
2330 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002331 if support.verbose:
2332 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002333
Antoine Pitrou480a1242010-04-28 21:37:09 +00002334 def test_recv_send(self):
2335 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002336 if support.verbose:
2337 sys.stdout.write("\n")
2338
2339 server = ThreadedEchoServer(CERTFILE,
2340 certreqs=ssl.CERT_NONE,
2341 ssl_version=ssl.PROTOCOL_TLSv1,
2342 cacerts=CERTFILE,
2343 chatty=True,
2344 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002345 with server:
2346 s = ssl.wrap_socket(socket.socket(),
2347 server_side=False,
2348 certfile=CERTFILE,
2349 ca_certs=CERTFILE,
2350 cert_reqs=ssl.CERT_NONE,
2351 ssl_version=ssl.PROTOCOL_TLSv1)
2352 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002353 # helper methods for standardising recv* method signatures
2354 def _recv_into():
2355 b = bytearray(b"\0"*100)
2356 count = s.recv_into(b)
2357 return b[:count]
2358
2359 def _recvfrom_into():
2360 b = bytearray(b"\0"*100)
2361 count, addr = s.recvfrom_into(b)
2362 return b[:count]
2363
2364 # (name, method, whether to expect success, *args)
2365 send_methods = [
2366 ('send', s.send, True, []),
2367 ('sendto', s.sendto, False, ["some.address"]),
2368 ('sendall', s.sendall, True, []),
2369 ]
2370 recv_methods = [
2371 ('recv', s.recv, True, []),
2372 ('recvfrom', s.recvfrom, False, ["some.address"]),
2373 ('recv_into', _recv_into, True, []),
2374 ('recvfrom_into', _recvfrom_into, False, []),
2375 ]
2376 data_prefix = "PREFIX_"
2377
2378 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002379 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002380 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002381 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002382 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002383 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002384 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002385 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002386 "<<{outdata:r}>> ({nout:d}) received; "
2387 "expected <<{indata:r}>> ({nin:d})\n".format(
2388 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002389 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002390 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002391 )
2392 )
2393 except ValueError as e:
2394 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002395 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002396 "Failed to send with method <<{name:s}>>; "
2397 "expected to succeed.\n".format(name=meth_name)
2398 )
2399 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002400 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002401 "Method <<{name:s}>> failed with unexpected "
2402 "exception message: {exp:s}\n".format(
2403 name=meth_name, exp=e
2404 )
2405 )
2406
2407 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002408 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002409 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002410 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002411 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002412 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002413 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002414 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002415 "<<{outdata:r}>> ({nout:d}) received; "
2416 "expected <<{indata:r}>> ({nin:d})\n".format(
2417 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002418 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002419 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002420 )
2421 )
2422 except ValueError as e:
2423 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002424 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002425 "Failed to receive with method <<{name:s}>>; "
2426 "expected to succeed.\n".format(name=meth_name)
2427 )
2428 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002429 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002430 "Method <<{name:s}>> failed with unexpected "
2431 "exception message: {exp:s}\n".format(
2432 name=meth_name, exp=e
2433 )
2434 )
2435 # consume data
2436 s.read()
2437
Nick Coghlan513886a2011-08-28 00:00:27 +10002438 # Make sure sendmsg et al are disallowed to avoid
2439 # inadvertent disclosure of data and/or corruption
2440 # of the encrypted data stream
2441 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2442 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2443 self.assertRaises(NotImplementedError,
2444 s.recvmsg_into, bytearray(100))
2445
Antoine Pitrou480a1242010-04-28 21:37:09 +00002446 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002447 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002448
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002449 def test_handshake_timeout(self):
2450 # Issue #5103: SSL handshake must respect the socket timeout
2451 server = socket.socket(socket.AF_INET)
2452 host = "127.0.0.1"
2453 port = support.bind_port(server)
2454 started = threading.Event()
2455 finish = False
2456
2457 def serve():
2458 server.listen(5)
2459 started.set()
2460 conns = []
2461 while not finish:
2462 r, w, e = select.select([server], [], [], 0.1)
2463 if server in r:
2464 # Let the socket hang around rather than having
2465 # it closed by garbage collection.
2466 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002467 for sock in conns:
2468 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002469
2470 t = threading.Thread(target=serve)
2471 t.start()
2472 started.wait()
2473
2474 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002475 try:
2476 c = socket.socket(socket.AF_INET)
2477 c.settimeout(0.2)
2478 c.connect((host, port))
2479 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002480 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002481 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002482 finally:
2483 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002484 try:
2485 c = socket.socket(socket.AF_INET)
2486 c = ssl.wrap_socket(c)
2487 c.settimeout(0.2)
2488 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002489 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002490 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002491 finally:
2492 c.close()
2493 finally:
2494 finish = True
2495 t.join()
2496 server.close()
2497
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002498 def test_server_accept(self):
2499 # Issue #16357: accept() on a SSLSocket created through
2500 # SSLContext.wrap_socket().
2501 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2502 context.verify_mode = ssl.CERT_REQUIRED
2503 context.load_verify_locations(CERTFILE)
2504 context.load_cert_chain(CERTFILE)
2505 server = socket.socket(socket.AF_INET)
2506 host = "127.0.0.1"
2507 port = support.bind_port(server)
2508 server = context.wrap_socket(server, server_side=True)
2509
2510 evt = threading.Event()
2511 remote = None
2512 peer = None
2513 def serve():
2514 nonlocal remote, peer
2515 server.listen(5)
2516 # Block on the accept and wait on the connection to close.
2517 evt.set()
2518 remote, peer = server.accept()
2519 remote.recv(1)
2520
2521 t = threading.Thread(target=serve)
2522 t.start()
2523 # Client wait until server setup and perform a connect.
2524 evt.wait()
2525 client = context.wrap_socket(socket.socket())
2526 client.connect((host, port))
2527 client_addr = client.getsockname()
2528 client.close()
2529 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002530 remote.close()
2531 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002532 # Sanity checks.
2533 self.assertIsInstance(remote, ssl.SSLSocket)
2534 self.assertEqual(peer, client_addr)
2535
Antoine Pitrou242db722013-05-01 20:52:07 +02002536 def test_getpeercert_enotconn(self):
2537 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2538 with context.wrap_socket(socket.socket()) as sock:
2539 with self.assertRaises(OSError) as cm:
2540 sock.getpeercert()
2541 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2542
2543 def test_do_handshake_enotconn(self):
2544 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2545 with context.wrap_socket(socket.socket()) as sock:
2546 with self.assertRaises(OSError) as cm:
2547 sock.do_handshake()
2548 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2549
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002550 def test_default_ciphers(self):
2551 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2552 try:
2553 # Force a set of weak ciphers on our client context
2554 context.set_ciphers("DES")
2555 except ssl.SSLError:
2556 self.skipTest("no DES cipher available")
2557 with ThreadedEchoServer(CERTFILE,
2558 ssl_version=ssl.PROTOCOL_SSLv23,
2559 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002560 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002561 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002562 s.connect((HOST, server.port))
2563 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2564
Antoine Pitroud6494802011-07-21 01:11:30 +02002565 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2566 "'tls-unique' channel binding not available")
2567 def test_tls_unique_channel_binding(self):
2568 """Test tls-unique channel binding."""
2569 if support.verbose:
2570 sys.stdout.write("\n")
2571
2572 server = ThreadedEchoServer(CERTFILE,
2573 certreqs=ssl.CERT_NONE,
2574 ssl_version=ssl.PROTOCOL_TLSv1,
2575 cacerts=CERTFILE,
2576 chatty=True,
2577 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002578 with server:
2579 s = ssl.wrap_socket(socket.socket(),
2580 server_side=False,
2581 certfile=CERTFILE,
2582 ca_certs=CERTFILE,
2583 cert_reqs=ssl.CERT_NONE,
2584 ssl_version=ssl.PROTOCOL_TLSv1)
2585 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002586 # get the data
2587 cb_data = s.get_channel_binding("tls-unique")
2588 if support.verbose:
2589 sys.stdout.write(" got channel binding data: {0!r}\n"
2590 .format(cb_data))
2591
2592 # check if it is sane
2593 self.assertIsNotNone(cb_data)
2594 self.assertEqual(len(cb_data), 12) # True for TLSv1
2595
2596 # and compare with the peers version
2597 s.write(b"CB tls-unique\n")
2598 peer_data_repr = s.read().strip()
2599 self.assertEqual(peer_data_repr,
2600 repr(cb_data).encode("us-ascii"))
2601 s.close()
2602
2603 # now, again
2604 s = ssl.wrap_socket(socket.socket(),
2605 server_side=False,
2606 certfile=CERTFILE,
2607 ca_certs=CERTFILE,
2608 cert_reqs=ssl.CERT_NONE,
2609 ssl_version=ssl.PROTOCOL_TLSv1)
2610 s.connect((HOST, server.port))
2611 new_cb_data = s.get_channel_binding("tls-unique")
2612 if support.verbose:
2613 sys.stdout.write(" got another channel binding data: {0!r}\n"
2614 .format(new_cb_data))
2615 # is it really unique
2616 self.assertNotEqual(cb_data, new_cb_data)
2617 self.assertIsNotNone(cb_data)
2618 self.assertEqual(len(cb_data), 12) # True for TLSv1
2619 s.write(b"CB tls-unique\n")
2620 peer_data_repr = s.read().strip()
2621 self.assertEqual(peer_data_repr,
2622 repr(new_cb_data).encode("us-ascii"))
2623 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002624
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002625 def test_compression(self):
2626 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2627 context.load_cert_chain(CERTFILE)
2628 stats = server_params_test(context, context,
2629 chatty=True, connectionchatty=True)
2630 if support.verbose:
2631 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2632 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2633
2634 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2635 "ssl.OP_NO_COMPRESSION needed for this test")
2636 def test_compression_disabled(self):
2637 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2638 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002639 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002640 stats = server_params_test(context, context,
2641 chatty=True, connectionchatty=True)
2642 self.assertIs(stats['compression'], None)
2643
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002644 def test_dh_params(self):
2645 # Check we can get a connection with ephemeral Diffie-Hellman
2646 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2647 context.load_cert_chain(CERTFILE)
2648 context.load_dh_params(DHFILE)
2649 context.set_ciphers("kEDH")
2650 stats = server_params_test(context, context,
2651 chatty=True, connectionchatty=True)
2652 cipher = stats["cipher"][0]
2653 parts = cipher.split("-")
2654 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2655 self.fail("Non-DH cipher: " + cipher[0])
2656
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002657 def test_selected_npn_protocol(self):
2658 # selected_npn_protocol() is None unless NPN is used
2659 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2660 context.load_cert_chain(CERTFILE)
2661 stats = server_params_test(context, context,
2662 chatty=True, connectionchatty=True)
2663 self.assertIs(stats['client_npn_protocol'], None)
2664
2665 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2666 def test_npn_protocols(self):
2667 server_protocols = ['http/1.1', 'spdy/2']
2668 protocol_tests = [
2669 (['http/1.1', 'spdy/2'], 'http/1.1'),
2670 (['spdy/2', 'http/1.1'], 'http/1.1'),
2671 (['spdy/2', 'test'], 'spdy/2'),
2672 (['abc', 'def'], 'abc')
2673 ]
2674 for client_protocols, expected in protocol_tests:
2675 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2676 server_context.load_cert_chain(CERTFILE)
2677 server_context.set_npn_protocols(server_protocols)
2678 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2679 client_context.load_cert_chain(CERTFILE)
2680 client_context.set_npn_protocols(client_protocols)
2681 stats = server_params_test(client_context, server_context,
2682 chatty=True, connectionchatty=True)
2683
2684 msg = "failed trying %s (s) and %s (c).\n" \
2685 "was expecting %s, but got %%s from the %%s" \
2686 % (str(server_protocols), str(client_protocols),
2687 str(expected))
2688 client_result = stats['client_npn_protocol']
2689 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2690 server_result = stats['server_npn_protocols'][-1] \
2691 if len(stats['server_npn_protocols']) else 'nothing'
2692 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2693
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002694 def sni_contexts(self):
2695 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2696 server_context.load_cert_chain(SIGNED_CERTFILE)
2697 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2698 other_context.load_cert_chain(SIGNED_CERTFILE2)
2699 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2700 client_context.verify_mode = ssl.CERT_REQUIRED
2701 client_context.load_verify_locations(SIGNING_CA)
2702 return server_context, other_context, client_context
2703
2704 def check_common_name(self, stats, name):
2705 cert = stats['peercert']
2706 self.assertIn((('commonName', name),), cert['subject'])
2707
2708 @needs_sni
2709 def test_sni_callback(self):
2710 calls = []
2711 server_context, other_context, client_context = self.sni_contexts()
2712
2713 def servername_cb(ssl_sock, server_name, initial_context):
2714 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002715 if server_name is not None:
2716 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002717 server_context.set_servername_callback(servername_cb)
2718
2719 stats = server_params_test(client_context, server_context,
2720 chatty=True,
2721 sni_name='supermessage')
2722 # The hostname was fetched properly, and the certificate was
2723 # changed for the connection.
2724 self.assertEqual(calls, [("supermessage", server_context)])
2725 # CERTFILE4 was selected
2726 self.check_common_name(stats, 'fakehostname')
2727
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002728 calls = []
2729 # The callback is called with server_name=None
2730 stats = server_params_test(client_context, server_context,
2731 chatty=True,
2732 sni_name=None)
2733 self.assertEqual(calls, [(None, server_context)])
2734 self.check_common_name(stats, 'localhost')
2735
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002736 # Check disabling the callback
2737 calls = []
2738 server_context.set_servername_callback(None)
2739
2740 stats = server_params_test(client_context, server_context,
2741 chatty=True,
2742 sni_name='notfunny')
2743 # Certificate didn't change
2744 self.check_common_name(stats, 'localhost')
2745 self.assertEqual(calls, [])
2746
2747 @needs_sni
2748 def test_sni_callback_alert(self):
2749 # Returning a TLS alert is reflected to the connecting client
2750 server_context, other_context, client_context = self.sni_contexts()
2751
2752 def cb_returning_alert(ssl_sock, server_name, initial_context):
2753 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2754 server_context.set_servername_callback(cb_returning_alert)
2755
2756 with self.assertRaises(ssl.SSLError) as cm:
2757 stats = server_params_test(client_context, server_context,
2758 chatty=False,
2759 sni_name='supermessage')
2760 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2761
2762 @needs_sni
2763 def test_sni_callback_raising(self):
2764 # Raising fails the connection with a TLS handshake failure alert.
2765 server_context, other_context, client_context = self.sni_contexts()
2766
2767 def cb_raising(ssl_sock, server_name, initial_context):
2768 1/0
2769 server_context.set_servername_callback(cb_raising)
2770
2771 with self.assertRaises(ssl.SSLError) as cm, \
2772 support.captured_stderr() as stderr:
2773 stats = server_params_test(client_context, server_context,
2774 chatty=False,
2775 sni_name='supermessage')
2776 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2777 self.assertIn("ZeroDivisionError", stderr.getvalue())
2778
2779 @needs_sni
2780 def test_sni_callback_wrong_return_type(self):
2781 # Returning the wrong return type terminates the TLS connection
2782 # with an internal error alert.
2783 server_context, other_context, client_context = self.sni_contexts()
2784
2785 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2786 return "foo"
2787 server_context.set_servername_callback(cb_wrong_return_type)
2788
2789 with self.assertRaises(ssl.SSLError) as cm, \
2790 support.captured_stderr() as stderr:
2791 stats = server_params_test(client_context, server_context,
2792 chatty=False,
2793 sni_name='supermessage')
2794 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2795 self.assertIn("TypeError", stderr.getvalue())
2796
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002797 def test_read_write_after_close_raises_valuerror(self):
2798 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2799 context.verify_mode = ssl.CERT_REQUIRED
2800 context.load_verify_locations(CERTFILE)
2801 context.load_cert_chain(CERTFILE)
2802 server = ThreadedEchoServer(context=context, chatty=False)
2803
2804 with server:
2805 s = context.wrap_socket(socket.socket())
2806 s.connect((HOST, server.port))
2807 s.close()
2808
2809 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002810 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002811
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002812
Thomas Woutersed03b412007-08-28 21:37:11 +00002813def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002814 if support.verbose:
2815 plats = {
2816 'Linux': platform.linux_distribution,
2817 'Mac': platform.mac_ver,
2818 'Windows': platform.win32_ver,
2819 }
2820 for name, func in plats.items():
2821 plat = func()
2822 if plat and plat[0]:
2823 plat = '%s %r' % (name, plat)
2824 break
2825 else:
2826 plat = repr(platform.platform())
2827 print("test_ssl: testing with %r %r" %
2828 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2829 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002830 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002831 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2832 try:
2833 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2834 except AttributeError:
2835 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002836
Antoine Pitrou152efa22010-05-16 18:19:27 +00002837 for filename in [
2838 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2839 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002840 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002841 BADCERT, BADKEY, EMPTYCERT]:
2842 if not os.path.exists(filename):
2843 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002844
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002845 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002846
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002847 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002848 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002849
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002850 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002851 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002852 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002853 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002854
Antoine Pitrou480a1242010-04-28 21:37:09 +00002855 try:
2856 support.run_unittest(*tests)
2857 finally:
2858 if _have_threads:
2859 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002860
2861if __name__ == "__main__":
2862 test_main()