blob: 07526c2cf159757b87924ee0c0dbeb83b38e95d6 [file] [log] [blame]
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001# -*- coding: utf-8 -*-
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00002# Test the support for SSL and sockets
3
4import sys
5import unittest
Benjamin Petersondaeb9252014-08-20 14:14:50 -05006from test import test_support as support
Nick Coghlandbcd4572016-03-20 22:39:15 +10007from test.script_helper import assert_python_ok
Bill Janssen934b16d2008-06-28 22:19:33 +00008import asyncore
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00009import socket
Bill Janssen934b16d2008-06-28 22:19:33 +000010import select
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000011import time
Benjamin Petersondaeb9252014-08-20 14:14:50 -050012import datetime
Antoine Pitroub558f172010-04-23 23:25:45 +000013import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000014import os
Antoine Pitroub558f172010-04-23 23:25:45 +000015import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000016import pprint
Benjamin Petersondaeb9252014-08-20 14:14:50 -050017import tempfile
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -060018import urllib2
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000019import traceback
Antoine Pitroudfb299b2010-04-23 22:54:59 +000020import weakref
Antoine Pitroud75efd92010-08-04 17:38:33 +000021import platform
Benjamin Petersondaeb9252014-08-20 14:14:50 -050022import functools
23from contextlib import closing
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000024
Benjamin Petersondaeb9252014-08-20 14:14:50 -050025ssl = support.import_module("ssl")
Bill Janssen296a59d2007-09-16 22:06:00 +000026
Benjamin Petersondaeb9252014-08-20 14:14:50 -050027PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
28HOST = support.HOST
Christian Heimesc2fc7c42016-09-05 23:37:13 +020029IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
30IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
31
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000032
Benjamin Petersondaeb9252014-08-20 14:14:50 -050033def data_file(*name):
34 return os.path.join(os.path.dirname(__file__), *name)
35
36# The custom key and certificate files used in test_ssl are generated
37# using Lib/test/make_ssl_certs.py.
38# Other certificates are simply fetched from the Internet servers they
39# are meant to authenticate.
40
41CERTFILE = data_file("keycert.pem")
42BYTES_CERTFILE = CERTFILE.encode(sys.getfilesystemencoding())
43ONLYCERT = data_file("ssl_cert.pem")
44ONLYKEY = data_file("ssl_key.pem")
45BYTES_ONLYCERT = ONLYCERT.encode(sys.getfilesystemencoding())
46BYTES_ONLYKEY = ONLYKEY.encode(sys.getfilesystemencoding())
47CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
48ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
49KEY_PASSWORD = "somepass"
50CAPATH = data_file("capath")
51BYTES_CAPATH = CAPATH.encode(sys.getfilesystemencoding())
52CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
53CAFILE_CACERT = data_file("capath", "5ed36f99.0")
54
55
56# empty CRL
57CRLFILE = data_file("revocation.crl")
58
59# Two keys and certs signed by the same CA (for SNI tests)
60SIGNED_CERTFILE = data_file("keycert3.pem")
61SIGNED_CERTFILE2 = data_file("keycert4.pem")
62SIGNING_CA = data_file("pycacert.pem")
Christian Heimes6663eb62016-09-06 23:25:35 +020063# cert with all kinds of subject alt names
64ALLSANFILE = data_file("allsans.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050065
Martin Panter71202bb2016-01-15 00:25:29 +000066REMOTE_HOST = "self-signed.pythontest.net"
67REMOTE_ROOT_CERT = data_file("selfsigned_pythontestdotnet.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050068
69EMPTYCERT = data_file("nullcert.pem")
70BADCERT = data_file("badcert.pem")
Martin Panterfd8e8502016-01-30 02:36:00 +000071NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050072BADKEY = data_file("badkey.pem")
73NOKIACERT = data_file("nokia.pem")
74NULLBYTECERT = data_file("nullbytecert.pem")
75
Benjamin Petersondf11d4c2015-04-02 00:04:06 -040076DHFILE = data_file("dh1024.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050077BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding())
78
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000079
Neal Norwitz3e533c22007-08-27 01:03:18 +000080def handle_error(prefix):
81 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersondaeb9252014-08-20 14:14:50 -050082 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +000083 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000084
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000085
86class BasicTests(unittest.TestCase):
87
Antoine Pitrou3945c862010-04-28 21:11:01 +000088 def test_sslwrap_simple(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000089 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000090 try:
91 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
92 except IOError, e:
93 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
94 pass
95 else:
96 raise
97 try:
98 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
99 except IOError, e:
100 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
101 pass
102 else:
103 raise
Benjamin Peterson2f334562014-10-01 23:53:01 -0400104
105
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500106def can_clear_options():
107 # 0.9.8m or higher
108 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
109
110def no_sslv2_implies_sslv3_hello():
111 # 0.9.7h or higher
112 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
113
114def have_verify_flags():
115 # 0.9.8 or higher
116 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
117
118def utc_offset(): #NOTE: ignore issues like #1647654
119 # local time = utc time + utc offset
120 if time.daylight and time.localtime().tm_isdst > 0:
121 return -time.altzone # seconds
122 return -time.timezone
123
124def asn1time(cert_time):
125 # Some versions of OpenSSL ignore seconds, see #18207
126 # 0.9.8.i
127 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
128 fmt = "%b %d %H:%M:%S %Y GMT"
129 dt = datetime.datetime.strptime(cert_time, fmt)
130 dt = dt.replace(second=0)
131 cert_time = dt.strftime(fmt)
132 # %d adds leading zero but ASN1_TIME_print() uses leading space
133 if cert_time[4] == "0":
134 cert_time = cert_time[:4] + " " + cert_time[5:]
135
136 return cert_time
Neal Norwitz3e533c22007-08-27 01:03:18 +0000137
Antoine Pitroud75efd92010-08-04 17:38:33 +0000138# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
139def skip_if_broken_ubuntu_ssl(func):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200140 if hasattr(ssl, 'PROTOCOL_SSLv2'):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200141 @functools.wraps(func)
142 def f(*args, **kwargs):
143 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500144 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
145 except ssl.SSLError:
Victor Stinnerb1241f92011-05-10 01:52:03 +0200146 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500147 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200148 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
149 return func(*args, **kwargs)
150 return f
151 else:
152 return func
Antoine Pitroud75efd92010-08-04 17:38:33 +0000153
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500154needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
155
Antoine Pitroud75efd92010-08-04 17:38:33 +0000156
157class BasicSocketTests(unittest.TestCase):
158
Antoine Pitrou3945c862010-04-28 21:11:01 +0000159 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000160 ssl.CERT_NONE
161 ssl.CERT_OPTIONAL
162 ssl.CERT_REQUIRED
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500163 ssl.OP_CIPHER_SERVER_PREFERENCE
164 ssl.OP_SINGLE_DH_USE
165 if ssl.HAS_ECDH:
166 ssl.OP_SINGLE_ECDH_USE
167 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
168 ssl.OP_NO_COMPRESSION
169 self.assertIn(ssl.HAS_SNI, {True, False})
170 self.assertIn(ssl.HAS_ECDH, {True, False})
171
Antoine Pitrou3945c862010-04-28 21:11:01 +0000172 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000173 v = ssl.RAND_status()
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500174 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000175 sys.stdout.write("\n RAND_status is %d (%s)\n"
176 % (v, (v and "sufficient randomness") or
177 "insufficient randomness"))
Victor Stinner7c906672015-01-06 13:53:37 +0100178 if hasattr(ssl, 'RAND_egd'):
179 self.assertRaises(TypeError, ssl.RAND_egd, 1)
180 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000181 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000182
Antoine Pitrou3945c862010-04-28 21:11:01 +0000183 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000184 # note that this uses an 'unofficial' function in _ssl.c,
185 # provided solely for this test, to exercise the certificate
186 # parsing code
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500187 p = ssl._ssl._test_decode_cert(CERTFILE)
188 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000189 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500190 self.assertEqual(p['issuer'],
191 ((('countryName', 'XY'),),
192 (('localityName', 'Castle Anthrax'),),
193 (('organizationName', 'Python Software Foundation'),),
194 (('commonName', 'localhost'),))
195 )
196 # Note the next three asserts will fail if the keys are regenerated
197 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
198 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
199 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200200 self.assertEqual(p['subject'],
Antoine Pitrou60982912013-02-16 21:39:28 +0100201 ((('countryName', 'XY'),),
202 (('localityName', 'Castle Anthrax'),),
203 (('organizationName', 'Python Software Foundation'),),
204 (('commonName', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200205 )
Antoine Pitrou60982912013-02-16 21:39:28 +0100206 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200207 # Issue #13034: the subjectAltName in some certificates
208 # (notably projects.developer.nokia.com:443) wasn't parsed
209 p = ssl._ssl._test_decode_cert(NOKIACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500210 if support.verbose:
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200211 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
212 self.assertEqual(p['subjectAltName'],
213 (('DNS', 'projects.developer.nokia.com'),
214 ('DNS', 'projects.forum.nokia.com'))
215 )
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500216 # extra OCSP and AIA fields
217 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
218 self.assertEqual(p['caIssuers'],
219 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
220 self.assertEqual(p['crlDistributionPoints'],
221 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000222
Christian Heimes88b174c2013-08-17 00:54:47 +0200223 def test_parse_cert_CVE_2013_4238(self):
224 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500225 if support.verbose:
Christian Heimes88b174c2013-08-17 00:54:47 +0200226 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
227 subject = ((('countryName', 'US'),),
228 (('stateOrProvinceName', 'Oregon'),),
229 (('localityName', 'Beaverton'),),
230 (('organizationName', 'Python Software Foundation'),),
231 (('organizationalUnitName', 'Python Core Development'),),
232 (('commonName', 'null.python.org\x00example.org'),),
233 (('emailAddress', 'python-dev@python.org'),))
234 self.assertEqual(p['subject'], subject)
235 self.assertEqual(p['issuer'], subject)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500236 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
Christian Heimesf869a942013-08-25 14:12:41 +0200237 san = (('DNS', 'altnull.python.org\x00example.com'),
238 ('email', 'null@python.org\x00user@example.org'),
239 ('URI', 'http://null.python.org\x00http://example.org'),
240 ('IP Address', '192.0.2.1'),
241 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
242 else:
243 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
244 san = (('DNS', 'altnull.python.org\x00example.com'),
245 ('email', 'null@python.org\x00user@example.org'),
246 ('URI', 'http://null.python.org\x00http://example.org'),
247 ('IP Address', '192.0.2.1'),
248 ('IP Address', '<invalid>'))
249
250 self.assertEqual(p['subjectAltName'], san)
Christian Heimes88b174c2013-08-17 00:54:47 +0200251
Christian Heimes6663eb62016-09-06 23:25:35 +0200252 def test_parse_all_sans(self):
253 p = ssl._ssl._test_decode_cert(ALLSANFILE)
254 self.assertEqual(p['subjectAltName'],
255 (
256 ('DNS', 'allsans'),
257 ('othername', '<unsupported>'),
258 ('othername', '<unsupported>'),
259 ('email', 'user@example.org'),
260 ('DNS', 'www.example.org'),
261 ('DirName',
262 ((('countryName', 'XY'),),
263 (('localityName', 'Castle Anthrax'),),
264 (('organizationName', 'Python Software Foundation'),),
265 (('commonName', 'dirname example'),))),
266 ('URI', 'https://www.python.org/'),
267 ('IP Address', '127.0.0.1'),
268 ('IP Address', '0:0:0:0:0:0:0:1\n'),
269 ('Registered ID', '1.2.3.4.5')
270 )
271 )
272
Antoine Pitrou3945c862010-04-28 21:11:01 +0000273 def test_DER_to_PEM(self):
Martin Panter71202bb2016-01-15 00:25:29 +0000274 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000275 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000276 d1 = ssl.PEM_cert_to_DER_cert(pem)
277 p2 = ssl.DER_cert_to_PEM_cert(d1)
278 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000279 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000280 if not p2.startswith(ssl.PEM_HEADER + '\n'):
281 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
282 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
283 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000284
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000285 def test_openssl_version(self):
286 n = ssl.OPENSSL_VERSION_NUMBER
287 t = ssl.OPENSSL_VERSION_INFO
288 s = ssl.OPENSSL_VERSION
289 self.assertIsInstance(n, (int, long))
290 self.assertIsInstance(t, tuple)
291 self.assertIsInstance(s, str)
292 # Some sanity checks follow
293 # >= 0.9
294 self.assertGreaterEqual(n, 0x900000)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400295 # < 3.0
296 self.assertLess(n, 0x30000000)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000297 major, minor, fix, patch, status = t
298 self.assertGreaterEqual(major, 0)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400299 self.assertLess(major, 3)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000300 self.assertGreaterEqual(minor, 0)
301 self.assertLess(minor, 256)
302 self.assertGreaterEqual(fix, 0)
303 self.assertLess(fix, 256)
304 self.assertGreaterEqual(patch, 0)
Ned Deilyfa119782015-02-05 17:19:11 +1100305 self.assertLessEqual(patch, 63)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000306 self.assertGreaterEqual(status, 0)
307 self.assertLessEqual(status, 15)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400308 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimesc2fc7c42016-09-05 23:37:13 +0200309 if IS_LIBRESSL:
310 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
311 (s, t, hex(n)))
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400312 else:
313 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
314 (s, t))
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000315
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500316 @support.cpython_only
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000317 def test_refcycle(self):
318 # Issue #7943: an SSL object doesn't create reference cycles with
319 # itself.
320 s = socket.socket(socket.AF_INET)
321 ss = ssl.wrap_socket(s)
322 wr = weakref.ref(ss)
323 del ss
324 self.assertEqual(wr(), None)
325
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000326 def test_wrapped_unconnected(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500327 # Methods on an unconnected SSLSocket propagate the original
328 # socket.error raise by the underlying socket object.
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000329 s = socket.socket(socket.AF_INET)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500330 with closing(ssl.wrap_socket(s)) as ss:
331 self.assertRaises(socket.error, ss.recv, 1)
332 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
333 self.assertRaises(socket.error, ss.recvfrom, 1)
334 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
335 self.assertRaises(socket.error, ss.send, b'x')
336 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
337
338 def test_timeout(self):
339 # Issue #8524: when creating an SSL socket, the timeout of the
340 # original socket should be retained.
341 for timeout in (None, 0.0, 5.0):
342 s = socket.socket(socket.AF_INET)
343 s.settimeout(timeout)
344 with closing(ssl.wrap_socket(s)) as ss:
345 self.assertEqual(timeout, ss.gettimeout())
346
347 def test_errors(self):
348 sock = socket.socket()
349 self.assertRaisesRegexp(ValueError,
350 "certfile must be specified",
351 ssl.wrap_socket, sock, keyfile=CERTFILE)
352 self.assertRaisesRegexp(ValueError,
353 "certfile must be specified for server-side operations",
354 ssl.wrap_socket, sock, server_side=True)
355 self.assertRaisesRegexp(ValueError,
356 "certfile must be specified for server-side operations",
357 ssl.wrap_socket, sock, server_side=True, certfile="")
358 with closing(ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)) as s:
359 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
360 s.connect, (HOST, 8080))
361 with self.assertRaises(IOError) as cm:
362 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000363 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500364 self.assertEqual(cm.exception.errno, errno.ENOENT)
365 with self.assertRaises(IOError) as cm:
366 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000367 ssl.wrap_socket(sock,
368 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500369 self.assertEqual(cm.exception.errno, errno.ENOENT)
370 with self.assertRaises(IOError) as cm:
371 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000372 ssl.wrap_socket(sock,
373 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500374 self.assertEqual(cm.exception.errno, errno.ENOENT)
375
Martin Panter886aba42016-02-01 21:58:11 +0000376 def bad_cert_test(self, certfile):
377 """Check that trying to use the given client certificate fails"""
378 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
379 certfile)
380 sock = socket.socket()
381 self.addCleanup(sock.close)
382 with self.assertRaises(ssl.SSLError):
383 ssl.wrap_socket(sock,
384 certfile=certfile,
385 ssl_version=ssl.PROTOCOL_TLSv1)
386
387 def test_empty_cert(self):
388 """Wrapping with an empty cert file"""
389 self.bad_cert_test("nullcert.pem")
390
391 def test_malformed_cert(self):
392 """Wrapping with a badly formatted certificate (syntax error)"""
393 self.bad_cert_test("badcert.pem")
394
395 def test_malformed_key(self):
396 """Wrapping with a badly formatted key (syntax error)"""
397 self.bad_cert_test("badkey.pem")
398
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500399 def test_match_hostname(self):
400 def ok(cert, hostname):
401 ssl.match_hostname(cert, hostname)
402 def fail(cert, hostname):
403 self.assertRaises(ssl.CertificateError,
404 ssl.match_hostname, cert, hostname)
405
406 cert = {'subject': ((('commonName', 'example.com'),),)}
407 ok(cert, 'example.com')
408 ok(cert, 'ExAmple.cOm')
409 fail(cert, 'www.example.com')
410 fail(cert, '.example.com')
411 fail(cert, 'example.org')
412 fail(cert, 'exampleXcom')
413
414 cert = {'subject': ((('commonName', '*.a.com'),),)}
415 ok(cert, 'foo.a.com')
416 fail(cert, 'bar.foo.a.com')
417 fail(cert, 'a.com')
418 fail(cert, 'Xa.com')
419 fail(cert, '.a.com')
420
421 # only match one left-most wildcard
422 cert = {'subject': ((('commonName', 'f*.com'),),)}
423 ok(cert, 'foo.com')
424 ok(cert, 'f.com')
425 fail(cert, 'bar.com')
426 fail(cert, 'foo.a.com')
427 fail(cert, 'bar.foo.com')
428
429 # NULL bytes are bad, CVE-2013-4073
430 cert = {'subject': ((('commonName',
431 'null.python.org\x00example.org'),),)}
432 ok(cert, 'null.python.org\x00example.org') # or raise an error?
433 fail(cert, 'example.org')
434 fail(cert, 'null.python.org')
435
436 # error cases with wildcards
437 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
438 fail(cert, 'bar.foo.a.com')
439 fail(cert, 'a.com')
440 fail(cert, 'Xa.com')
441 fail(cert, '.a.com')
442
443 cert = {'subject': ((('commonName', 'a.*.com'),),)}
444 fail(cert, 'a.foo.com')
445 fail(cert, 'a..com')
446 fail(cert, 'a.com')
447
448 # wildcard doesn't match IDNA prefix 'xn--'
449 idna = u'püthon.python.org'.encode("idna").decode("ascii")
450 cert = {'subject': ((('commonName', idna),),)}
451 ok(cert, idna)
452 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
453 fail(cert, idna)
454 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
455 fail(cert, idna)
456
457 # wildcard in first fragment and IDNA A-labels in sequent fragments
458 # are supported.
459 idna = u'www*.pythön.org'.encode("idna").decode("ascii")
460 cert = {'subject': ((('commonName', idna),),)}
461 ok(cert, u'www.pythön.org'.encode("idna").decode("ascii"))
462 ok(cert, u'www1.pythön.org'.encode("idna").decode("ascii"))
463 fail(cert, u'ftp.pythön.org'.encode("idna").decode("ascii"))
464 fail(cert, u'pythön.org'.encode("idna").decode("ascii"))
465
466 # Slightly fake real-world example
467 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
468 'subject': ((('commonName', 'linuxfrz.org'),),),
469 'subjectAltName': (('DNS', 'linuxfr.org'),
470 ('DNS', 'linuxfr.com'),
471 ('othername', '<unsupported>'))}
472 ok(cert, 'linuxfr.org')
473 ok(cert, 'linuxfr.com')
474 # Not a "DNS" entry
475 fail(cert, '<unsupported>')
476 # When there is a subjectAltName, commonName isn't used
477 fail(cert, 'linuxfrz.org')
478
479 # A pristine real-world example
480 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
481 'subject': ((('countryName', 'US'),),
482 (('stateOrProvinceName', 'California'),),
483 (('localityName', 'Mountain View'),),
484 (('organizationName', 'Google Inc'),),
485 (('commonName', 'mail.google.com'),))}
486 ok(cert, 'mail.google.com')
487 fail(cert, 'gmail.com')
488 # Only commonName is considered
489 fail(cert, 'California')
490
491 # Neither commonName nor subjectAltName
492 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
493 'subject': ((('countryName', 'US'),),
494 (('stateOrProvinceName', 'California'),),
495 (('localityName', 'Mountain View'),),
496 (('organizationName', 'Google Inc'),))}
497 fail(cert, 'mail.google.com')
498
499 # No DNS entry in subjectAltName but a commonName
500 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
501 'subject': ((('countryName', 'US'),),
502 (('stateOrProvinceName', 'California'),),
503 (('localityName', 'Mountain View'),),
504 (('commonName', 'mail.google.com'),)),
505 'subjectAltName': (('othername', 'blabla'), )}
506 ok(cert, 'mail.google.com')
507
508 # No DNS entry subjectAltName and no commonName
509 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
510 'subject': ((('countryName', 'US'),),
511 (('stateOrProvinceName', 'California'),),
512 (('localityName', 'Mountain View'),),
513 (('organizationName', 'Google Inc'),)),
514 'subjectAltName': (('othername', 'blabla'),)}
515 fail(cert, 'google.com')
516
517 # Empty cert / no cert
518 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
519 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
520
521 # Issue #17980: avoid denials of service by refusing more than one
522 # wildcard per fragment.
523 cert = {'subject': ((('commonName', 'a*b.com'),),)}
524 ok(cert, 'axxb.com')
525 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
526 fail(cert, 'axxb.com')
527 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
528 with self.assertRaises(ssl.CertificateError) as cm:
529 ssl.match_hostname(cert, 'axxbxxc.com')
530 self.assertIn("too many wildcards", str(cm.exception))
531
532 def test_server_side(self):
533 # server_hostname doesn't work for server sockets
534 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
535 with closing(socket.socket()) as sock:
536 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
537 server_hostname="some.hostname")
538
539 def test_unknown_channel_binding(self):
540 # should raise ValueError for unknown type
541 s = socket.socket(socket.AF_INET)
542 with closing(ssl.wrap_socket(s)) as ss:
543 with self.assertRaises(ValueError):
544 ss.get_channel_binding("unknown-type")
545
546 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
547 "'tls-unique' channel binding not available")
548 def test_tls_unique_channel_binding(self):
549 # unconnected should return None for known type
550 s = socket.socket(socket.AF_INET)
551 with closing(ssl.wrap_socket(s)) as ss:
552 self.assertIsNone(ss.get_channel_binding("tls-unique"))
553 # the same for server-side
554 s = socket.socket(socket.AF_INET)
555 with closing(ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)) as ss:
556 self.assertIsNone(ss.get_channel_binding("tls-unique"))
557
558 def test_get_default_verify_paths(self):
559 paths = ssl.get_default_verify_paths()
560 self.assertEqual(len(paths), 6)
561 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
562
563 with support.EnvironmentVarGuard() as env:
564 env["SSL_CERT_DIR"] = CAPATH
565 env["SSL_CERT_FILE"] = CERTFILE
566 paths = ssl.get_default_verify_paths()
567 self.assertEqual(paths.cafile, CERTFILE)
568 self.assertEqual(paths.capath, CAPATH)
569
570 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
571 def test_enum_certificates(self):
572 self.assertTrue(ssl.enum_certificates("CA"))
573 self.assertTrue(ssl.enum_certificates("ROOT"))
574
575 self.assertRaises(TypeError, ssl.enum_certificates)
576 self.assertRaises(WindowsError, ssl.enum_certificates, "")
577
578 trust_oids = set()
579 for storename in ("CA", "ROOT"):
580 store = ssl.enum_certificates(storename)
581 self.assertIsInstance(store, list)
582 for element in store:
583 self.assertIsInstance(element, tuple)
584 self.assertEqual(len(element), 3)
585 cert, enc, trust = element
586 self.assertIsInstance(cert, bytes)
587 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
588 self.assertIsInstance(trust, (set, bool))
589 if isinstance(trust, set):
590 trust_oids.update(trust)
591
592 serverAuth = "1.3.6.1.5.5.7.3.1"
593 self.assertIn(serverAuth, trust_oids)
594
595 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
596 def test_enum_crls(self):
597 self.assertTrue(ssl.enum_crls("CA"))
598 self.assertRaises(TypeError, ssl.enum_crls)
599 self.assertRaises(WindowsError, ssl.enum_crls, "")
600
601 crls = ssl.enum_crls("CA")
602 self.assertIsInstance(crls, list)
603 for element in crls:
604 self.assertIsInstance(element, tuple)
605 self.assertEqual(len(element), 2)
606 self.assertIsInstance(element[0], bytes)
607 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
608
609
610 def test_asn1object(self):
611 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
612 '1.3.6.1.5.5.7.3.1')
613
614 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
615 self.assertEqual(val, expected)
616 self.assertEqual(val.nid, 129)
617 self.assertEqual(val.shortname, 'serverAuth')
618 self.assertEqual(val.longname, 'TLS Web Server Authentication')
619 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
620 self.assertIsInstance(val, ssl._ASN1Object)
621 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
622
623 val = ssl._ASN1Object.fromnid(129)
624 self.assertEqual(val, expected)
625 self.assertIsInstance(val, ssl._ASN1Object)
626 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
627 with self.assertRaisesRegexp(ValueError, "unknown NID 100000"):
628 ssl._ASN1Object.fromnid(100000)
629 for i in range(1000):
630 try:
631 obj = ssl._ASN1Object.fromnid(i)
632 except ValueError:
633 pass
634 else:
635 self.assertIsInstance(obj.nid, int)
636 self.assertIsInstance(obj.shortname, str)
637 self.assertIsInstance(obj.longname, str)
638 self.assertIsInstance(obj.oid, (str, type(None)))
639
640 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
641 self.assertEqual(val, expected)
642 self.assertIsInstance(val, ssl._ASN1Object)
643 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
644 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
645 expected)
646 with self.assertRaisesRegexp(ValueError, "unknown object 'serverauth'"):
647 ssl._ASN1Object.fromname('serverauth')
648
649 def test_purpose_enum(self):
650 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
651 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
652 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
653 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
654 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
655 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
656 '1.3.6.1.5.5.7.3.1')
657
658 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
659 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
660 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
661 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
662 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
663 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
664 '1.3.6.1.5.5.7.3.2')
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000665
Antoine Pitrou63cc99d2013-12-28 17:26:33 +0100666 def test_unsupported_dtls(self):
667 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
668 self.addCleanup(s.close)
669 with self.assertRaises(NotImplementedError) as cx:
670 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
671 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500672 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
673 with self.assertRaises(NotImplementedError) as cx:
674 ctx.wrap_socket(s)
675 self.assertEqual(str(cx.exception), "only stream sockets are supported")
676
677 def cert_time_ok(self, timestring, timestamp):
678 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
679
680 def cert_time_fail(self, timestring):
681 with self.assertRaises(ValueError):
682 ssl.cert_time_to_seconds(timestring)
683
684 @unittest.skipUnless(utc_offset(),
685 'local time needs to be different from UTC')
686 def test_cert_time_to_seconds_timezone(self):
687 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
688 # results if local timezone is not UTC
689 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
690 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
691
692 def test_cert_time_to_seconds(self):
693 timestring = "Jan 5 09:34:43 2018 GMT"
694 ts = 1515144883.0
695 self.cert_time_ok(timestring, ts)
696 # accept keyword parameter, assert its name
697 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
698 # accept both %e and %d (space or zero generated by strftime)
699 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
700 # case-insensitive
701 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
702 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
703 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
704 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
705 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
706 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
707 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
708 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
709
710 newyear_ts = 1230768000.0
711 # leap seconds
712 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
713 # same timestamp
714 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
715
716 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
717 # allow 60th second (even if it is not a leap second)
718 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
719 # allow 2nd leap second for compatibility with time.strptime()
720 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
721 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
722
723 # no special treatement for the special value:
724 # 99991231235959Z (rfc 5280)
725 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
726
727 @support.run_with_locale('LC_ALL', '')
728 def test_cert_time_to_seconds_locale(self):
729 # `cert_time_to_seconds()` should be locale independent
730
731 def local_february_name():
732 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
733
734 if local_february_name().lower() == 'feb':
735 self.skipTest("locale-specific month name needs to be "
736 "different from C locale")
737
738 # locale-independent
739 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
740 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
741
742
743class ContextTests(unittest.TestCase):
744
745 @skip_if_broken_ubuntu_ssl
746 def test_constructor(self):
747 for protocol in PROTOCOLS:
748 ssl.SSLContext(protocol)
749 self.assertRaises(TypeError, ssl.SSLContext)
750 self.assertRaises(ValueError, ssl.SSLContext, -1)
751 self.assertRaises(ValueError, ssl.SSLContext, 42)
752
753 @skip_if_broken_ubuntu_ssl
754 def test_protocol(self):
755 for proto in PROTOCOLS:
756 ctx = ssl.SSLContext(proto)
757 self.assertEqual(ctx.protocol, proto)
758
759 def test_ciphers(self):
760 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
761 ctx.set_ciphers("ALL")
762 ctx.set_ciphers("DEFAULT")
763 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
764 ctx.set_ciphers("^$:,;?*'dorothyx")
765
766 @skip_if_broken_ubuntu_ssl
767 def test_options(self):
768 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800769 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimesc2fc7c42016-09-05 23:37:13 +0200770 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
771 if not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0):
772 default |= ssl.OP_NO_COMPRESSION
773 self.assertEqual(default, ctx.options)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800774 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimesc2fc7c42016-09-05 23:37:13 +0200775 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500776 if can_clear_options():
Christian Heimesc2fc7c42016-09-05 23:37:13 +0200777 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
778 self.assertEqual(default, ctx.options)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500779 ctx.options = 0
Xiang Zhangc9ba1862017-03-01 15:36:15 +0800780 # Ubuntu has OP_NO_SSLv3 forced on by default
781 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500782 else:
783 with self.assertRaises(ValueError):
784 ctx.options = 0
785
786 def test_verify_mode(self):
787 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
788 # Default value
789 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
790 ctx.verify_mode = ssl.CERT_OPTIONAL
791 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
792 ctx.verify_mode = ssl.CERT_REQUIRED
793 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
794 ctx.verify_mode = ssl.CERT_NONE
795 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
796 with self.assertRaises(TypeError):
797 ctx.verify_mode = None
798 with self.assertRaises(ValueError):
799 ctx.verify_mode = 42
800
801 @unittest.skipUnless(have_verify_flags(),
802 "verify_flags need OpenSSL > 0.9.8")
803 def test_verify_flags(self):
804 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson72ef9612015-03-04 22:49:41 -0500805 # default value
806 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
807 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500808 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
809 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
810 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
811 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
812 ctx.verify_flags = ssl.VERIFY_DEFAULT
813 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
814 # supports any value
815 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
816 self.assertEqual(ctx.verify_flags,
817 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
818 with self.assertRaises(TypeError):
819 ctx.verify_flags = None
820
821 def test_load_cert_chain(self):
822 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
823 # Combined key and cert in a single file
Benjamin Peterson04439fd2014-11-03 21:05:01 -0500824 ctx.load_cert_chain(CERTFILE, keyfile=None)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500825 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
826 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
827 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000828 ctx.load_cert_chain(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500829 self.assertEqual(cm.exception.errno, errno.ENOENT)
830 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
831 ctx.load_cert_chain(BADCERT)
832 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
833 ctx.load_cert_chain(EMPTYCERT)
834 # Separate key and cert
835 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
836 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
837 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
838 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
839 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
840 ctx.load_cert_chain(ONLYCERT)
841 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
842 ctx.load_cert_chain(ONLYKEY)
843 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
844 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
845 # Mismatching key and cert
846 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
847 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Martin Panter71202bb2016-01-15 00:25:29 +0000848 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500849 # Password protected key and cert
850 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
851 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
852 ctx.load_cert_chain(CERTFILE_PROTECTED,
853 password=bytearray(KEY_PASSWORD.encode()))
854 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
855 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
856 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
857 bytearray(KEY_PASSWORD.encode()))
858 with self.assertRaisesRegexp(TypeError, "should be a string"):
859 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
860 with self.assertRaises(ssl.SSLError):
861 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
862 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
863 # openssl has a fixed limit on the password buffer.
864 # PEM_BUFSIZE is generally set to 1kb.
865 # Return a string larger than this.
866 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
867 # Password callback
868 def getpass_unicode():
869 return KEY_PASSWORD
870 def getpass_bytes():
871 return KEY_PASSWORD.encode()
872 def getpass_bytearray():
873 return bytearray(KEY_PASSWORD.encode())
874 def getpass_badpass():
875 return "badpass"
876 def getpass_huge():
877 return b'a' * (1024 * 1024)
878 def getpass_bad_type():
879 return 9
880 def getpass_exception():
881 raise Exception('getpass error')
882 class GetPassCallable:
883 def __call__(self):
884 return KEY_PASSWORD
885 def getpass(self):
886 return KEY_PASSWORD
887 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
888 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
889 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
890 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
891 ctx.load_cert_chain(CERTFILE_PROTECTED,
892 password=GetPassCallable().getpass)
893 with self.assertRaises(ssl.SSLError):
894 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
895 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
896 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
897 with self.assertRaisesRegexp(TypeError, "must return a string"):
898 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
899 with self.assertRaisesRegexp(Exception, "getpass error"):
900 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
901 # Make sure the password function isn't called if it isn't needed
902 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
903
904 def test_load_verify_locations(self):
905 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
906 ctx.load_verify_locations(CERTFILE)
907 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
908 ctx.load_verify_locations(BYTES_CERTFILE)
909 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400910 ctx.load_verify_locations(cafile=BYTES_CERTFILE.decode('utf-8'))
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500911 self.assertRaises(TypeError, ctx.load_verify_locations)
912 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
913 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000914 ctx.load_verify_locations(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500915 self.assertEqual(cm.exception.errno, errno.ENOENT)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400916 with self.assertRaises(IOError):
917 ctx.load_verify_locations(u'')
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500918 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
919 ctx.load_verify_locations(BADCERT)
920 ctx.load_verify_locations(CERTFILE, CAPATH)
921 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
922
923 # Issue #10989: crash if the second argument type is invalid
924 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
925
926 def test_load_verify_cadata(self):
927 # test cadata
928 with open(CAFILE_CACERT) as f:
929 cacert_pem = f.read().decode("ascii")
930 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
931 with open(CAFILE_NEURONIO) as f:
932 neuronio_pem = f.read().decode("ascii")
933 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
934
935 # test PEM
936 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
937 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
938 ctx.load_verify_locations(cadata=cacert_pem)
939 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
940 ctx.load_verify_locations(cadata=neuronio_pem)
941 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
942 # cert already in hash table
943 ctx.load_verify_locations(cadata=neuronio_pem)
944 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
945
946 # combined
947 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
948 combined = "\n".join((cacert_pem, neuronio_pem))
949 ctx.load_verify_locations(cadata=combined)
950 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
951
952 # with junk around the certs
953 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
954 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
955 neuronio_pem, "tail"]
956 ctx.load_verify_locations(cadata="\n".join(combined))
957 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
958
959 # test DER
960 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
961 ctx.load_verify_locations(cadata=cacert_der)
962 ctx.load_verify_locations(cadata=neuronio_der)
963 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
964 # cert already in hash table
965 ctx.load_verify_locations(cadata=cacert_der)
966 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
967
968 # combined
969 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
970 combined = b"".join((cacert_der, neuronio_der))
971 ctx.load_verify_locations(cadata=combined)
972 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
973
974 # error cases
975 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
976 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
977
978 with self.assertRaisesRegexp(ssl.SSLError, "no start line"):
979 ctx.load_verify_locations(cadata=u"broken")
980 with self.assertRaisesRegexp(ssl.SSLError, "not enough data"):
981 ctx.load_verify_locations(cadata=b"broken")
982
983
984 def test_load_dh_params(self):
985 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
986 ctx.load_dh_params(DHFILE)
987 if os.name != 'nt':
988 ctx.load_dh_params(BYTES_DHFILE)
989 self.assertRaises(TypeError, ctx.load_dh_params)
990 self.assertRaises(TypeError, ctx.load_dh_params, None)
991 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000992 ctx.load_dh_params(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500993 self.assertEqual(cm.exception.errno, errno.ENOENT)
994 with self.assertRaises(ssl.SSLError) as cm:
995 ctx.load_dh_params(CERTFILE)
996
997 @skip_if_broken_ubuntu_ssl
998 def test_session_stats(self):
999 for proto in PROTOCOLS:
1000 ctx = ssl.SSLContext(proto)
1001 self.assertEqual(ctx.session_stats(), {
1002 'number': 0,
1003 'connect': 0,
1004 'connect_good': 0,
1005 'connect_renegotiate': 0,
1006 'accept': 0,
1007 'accept_good': 0,
1008 'accept_renegotiate': 0,
1009 'hits': 0,
1010 'misses': 0,
1011 'timeouts': 0,
1012 'cache_full': 0,
1013 })
1014
1015 def test_set_default_verify_paths(self):
1016 # There's not much we can do to test that it acts as expected,
1017 # so just check it doesn't crash or raise an exception.
1018 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1019 ctx.set_default_verify_paths()
1020
1021 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
1022 def test_set_ecdh_curve(self):
1023 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1024 ctx.set_ecdh_curve("prime256v1")
1025 ctx.set_ecdh_curve(b"prime256v1")
1026 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1027 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1028 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1029 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1030
1031 @needs_sni
1032 def test_sni_callback(self):
1033 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1034
1035 # set_servername_callback expects a callable, or None
1036 self.assertRaises(TypeError, ctx.set_servername_callback)
1037 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1038 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1039 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1040
1041 def dummycallback(sock, servername, ctx):
1042 pass
1043 ctx.set_servername_callback(None)
1044 ctx.set_servername_callback(dummycallback)
1045
1046 @needs_sni
1047 def test_sni_callback_refcycle(self):
1048 # Reference cycles through the servername callback are detected
1049 # and cleared.
1050 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1051 def dummycallback(sock, servername, ctx, cycle=ctx):
1052 pass
1053 ctx.set_servername_callback(dummycallback)
1054 wr = weakref.ref(ctx)
1055 del ctx, dummycallback
1056 gc.collect()
1057 self.assertIs(wr(), None)
1058
1059 def test_cert_store_stats(self):
1060 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1061 self.assertEqual(ctx.cert_store_stats(),
1062 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1063 ctx.load_cert_chain(CERTFILE)
1064 self.assertEqual(ctx.cert_store_stats(),
1065 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1066 ctx.load_verify_locations(CERTFILE)
1067 self.assertEqual(ctx.cert_store_stats(),
1068 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panter71202bb2016-01-15 00:25:29 +00001069 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001070 self.assertEqual(ctx.cert_store_stats(),
1071 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1072
1073 def test_get_ca_certs(self):
1074 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1075 self.assertEqual(ctx.get_ca_certs(), [])
1076 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1077 ctx.load_verify_locations(CERTFILE)
1078 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panter71202bb2016-01-15 00:25:29 +00001079 # but CAFILE_CACERT is a CA cert
1080 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001081 self.assertEqual(ctx.get_ca_certs(),
1082 [{'issuer': ((('organizationName', 'Root CA'),),
1083 (('organizationalUnitName', 'http://www.cacert.org'),),
1084 (('commonName', 'CA Cert Signing Authority'),),
1085 (('emailAddress', 'support@cacert.org'),)),
1086 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1087 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1088 'serialNumber': '00',
1089 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
1090 'subject': ((('organizationName', 'Root CA'),),
1091 (('organizationalUnitName', 'http://www.cacert.org'),),
1092 (('commonName', 'CA Cert Signing Authority'),),
1093 (('emailAddress', 'support@cacert.org'),)),
1094 'version': 3}])
1095
Martin Panter71202bb2016-01-15 00:25:29 +00001096 with open(CAFILE_CACERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001097 pem = f.read()
1098 der = ssl.PEM_cert_to_DER_cert(pem)
1099 self.assertEqual(ctx.get_ca_certs(True), [der])
1100
1101 def test_load_default_certs(self):
1102 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1103 ctx.load_default_certs()
1104
1105 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1106 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1107 ctx.load_default_certs()
1108
1109 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1110 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1111
1112 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1113 self.assertRaises(TypeError, ctx.load_default_certs, None)
1114 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1115
Benjamin Petersona02ae252014-10-03 18:17:15 -04001116 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimesc2fc7c42016-09-05 23:37:13 +02001117 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson0b30a2b2014-10-03 17:27:05 -04001118 def test_load_default_certs_env(self):
1119 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1120 with support.EnvironmentVarGuard() as env:
1121 env["SSL_CERT_DIR"] = CAPATH
1122 env["SSL_CERT_FILE"] = CERTFILE
1123 ctx.load_default_certs()
1124 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1125
Benjamin Petersona02ae252014-10-03 18:17:15 -04001126 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1127 def test_load_default_certs_env_windows(self):
1128 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1129 ctx.load_default_certs()
1130 stats = ctx.cert_store_stats()
1131
1132 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1133 with support.EnvironmentVarGuard() as env:
1134 env["SSL_CERT_DIR"] = CAPATH
1135 env["SSL_CERT_FILE"] = CERTFILE
1136 ctx.load_default_certs()
1137 stats["x509"] += 1
1138 self.assertEqual(ctx.cert_store_stats(), stats)
1139
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001140 def test_create_default_context(self):
1141 ctx = ssl.create_default_context()
1142 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1143 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1144 self.assertTrue(ctx.check_hostname)
1145 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1146 self.assertEqual(
1147 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1148 getattr(ssl, "OP_NO_COMPRESSION", 0),
1149 )
1150
1151 with open(SIGNING_CA) as f:
1152 cadata = f.read().decode("ascii")
1153 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1154 cadata=cadata)
1155 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1156 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1157 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1158 self.assertEqual(
1159 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1160 getattr(ssl, "OP_NO_COMPRESSION", 0),
1161 )
1162
1163 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
1164 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1165 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1166 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1167 self.assertEqual(
1168 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1169 getattr(ssl, "OP_NO_COMPRESSION", 0),
1170 )
1171 self.assertEqual(
1172 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1173 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1174 )
1175 self.assertEqual(
1176 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1177 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1178 )
1179
1180 def test__create_stdlib_context(self):
1181 ctx = ssl._create_stdlib_context()
1182 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1183 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1184 self.assertFalse(ctx.check_hostname)
1185 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1186
1187 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1188 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1189 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1190 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1191
1192 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
1193 cert_reqs=ssl.CERT_REQUIRED,
1194 check_hostname=True)
1195 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1196 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1197 self.assertTrue(ctx.check_hostname)
1198 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1199
1200 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1201 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1202 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1203 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1204
Nick Coghlandbcd4572016-03-20 22:39:15 +10001205 def test__https_verify_certificates(self):
1206 # Unit test to check the contect factory mapping
1207 # The factories themselves are tested above
1208 # This test will fail by design if run under PYTHONHTTPSVERIFY=0
1209 # (as will various test_httplib tests)
1210
1211 # Uses a fresh SSL module to avoid affecting the real one
1212 local_ssl = support.import_fresh_module("ssl")
1213 # Certificate verification is enabled by default
1214 self.assertIs(local_ssl._create_default_https_context,
1215 local_ssl.create_default_context)
1216 # Turn default verification off
1217 local_ssl._https_verify_certificates(enable=False)
1218 self.assertIs(local_ssl._create_default_https_context,
1219 local_ssl._create_unverified_context)
1220 # And back on
1221 local_ssl._https_verify_certificates(enable=True)
1222 self.assertIs(local_ssl._create_default_https_context,
1223 local_ssl.create_default_context)
1224 # The default behaviour is to enable
1225 local_ssl._https_verify_certificates(enable=False)
1226 local_ssl._https_verify_certificates()
1227 self.assertIs(local_ssl._create_default_https_context,
1228 local_ssl.create_default_context)
1229
1230 def test__https_verify_envvar(self):
1231 # Unit test to check the PYTHONHTTPSVERIFY handling
1232 # Need to use a subprocess so it can still be run under -E
1233 https_is_verified = """import ssl, sys; \
1234 status = "Error: _create_default_https_context does not verify certs" \
1235 if ssl._create_default_https_context is \
1236 ssl._create_unverified_context \
1237 else None; \
1238 sys.exit(status)"""
1239 https_is_not_verified = """import ssl, sys; \
1240 status = "Error: _create_default_https_context verifies certs" \
1241 if ssl._create_default_https_context is \
1242 ssl.create_default_context \
1243 else None; \
1244 sys.exit(status)"""
1245 extra_env = {}
1246 # Omitting it leaves verification on
1247 assert_python_ok("-c", https_is_verified, **extra_env)
1248 # Setting it to zero turns verification off
1249 extra_env[ssl._https_verify_envvar] = "0"
1250 assert_python_ok("-c", https_is_not_verified, **extra_env)
1251 # Any other value should also leave it on
1252 for setting in ("", "1", "enabled", "foo"):
1253 extra_env[ssl._https_verify_envvar] = setting
1254 assert_python_ok("-c", https_is_verified, **extra_env)
1255
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001256 def test_check_hostname(self):
1257 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1258 self.assertFalse(ctx.check_hostname)
1259
1260 # Requires CERT_REQUIRED or CERT_OPTIONAL
1261 with self.assertRaises(ValueError):
1262 ctx.check_hostname = True
1263 ctx.verify_mode = ssl.CERT_REQUIRED
1264 self.assertFalse(ctx.check_hostname)
1265 ctx.check_hostname = True
1266 self.assertTrue(ctx.check_hostname)
1267
1268 ctx.verify_mode = ssl.CERT_OPTIONAL
1269 ctx.check_hostname = True
1270 self.assertTrue(ctx.check_hostname)
1271
1272 # Cannot set CERT_NONE with check_hostname enabled
1273 with self.assertRaises(ValueError):
1274 ctx.verify_mode = ssl.CERT_NONE
1275 ctx.check_hostname = False
1276 self.assertFalse(ctx.check_hostname)
1277
1278
1279class SSLErrorTests(unittest.TestCase):
1280
1281 def test_str(self):
1282 # The str() of a SSLError doesn't include the errno
1283 e = ssl.SSLError(1, "foo")
1284 self.assertEqual(str(e), "foo")
1285 self.assertEqual(e.errno, 1)
1286 # Same for a subclass
1287 e = ssl.SSLZeroReturnError(1, "foo")
1288 self.assertEqual(str(e), "foo")
1289 self.assertEqual(e.errno, 1)
1290
1291 def test_lib_reason(self):
1292 # Test the library and reason attributes
1293 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1294 with self.assertRaises(ssl.SSLError) as cm:
1295 ctx.load_dh_params(CERTFILE)
1296 self.assertEqual(cm.exception.library, 'PEM')
1297 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1298 s = str(cm.exception)
1299 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1300
1301 def test_subclass(self):
1302 # Check that the appropriate SSLError subclass is raised
1303 # (this only tests one of them)
1304 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1305 with closing(socket.socket()) as s:
1306 s.bind(("127.0.0.1", 0))
1307 s.listen(5)
1308 c = socket.socket()
1309 c.connect(s.getsockname())
1310 c.setblocking(False)
1311 with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c:
1312 with self.assertRaises(ssl.SSLWantReadError) as cm:
1313 c.do_handshake()
1314 s = str(cm.exception)
1315 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1316 # For compatibility
1317 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
Antoine Pitrou63cc99d2013-12-28 17:26:33 +01001318
Antoine Pitrouf9de5342010-04-05 21:35:07 +00001319
Bill Janssen934b16d2008-06-28 22:19:33 +00001320class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +00001321
Antoine Pitrou3945c862010-04-28 21:11:01 +00001322 def test_connect(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001323 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001324 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1325 cert_reqs=ssl.CERT_NONE)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001326 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001327 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001328 self.assertEqual({}, s.getpeercert())
1329 finally:
1330 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001331
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001332 # this should fail because we have no verification certs
1333 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1334 cert_reqs=ssl.CERT_REQUIRED)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001335 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001336 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001337 s.close()
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001338
1339 # this should succeed because we specify the root cert
1340 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1341 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001342 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001343 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001344 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001345 self.assertTrue(s.getpeercert())
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001346 finally:
1347 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001348
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001349 def test_connect_ex(self):
1350 # Issue #11326: check connect_ex() implementation
Martin Panter71202bb2016-01-15 00:25:29 +00001351 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001352 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1353 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001354 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001355 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001356 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001357 self.assertTrue(s.getpeercert())
1358 finally:
1359 s.close()
1360
1361 def test_non_blocking_connect_ex(self):
1362 # Issue #11326: non-blocking connect_ex() should allow handshake
1363 # to proceed after the socket gets ready.
Martin Panter71202bb2016-01-15 00:25:29 +00001364 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001365 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1366 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001367 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001368 do_handshake_on_connect=False)
1369 try:
1370 s.setblocking(False)
Martin Panter71202bb2016-01-15 00:25:29 +00001371 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +00001372 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1373 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001374 # Wait for connect to finish
1375 select.select([], [s], [], 5.0)
1376 # Non-blocking handshake
1377 while True:
1378 try:
1379 s.do_handshake()
1380 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001381 except ssl.SSLWantReadError:
1382 select.select([s], [], [], 5.0)
1383 except ssl.SSLWantWriteError:
1384 select.select([], [s], [], 5.0)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001385 # SSL established
1386 self.assertTrue(s.getpeercert())
1387 finally:
1388 s.close()
1389
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001390 def test_timeout_connect_ex(self):
1391 # Issue #12065: on a timeout, connect_ex() should return the original
1392 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter71202bb2016-01-15 00:25:29 +00001393 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001394 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1395 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001396 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001397 do_handshake_on_connect=False)
1398 try:
1399 s.settimeout(0.0000001)
Martin Panter71202bb2016-01-15 00:25:29 +00001400 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001401 if rc == 0:
Martin Panter71202bb2016-01-15 00:25:29 +00001402 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001403 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1404 finally:
1405 s.close()
1406
1407 def test_connect_ex_error(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001408 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001409 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1410 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001411 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001412 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001413 rc = s.connect_ex((REMOTE_HOST, 444))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001414 # Issue #19919: Windows machines or VMs hosted on Windows
1415 # machines sometimes return EWOULDBLOCK.
Martin Panter71202bb2016-01-15 00:25:29 +00001416 errors = (
1417 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1418 errno.EWOULDBLOCK,
1419 )
1420 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001421 finally:
1422 s.close()
1423
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001424 def test_connect_with_context(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001425 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001426 # Same as test_connect, but with a separately created context
1427 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1428 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001429 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001430 try:
1431 self.assertEqual({}, s.getpeercert())
1432 finally:
1433 s.close()
1434 # Same with a server hostname
1435 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter71202bb2016-01-15 00:25:29 +00001436 server_hostname=REMOTE_HOST)
1437 s.connect((REMOTE_HOST, 443))
Benjamin Peterson31aa69e2014-11-23 20:13:31 -06001438 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001439 # This should fail because we have no verification certs
1440 ctx.verify_mode = ssl.CERT_REQUIRED
1441 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1442 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001443 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001444 s.close()
1445 # This should succeed because we specify the root cert
Martin Panter71202bb2016-01-15 00:25:29 +00001446 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001447 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001448 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001449 try:
1450 cert = s.getpeercert()
1451 self.assertTrue(cert)
1452 finally:
1453 s.close()
1454
1455 def test_connect_capath(self):
1456 # Verify server certificates using the `capath` argument
1457 # NOTE: the subject hashing algorithm has been changed between
1458 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1459 # contain both versions of each certificate (same content, different
1460 # filename) for this test to be portable across OpenSSL releases.
Martin Panter71202bb2016-01-15 00:25:29 +00001461 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001462 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1463 ctx.verify_mode = ssl.CERT_REQUIRED
1464 ctx.load_verify_locations(capath=CAPATH)
1465 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001466 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001467 try:
1468 cert = s.getpeercert()
1469 self.assertTrue(cert)
1470 finally:
1471 s.close()
1472 # Same with a bytes `capath` argument
1473 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1474 ctx.verify_mode = ssl.CERT_REQUIRED
1475 ctx.load_verify_locations(capath=BYTES_CAPATH)
1476 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001477 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001478 try:
1479 cert = s.getpeercert()
1480 self.assertTrue(cert)
1481 finally:
1482 s.close()
1483
1484 def test_connect_cadata(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001485 with open(REMOTE_ROOT_CERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001486 pem = f.read().decode('ascii')
1487 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panter71202bb2016-01-15 00:25:29 +00001488 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001489 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1490 ctx.verify_mode = ssl.CERT_REQUIRED
1491 ctx.load_verify_locations(cadata=pem)
1492 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001493 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001494 cert = s.getpeercert()
1495 self.assertTrue(cert)
1496
1497 # same with DER
1498 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1499 ctx.verify_mode = ssl.CERT_REQUIRED
1500 ctx.load_verify_locations(cadata=der)
1501 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001502 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001503 cert = s.getpeercert()
1504 self.assertTrue(cert)
1505
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001506 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1507 def test_makefile_close(self):
1508 # Issue #5238: creating a file-like object with makefile() shouldn't
1509 # delay closing the underlying "real socket" (here tested with its
1510 # file descriptor, hence skipping the test under Windows).
Martin Panter71202bb2016-01-15 00:25:29 +00001511 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001512 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001513 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001514 fd = ss.fileno()
1515 f = ss.makefile()
1516 f.close()
1517 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001518 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001519 # Closing the SSL socket should close the fd too
1520 ss.close()
1521 gc.collect()
1522 with self.assertRaises(OSError) as e:
1523 os.read(fd, 0)
1524 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +00001525
Antoine Pitrou3945c862010-04-28 21:11:01 +00001526 def test_non_blocking_handshake(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001527 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001528 s = socket.socket(socket.AF_INET)
Martin Panter71202bb2016-01-15 00:25:29 +00001529 s.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001530 s.setblocking(False)
1531 s = ssl.wrap_socket(s,
1532 cert_reqs=ssl.CERT_NONE,
1533 do_handshake_on_connect=False)
1534 count = 0
1535 while True:
1536 try:
1537 count += 1
1538 s.do_handshake()
1539 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001540 except ssl.SSLWantReadError:
1541 select.select([s], [], [])
1542 except ssl.SSLWantWriteError:
1543 select.select([], [s], [])
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001544 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001545 if support.verbose:
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001546 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +00001547
Antoine Pitrou3945c862010-04-28 21:11:01 +00001548 def test_get_server_certificate(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001549 def _test_get_server_certificate(host, port, cert=None):
1550 with support.transient_internet(host):
1551 pem = ssl.get_server_certificate((host, port))
1552 if not pem:
1553 self.fail("No server certificate on %s:%s!" % (host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001554
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001555 try:
1556 pem = ssl.get_server_certificate((host, port),
1557 ca_certs=CERTFILE)
1558 except ssl.SSLError as x:
1559 #should fail
1560 if support.verbose:
1561 sys.stdout.write("%s\n" % x)
1562 else:
1563 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001564 pem = ssl.get_server_certificate((host, port),
1565 ca_certs=cert)
1566 if not pem:
1567 self.fail("No server certificate on %s:%s!" % (host, port))
1568 if support.verbose:
1569 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1570
Martin Panter71202bb2016-01-15 00:25:29 +00001571 _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001572 if support.IPV6_ENABLED:
1573 _test_get_server_certificate('ipv6.google.com', 443)
1574
1575 def test_ciphers(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001576 remote = (REMOTE_HOST, 443)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001577 with support.transient_internet(remote[0]):
1578 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1579 cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s:
1580 s.connect(remote)
1581 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1582 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s:
1583 s.connect(remote)
1584 # Error checking can happen at instantiation or when connecting
1585 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
1586 with closing(socket.socket(socket.AF_INET)) as sock:
1587 s = ssl.wrap_socket(sock,
1588 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1589 s.connect(remote)
Bill Janssen296a59d2007-09-16 22:06:00 +00001590
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001591 def test_algorithms(self):
1592 # Issue #8484: all algorithms should be available when verifying a
1593 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +00001594 # SHA256 was added in OpenSSL 0.9.8
1595 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1596 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001597 # sha256.tbs-internet.com needs SNI to use the correct certificate
1598 if not ssl.HAS_SNI:
1599 self.skipTest("SNI needed for this test")
1600 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
Antoine Pitroud43245a2011-01-08 10:32:51 +00001601 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001602 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001603 with support.transient_internet("sha256.tbs-internet.com"):
1604 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1605 ctx.verify_mode = ssl.CERT_REQUIRED
1606 ctx.load_verify_locations(sha256_cert)
1607 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1608 server_hostname="sha256.tbs-internet.com")
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001609 try:
1610 s.connect(remote)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001611 if support.verbose:
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001612 sys.stdout.write("\nCipher with %r is %r\n" %
1613 (remote, s.cipher()))
1614 sys.stdout.write("Certificate is:\n%s\n" %
1615 pprint.pformat(s.getpeercert()))
1616 finally:
1617 s.close()
1618
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001619 def test_get_ca_certs_capath(self):
1620 # capath certs are loaded on request
Martin Panter71202bb2016-01-15 00:25:29 +00001621 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001622 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1623 ctx.verify_mode = ssl.CERT_REQUIRED
1624 ctx.load_verify_locations(capath=CAPATH)
1625 self.assertEqual(ctx.get_ca_certs(), [])
1626 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001627 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001628 try:
1629 cert = s.getpeercert()
1630 self.assertTrue(cert)
1631 finally:
1632 s.close()
1633 self.assertEqual(len(ctx.get_ca_certs()), 1)
1634
1635 @needs_sni
1636 def test_context_setget(self):
1637 # Check that the context of a connected socket can be replaced.
Martin Panter71202bb2016-01-15 00:25:29 +00001638 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001639 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1640 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1641 s = socket.socket(socket.AF_INET)
1642 with closing(ctx1.wrap_socket(s)) as ss:
Martin Panter71202bb2016-01-15 00:25:29 +00001643 ss.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001644 self.assertIs(ss.context, ctx1)
1645 self.assertIs(ss._sslobj.context, ctx1)
1646 ss.context = ctx2
1647 self.assertIs(ss.context, ctx2)
1648 self.assertIs(ss._sslobj.context, ctx2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001649
Bill Janssen98d19da2007-09-10 21:51:02 +00001650try:
1651 import threading
1652except ImportError:
1653 _have_threads = False
1654else:
Bill Janssen98d19da2007-09-10 21:51:02 +00001655 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001656
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001657 from test.ssl_servers import make_https_server
1658
Bill Janssen98d19da2007-09-10 21:51:02 +00001659 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001660
Bill Janssen98d19da2007-09-10 21:51:02 +00001661 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001662
Bill Janssen98d19da2007-09-10 21:51:02 +00001663 """A mildly complicated class, because we want it to work both
1664 with and without the SSL wrapper around the socket connection, so
1665 that we can test the STARTTLS functionality."""
1666
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001667 def __init__(self, server, connsock, addr):
Bill Janssen98d19da2007-09-10 21:51:02 +00001668 self.server = server
1669 self.running = False
1670 self.sock = connsock
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001671 self.addr = addr
Bill Janssen98d19da2007-09-10 21:51:02 +00001672 self.sock.setblocking(1)
1673 self.sslconn = None
1674 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001675 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001676
Antoine Pitrou3945c862010-04-28 21:11:01 +00001677 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001678 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001679 self.sslconn = self.server.context.wrap_socket(
1680 self.sock, server_side=True)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001681 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1682 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001683 except socket.error as e:
1684 # We treat ConnectionResetError as though it were an
1685 # SSLError - OpenSSL on Ubuntu abruptly closes the
1686 # connection when asked to use an unsupported protocol.
1687 #
Antoine Pitroudb187842010-04-27 10:32:58 +00001688 # XXX Various errors can have happened here, for example
1689 # a mismatching protocol version, an invalid certificate,
1690 # or a low-level bug. This should be made more discriminating.
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001691 if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET:
1692 raise
Antoine Pitroud76088d2012-01-03 22:46:48 +01001693 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +00001694 if self.server.chatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001695 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00001696 self.running = False
1697 self.server.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001698 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001699 return False
Bill Janssen98d19da2007-09-10 21:51:02 +00001700 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001701 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
1702 cert = self.sslconn.getpeercert()
1703 if support.verbose and self.server.chatty:
1704 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1705 cert_binary = self.sslconn.getpeercert(True)
1706 if support.verbose and self.server.chatty:
1707 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1708 cipher = self.sslconn.cipher()
1709 if support.verbose and self.server.chatty:
1710 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
1711 sys.stdout.write(" server: selected protocol is now "
1712 + str(self.sslconn.selected_npn_protocol()) + "\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001713 return True
1714
1715 def read(self):
1716 if self.sslconn:
1717 return self.sslconn.read()
1718 else:
1719 return self.sock.recv(1024)
1720
1721 def write(self, bytes):
1722 if self.sslconn:
1723 return self.sslconn.write(bytes)
1724 else:
1725 return self.sock.send(bytes)
1726
1727 def close(self):
1728 if self.sslconn:
1729 self.sslconn.close()
1730 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001731 self.sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001732
Antoine Pitrou3945c862010-04-28 21:11:01 +00001733 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001734 self.running = True
1735 if not self.server.starttls_server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001736 if not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +00001737 return
1738 while self.running:
1739 try:
1740 msg = self.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001741 stripped = msg.strip()
1742 if not stripped:
Bill Janssen98d19da2007-09-10 21:51:02 +00001743 # eof, so quit this handler
1744 self.running = False
1745 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001746 elif stripped == b'over':
1747 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001748 sys.stdout.write(" server: client closed connection\n")
1749 self.close()
1750 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001751 elif (self.server.starttls_server and
1752 stripped == b'STARTTLS'):
1753 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001754 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001755 self.write(b"OK\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001756 if not self.wrap_conn():
1757 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001758 elif (self.server.starttls_server and self.sslconn
1759 and stripped == b'ENDTLS'):
1760 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001761 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001762 self.write(b"OK\n")
1763 self.sock = self.sslconn.unwrap()
Bill Janssen39295c22008-08-12 16:31:21 +00001764 self.sslconn = None
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001765 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001766 sys.stdout.write(" server: connection is now unencrypted...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001767 elif stripped == b'CB tls-unique':
1768 if support.verbose and self.server.connectionchatty:
1769 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1770 data = self.sslconn.get_channel_binding("tls-unique")
1771 self.write(repr(data).encode("us-ascii") + b"\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001772 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001773 if (support.verbose and
Bill Janssen98d19da2007-09-10 21:51:02 +00001774 self.server.connectionchatty):
1775 ctype = (self.sslconn and "encrypted") or "unencrypted"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001776 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1777 % (msg, ctype, msg.lower(), ctype))
Bill Janssen98d19da2007-09-10 21:51:02 +00001778 self.write(msg.lower())
1779 except ssl.SSLError:
1780 if self.server.chatty:
1781 handle_error("Test server failure:\n")
1782 self.close()
1783 self.running = False
1784 # normally, we'd just stop here, but for the test
1785 # harness, we want to stop the server
1786 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +00001787
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001788 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +00001789 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +00001790 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001791 npn_protocols=None, alpn_protocols=None,
1792 ciphers=None, context=None):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001793 if context:
1794 self.context = context
1795 else:
1796 self.context = ssl.SSLContext(ssl_version
1797 if ssl_version is not None
1798 else ssl.PROTOCOL_TLSv1)
1799 self.context.verify_mode = (certreqs if certreqs is not None
1800 else ssl.CERT_NONE)
1801 if cacerts:
1802 self.context.load_verify_locations(cacerts)
1803 if certificate:
1804 self.context.load_cert_chain(certificate)
1805 if npn_protocols:
1806 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001807 if alpn_protocols:
1808 self.context.set_alpn_protocols(alpn_protocols)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001809 if ciphers:
1810 self.context.set_ciphers(ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +00001811 self.chatty = chatty
1812 self.connectionchatty = connectionchatty
1813 self.starttls_server = starttls_server
1814 self.sock = socket.socket()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001815 self.port = support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +00001816 self.flag = None
Bill Janssen98d19da2007-09-10 21:51:02 +00001817 self.active = False
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001818 self.selected_npn_protocols = []
1819 self.selected_alpn_protocols = []
Antoine Pitroud76088d2012-01-03 22:46:48 +01001820 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001821 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001822 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001823
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001824 def __enter__(self):
1825 self.start(threading.Event())
1826 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001827 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001828
1829 def __exit__(self, *args):
1830 self.stop()
1831 self.join()
1832
Antoine Pitrou3945c862010-04-28 21:11:01 +00001833 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +00001834 self.flag = flag
1835 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001836
Antoine Pitrou3945c862010-04-28 21:11:01 +00001837 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +00001838 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +00001839 self.sock.listen(5)
1840 self.active = True
1841 if self.flag:
1842 # signal an event
1843 self.flag.set()
1844 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001845 try:
Bill Janssen98d19da2007-09-10 21:51:02 +00001846 newconn, connaddr = self.sock.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001847 if support.verbose and self.chatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001848 sys.stdout.write(' server: new connection from '
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001849 + repr(connaddr) + '\n')
1850 handler = self.ConnectionHandler(self, newconn, connaddr)
Bill Janssen98d19da2007-09-10 21:51:02 +00001851 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +01001852 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +00001853 except socket.timeout:
1854 pass
1855 except KeyboardInterrupt:
1856 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +00001857 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001858
Antoine Pitrou3945c862010-04-28 21:11:01 +00001859 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001860 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001861
Bill Janssen934b16d2008-06-28 22:19:33 +00001862 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +00001863
Antoine Pitrou3945c862010-04-28 21:11:01 +00001864 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +00001865
Antoine Pitrou3945c862010-04-28 21:11:01 +00001866 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +00001867
1868 def __init__(self, conn, certfile):
Bill Janssen934b16d2008-06-28 22:19:33 +00001869 self.socket = ssl.wrap_socket(conn, server_side=True,
1870 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +00001871 do_handshake_on_connect=False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001872 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroufc69af12010-04-24 20:04:58 +00001873 self._ssl_accepting = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001874 self._do_ssl_handshake()
Bill Janssen934b16d2008-06-28 22:19:33 +00001875
1876 def readable(self):
1877 if isinstance(self.socket, ssl.SSLSocket):
1878 while self.socket.pending() > 0:
1879 self.handle_read_event()
1880 return True
1881
Antoine Pitroufc69af12010-04-24 20:04:58 +00001882 def _do_ssl_handshake(self):
1883 try:
1884 self.socket.do_handshake()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001885 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1886 return
1887 except ssl.SSLEOFError:
1888 return self.handle_close()
1889 except ssl.SSLError:
Antoine Pitroufc69af12010-04-24 20:04:58 +00001890 raise
1891 except socket.error, err:
1892 if err.args[0] == errno.ECONNABORTED:
1893 return self.handle_close()
1894 else:
1895 self._ssl_accepting = False
1896
Bill Janssen934b16d2008-06-28 22:19:33 +00001897 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +00001898 if self._ssl_accepting:
1899 self._do_ssl_handshake()
1900 else:
1901 data = self.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001902 if support.verbose:
1903 sys.stdout.write(" server: read %s from client\n" % repr(data))
1904 if not data:
1905 self.close()
1906 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001907 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +00001908
1909 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +00001910 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001911 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001912 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1913
1914 def handle_error(self):
1915 raise
1916
1917 def __init__(self, certfile):
1918 self.certfile = certfile
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001919 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1920 self.port = support.bind_port(sock, '')
1921 asyncore.dispatcher.__init__(self, sock)
Bill Janssen934b16d2008-06-28 22:19:33 +00001922 self.listen(5)
1923
1924 def handle_accept(self):
1925 sock_obj, addr = self.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001926 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001927 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1928 self.ConnectionHandler(sock_obj, self.certfile)
1929
1930 def handle_error(self):
1931 raise
1932
1933 def __init__(self, certfile):
1934 self.flag = None
1935 self.active = False
1936 self.server = self.EchoServer(certfile)
1937 self.port = self.server.port
1938 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001939 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +00001940
1941 def __str__(self):
1942 return "<%s %s>" % (self.__class__.__name__, self.server)
1943
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001944 def __enter__(self):
1945 self.start(threading.Event())
1946 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001947 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001948
1949 def __exit__(self, *args):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001950 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001951 sys.stdout.write(" cleanup: stopping server.\n")
1952 self.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001953 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001954 sys.stdout.write(" cleanup: joining server thread.\n")
1955 self.join()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001956 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001957 sys.stdout.write(" cleanup: successfully joined.\n")
Victor Stinnerd1c862f2017-05-03 03:47:34 +02001958 # make sure that ConnectionHandler is removed from socket_map
1959 asyncore.close_all(ignore_all=True)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001960
Antoine Pitrou3945c862010-04-28 21:11:01 +00001961 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +00001962 self.flag = flag
1963 threading.Thread.start(self)
1964
Antoine Pitrou3945c862010-04-28 21:11:01 +00001965 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001966 self.active = True
1967 if self.flag:
1968 self.flag.set()
1969 while self.active:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001970 try:
1971 asyncore.loop(1)
1972 except:
1973 pass
Bill Janssen934b16d2008-06-28 22:19:33 +00001974
Antoine Pitrou3945c862010-04-28 21:11:01 +00001975 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001976 self.active = False
1977 self.server.close()
1978
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001979 def server_params_test(client_context, server_context, indata=b"FOO\n",
1980 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001981 """
1982 Launch a server, connect a client to it and try various reads
1983 and writes.
1984 """
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001985 stats = {}
1986 server = ThreadedEchoServer(context=server_context,
Bill Janssen98d19da2007-09-10 21:51:02 +00001987 chatty=chatty,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001988 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001989 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001990 with closing(client_context.wrap_socket(socket.socket(),
1991 server_hostname=sni_name)) as s:
1992 s.connect((HOST, server.port))
1993 for arg in [indata, bytearray(indata), memoryview(indata)]:
1994 if connectionchatty:
1995 if support.verbose:
1996 sys.stdout.write(
1997 " client: sending %r...\n" % indata)
1998 s.write(arg)
1999 outdata = s.read()
2000 if connectionchatty:
2001 if support.verbose:
2002 sys.stdout.write(" client: read %r\n" % outdata)
2003 if outdata != indata.lower():
2004 raise AssertionError(
2005 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2006 % (outdata[:20], len(outdata),
2007 indata[:20].lower(), len(indata)))
2008 s.write(b"over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00002009 if connectionchatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002010 if support.verbose:
2011 sys.stdout.write(" client: closing connection.\n")
2012 stats.update({
2013 'compression': s.compression(),
2014 'cipher': s.cipher(),
2015 'peercert': s.getpeercert(),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002016 'client_alpn_protocol': s.selected_alpn_protocol(),
Alex Gaynore98205d2014-09-04 13:33:22 -07002017 'client_npn_protocol': s.selected_npn_protocol(),
2018 'version': s.version(),
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002019 })
2020 s.close()
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002021 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2022 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002023 return stats
Bill Janssen98d19da2007-09-10 21:51:02 +00002024
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002025 def try_protocol_combo(server_protocol, client_protocol, expect_success,
2026 certsreqs=None, server_options=0, client_options=0):
Alex Gaynore98205d2014-09-04 13:33:22 -07002027 """
2028 Try to SSL-connect using *client_protocol* to *server_protocol*.
2029 If *expect_success* is true, assert that the connection succeeds,
2030 if it's false, assert that the connection fails.
2031 Also, if *expect_success* is a string, assert that it is the protocol
2032 version actually used by the connection.
2033 """
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00002034 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +00002035 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +00002036 certtype = {
2037 ssl.CERT_NONE: "CERT_NONE",
2038 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2039 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2040 }[certsreqs]
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002041 if support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002042 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +00002043 sys.stdout.write(formatstr %
2044 (ssl.get_protocol_name(client_protocol),
2045 ssl.get_protocol_name(server_protocol),
2046 certtype))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002047 client_context = ssl.SSLContext(client_protocol)
2048 client_context.options |= client_options
2049 server_context = ssl.SSLContext(server_protocol)
2050 server_context.options |= server_options
2051
2052 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2053 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2054 # starting from OpenSSL 1.0.0 (see issue #8322).
2055 if client_context.protocol == ssl.PROTOCOL_SSLv23:
2056 client_context.set_ciphers("ALL")
2057
2058 for ctx in (client_context, server_context):
2059 ctx.verify_mode = certsreqs
2060 ctx.load_cert_chain(CERTFILE)
2061 ctx.load_verify_locations(CERTFILE)
Bill Janssen98d19da2007-09-10 21:51:02 +00002062 try:
Alex Gaynore98205d2014-09-04 13:33:22 -07002063 stats = server_params_test(client_context, server_context,
2064 chatty=False, connectionchatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002065 # Protocol mismatch can result in either an SSLError, or a
2066 # "Connection reset by peer" error.
2067 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002068 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +00002069 raise
Antoine Pitroudb187842010-04-27 10:32:58 +00002070 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002071 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +00002072 raise
Bill Janssen98d19da2007-09-10 21:51:02 +00002073 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002074 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00002075 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +00002076 "Client protocol %s succeeded with server protocol %s!"
2077 % (ssl.get_protocol_name(client_protocol),
2078 ssl.get_protocol_name(server_protocol)))
Alex Gaynore98205d2014-09-04 13:33:22 -07002079 elif (expect_success is not True
2080 and expect_success != stats['version']):
2081 raise AssertionError("version mismatch: expected %r, got %r"
2082 % (expect_success, stats['version']))
Bill Janssen98d19da2007-09-10 21:51:02 +00002083
2084
Bill Janssen934b16d2008-06-28 22:19:33 +00002085 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +00002086
Antoine Pitroud75efd92010-08-04 17:38:33 +00002087 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002088 def test_echo(self):
2089 """Basic test of an SSL client connecting to a server"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002090 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002091 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002092 for protocol in PROTOCOLS:
2093 context = ssl.SSLContext(protocol)
2094 context.load_cert_chain(CERTFILE)
2095 server_params_test(context, context,
2096 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002097
Antoine Pitrou3945c862010-04-28 21:11:01 +00002098 def test_getpeercert(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002099 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002100 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002101 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2102 context.verify_mode = ssl.CERT_REQUIRED
2103 context.load_verify_locations(CERTFILE)
2104 context.load_cert_chain(CERTFILE)
2105 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002106 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002107 s = context.wrap_socket(socket.socket(),
2108 do_handshake_on_connect=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002109 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002110 # getpeercert() raise ValueError while the handshake isn't
2111 # done.
2112 with self.assertRaises(ValueError):
2113 s.getpeercert()
2114 s.do_handshake()
Antoine Pitroudb187842010-04-27 10:32:58 +00002115 cert = s.getpeercert()
2116 self.assertTrue(cert, "Can't get peer certificate.")
2117 cipher = s.cipher()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002118 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002119 sys.stdout.write(pprint.pformat(cert) + '\n')
2120 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2121 if 'subject' not in cert:
2122 self.fail("No subject field in certificate: %s." %
2123 pprint.pformat(cert))
2124 if ((('organizationName', 'Python Software Foundation'),)
2125 not in cert['subject']):
2126 self.fail(
2127 "Missing or invalid 'organizationName' field in certificate subject; "
2128 "should be 'Python Software Foundation'.")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002129 self.assertIn('notBefore', cert)
2130 self.assertIn('notAfter', cert)
2131 before = ssl.cert_time_to_seconds(cert['notBefore'])
2132 after = ssl.cert_time_to_seconds(cert['notAfter'])
2133 self.assertLess(before, after)
Antoine Pitroudb187842010-04-27 10:32:58 +00002134 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002135
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002136 @unittest.skipUnless(have_verify_flags(),
2137 "verify_flags need OpenSSL > 0.9.8")
2138 def test_crl_check(self):
2139 if support.verbose:
2140 sys.stdout.write("\n")
2141
2142 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2143 server_context.load_cert_chain(SIGNED_CERTFILE)
2144
2145 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2146 context.verify_mode = ssl.CERT_REQUIRED
2147 context.load_verify_locations(SIGNING_CA)
Benjamin Petersond86699f2015-03-04 23:18:48 -05002148 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2149 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002150
2151 # VERIFY_DEFAULT should pass
2152 server = ThreadedEchoServer(context=server_context, chatty=True)
2153 with server:
2154 with closing(context.wrap_socket(socket.socket())) as s:
2155 s.connect((HOST, server.port))
2156 cert = s.getpeercert()
2157 self.assertTrue(cert, "Can't get peer certificate.")
2158
2159 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
2160 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
2161
2162 server = ThreadedEchoServer(context=server_context, chatty=True)
2163 with server:
2164 with closing(context.wrap_socket(socket.socket())) as s:
2165 with self.assertRaisesRegexp(ssl.SSLError,
2166 "certificate verify failed"):
2167 s.connect((HOST, server.port))
2168
2169 # now load a CRL file. The CRL file is signed by the CA.
2170 context.load_verify_locations(CRLFILE)
2171
2172 server = ThreadedEchoServer(context=server_context, chatty=True)
2173 with server:
2174 with closing(context.wrap_socket(socket.socket())) as s:
2175 s.connect((HOST, server.port))
2176 cert = s.getpeercert()
2177 self.assertTrue(cert, "Can't get peer certificate.")
2178
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002179 def test_check_hostname(self):
2180 if support.verbose:
2181 sys.stdout.write("\n")
2182
2183 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2184 server_context.load_cert_chain(SIGNED_CERTFILE)
2185
2186 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2187 context.verify_mode = ssl.CERT_REQUIRED
2188 context.check_hostname = True
2189 context.load_verify_locations(SIGNING_CA)
2190
2191 # correct hostname should verify
2192 server = ThreadedEchoServer(context=server_context, chatty=True)
2193 with server:
2194 with closing(context.wrap_socket(socket.socket(),
2195 server_hostname="localhost")) as s:
2196 s.connect((HOST, server.port))
2197 cert = s.getpeercert()
2198 self.assertTrue(cert, "Can't get peer certificate.")
2199
2200 # incorrect hostname should raise an exception
2201 server = ThreadedEchoServer(context=server_context, chatty=True)
2202 with server:
2203 with closing(context.wrap_socket(socket.socket(),
2204 server_hostname="invalid")) as s:
2205 with self.assertRaisesRegexp(ssl.CertificateError,
2206 "hostname 'invalid' doesn't match u?'localhost'"):
2207 s.connect((HOST, server.port))
2208
2209 # missing server_hostname arg should cause an exception, too
2210 server = ThreadedEchoServer(context=server_context, chatty=True)
2211 with server:
2212 with closing(socket.socket()) as s:
2213 with self.assertRaisesRegexp(ValueError,
2214 "check_hostname requires server_hostname"):
2215 context.wrap_socket(s)
2216
Martin Panterfd8e8502016-01-30 02:36:00 +00002217 def test_wrong_cert(self):
Martin Panter886aba42016-02-01 21:58:11 +00002218 """Connecting when the server rejects the client's certificate
2219
2220 Launch a server with CERT_REQUIRED, and check that trying to
2221 connect to it with a wrong client certificate fails.
2222 """
2223 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
2224 "wrongcert.pem")
2225 server = ThreadedEchoServer(CERTFILE,
2226 certreqs=ssl.CERT_REQUIRED,
2227 cacerts=CERTFILE, chatty=False,
2228 connectionchatty=False)
2229 with server, \
2230 closing(socket.socket()) as sock, \
2231 closing(ssl.wrap_socket(sock,
2232 certfile=certfile,
2233 ssl_version=ssl.PROTOCOL_TLSv1)) as s:
2234 try:
2235 # Expect either an SSL error about the server rejecting
2236 # the connection, or a low-level connection reset (which
2237 # sometimes happens on Windows)
2238 s.connect((HOST, server.port))
2239 except ssl.SSLError as e:
2240 if support.verbose:
2241 sys.stdout.write("\nSSLError is %r\n" % e)
2242 except socket.error as e:
2243 if e.errno != errno.ECONNRESET:
2244 raise
2245 if support.verbose:
2246 sys.stdout.write("\nsocket.error is %r\n" % e)
2247 else:
2248 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +00002249
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002250 def test_rude_shutdown(self):
2251 """A brutal shutdown of an SSL server should raise an OSError
2252 in the client when attempting handshake.
2253 """
2254 listener_ready = threading.Event()
2255 listener_gone = threading.Event()
2256
2257 s = socket.socket()
2258 port = support.bind_port(s, HOST)
2259
2260 # `listener` runs in a thread. It sits in an accept() until
2261 # the main thread connects. Then it rudely closes the socket,
2262 # and sets Event `listener_gone` to let the main thread know
2263 # the socket is gone.
2264 def listener():
2265 s.listen(5)
2266 listener_ready.set()
2267 newsock, addr = s.accept()
2268 newsock.close()
2269 s.close()
2270 listener_gone.set()
2271
2272 def connector():
2273 listener_ready.wait()
2274 with closing(socket.socket()) as c:
2275 c.connect((HOST, port))
2276 listener_gone.wait()
2277 try:
2278 ssl_sock = ssl.wrap_socket(c)
Benjamin Petersone208b572014-08-20 14:49:08 -05002279 except socket.error:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002280 pass
2281 else:
2282 self.fail('connecting to closed SSL socket should have failed')
2283
2284 t = threading.Thread(target=listener)
2285 t.start()
2286 try:
2287 connector()
2288 finally:
2289 t.join()
2290
Antoine Pitroud75efd92010-08-04 17:38:33 +00002291 @skip_if_broken_ubuntu_ssl
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002292 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2293 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002294 def test_protocol_sslv2(self):
2295 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002296 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002297 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002298 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2299 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2300 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01002301 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002302 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2303 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002304 # SSLv23 client with specific SSL options
2305 if no_sslv2_implies_sslv3_hello():
2306 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2307 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2308 client_options=ssl.OP_NO_SSLv2)
2309 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2310 client_options=ssl.OP_NO_SSLv3)
2311 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2312 client_options=ssl.OP_NO_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00002313
Antoine Pitroud75efd92010-08-04 17:38:33 +00002314 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002315 def test_protocol_sslv23(self):
2316 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002317 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002318 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002319 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2320 try:
2321 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
2322 except socket.error as x:
2323 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2324 if support.verbose:
2325 sys.stdout.write(
2326 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2327 % str(x))
Benjamin Peterson60766c42014-12-05 21:59:35 -05002328 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002329 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002330 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Alex Gaynore98205d2014-09-04 13:33:22 -07002331 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Bill Janssen98d19da2007-09-10 21:51:02 +00002332
Benjamin Peterson60766c42014-12-05 21:59:35 -05002333 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002334 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002335 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Alex Gaynore98205d2014-09-04 13:33:22 -07002336 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00002337
Benjamin Peterson60766c42014-12-05 21:59:35 -05002338 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002339 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002340 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Alex Gaynore98205d2014-09-04 13:33:22 -07002341 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00002342
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002343 # Server with specific SSL options
Benjamin Peterson60766c42014-12-05 21:59:35 -05002344 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2345 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002346 server_options=ssl.OP_NO_SSLv3)
2347 # Will choose TLSv1
2348 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2349 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2350 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2351 server_options=ssl.OP_NO_TLSv1)
2352
2353
Antoine Pitroud75efd92010-08-04 17:38:33 +00002354 @skip_if_broken_ubuntu_ssl
Benjamin Peterson60766c42014-12-05 21:59:35 -05002355 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2356 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002357 def test_protocol_sslv3(self):
2358 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002359 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002360 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002361 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2362 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2363 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002364 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2365 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002366 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2367 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002368 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002369 if no_sslv2_implies_sslv3_hello():
2370 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002371 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2372 False, client_options=ssl.OP_NO_SSLv2)
Bill Janssen98d19da2007-09-10 21:51:02 +00002373
Antoine Pitroud75efd92010-08-04 17:38:33 +00002374 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002375 def test_protocol_tlsv1(self):
2376 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002377 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002378 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002379 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2380 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2381 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002382 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2383 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002384 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2385 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002386 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2387 client_options=ssl.OP_NO_TLSv1)
2388
2389 @skip_if_broken_ubuntu_ssl
2390 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2391 "TLS version 1.1 not supported.")
2392 def test_protocol_tlsv1_1(self):
2393 """Connecting to a TLSv1.1 server with various client options.
2394 Testing against older TLS versions."""
2395 if support.verbose:
2396 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002397 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002398 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2399 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002400 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2401 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002402 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2403 client_options=ssl.OP_NO_TLSv1_1)
2404
Alex Gaynore98205d2014-09-04 13:33:22 -07002405 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002406 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2407 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2408
2409
2410 @skip_if_broken_ubuntu_ssl
2411 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2412 "TLS version 1.2 not supported.")
2413 def test_protocol_tlsv1_2(self):
2414 """Connecting to a TLSv1.2 server with various client options.
2415 Testing against older TLS versions."""
2416 if support.verbose:
2417 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002418 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002419 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2420 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2421 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2422 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002423 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2424 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002425 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2426 client_options=ssl.OP_NO_TLSv1_2)
2427
Alex Gaynore98205d2014-09-04 13:33:22 -07002428 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002429 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2430 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2431 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2432 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00002433
Antoine Pitrou3945c862010-04-28 21:11:01 +00002434 def test_starttls(self):
2435 """Switching from clear text to encrypted and back again."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002436 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00002437
Trent Nelsone41b0062008-04-08 23:47:30 +00002438 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00002439 ssl_version=ssl.PROTOCOL_TLSv1,
2440 starttls_server=True,
2441 chatty=True,
2442 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002443 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002444 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002445 s = socket.socket()
2446 s.setblocking(1)
2447 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002448 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002449 sys.stdout.write("\n")
2450 for indata in msgs:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002451 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002452 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002453 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002454 if wrapped:
2455 conn.write(indata)
2456 outdata = conn.read()
2457 else:
2458 s.send(indata)
2459 outdata = s.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002460 msg = outdata.strip().lower()
2461 if indata == b"STARTTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002462 # STARTTLS ok, switch to secure mode
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002463 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002464 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002465 " client: read %r from server, starting TLS...\n"
2466 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002467 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2468 wrapped = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002469 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002470 # ENDTLS ok, switch back to clear text
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002471 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002472 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002473 " client: read %r from server, ending TLS...\n"
2474 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002475 s = conn.unwrap()
2476 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00002477 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002478 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002479 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002480 " client: read %r from server\n" % msg)
2481 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002482 sys.stdout.write(" client: closing connection.\n")
2483 if wrapped:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002484 conn.write(b"over\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00002485 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002486 s.send(b"over\n")
2487 if wrapped:
2488 conn.close()
2489 else:
2490 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002491
Antoine Pitrou3945c862010-04-28 21:11:01 +00002492 def test_socketserver(self):
2493 """Using a SocketServer to create and manage SSL connections."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002494 server = make_https_server(self, certfile=CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00002495 # try to connect
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002496 if support.verbose:
2497 sys.stdout.write('\n')
2498 with open(CERTFILE, 'rb') as f:
2499 d1 = f.read()
2500 d2 = ''
2501 # now fetch the same data from the HTTPS server
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -06002502 url = 'https://localhost:%d/%s' % (
2503 server.port, os.path.split(CERTFILE)[1])
2504 context = ssl.create_default_context(cafile=CERTFILE)
Benjamin Petersonb0609ec2014-11-23 11:52:46 -06002505 f = urllib2.urlopen(url, context=context)
Bill Janssen296a59d2007-09-16 22:06:00 +00002506 try:
Bill Janssen296a59d2007-09-16 22:06:00 +00002507 dlen = f.info().getheader("content-length")
2508 if dlen and (int(dlen) > 0):
2509 d2 = f.read(int(dlen))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002510 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002511 sys.stdout.write(
2512 " client: read %d bytes from remote server '%s'\n"
2513 % (len(d2), server))
Bill Janssen296a59d2007-09-16 22:06:00 +00002514 finally:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002515 f.close()
2516 self.assertEqual(d1, d2)
Bill Janssen934b16d2008-06-28 22:19:33 +00002517
Antoine Pitrou3945c862010-04-28 21:11:01 +00002518 def test_asyncore_server(self):
2519 """Check the example asyncore integration."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002520 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00002521 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002522
2523 indata = b"FOO\n"
Bill Janssen934b16d2008-06-28 22:19:33 +00002524 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002525 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002526 s = ssl.wrap_socket(socket.socket())
2527 s.connect(('127.0.0.1', server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002528 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002529 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002530 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002531 s.write(indata)
2532 outdata = s.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002533 if support.verbose:
2534 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002535 if outdata != indata.lower():
2536 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002537 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2538 % (outdata[:20], len(outdata),
2539 indata[:20].lower(), len(indata)))
2540 s.write(b"over\n")
2541 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002542 sys.stdout.write(" client: closing connection.\n")
2543 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002544 if support.verbose:
2545 sys.stdout.write(" client: connection closed.\n")
Bill Janssen934b16d2008-06-28 22:19:33 +00002546
Antoine Pitrou3945c862010-04-28 21:11:01 +00002547 def test_recv_send(self):
2548 """Test recv(), send() and friends."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002549 if support.verbose:
Bill Janssen61c001a2008-09-08 16:37:24 +00002550 sys.stdout.write("\n")
2551
2552 server = ThreadedEchoServer(CERTFILE,
2553 certreqs=ssl.CERT_NONE,
2554 ssl_version=ssl.PROTOCOL_TLSv1,
2555 cacerts=CERTFILE,
2556 chatty=True,
2557 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002558 with server:
2559 s = ssl.wrap_socket(socket.socket(),
2560 server_side=False,
2561 certfile=CERTFILE,
2562 ca_certs=CERTFILE,
2563 cert_reqs=ssl.CERT_NONE,
2564 ssl_version=ssl.PROTOCOL_TLSv1)
2565 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00002566 # helper methods for standardising recv* method signatures
2567 def _recv_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002568 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002569 count = s.recv_into(b)
2570 return b[:count]
2571
2572 def _recvfrom_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002573 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002574 count, addr = s.recvfrom_into(b)
2575 return b[:count]
2576
2577 # (name, method, whether to expect success, *args)
2578 send_methods = [
2579 ('send', s.send, True, []),
2580 ('sendto', s.sendto, False, ["some.address"]),
2581 ('sendall', s.sendall, True, []),
2582 ]
2583 recv_methods = [
2584 ('recv', s.recv, True, []),
2585 ('recvfrom', s.recvfrom, False, ["some.address"]),
2586 ('recv_into', _recv_into, True, []),
2587 ('recvfrom_into', _recvfrom_into, False, []),
2588 ]
2589 data_prefix = u"PREFIX_"
2590
2591 for meth_name, send_meth, expect_success, args in send_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002592 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002593 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002594 send_meth(indata, *args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002595 outdata = s.read()
Bill Janssen61c001a2008-09-08 16:37:24 +00002596 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002597 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002598 "While sending with <<{name:s}>> bad data "
2599 "<<{outdata:r}>> ({nout:d}) received; "
2600 "expected <<{indata:r}>> ({nin:d})\n".format(
2601 name=meth_name, outdata=outdata[:20],
2602 nout=len(outdata),
2603 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002604 )
2605 )
2606 except ValueError as e:
2607 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002608 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002609 "Failed to send with method <<{name:s}>>; "
2610 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002611 )
2612 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002613 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002614 "Method <<{name:s}>> failed with unexpected "
2615 "exception message: {exp:s}\n".format(
2616 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002617 )
2618 )
2619
2620 for meth_name, recv_meth, expect_success, args in recv_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002621 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002622 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002623 s.send(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002624 outdata = recv_meth(*args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002625 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002626 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002627 "While receiving with <<{name:s}>> bad data "
2628 "<<{outdata:r}>> ({nout:d}) received; "
2629 "expected <<{indata:r}>> ({nin:d})\n".format(
2630 name=meth_name, outdata=outdata[:20],
2631 nout=len(outdata),
2632 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002633 )
2634 )
2635 except ValueError as e:
2636 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002637 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002638 "Failed to receive with method <<{name:s}>>; "
2639 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002640 )
2641 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002642 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002643 "Method <<{name:s}>> failed with unexpected "
2644 "exception message: {exp:s}\n".format(
2645 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002646 )
2647 )
2648 # consume data
2649 s.read()
2650
Martin Panterd524b702016-03-28 00:22:09 +00002651 # read(-1, buffer) is supported, even though read(-1) is not
Martin Panter8c6849b2016-07-11 00:17:13 +00002652 data = b"data"
Martin Panterb8089b42016-03-27 05:35:19 +00002653 s.send(data)
2654 buffer = bytearray(len(data))
2655 self.assertEqual(s.read(-1, buffer), len(data))
2656 self.assertEqual(buffer, data)
2657
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002658 s.write(b"over\n")
Martin Panterb8089b42016-03-27 05:35:19 +00002659
2660 self.assertRaises(ValueError, s.recv, -1)
2661 self.assertRaises(ValueError, s.read, -1)
2662
Bill Janssen61c001a2008-09-08 16:37:24 +00002663 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00002664
Martin Panter8c6849b2016-07-11 00:17:13 +00002665 def test_recv_zero(self):
2666 server = ThreadedEchoServer(CERTFILE)
2667 server.__enter__()
2668 self.addCleanup(server.__exit__, None, None)
2669 s = socket.create_connection((HOST, server.port))
2670 self.addCleanup(s.close)
2671 s = ssl.wrap_socket(s, suppress_ragged_eofs=False)
2672 self.addCleanup(s.close)
2673
2674 # recv/read(0) should return no data
2675 s.send(b"data")
2676 self.assertEqual(s.recv(0), b"")
2677 self.assertEqual(s.read(0), b"")
2678 self.assertEqual(s.read(), b"data")
2679
2680 # Should not block if the other end sends no data
2681 s.setblocking(False)
2682 self.assertEqual(s.recv(0), b"")
2683 self.assertEqual(s.recv_into(bytearray()), 0)
2684
Antoine Pitroufc69af12010-04-24 20:04:58 +00002685 def test_handshake_timeout(self):
2686 # Issue #5103: SSL handshake must respect the socket timeout
2687 server = socket.socket(socket.AF_INET)
2688 host = "127.0.0.1"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002689 port = support.bind_port(server)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002690 started = threading.Event()
2691 finish = False
2692
2693 def serve():
2694 server.listen(5)
2695 started.set()
2696 conns = []
2697 while not finish:
2698 r, w, e = select.select([server], [], [], 0.1)
2699 if server in r:
2700 # Let the socket hang around rather than having
2701 # it closed by garbage collection.
2702 conns.append(server.accept()[0])
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002703 for sock in conns:
2704 sock.close()
Antoine Pitroufc69af12010-04-24 20:04:58 +00002705
2706 t = threading.Thread(target=serve)
2707 t.start()
2708 started.wait()
2709
2710 try:
2711 try:
2712 c = socket.socket(socket.AF_INET)
2713 c.settimeout(0.2)
2714 c.connect((host, port))
2715 # Will attempt handshake and time out
2716 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2717 ssl.wrap_socket, c)
2718 finally:
2719 c.close()
2720 try:
2721 c = socket.socket(socket.AF_INET)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002722 c = ssl.wrap_socket(c)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002723 c.settimeout(0.2)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002724 # Will attempt handshake and time out
2725 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2726 c.connect, (host, port))
2727 finally:
2728 c.close()
2729 finally:
2730 finish = True
2731 t.join()
2732 server.close()
2733
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002734 def test_server_accept(self):
2735 # Issue #16357: accept() on a SSLSocket created through
2736 # SSLContext.wrap_socket().
2737 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2738 context.verify_mode = ssl.CERT_REQUIRED
2739 context.load_verify_locations(CERTFILE)
2740 context.load_cert_chain(CERTFILE)
2741 server = socket.socket(socket.AF_INET)
2742 host = "127.0.0.1"
2743 port = support.bind_port(server)
2744 server = context.wrap_socket(server, server_side=True)
2745
2746 evt = threading.Event()
2747 remote = [None]
2748 peer = [None]
2749 def serve():
2750 server.listen(5)
2751 # Block on the accept and wait on the connection to close.
2752 evt.set()
2753 remote[0], peer[0] = server.accept()
2754 remote[0].recv(1)
2755
2756 t = threading.Thread(target=serve)
2757 t.start()
2758 # Client wait until server setup and perform a connect.
2759 evt.wait()
2760 client = context.wrap_socket(socket.socket())
2761 client.connect((host, port))
2762 client_addr = client.getsockname()
2763 client.close()
2764 t.join()
2765 remote[0].close()
2766 server.close()
2767 # Sanity checks.
2768 self.assertIsInstance(remote[0], ssl.SSLSocket)
2769 self.assertEqual(peer[0], client_addr)
2770
2771 def test_getpeercert_enotconn(self):
2772 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2773 with closing(context.wrap_socket(socket.socket())) as sock:
2774 with self.assertRaises(socket.error) as cm:
2775 sock.getpeercert()
2776 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2777
2778 def test_do_handshake_enotconn(self):
2779 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2780 with closing(context.wrap_socket(socket.socket())) as sock:
2781 with self.assertRaises(socket.error) as cm:
2782 sock.do_handshake()
2783 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2784
Antoine Pitroud76088d2012-01-03 22:46:48 +01002785 def test_default_ciphers(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002786 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2787 try:
2788 # Force a set of weak ciphers on our client context
2789 context.set_ciphers("DES")
2790 except ssl.SSLError:
2791 self.skipTest("no DES cipher available")
Antoine Pitroud76088d2012-01-03 22:46:48 +01002792 with ThreadedEchoServer(CERTFILE,
2793 ssl_version=ssl.PROTOCOL_SSLv23,
2794 chatty=False) as server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002795 with closing(context.wrap_socket(socket.socket())) as s:
2796 with self.assertRaises(ssl.SSLError):
Antoine Pitroud76088d2012-01-03 22:46:48 +01002797 s.connect((HOST, server.port))
Antoine Pitroud76088d2012-01-03 22:46:48 +01002798 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2799
Alex Gaynore98205d2014-09-04 13:33:22 -07002800 def test_version_basic(self):
2801 """
2802 Basic tests for SSLSocket.version().
2803 More tests are done in the test_protocol_*() methods.
2804 """
2805 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2806 with ThreadedEchoServer(CERTFILE,
2807 ssl_version=ssl.PROTOCOL_TLSv1,
2808 chatty=False) as server:
2809 with closing(context.wrap_socket(socket.socket())) as s:
2810 self.assertIs(s.version(), None)
2811 s.connect((HOST, server.port))
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002812 self.assertEqual(s.version(), 'TLSv1')
Alex Gaynore98205d2014-09-04 13:33:22 -07002813 self.assertIs(s.version(), None)
2814
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002815 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2816 def test_default_ecdh_curve(self):
2817 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2818 # should be enabled by default on SSL contexts.
2819 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2820 context.load_cert_chain(CERTFILE)
2821 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2822 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2823 # our default cipher list should prefer ECDH-based ciphers
2824 # automatically.
2825 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2826 context.set_ciphers("ECCdraft:ECDH")
2827 with ThreadedEchoServer(context=context) as server:
2828 with closing(context.wrap_socket(socket.socket())) as s:
2829 s.connect((HOST, server.port))
2830 self.assertIn("ECDH", s.cipher()[0])
2831
2832 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2833 "'tls-unique' channel binding not available")
2834 def test_tls_unique_channel_binding(self):
2835 """Test tls-unique channel binding."""
2836 if support.verbose:
2837 sys.stdout.write("\n")
2838
2839 server = ThreadedEchoServer(CERTFILE,
2840 certreqs=ssl.CERT_NONE,
2841 ssl_version=ssl.PROTOCOL_TLSv1,
2842 cacerts=CERTFILE,
2843 chatty=True,
2844 connectionchatty=False)
2845 with server:
2846 s = ssl.wrap_socket(socket.socket(),
2847 server_side=False,
2848 certfile=CERTFILE,
2849 ca_certs=CERTFILE,
2850 cert_reqs=ssl.CERT_NONE,
2851 ssl_version=ssl.PROTOCOL_TLSv1)
2852 s.connect((HOST, server.port))
2853 # get the data
2854 cb_data = s.get_channel_binding("tls-unique")
2855 if support.verbose:
2856 sys.stdout.write(" got channel binding data: {0!r}\n"
2857 .format(cb_data))
2858
2859 # check if it is sane
2860 self.assertIsNotNone(cb_data)
2861 self.assertEqual(len(cb_data), 12) # True for TLSv1
2862
2863 # and compare with the peers version
2864 s.write(b"CB tls-unique\n")
2865 peer_data_repr = s.read().strip()
2866 self.assertEqual(peer_data_repr,
2867 repr(cb_data).encode("us-ascii"))
2868 s.close()
2869
2870 # now, again
2871 s = ssl.wrap_socket(socket.socket(),
2872 server_side=False,
2873 certfile=CERTFILE,
2874 ca_certs=CERTFILE,
2875 cert_reqs=ssl.CERT_NONE,
2876 ssl_version=ssl.PROTOCOL_TLSv1)
2877 s.connect((HOST, server.port))
2878 new_cb_data = s.get_channel_binding("tls-unique")
2879 if support.verbose:
2880 sys.stdout.write(" got another channel binding data: {0!r}\n"
2881 .format(new_cb_data))
2882 # is it really unique
2883 self.assertNotEqual(cb_data, new_cb_data)
2884 self.assertIsNotNone(cb_data)
2885 self.assertEqual(len(cb_data), 12) # True for TLSv1
2886 s.write(b"CB tls-unique\n")
2887 peer_data_repr = s.read().strip()
2888 self.assertEqual(peer_data_repr,
2889 repr(new_cb_data).encode("us-ascii"))
2890 s.close()
2891
2892 def test_compression(self):
2893 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2894 context.load_cert_chain(CERTFILE)
2895 stats = server_params_test(context, context,
2896 chatty=True, connectionchatty=True)
2897 if support.verbose:
2898 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2899 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2900
2901 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2902 "ssl.OP_NO_COMPRESSION needed for this test")
2903 def test_compression_disabled(self):
2904 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2905 context.load_cert_chain(CERTFILE)
2906 context.options |= ssl.OP_NO_COMPRESSION
2907 stats = server_params_test(context, context,
2908 chatty=True, connectionchatty=True)
2909 self.assertIs(stats['compression'], None)
2910
2911 def test_dh_params(self):
2912 # Check we can get a connection with ephemeral Diffie-Hellman
2913 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2914 context.load_cert_chain(CERTFILE)
2915 context.load_dh_params(DHFILE)
2916 context.set_ciphers("kEDH")
2917 stats = server_params_test(context, context,
2918 chatty=True, connectionchatty=True)
2919 cipher = stats["cipher"][0]
2920 parts = cipher.split("-")
2921 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2922 self.fail("Non-DH cipher: " + cipher[0])
2923
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002924 def test_selected_alpn_protocol(self):
2925 # selected_alpn_protocol() is None unless ALPN is used.
2926 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2927 context.load_cert_chain(CERTFILE)
2928 stats = server_params_test(context, context,
2929 chatty=True, connectionchatty=True)
2930 self.assertIs(stats['client_alpn_protocol'], None)
2931
2932 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
2933 def test_selected_alpn_protocol_if_server_uses_alpn(self):
2934 # selected_alpn_protocol() is None unless ALPN is used by the client.
2935 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2936 client_context.load_verify_locations(CERTFILE)
2937 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2938 server_context.load_cert_chain(CERTFILE)
2939 server_context.set_alpn_protocols(['foo', 'bar'])
2940 stats = server_params_test(client_context, server_context,
2941 chatty=True, connectionchatty=True)
2942 self.assertIs(stats['client_alpn_protocol'], None)
2943
2944 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
2945 def test_alpn_protocols(self):
2946 server_protocols = ['foo', 'bar', 'milkshake']
2947 protocol_tests = [
2948 (['foo', 'bar'], 'foo'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002949 (['bar', 'foo'], 'foo'),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002950 (['milkshake'], 'milkshake'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002951 (['http/3.0', 'http/4.0'], None)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002952 ]
2953 for client_protocols, expected in protocol_tests:
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002954 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002955 server_context.load_cert_chain(CERTFILE)
2956 server_context.set_alpn_protocols(server_protocols)
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002957 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002958 client_context.load_cert_chain(CERTFILE)
2959 client_context.set_alpn_protocols(client_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002960
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002961 try:
2962 stats = server_params_test(client_context,
2963 server_context,
2964 chatty=True,
2965 connectionchatty=True)
2966 except ssl.SSLError as e:
2967 stats = e
2968
Christian Heimes05b7d9c2017-08-15 10:55:03 +02002969 if (expected is None and IS_OPENSSL_1_1
2970 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
2971 # OpenSSL 1.1.0 to 1.1.0e raises handshake error
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002972 self.assertIsInstance(stats, ssl.SSLError)
2973 else:
2974 msg = "failed trying %s (s) and %s (c).\n" \
2975 "was expecting %s, but got %%s from the %%s" \
2976 % (str(server_protocols), str(client_protocols),
2977 str(expected))
2978 client_result = stats['client_alpn_protocol']
2979 self.assertEqual(client_result, expected,
2980 msg % (client_result, "client"))
2981 server_result = stats['server_alpn_protocols'][-1] \
2982 if len(stats['server_alpn_protocols']) else 'nothing'
2983 self.assertEqual(server_result, expected,
2984 msg % (server_result, "server"))
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002985
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002986 def test_selected_npn_protocol(self):
2987 # selected_npn_protocol() is None unless NPN is used
2988 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2989 context.load_cert_chain(CERTFILE)
2990 stats = server_params_test(context, context,
2991 chatty=True, connectionchatty=True)
2992 self.assertIs(stats['client_npn_protocol'], None)
2993
2994 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2995 def test_npn_protocols(self):
2996 server_protocols = ['http/1.1', 'spdy/2']
2997 protocol_tests = [
2998 (['http/1.1', 'spdy/2'], 'http/1.1'),
2999 (['spdy/2', 'http/1.1'], 'http/1.1'),
3000 (['spdy/2', 'test'], 'spdy/2'),
3001 (['abc', 'def'], 'abc')
3002 ]
3003 for client_protocols, expected in protocol_tests:
3004 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3005 server_context.load_cert_chain(CERTFILE)
3006 server_context.set_npn_protocols(server_protocols)
3007 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3008 client_context.load_cert_chain(CERTFILE)
3009 client_context.set_npn_protocols(client_protocols)
3010 stats = server_params_test(client_context, server_context,
3011 chatty=True, connectionchatty=True)
3012
3013 msg = "failed trying %s (s) and %s (c).\n" \
3014 "was expecting %s, but got %%s from the %%s" \
3015 % (str(server_protocols), str(client_protocols),
3016 str(expected))
3017 client_result = stats['client_npn_protocol']
3018 self.assertEqual(client_result, expected, msg % (client_result, "client"))
3019 server_result = stats['server_npn_protocols'][-1] \
3020 if len(stats['server_npn_protocols']) else 'nothing'
3021 self.assertEqual(server_result, expected, msg % (server_result, "server"))
3022
3023 def sni_contexts(self):
3024 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3025 server_context.load_cert_chain(SIGNED_CERTFILE)
3026 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3027 other_context.load_cert_chain(SIGNED_CERTFILE2)
3028 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3029 client_context.verify_mode = ssl.CERT_REQUIRED
3030 client_context.load_verify_locations(SIGNING_CA)
3031 return server_context, other_context, client_context
3032
3033 def check_common_name(self, stats, name):
3034 cert = stats['peercert']
3035 self.assertIn((('commonName', name),), cert['subject'])
3036
3037 @needs_sni
3038 def test_sni_callback(self):
3039 calls = []
3040 server_context, other_context, client_context = self.sni_contexts()
3041
3042 def servername_cb(ssl_sock, server_name, initial_context):
3043 calls.append((server_name, initial_context))
3044 if server_name is not None:
3045 ssl_sock.context = other_context
3046 server_context.set_servername_callback(servername_cb)
3047
3048 stats = server_params_test(client_context, server_context,
3049 chatty=True,
3050 sni_name='supermessage')
3051 # The hostname was fetched properly, and the certificate was
3052 # changed for the connection.
3053 self.assertEqual(calls, [("supermessage", server_context)])
3054 # CERTFILE4 was selected
3055 self.check_common_name(stats, 'fakehostname')
3056
3057 calls = []
3058 # The callback is called with server_name=None
3059 stats = server_params_test(client_context, server_context,
3060 chatty=True,
3061 sni_name=None)
3062 self.assertEqual(calls, [(None, server_context)])
3063 self.check_common_name(stats, 'localhost')
3064
3065 # Check disabling the callback
3066 calls = []
3067 server_context.set_servername_callback(None)
3068
3069 stats = server_params_test(client_context, server_context,
3070 chatty=True,
3071 sni_name='notfunny')
3072 # Certificate didn't change
3073 self.check_common_name(stats, 'localhost')
3074 self.assertEqual(calls, [])
3075
3076 @needs_sni
3077 def test_sni_callback_alert(self):
3078 # Returning a TLS alert is reflected to the connecting client
3079 server_context, other_context, client_context = self.sni_contexts()
3080
3081 def cb_returning_alert(ssl_sock, server_name, initial_context):
3082 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
3083 server_context.set_servername_callback(cb_returning_alert)
3084
3085 with self.assertRaises(ssl.SSLError) as cm:
3086 stats = server_params_test(client_context, server_context,
3087 chatty=False,
3088 sni_name='supermessage')
3089 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
3090
3091 @needs_sni
3092 def test_sni_callback_raising(self):
3093 # Raising fails the connection with a TLS handshake failure alert.
3094 server_context, other_context, client_context = self.sni_contexts()
3095
3096 def cb_raising(ssl_sock, server_name, initial_context):
Serhiy Storchaka5312a7f2015-01-31 11:27:06 +02003097 1.0/0.0
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003098 server_context.set_servername_callback(cb_raising)
3099
3100 with self.assertRaises(ssl.SSLError) as cm, \
3101 support.captured_stderr() as stderr:
3102 stats = server_params_test(client_context, server_context,
3103 chatty=False,
3104 sni_name='supermessage')
3105 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
3106 self.assertIn("ZeroDivisionError", stderr.getvalue())
3107
3108 @needs_sni
3109 def test_sni_callback_wrong_return_type(self):
3110 # Returning the wrong return type terminates the TLS connection
3111 # with an internal error alert.
3112 server_context, other_context, client_context = self.sni_contexts()
3113
3114 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
3115 return "foo"
3116 server_context.set_servername_callback(cb_wrong_return_type)
3117
3118 with self.assertRaises(ssl.SSLError) as cm, \
3119 support.captured_stderr() as stderr:
3120 stats = server_params_test(client_context, server_context,
3121 chatty=False,
3122 sni_name='supermessage')
3123 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
3124 self.assertIn("TypeError", stderr.getvalue())
3125
3126 def test_read_write_after_close_raises_valuerror(self):
3127 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3128 context.verify_mode = ssl.CERT_REQUIRED
3129 context.load_verify_locations(CERTFILE)
3130 context.load_cert_chain(CERTFILE)
3131 server = ThreadedEchoServer(context=context, chatty=False)
3132
3133 with server:
3134 s = context.wrap_socket(socket.socket())
3135 s.connect((HOST, server.port))
3136 s.close()
3137
3138 self.assertRaises(ValueError, s.read, 1024)
3139 self.assertRaises(ValueError, s.write, b'hello')
3140
Bill Janssen61c001a2008-09-08 16:37:24 +00003141
Neal Norwitz9eb9b102007-08-27 01:15:33 +00003142def test_main(verbose=False):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003143 if support.verbose:
3144 plats = {
3145 'Linux': platform.linux_distribution,
3146 'Mac': platform.mac_ver,
3147 'Windows': platform.win32_ver,
3148 }
3149 for name, func in plats.items():
3150 plat = func()
3151 if plat and plat[0]:
3152 plat = '%s %r' % (name, plat)
3153 break
3154 else:
3155 plat = repr(platform.platform())
3156 print("test_ssl: testing with %r %r" %
3157 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3158 print(" under %s" % plat)
3159 print(" HAS_SNI = %r" % ssl.HAS_SNI)
3160 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3161 try:
3162 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3163 except AttributeError:
3164 pass
Bill Janssen296a59d2007-09-16 22:06:00 +00003165
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003166 for filename in [
Martin Panter71202bb2016-01-15 00:25:29 +00003167 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003168 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
3169 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
3170 BADCERT, BADKEY, EMPTYCERT]:
3171 if not os.path.exists(filename):
3172 raise support.TestFailed("Can't read certificate file %r" % filename)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003173
Benjamin Peterson2f334562014-10-01 23:53:01 -04003174 tests = [ContextTests, BasicTests, BasicSocketTests, SSLErrorTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003175
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003176 if support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00003177 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00003178
Bill Janssen98d19da2007-09-10 21:51:02 +00003179 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003180 thread_info = support.threading_setup()
3181 if thread_info:
Bill Janssen934b16d2008-06-28 22:19:33 +00003182 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003183
Antoine Pitrou3945c862010-04-28 21:11:01 +00003184 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003185 support.run_unittest(*tests)
Antoine Pitrou3945c862010-04-28 21:11:01 +00003186 finally:
3187 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003188 support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003189
3190if __name__ == "__main__":
3191 test_main()