blob: a17d6131a6eb6853f8162114b89c31be18c6a761 [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
780 self.assertEqual(0, ctx.options)
781 else:
782 with self.assertRaises(ValueError):
783 ctx.options = 0
784
785 def test_verify_mode(self):
786 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
787 # Default value
788 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
789 ctx.verify_mode = ssl.CERT_OPTIONAL
790 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
791 ctx.verify_mode = ssl.CERT_REQUIRED
792 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
793 ctx.verify_mode = ssl.CERT_NONE
794 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
795 with self.assertRaises(TypeError):
796 ctx.verify_mode = None
797 with self.assertRaises(ValueError):
798 ctx.verify_mode = 42
799
800 @unittest.skipUnless(have_verify_flags(),
801 "verify_flags need OpenSSL > 0.9.8")
802 def test_verify_flags(self):
803 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson72ef9612015-03-04 22:49:41 -0500804 # default value
805 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
806 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500807 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
808 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
809 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
810 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
811 ctx.verify_flags = ssl.VERIFY_DEFAULT
812 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
813 # supports any value
814 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
815 self.assertEqual(ctx.verify_flags,
816 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
817 with self.assertRaises(TypeError):
818 ctx.verify_flags = None
819
820 def test_load_cert_chain(self):
821 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
822 # Combined key and cert in a single file
Benjamin Peterson04439fd2014-11-03 21:05:01 -0500823 ctx.load_cert_chain(CERTFILE, keyfile=None)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500824 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
825 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
826 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000827 ctx.load_cert_chain(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500828 self.assertEqual(cm.exception.errno, errno.ENOENT)
829 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
830 ctx.load_cert_chain(BADCERT)
831 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
832 ctx.load_cert_chain(EMPTYCERT)
833 # Separate key and cert
834 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
835 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
836 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
837 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
838 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
839 ctx.load_cert_chain(ONLYCERT)
840 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
841 ctx.load_cert_chain(ONLYKEY)
842 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
843 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
844 # Mismatching key and cert
845 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
846 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Martin Panter71202bb2016-01-15 00:25:29 +0000847 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500848 # Password protected key and cert
849 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
850 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
851 ctx.load_cert_chain(CERTFILE_PROTECTED,
852 password=bytearray(KEY_PASSWORD.encode()))
853 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
854 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
855 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
856 bytearray(KEY_PASSWORD.encode()))
857 with self.assertRaisesRegexp(TypeError, "should be a string"):
858 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
859 with self.assertRaises(ssl.SSLError):
860 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
861 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
862 # openssl has a fixed limit on the password buffer.
863 # PEM_BUFSIZE is generally set to 1kb.
864 # Return a string larger than this.
865 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
866 # Password callback
867 def getpass_unicode():
868 return KEY_PASSWORD
869 def getpass_bytes():
870 return KEY_PASSWORD.encode()
871 def getpass_bytearray():
872 return bytearray(KEY_PASSWORD.encode())
873 def getpass_badpass():
874 return "badpass"
875 def getpass_huge():
876 return b'a' * (1024 * 1024)
877 def getpass_bad_type():
878 return 9
879 def getpass_exception():
880 raise Exception('getpass error')
881 class GetPassCallable:
882 def __call__(self):
883 return KEY_PASSWORD
884 def getpass(self):
885 return KEY_PASSWORD
886 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
887 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
888 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
889 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
890 ctx.load_cert_chain(CERTFILE_PROTECTED,
891 password=GetPassCallable().getpass)
892 with self.assertRaises(ssl.SSLError):
893 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
894 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
895 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
896 with self.assertRaisesRegexp(TypeError, "must return a string"):
897 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
898 with self.assertRaisesRegexp(Exception, "getpass error"):
899 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
900 # Make sure the password function isn't called if it isn't needed
901 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
902
903 def test_load_verify_locations(self):
904 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
905 ctx.load_verify_locations(CERTFILE)
906 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
907 ctx.load_verify_locations(BYTES_CERTFILE)
908 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400909 ctx.load_verify_locations(cafile=BYTES_CERTFILE.decode('utf-8'))
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500910 self.assertRaises(TypeError, ctx.load_verify_locations)
911 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
912 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000913 ctx.load_verify_locations(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500914 self.assertEqual(cm.exception.errno, errno.ENOENT)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400915 with self.assertRaises(IOError):
916 ctx.load_verify_locations(u'')
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500917 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
918 ctx.load_verify_locations(BADCERT)
919 ctx.load_verify_locations(CERTFILE, CAPATH)
920 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
921
922 # Issue #10989: crash if the second argument type is invalid
923 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
924
925 def test_load_verify_cadata(self):
926 # test cadata
927 with open(CAFILE_CACERT) as f:
928 cacert_pem = f.read().decode("ascii")
929 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
930 with open(CAFILE_NEURONIO) as f:
931 neuronio_pem = f.read().decode("ascii")
932 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
933
934 # test PEM
935 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
936 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
937 ctx.load_verify_locations(cadata=cacert_pem)
938 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
939 ctx.load_verify_locations(cadata=neuronio_pem)
940 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
941 # cert already in hash table
942 ctx.load_verify_locations(cadata=neuronio_pem)
943 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
944
945 # combined
946 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
947 combined = "\n".join((cacert_pem, neuronio_pem))
948 ctx.load_verify_locations(cadata=combined)
949 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
950
951 # with junk around the certs
952 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
953 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
954 neuronio_pem, "tail"]
955 ctx.load_verify_locations(cadata="\n".join(combined))
956 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
957
958 # test DER
959 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
960 ctx.load_verify_locations(cadata=cacert_der)
961 ctx.load_verify_locations(cadata=neuronio_der)
962 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
963 # cert already in hash table
964 ctx.load_verify_locations(cadata=cacert_der)
965 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
966
967 # combined
968 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
969 combined = b"".join((cacert_der, neuronio_der))
970 ctx.load_verify_locations(cadata=combined)
971 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
972
973 # error cases
974 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
975 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
976
977 with self.assertRaisesRegexp(ssl.SSLError, "no start line"):
978 ctx.load_verify_locations(cadata=u"broken")
979 with self.assertRaisesRegexp(ssl.SSLError, "not enough data"):
980 ctx.load_verify_locations(cadata=b"broken")
981
982
983 def test_load_dh_params(self):
984 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
985 ctx.load_dh_params(DHFILE)
986 if os.name != 'nt':
987 ctx.load_dh_params(BYTES_DHFILE)
988 self.assertRaises(TypeError, ctx.load_dh_params)
989 self.assertRaises(TypeError, ctx.load_dh_params, None)
990 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000991 ctx.load_dh_params(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500992 self.assertEqual(cm.exception.errno, errno.ENOENT)
993 with self.assertRaises(ssl.SSLError) as cm:
994 ctx.load_dh_params(CERTFILE)
995
996 @skip_if_broken_ubuntu_ssl
997 def test_session_stats(self):
998 for proto in PROTOCOLS:
999 ctx = ssl.SSLContext(proto)
1000 self.assertEqual(ctx.session_stats(), {
1001 'number': 0,
1002 'connect': 0,
1003 'connect_good': 0,
1004 'connect_renegotiate': 0,
1005 'accept': 0,
1006 'accept_good': 0,
1007 'accept_renegotiate': 0,
1008 'hits': 0,
1009 'misses': 0,
1010 'timeouts': 0,
1011 'cache_full': 0,
1012 })
1013
1014 def test_set_default_verify_paths(self):
1015 # There's not much we can do to test that it acts as expected,
1016 # so just check it doesn't crash or raise an exception.
1017 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1018 ctx.set_default_verify_paths()
1019
1020 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
1021 def test_set_ecdh_curve(self):
1022 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1023 ctx.set_ecdh_curve("prime256v1")
1024 ctx.set_ecdh_curve(b"prime256v1")
1025 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1026 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1027 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1028 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1029
1030 @needs_sni
1031 def test_sni_callback(self):
1032 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1033
1034 # set_servername_callback expects a callable, or None
1035 self.assertRaises(TypeError, ctx.set_servername_callback)
1036 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1037 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1038 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1039
1040 def dummycallback(sock, servername, ctx):
1041 pass
1042 ctx.set_servername_callback(None)
1043 ctx.set_servername_callback(dummycallback)
1044
1045 @needs_sni
1046 def test_sni_callback_refcycle(self):
1047 # Reference cycles through the servername callback are detected
1048 # and cleared.
1049 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1050 def dummycallback(sock, servername, ctx, cycle=ctx):
1051 pass
1052 ctx.set_servername_callback(dummycallback)
1053 wr = weakref.ref(ctx)
1054 del ctx, dummycallback
1055 gc.collect()
1056 self.assertIs(wr(), None)
1057
1058 def test_cert_store_stats(self):
1059 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1060 self.assertEqual(ctx.cert_store_stats(),
1061 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1062 ctx.load_cert_chain(CERTFILE)
1063 self.assertEqual(ctx.cert_store_stats(),
1064 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1065 ctx.load_verify_locations(CERTFILE)
1066 self.assertEqual(ctx.cert_store_stats(),
1067 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panter71202bb2016-01-15 00:25:29 +00001068 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001069 self.assertEqual(ctx.cert_store_stats(),
1070 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1071
1072 def test_get_ca_certs(self):
1073 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1074 self.assertEqual(ctx.get_ca_certs(), [])
1075 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1076 ctx.load_verify_locations(CERTFILE)
1077 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panter71202bb2016-01-15 00:25:29 +00001078 # but CAFILE_CACERT is a CA cert
1079 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001080 self.assertEqual(ctx.get_ca_certs(),
1081 [{'issuer': ((('organizationName', 'Root CA'),),
1082 (('organizationalUnitName', 'http://www.cacert.org'),),
1083 (('commonName', 'CA Cert Signing Authority'),),
1084 (('emailAddress', 'support@cacert.org'),)),
1085 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1086 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1087 'serialNumber': '00',
1088 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
1089 'subject': ((('organizationName', 'Root CA'),),
1090 (('organizationalUnitName', 'http://www.cacert.org'),),
1091 (('commonName', 'CA Cert Signing Authority'),),
1092 (('emailAddress', 'support@cacert.org'),)),
1093 'version': 3}])
1094
Martin Panter71202bb2016-01-15 00:25:29 +00001095 with open(CAFILE_CACERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001096 pem = f.read()
1097 der = ssl.PEM_cert_to_DER_cert(pem)
1098 self.assertEqual(ctx.get_ca_certs(True), [der])
1099
1100 def test_load_default_certs(self):
1101 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1102 ctx.load_default_certs()
1103
1104 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1105 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1106 ctx.load_default_certs()
1107
1108 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1109 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1110
1111 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1112 self.assertRaises(TypeError, ctx.load_default_certs, None)
1113 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1114
Benjamin Petersona02ae252014-10-03 18:17:15 -04001115 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimesc2fc7c42016-09-05 23:37:13 +02001116 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson0b30a2b2014-10-03 17:27:05 -04001117 def test_load_default_certs_env(self):
1118 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1119 with support.EnvironmentVarGuard() as env:
1120 env["SSL_CERT_DIR"] = CAPATH
1121 env["SSL_CERT_FILE"] = CERTFILE
1122 ctx.load_default_certs()
1123 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1124
Benjamin Petersona02ae252014-10-03 18:17:15 -04001125 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1126 def test_load_default_certs_env_windows(self):
1127 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1128 ctx.load_default_certs()
1129 stats = ctx.cert_store_stats()
1130
1131 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1132 with support.EnvironmentVarGuard() as env:
1133 env["SSL_CERT_DIR"] = CAPATH
1134 env["SSL_CERT_FILE"] = CERTFILE
1135 ctx.load_default_certs()
1136 stats["x509"] += 1
1137 self.assertEqual(ctx.cert_store_stats(), stats)
1138
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001139 def test_create_default_context(self):
1140 ctx = ssl.create_default_context()
1141 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1142 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1143 self.assertTrue(ctx.check_hostname)
1144 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1145 self.assertEqual(
1146 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1147 getattr(ssl, "OP_NO_COMPRESSION", 0),
1148 )
1149
1150 with open(SIGNING_CA) as f:
1151 cadata = f.read().decode("ascii")
1152 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1153 cadata=cadata)
1154 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1155 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1156 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1157 self.assertEqual(
1158 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1159 getattr(ssl, "OP_NO_COMPRESSION", 0),
1160 )
1161
1162 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
1163 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1164 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1165 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1166 self.assertEqual(
1167 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1168 getattr(ssl, "OP_NO_COMPRESSION", 0),
1169 )
1170 self.assertEqual(
1171 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1172 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1173 )
1174 self.assertEqual(
1175 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1176 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1177 )
1178
1179 def test__create_stdlib_context(self):
1180 ctx = ssl._create_stdlib_context()
1181 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1182 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1183 self.assertFalse(ctx.check_hostname)
1184 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1185
1186 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1187 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1188 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1189 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1190
1191 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
1192 cert_reqs=ssl.CERT_REQUIRED,
1193 check_hostname=True)
1194 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1195 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1196 self.assertTrue(ctx.check_hostname)
1197 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1198
1199 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1200 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1201 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1202 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1203
Nick Coghlandbcd4572016-03-20 22:39:15 +10001204 def test__https_verify_certificates(self):
1205 # Unit test to check the contect factory mapping
1206 # The factories themselves are tested above
1207 # This test will fail by design if run under PYTHONHTTPSVERIFY=0
1208 # (as will various test_httplib tests)
1209
1210 # Uses a fresh SSL module to avoid affecting the real one
1211 local_ssl = support.import_fresh_module("ssl")
1212 # Certificate verification is enabled by default
1213 self.assertIs(local_ssl._create_default_https_context,
1214 local_ssl.create_default_context)
1215 # Turn default verification off
1216 local_ssl._https_verify_certificates(enable=False)
1217 self.assertIs(local_ssl._create_default_https_context,
1218 local_ssl._create_unverified_context)
1219 # And back on
1220 local_ssl._https_verify_certificates(enable=True)
1221 self.assertIs(local_ssl._create_default_https_context,
1222 local_ssl.create_default_context)
1223 # The default behaviour is to enable
1224 local_ssl._https_verify_certificates(enable=False)
1225 local_ssl._https_verify_certificates()
1226 self.assertIs(local_ssl._create_default_https_context,
1227 local_ssl.create_default_context)
1228
1229 def test__https_verify_envvar(self):
1230 # Unit test to check the PYTHONHTTPSVERIFY handling
1231 # Need to use a subprocess so it can still be run under -E
1232 https_is_verified = """import ssl, sys; \
1233 status = "Error: _create_default_https_context does not verify certs" \
1234 if ssl._create_default_https_context is \
1235 ssl._create_unverified_context \
1236 else None; \
1237 sys.exit(status)"""
1238 https_is_not_verified = """import ssl, sys; \
1239 status = "Error: _create_default_https_context verifies certs" \
1240 if ssl._create_default_https_context is \
1241 ssl.create_default_context \
1242 else None; \
1243 sys.exit(status)"""
1244 extra_env = {}
1245 # Omitting it leaves verification on
1246 assert_python_ok("-c", https_is_verified, **extra_env)
1247 # Setting it to zero turns verification off
1248 extra_env[ssl._https_verify_envvar] = "0"
1249 assert_python_ok("-c", https_is_not_verified, **extra_env)
1250 # Any other value should also leave it on
1251 for setting in ("", "1", "enabled", "foo"):
1252 extra_env[ssl._https_verify_envvar] = setting
1253 assert_python_ok("-c", https_is_verified, **extra_env)
1254
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001255 def test_check_hostname(self):
1256 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1257 self.assertFalse(ctx.check_hostname)
1258
1259 # Requires CERT_REQUIRED or CERT_OPTIONAL
1260 with self.assertRaises(ValueError):
1261 ctx.check_hostname = True
1262 ctx.verify_mode = ssl.CERT_REQUIRED
1263 self.assertFalse(ctx.check_hostname)
1264 ctx.check_hostname = True
1265 self.assertTrue(ctx.check_hostname)
1266
1267 ctx.verify_mode = ssl.CERT_OPTIONAL
1268 ctx.check_hostname = True
1269 self.assertTrue(ctx.check_hostname)
1270
1271 # Cannot set CERT_NONE with check_hostname enabled
1272 with self.assertRaises(ValueError):
1273 ctx.verify_mode = ssl.CERT_NONE
1274 ctx.check_hostname = False
1275 self.assertFalse(ctx.check_hostname)
1276
1277
1278class SSLErrorTests(unittest.TestCase):
1279
1280 def test_str(self):
1281 # The str() of a SSLError doesn't include the errno
1282 e = ssl.SSLError(1, "foo")
1283 self.assertEqual(str(e), "foo")
1284 self.assertEqual(e.errno, 1)
1285 # Same for a subclass
1286 e = ssl.SSLZeroReturnError(1, "foo")
1287 self.assertEqual(str(e), "foo")
1288 self.assertEqual(e.errno, 1)
1289
1290 def test_lib_reason(self):
1291 # Test the library and reason attributes
1292 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1293 with self.assertRaises(ssl.SSLError) as cm:
1294 ctx.load_dh_params(CERTFILE)
1295 self.assertEqual(cm.exception.library, 'PEM')
1296 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1297 s = str(cm.exception)
1298 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1299
1300 def test_subclass(self):
1301 # Check that the appropriate SSLError subclass is raised
1302 # (this only tests one of them)
1303 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1304 with closing(socket.socket()) as s:
1305 s.bind(("127.0.0.1", 0))
1306 s.listen(5)
1307 c = socket.socket()
1308 c.connect(s.getsockname())
1309 c.setblocking(False)
1310 with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c:
1311 with self.assertRaises(ssl.SSLWantReadError) as cm:
1312 c.do_handshake()
1313 s = str(cm.exception)
1314 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1315 # For compatibility
1316 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
Antoine Pitrou63cc99d2013-12-28 17:26:33 +01001317
Antoine Pitrouf9de5342010-04-05 21:35:07 +00001318
Bill Janssen934b16d2008-06-28 22:19:33 +00001319class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +00001320
Antoine Pitrou3945c862010-04-28 21:11:01 +00001321 def test_connect(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001322 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001323 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1324 cert_reqs=ssl.CERT_NONE)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001325 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001326 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001327 self.assertEqual({}, s.getpeercert())
1328 finally:
1329 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001330
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001331 # this should fail because we have no verification certs
1332 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1333 cert_reqs=ssl.CERT_REQUIRED)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001334 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001335 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001336 s.close()
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001337
1338 # this should succeed because we specify the root cert
1339 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1340 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001341 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001342 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001343 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001344 self.assertTrue(s.getpeercert())
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001345 finally:
1346 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001347
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001348 def test_connect_ex(self):
1349 # Issue #11326: check connect_ex() implementation
Martin Panter71202bb2016-01-15 00:25:29 +00001350 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001351 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1352 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001353 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001354 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001355 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001356 self.assertTrue(s.getpeercert())
1357 finally:
1358 s.close()
1359
1360 def test_non_blocking_connect_ex(self):
1361 # Issue #11326: non-blocking connect_ex() should allow handshake
1362 # to proceed after the socket gets ready.
Martin Panter71202bb2016-01-15 00:25:29 +00001363 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001364 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1365 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001366 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001367 do_handshake_on_connect=False)
1368 try:
1369 s.setblocking(False)
Martin Panter71202bb2016-01-15 00:25:29 +00001370 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +00001371 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1372 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001373 # Wait for connect to finish
1374 select.select([], [s], [], 5.0)
1375 # Non-blocking handshake
1376 while True:
1377 try:
1378 s.do_handshake()
1379 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001380 except ssl.SSLWantReadError:
1381 select.select([s], [], [], 5.0)
1382 except ssl.SSLWantWriteError:
1383 select.select([], [s], [], 5.0)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001384 # SSL established
1385 self.assertTrue(s.getpeercert())
1386 finally:
1387 s.close()
1388
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001389 def test_timeout_connect_ex(self):
1390 # Issue #12065: on a timeout, connect_ex() should return the original
1391 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter71202bb2016-01-15 00:25:29 +00001392 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001393 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1394 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001395 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001396 do_handshake_on_connect=False)
1397 try:
1398 s.settimeout(0.0000001)
Martin Panter71202bb2016-01-15 00:25:29 +00001399 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001400 if rc == 0:
Martin Panter71202bb2016-01-15 00:25:29 +00001401 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001402 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1403 finally:
1404 s.close()
1405
1406 def test_connect_ex_error(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001407 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001408 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1409 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001410 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001411 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001412 rc = s.connect_ex((REMOTE_HOST, 444))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001413 # Issue #19919: Windows machines or VMs hosted on Windows
1414 # machines sometimes return EWOULDBLOCK.
Martin Panter71202bb2016-01-15 00:25:29 +00001415 errors = (
1416 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1417 errno.EWOULDBLOCK,
1418 )
1419 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001420 finally:
1421 s.close()
1422
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001423 def test_connect_with_context(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001424 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001425 # Same as test_connect, but with a separately created context
1426 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1427 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001428 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001429 try:
1430 self.assertEqual({}, s.getpeercert())
1431 finally:
1432 s.close()
1433 # Same with a server hostname
1434 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter71202bb2016-01-15 00:25:29 +00001435 server_hostname=REMOTE_HOST)
1436 s.connect((REMOTE_HOST, 443))
Benjamin Peterson31aa69e2014-11-23 20:13:31 -06001437 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001438 # This should fail because we have no verification certs
1439 ctx.verify_mode = ssl.CERT_REQUIRED
1440 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1441 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001442 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001443 s.close()
1444 # This should succeed because we specify the root cert
Martin Panter71202bb2016-01-15 00:25:29 +00001445 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001446 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001447 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001448 try:
1449 cert = s.getpeercert()
1450 self.assertTrue(cert)
1451 finally:
1452 s.close()
1453
1454 def test_connect_capath(self):
1455 # Verify server certificates using the `capath` argument
1456 # NOTE: the subject hashing algorithm has been changed between
1457 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1458 # contain both versions of each certificate (same content, different
1459 # filename) for this test to be portable across OpenSSL releases.
Martin Panter71202bb2016-01-15 00:25:29 +00001460 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001461 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1462 ctx.verify_mode = ssl.CERT_REQUIRED
1463 ctx.load_verify_locations(capath=CAPATH)
1464 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001465 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001466 try:
1467 cert = s.getpeercert()
1468 self.assertTrue(cert)
1469 finally:
1470 s.close()
1471 # Same with a bytes `capath` argument
1472 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1473 ctx.verify_mode = ssl.CERT_REQUIRED
1474 ctx.load_verify_locations(capath=BYTES_CAPATH)
1475 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001476 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001477 try:
1478 cert = s.getpeercert()
1479 self.assertTrue(cert)
1480 finally:
1481 s.close()
1482
1483 def test_connect_cadata(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001484 with open(REMOTE_ROOT_CERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001485 pem = f.read().decode('ascii')
1486 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panter71202bb2016-01-15 00:25:29 +00001487 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001488 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1489 ctx.verify_mode = ssl.CERT_REQUIRED
1490 ctx.load_verify_locations(cadata=pem)
1491 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001492 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001493 cert = s.getpeercert()
1494 self.assertTrue(cert)
1495
1496 # same with DER
1497 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1498 ctx.verify_mode = ssl.CERT_REQUIRED
1499 ctx.load_verify_locations(cadata=der)
1500 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001501 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001502 cert = s.getpeercert()
1503 self.assertTrue(cert)
1504
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001505 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1506 def test_makefile_close(self):
1507 # Issue #5238: creating a file-like object with makefile() shouldn't
1508 # delay closing the underlying "real socket" (here tested with its
1509 # file descriptor, hence skipping the test under Windows).
Martin Panter71202bb2016-01-15 00:25:29 +00001510 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001511 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001512 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001513 fd = ss.fileno()
1514 f = ss.makefile()
1515 f.close()
1516 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001517 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001518 # Closing the SSL socket should close the fd too
1519 ss.close()
1520 gc.collect()
1521 with self.assertRaises(OSError) as e:
1522 os.read(fd, 0)
1523 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +00001524
Antoine Pitrou3945c862010-04-28 21:11:01 +00001525 def test_non_blocking_handshake(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001526 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001527 s = socket.socket(socket.AF_INET)
Martin Panter71202bb2016-01-15 00:25:29 +00001528 s.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001529 s.setblocking(False)
1530 s = ssl.wrap_socket(s,
1531 cert_reqs=ssl.CERT_NONE,
1532 do_handshake_on_connect=False)
1533 count = 0
1534 while True:
1535 try:
1536 count += 1
1537 s.do_handshake()
1538 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001539 except ssl.SSLWantReadError:
1540 select.select([s], [], [])
1541 except ssl.SSLWantWriteError:
1542 select.select([], [s], [])
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001543 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001544 if support.verbose:
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001545 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +00001546
Antoine Pitrou3945c862010-04-28 21:11:01 +00001547 def test_get_server_certificate(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001548 def _test_get_server_certificate(host, port, cert=None):
1549 with support.transient_internet(host):
1550 pem = ssl.get_server_certificate((host, port))
1551 if not pem:
1552 self.fail("No server certificate on %s:%s!" % (host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001553
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001554 try:
1555 pem = ssl.get_server_certificate((host, port),
1556 ca_certs=CERTFILE)
1557 except ssl.SSLError as x:
1558 #should fail
1559 if support.verbose:
1560 sys.stdout.write("%s\n" % x)
1561 else:
1562 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001563 pem = ssl.get_server_certificate((host, port),
1564 ca_certs=cert)
1565 if not pem:
1566 self.fail("No server certificate on %s:%s!" % (host, port))
1567 if support.verbose:
1568 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1569
Martin Panter71202bb2016-01-15 00:25:29 +00001570 _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001571 if support.IPV6_ENABLED:
1572 _test_get_server_certificate('ipv6.google.com', 443)
1573
1574 def test_ciphers(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001575 remote = (REMOTE_HOST, 443)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001576 with support.transient_internet(remote[0]):
1577 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1578 cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s:
1579 s.connect(remote)
1580 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1581 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s:
1582 s.connect(remote)
1583 # Error checking can happen at instantiation or when connecting
1584 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
1585 with closing(socket.socket(socket.AF_INET)) as sock:
1586 s = ssl.wrap_socket(sock,
1587 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1588 s.connect(remote)
Bill Janssen296a59d2007-09-16 22:06:00 +00001589
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001590 def test_algorithms(self):
1591 # Issue #8484: all algorithms should be available when verifying a
1592 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +00001593 # SHA256 was added in OpenSSL 0.9.8
1594 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1595 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001596 # sha256.tbs-internet.com needs SNI to use the correct certificate
1597 if not ssl.HAS_SNI:
1598 self.skipTest("SNI needed for this test")
1599 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
Antoine Pitroud43245a2011-01-08 10:32:51 +00001600 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001601 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001602 with support.transient_internet("sha256.tbs-internet.com"):
1603 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1604 ctx.verify_mode = ssl.CERT_REQUIRED
1605 ctx.load_verify_locations(sha256_cert)
1606 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1607 server_hostname="sha256.tbs-internet.com")
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001608 try:
1609 s.connect(remote)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001610 if support.verbose:
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001611 sys.stdout.write("\nCipher with %r is %r\n" %
1612 (remote, s.cipher()))
1613 sys.stdout.write("Certificate is:\n%s\n" %
1614 pprint.pformat(s.getpeercert()))
1615 finally:
1616 s.close()
1617
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001618 def test_get_ca_certs_capath(self):
1619 # capath certs are loaded on request
Martin Panter71202bb2016-01-15 00:25:29 +00001620 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001621 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1622 ctx.verify_mode = ssl.CERT_REQUIRED
1623 ctx.load_verify_locations(capath=CAPATH)
1624 self.assertEqual(ctx.get_ca_certs(), [])
1625 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001626 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001627 try:
1628 cert = s.getpeercert()
1629 self.assertTrue(cert)
1630 finally:
1631 s.close()
1632 self.assertEqual(len(ctx.get_ca_certs()), 1)
1633
1634 @needs_sni
1635 def test_context_setget(self):
1636 # Check that the context of a connected socket can be replaced.
Martin Panter71202bb2016-01-15 00:25:29 +00001637 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001638 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1639 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1640 s = socket.socket(socket.AF_INET)
1641 with closing(ctx1.wrap_socket(s)) as ss:
Martin Panter71202bb2016-01-15 00:25:29 +00001642 ss.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001643 self.assertIs(ss.context, ctx1)
1644 self.assertIs(ss._sslobj.context, ctx1)
1645 ss.context = ctx2
1646 self.assertIs(ss.context, ctx2)
1647 self.assertIs(ss._sslobj.context, ctx2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001648
Bill Janssen98d19da2007-09-10 21:51:02 +00001649try:
1650 import threading
1651except ImportError:
1652 _have_threads = False
1653else:
Bill Janssen98d19da2007-09-10 21:51:02 +00001654 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001655
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001656 from test.ssl_servers import make_https_server
1657
Bill Janssen98d19da2007-09-10 21:51:02 +00001658 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001659
Bill Janssen98d19da2007-09-10 21:51:02 +00001660 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001661
Bill Janssen98d19da2007-09-10 21:51:02 +00001662 """A mildly complicated class, because we want it to work both
1663 with and without the SSL wrapper around the socket connection, so
1664 that we can test the STARTTLS functionality."""
1665
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001666 def __init__(self, server, connsock, addr):
Bill Janssen98d19da2007-09-10 21:51:02 +00001667 self.server = server
1668 self.running = False
1669 self.sock = connsock
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001670 self.addr = addr
Bill Janssen98d19da2007-09-10 21:51:02 +00001671 self.sock.setblocking(1)
1672 self.sslconn = None
1673 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001674 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001675
Antoine Pitrou3945c862010-04-28 21:11:01 +00001676 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001677 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001678 self.sslconn = self.server.context.wrap_socket(
1679 self.sock, server_side=True)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001680 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1681 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001682 except socket.error as e:
1683 # We treat ConnectionResetError as though it were an
1684 # SSLError - OpenSSL on Ubuntu abruptly closes the
1685 # connection when asked to use an unsupported protocol.
1686 #
Antoine Pitroudb187842010-04-27 10:32:58 +00001687 # XXX Various errors can have happened here, for example
1688 # a mismatching protocol version, an invalid certificate,
1689 # or a low-level bug. This should be made more discriminating.
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001690 if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET:
1691 raise
Antoine Pitroud76088d2012-01-03 22:46:48 +01001692 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +00001693 if self.server.chatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001694 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00001695 self.running = False
1696 self.server.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001697 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001698 return False
Bill Janssen98d19da2007-09-10 21:51:02 +00001699 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001700 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
1701 cert = self.sslconn.getpeercert()
1702 if support.verbose and self.server.chatty:
1703 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1704 cert_binary = self.sslconn.getpeercert(True)
1705 if support.verbose and self.server.chatty:
1706 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1707 cipher = self.sslconn.cipher()
1708 if support.verbose and self.server.chatty:
1709 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
1710 sys.stdout.write(" server: selected protocol is now "
1711 + str(self.sslconn.selected_npn_protocol()) + "\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001712 return True
1713
1714 def read(self):
1715 if self.sslconn:
1716 return self.sslconn.read()
1717 else:
1718 return self.sock.recv(1024)
1719
1720 def write(self, bytes):
1721 if self.sslconn:
1722 return self.sslconn.write(bytes)
1723 else:
1724 return self.sock.send(bytes)
1725
1726 def close(self):
1727 if self.sslconn:
1728 self.sslconn.close()
1729 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001730 self.sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001731
Antoine Pitrou3945c862010-04-28 21:11:01 +00001732 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001733 self.running = True
1734 if not self.server.starttls_server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001735 if not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +00001736 return
1737 while self.running:
1738 try:
1739 msg = self.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001740 stripped = msg.strip()
1741 if not stripped:
Bill Janssen98d19da2007-09-10 21:51:02 +00001742 # eof, so quit this handler
1743 self.running = False
1744 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001745 elif stripped == b'over':
1746 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001747 sys.stdout.write(" server: client closed connection\n")
1748 self.close()
1749 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001750 elif (self.server.starttls_server and
1751 stripped == b'STARTTLS'):
1752 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001753 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001754 self.write(b"OK\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001755 if not self.wrap_conn():
1756 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001757 elif (self.server.starttls_server and self.sslconn
1758 and stripped == b'ENDTLS'):
1759 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001760 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001761 self.write(b"OK\n")
1762 self.sock = self.sslconn.unwrap()
Bill Janssen39295c22008-08-12 16:31:21 +00001763 self.sslconn = None
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001764 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001765 sys.stdout.write(" server: connection is now unencrypted...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001766 elif stripped == b'CB tls-unique':
1767 if support.verbose and self.server.connectionchatty:
1768 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1769 data = self.sslconn.get_channel_binding("tls-unique")
1770 self.write(repr(data).encode("us-ascii") + b"\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001771 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001772 if (support.verbose and
Bill Janssen98d19da2007-09-10 21:51:02 +00001773 self.server.connectionchatty):
1774 ctype = (self.sslconn and "encrypted") or "unencrypted"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001775 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1776 % (msg, ctype, msg.lower(), ctype))
Bill Janssen98d19da2007-09-10 21:51:02 +00001777 self.write(msg.lower())
1778 except ssl.SSLError:
1779 if self.server.chatty:
1780 handle_error("Test server failure:\n")
1781 self.close()
1782 self.running = False
1783 # normally, we'd just stop here, but for the test
1784 # harness, we want to stop the server
1785 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +00001786
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001787 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +00001788 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +00001789 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001790 npn_protocols=None, alpn_protocols=None,
1791 ciphers=None, context=None):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001792 if context:
1793 self.context = context
1794 else:
1795 self.context = ssl.SSLContext(ssl_version
1796 if ssl_version is not None
1797 else ssl.PROTOCOL_TLSv1)
1798 self.context.verify_mode = (certreqs if certreqs is not None
1799 else ssl.CERT_NONE)
1800 if cacerts:
1801 self.context.load_verify_locations(cacerts)
1802 if certificate:
1803 self.context.load_cert_chain(certificate)
1804 if npn_protocols:
1805 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001806 if alpn_protocols:
1807 self.context.set_alpn_protocols(alpn_protocols)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001808 if ciphers:
1809 self.context.set_ciphers(ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +00001810 self.chatty = chatty
1811 self.connectionchatty = connectionchatty
1812 self.starttls_server = starttls_server
1813 self.sock = socket.socket()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001814 self.port = support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +00001815 self.flag = None
Bill Janssen98d19da2007-09-10 21:51:02 +00001816 self.active = False
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001817 self.selected_npn_protocols = []
1818 self.selected_alpn_protocols = []
Antoine Pitroud76088d2012-01-03 22:46:48 +01001819 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001820 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001821 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001822
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001823 def __enter__(self):
1824 self.start(threading.Event())
1825 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001826 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001827
1828 def __exit__(self, *args):
1829 self.stop()
1830 self.join()
1831
Antoine Pitrou3945c862010-04-28 21:11:01 +00001832 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +00001833 self.flag = flag
1834 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001835
Antoine Pitrou3945c862010-04-28 21:11:01 +00001836 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +00001837 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +00001838 self.sock.listen(5)
1839 self.active = True
1840 if self.flag:
1841 # signal an event
1842 self.flag.set()
1843 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001844 try:
Bill Janssen98d19da2007-09-10 21:51:02 +00001845 newconn, connaddr = self.sock.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001846 if support.verbose and self.chatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001847 sys.stdout.write(' server: new connection from '
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001848 + repr(connaddr) + '\n')
1849 handler = self.ConnectionHandler(self, newconn, connaddr)
Bill Janssen98d19da2007-09-10 21:51:02 +00001850 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +01001851 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +00001852 except socket.timeout:
1853 pass
1854 except KeyboardInterrupt:
1855 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +00001856 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001857
Antoine Pitrou3945c862010-04-28 21:11:01 +00001858 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001859 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001860
Bill Janssen934b16d2008-06-28 22:19:33 +00001861 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +00001862
Antoine Pitrou3945c862010-04-28 21:11:01 +00001863 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +00001864
Antoine Pitrou3945c862010-04-28 21:11:01 +00001865 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +00001866
1867 def __init__(self, conn, certfile):
Bill Janssen934b16d2008-06-28 22:19:33 +00001868 self.socket = ssl.wrap_socket(conn, server_side=True,
1869 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +00001870 do_handshake_on_connect=False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001871 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroufc69af12010-04-24 20:04:58 +00001872 self._ssl_accepting = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001873 self._do_ssl_handshake()
Bill Janssen934b16d2008-06-28 22:19:33 +00001874
1875 def readable(self):
1876 if isinstance(self.socket, ssl.SSLSocket):
1877 while self.socket.pending() > 0:
1878 self.handle_read_event()
1879 return True
1880
Antoine Pitroufc69af12010-04-24 20:04:58 +00001881 def _do_ssl_handshake(self):
1882 try:
1883 self.socket.do_handshake()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001884 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1885 return
1886 except ssl.SSLEOFError:
1887 return self.handle_close()
1888 except ssl.SSLError:
Antoine Pitroufc69af12010-04-24 20:04:58 +00001889 raise
1890 except socket.error, err:
1891 if err.args[0] == errno.ECONNABORTED:
1892 return self.handle_close()
1893 else:
1894 self._ssl_accepting = False
1895
Bill Janssen934b16d2008-06-28 22:19:33 +00001896 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +00001897 if self._ssl_accepting:
1898 self._do_ssl_handshake()
1899 else:
1900 data = self.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001901 if support.verbose:
1902 sys.stdout.write(" server: read %s from client\n" % repr(data))
1903 if not data:
1904 self.close()
1905 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001906 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +00001907
1908 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +00001909 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001910 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001911 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1912
1913 def handle_error(self):
1914 raise
1915
1916 def __init__(self, certfile):
1917 self.certfile = certfile
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001918 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1919 self.port = support.bind_port(sock, '')
1920 asyncore.dispatcher.__init__(self, sock)
Bill Janssen934b16d2008-06-28 22:19:33 +00001921 self.listen(5)
1922
1923 def handle_accept(self):
1924 sock_obj, addr = self.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001925 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001926 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1927 self.ConnectionHandler(sock_obj, self.certfile)
1928
1929 def handle_error(self):
1930 raise
1931
1932 def __init__(self, certfile):
1933 self.flag = None
1934 self.active = False
1935 self.server = self.EchoServer(certfile)
1936 self.port = self.server.port
1937 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001938 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +00001939
1940 def __str__(self):
1941 return "<%s %s>" % (self.__class__.__name__, self.server)
1942
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001943 def __enter__(self):
1944 self.start(threading.Event())
1945 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001946 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001947
1948 def __exit__(self, *args):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001949 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001950 sys.stdout.write(" cleanup: stopping server.\n")
1951 self.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001952 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001953 sys.stdout.write(" cleanup: joining server thread.\n")
1954 self.join()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001955 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001956 sys.stdout.write(" cleanup: successfully joined.\n")
1957
Antoine Pitrou3945c862010-04-28 21:11:01 +00001958 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +00001959 self.flag = flag
1960 threading.Thread.start(self)
1961
Antoine Pitrou3945c862010-04-28 21:11:01 +00001962 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001963 self.active = True
1964 if self.flag:
1965 self.flag.set()
1966 while self.active:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001967 try:
1968 asyncore.loop(1)
1969 except:
1970 pass
Bill Janssen934b16d2008-06-28 22:19:33 +00001971
Antoine Pitrou3945c862010-04-28 21:11:01 +00001972 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001973 self.active = False
1974 self.server.close()
1975
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001976 def server_params_test(client_context, server_context, indata=b"FOO\n",
1977 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001978 """
1979 Launch a server, connect a client to it and try various reads
1980 and writes.
1981 """
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001982 stats = {}
1983 server = ThreadedEchoServer(context=server_context,
Bill Janssen98d19da2007-09-10 21:51:02 +00001984 chatty=chatty,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001985 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001986 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001987 with closing(client_context.wrap_socket(socket.socket(),
1988 server_hostname=sni_name)) as s:
1989 s.connect((HOST, server.port))
1990 for arg in [indata, bytearray(indata), memoryview(indata)]:
1991 if connectionchatty:
1992 if support.verbose:
1993 sys.stdout.write(
1994 " client: sending %r...\n" % indata)
1995 s.write(arg)
1996 outdata = s.read()
1997 if connectionchatty:
1998 if support.verbose:
1999 sys.stdout.write(" client: read %r\n" % outdata)
2000 if outdata != indata.lower():
2001 raise AssertionError(
2002 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2003 % (outdata[:20], len(outdata),
2004 indata[:20].lower(), len(indata)))
2005 s.write(b"over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00002006 if connectionchatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002007 if support.verbose:
2008 sys.stdout.write(" client: closing connection.\n")
2009 stats.update({
2010 'compression': s.compression(),
2011 'cipher': s.cipher(),
2012 'peercert': s.getpeercert(),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002013 'client_alpn_protocol': s.selected_alpn_protocol(),
Alex Gaynore98205d2014-09-04 13:33:22 -07002014 'client_npn_protocol': s.selected_npn_protocol(),
2015 'version': s.version(),
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002016 })
2017 s.close()
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002018 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2019 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002020 return stats
Bill Janssen98d19da2007-09-10 21:51:02 +00002021
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002022 def try_protocol_combo(server_protocol, client_protocol, expect_success,
2023 certsreqs=None, server_options=0, client_options=0):
Alex Gaynore98205d2014-09-04 13:33:22 -07002024 """
2025 Try to SSL-connect using *client_protocol* to *server_protocol*.
2026 If *expect_success* is true, assert that the connection succeeds,
2027 if it's false, assert that the connection fails.
2028 Also, if *expect_success* is a string, assert that it is the protocol
2029 version actually used by the connection.
2030 """
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00002031 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +00002032 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +00002033 certtype = {
2034 ssl.CERT_NONE: "CERT_NONE",
2035 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2036 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2037 }[certsreqs]
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002038 if support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002039 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +00002040 sys.stdout.write(formatstr %
2041 (ssl.get_protocol_name(client_protocol),
2042 ssl.get_protocol_name(server_protocol),
2043 certtype))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002044 client_context = ssl.SSLContext(client_protocol)
2045 client_context.options |= client_options
2046 server_context = ssl.SSLContext(server_protocol)
2047 server_context.options |= server_options
2048
2049 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2050 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2051 # starting from OpenSSL 1.0.0 (see issue #8322).
2052 if client_context.protocol == ssl.PROTOCOL_SSLv23:
2053 client_context.set_ciphers("ALL")
2054
2055 for ctx in (client_context, server_context):
2056 ctx.verify_mode = certsreqs
2057 ctx.load_cert_chain(CERTFILE)
2058 ctx.load_verify_locations(CERTFILE)
Bill Janssen98d19da2007-09-10 21:51:02 +00002059 try:
Alex Gaynore98205d2014-09-04 13:33:22 -07002060 stats = server_params_test(client_context, server_context,
2061 chatty=False, connectionchatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002062 # Protocol mismatch can result in either an SSLError, or a
2063 # "Connection reset by peer" error.
2064 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002065 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +00002066 raise
Antoine Pitroudb187842010-04-27 10:32:58 +00002067 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002068 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +00002069 raise
Bill Janssen98d19da2007-09-10 21:51:02 +00002070 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002071 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00002072 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +00002073 "Client protocol %s succeeded with server protocol %s!"
2074 % (ssl.get_protocol_name(client_protocol),
2075 ssl.get_protocol_name(server_protocol)))
Alex Gaynore98205d2014-09-04 13:33:22 -07002076 elif (expect_success is not True
2077 and expect_success != stats['version']):
2078 raise AssertionError("version mismatch: expected %r, got %r"
2079 % (expect_success, stats['version']))
Bill Janssen98d19da2007-09-10 21:51:02 +00002080
2081
Bill Janssen934b16d2008-06-28 22:19:33 +00002082 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +00002083
Antoine Pitroud75efd92010-08-04 17:38:33 +00002084 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002085 def test_echo(self):
2086 """Basic test of an SSL client connecting to a server"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002087 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002088 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002089 for protocol in PROTOCOLS:
2090 context = ssl.SSLContext(protocol)
2091 context.load_cert_chain(CERTFILE)
2092 server_params_test(context, context,
2093 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002094
Antoine Pitrou3945c862010-04-28 21:11:01 +00002095 def test_getpeercert(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002096 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002097 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002098 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2099 context.verify_mode = ssl.CERT_REQUIRED
2100 context.load_verify_locations(CERTFILE)
2101 context.load_cert_chain(CERTFILE)
2102 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002103 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002104 s = context.wrap_socket(socket.socket(),
2105 do_handshake_on_connect=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002106 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002107 # getpeercert() raise ValueError while the handshake isn't
2108 # done.
2109 with self.assertRaises(ValueError):
2110 s.getpeercert()
2111 s.do_handshake()
Antoine Pitroudb187842010-04-27 10:32:58 +00002112 cert = s.getpeercert()
2113 self.assertTrue(cert, "Can't get peer certificate.")
2114 cipher = s.cipher()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002115 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002116 sys.stdout.write(pprint.pformat(cert) + '\n')
2117 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2118 if 'subject' not in cert:
2119 self.fail("No subject field in certificate: %s." %
2120 pprint.pformat(cert))
2121 if ((('organizationName', 'Python Software Foundation'),)
2122 not in cert['subject']):
2123 self.fail(
2124 "Missing or invalid 'organizationName' field in certificate subject; "
2125 "should be 'Python Software Foundation'.")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002126 self.assertIn('notBefore', cert)
2127 self.assertIn('notAfter', cert)
2128 before = ssl.cert_time_to_seconds(cert['notBefore'])
2129 after = ssl.cert_time_to_seconds(cert['notAfter'])
2130 self.assertLess(before, after)
Antoine Pitroudb187842010-04-27 10:32:58 +00002131 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002132
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002133 @unittest.skipUnless(have_verify_flags(),
2134 "verify_flags need OpenSSL > 0.9.8")
2135 def test_crl_check(self):
2136 if support.verbose:
2137 sys.stdout.write("\n")
2138
2139 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2140 server_context.load_cert_chain(SIGNED_CERTFILE)
2141
2142 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2143 context.verify_mode = ssl.CERT_REQUIRED
2144 context.load_verify_locations(SIGNING_CA)
Benjamin Petersond86699f2015-03-04 23:18:48 -05002145 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2146 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002147
2148 # VERIFY_DEFAULT should pass
2149 server = ThreadedEchoServer(context=server_context, chatty=True)
2150 with server:
2151 with closing(context.wrap_socket(socket.socket())) as s:
2152 s.connect((HOST, server.port))
2153 cert = s.getpeercert()
2154 self.assertTrue(cert, "Can't get peer certificate.")
2155
2156 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
2157 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
2158
2159 server = ThreadedEchoServer(context=server_context, chatty=True)
2160 with server:
2161 with closing(context.wrap_socket(socket.socket())) as s:
2162 with self.assertRaisesRegexp(ssl.SSLError,
2163 "certificate verify failed"):
2164 s.connect((HOST, server.port))
2165
2166 # now load a CRL file. The CRL file is signed by the CA.
2167 context.load_verify_locations(CRLFILE)
2168
2169 server = ThreadedEchoServer(context=server_context, chatty=True)
2170 with server:
2171 with closing(context.wrap_socket(socket.socket())) as s:
2172 s.connect((HOST, server.port))
2173 cert = s.getpeercert()
2174 self.assertTrue(cert, "Can't get peer certificate.")
2175
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002176 def test_check_hostname(self):
2177 if support.verbose:
2178 sys.stdout.write("\n")
2179
2180 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2181 server_context.load_cert_chain(SIGNED_CERTFILE)
2182
2183 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2184 context.verify_mode = ssl.CERT_REQUIRED
2185 context.check_hostname = True
2186 context.load_verify_locations(SIGNING_CA)
2187
2188 # correct hostname should verify
2189 server = ThreadedEchoServer(context=server_context, chatty=True)
2190 with server:
2191 with closing(context.wrap_socket(socket.socket(),
2192 server_hostname="localhost")) as s:
2193 s.connect((HOST, server.port))
2194 cert = s.getpeercert()
2195 self.assertTrue(cert, "Can't get peer certificate.")
2196
2197 # incorrect hostname should raise an exception
2198 server = ThreadedEchoServer(context=server_context, chatty=True)
2199 with server:
2200 with closing(context.wrap_socket(socket.socket(),
2201 server_hostname="invalid")) as s:
2202 with self.assertRaisesRegexp(ssl.CertificateError,
2203 "hostname 'invalid' doesn't match u?'localhost'"):
2204 s.connect((HOST, server.port))
2205
2206 # missing server_hostname arg should cause an exception, too
2207 server = ThreadedEchoServer(context=server_context, chatty=True)
2208 with server:
2209 with closing(socket.socket()) as s:
2210 with self.assertRaisesRegexp(ValueError,
2211 "check_hostname requires server_hostname"):
2212 context.wrap_socket(s)
2213
Martin Panterfd8e8502016-01-30 02:36:00 +00002214 def test_wrong_cert(self):
Martin Panter886aba42016-02-01 21:58:11 +00002215 """Connecting when the server rejects the client's certificate
2216
2217 Launch a server with CERT_REQUIRED, and check that trying to
2218 connect to it with a wrong client certificate fails.
2219 """
2220 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
2221 "wrongcert.pem")
2222 server = ThreadedEchoServer(CERTFILE,
2223 certreqs=ssl.CERT_REQUIRED,
2224 cacerts=CERTFILE, chatty=False,
2225 connectionchatty=False)
2226 with server, \
2227 closing(socket.socket()) as sock, \
2228 closing(ssl.wrap_socket(sock,
2229 certfile=certfile,
2230 ssl_version=ssl.PROTOCOL_TLSv1)) as s:
2231 try:
2232 # Expect either an SSL error about the server rejecting
2233 # the connection, or a low-level connection reset (which
2234 # sometimes happens on Windows)
2235 s.connect((HOST, server.port))
2236 except ssl.SSLError as e:
2237 if support.verbose:
2238 sys.stdout.write("\nSSLError is %r\n" % e)
2239 except socket.error as e:
2240 if e.errno != errno.ECONNRESET:
2241 raise
2242 if support.verbose:
2243 sys.stdout.write("\nsocket.error is %r\n" % e)
2244 else:
2245 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +00002246
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002247 def test_rude_shutdown(self):
2248 """A brutal shutdown of an SSL server should raise an OSError
2249 in the client when attempting handshake.
2250 """
2251 listener_ready = threading.Event()
2252 listener_gone = threading.Event()
2253
2254 s = socket.socket()
2255 port = support.bind_port(s, HOST)
2256
2257 # `listener` runs in a thread. It sits in an accept() until
2258 # the main thread connects. Then it rudely closes the socket,
2259 # and sets Event `listener_gone` to let the main thread know
2260 # the socket is gone.
2261 def listener():
2262 s.listen(5)
2263 listener_ready.set()
2264 newsock, addr = s.accept()
2265 newsock.close()
2266 s.close()
2267 listener_gone.set()
2268
2269 def connector():
2270 listener_ready.wait()
2271 with closing(socket.socket()) as c:
2272 c.connect((HOST, port))
2273 listener_gone.wait()
2274 try:
2275 ssl_sock = ssl.wrap_socket(c)
Benjamin Petersone208b572014-08-20 14:49:08 -05002276 except socket.error:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002277 pass
2278 else:
2279 self.fail('connecting to closed SSL socket should have failed')
2280
2281 t = threading.Thread(target=listener)
2282 t.start()
2283 try:
2284 connector()
2285 finally:
2286 t.join()
2287
Antoine Pitroud75efd92010-08-04 17:38:33 +00002288 @skip_if_broken_ubuntu_ssl
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002289 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2290 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002291 def test_protocol_sslv2(self):
2292 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002293 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002294 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002295 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2296 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2297 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01002298 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002299 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2300 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002301 # SSLv23 client with specific SSL options
2302 if no_sslv2_implies_sslv3_hello():
2303 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2304 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2305 client_options=ssl.OP_NO_SSLv2)
2306 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2307 client_options=ssl.OP_NO_SSLv3)
2308 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2309 client_options=ssl.OP_NO_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00002310
Antoine Pitroud75efd92010-08-04 17:38:33 +00002311 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002312 def test_protocol_sslv23(self):
2313 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002314 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002315 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002316 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2317 try:
2318 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
2319 except socket.error as x:
2320 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2321 if support.verbose:
2322 sys.stdout.write(
2323 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2324 % str(x))
Benjamin Peterson60766c42014-12-05 21:59:35 -05002325 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002326 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002327 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Alex Gaynore98205d2014-09-04 13:33:22 -07002328 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Bill Janssen98d19da2007-09-10 21:51:02 +00002329
Benjamin Peterson60766c42014-12-05 21:59:35 -05002330 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002331 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002332 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Alex Gaynore98205d2014-09-04 13:33:22 -07002333 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00002334
Benjamin Peterson60766c42014-12-05 21:59:35 -05002335 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002336 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002337 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Alex Gaynore98205d2014-09-04 13:33:22 -07002338 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00002339
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002340 # Server with specific SSL options
Benjamin Peterson60766c42014-12-05 21:59:35 -05002341 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2342 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002343 server_options=ssl.OP_NO_SSLv3)
2344 # Will choose TLSv1
2345 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2346 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2347 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2348 server_options=ssl.OP_NO_TLSv1)
2349
2350
Antoine Pitroud75efd92010-08-04 17:38:33 +00002351 @skip_if_broken_ubuntu_ssl
Benjamin Peterson60766c42014-12-05 21:59:35 -05002352 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2353 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002354 def test_protocol_sslv3(self):
2355 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002356 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002357 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002358 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2359 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2360 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002361 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2362 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002363 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2364 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002365 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002366 if no_sslv2_implies_sslv3_hello():
2367 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002368 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2369 False, client_options=ssl.OP_NO_SSLv2)
Bill Janssen98d19da2007-09-10 21:51:02 +00002370
Antoine Pitroud75efd92010-08-04 17:38:33 +00002371 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002372 def test_protocol_tlsv1(self):
2373 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002374 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002375 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002376 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2377 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2378 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002379 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2380 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002381 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2382 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002383 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2384 client_options=ssl.OP_NO_TLSv1)
2385
2386 @skip_if_broken_ubuntu_ssl
2387 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2388 "TLS version 1.1 not supported.")
2389 def test_protocol_tlsv1_1(self):
2390 """Connecting to a TLSv1.1 server with various client options.
2391 Testing against older TLS versions."""
2392 if support.verbose:
2393 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002394 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002395 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2396 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002397 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2398 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002399 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2400 client_options=ssl.OP_NO_TLSv1_1)
2401
Alex Gaynore98205d2014-09-04 13:33:22 -07002402 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002403 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2404 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2405
2406
2407 @skip_if_broken_ubuntu_ssl
2408 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2409 "TLS version 1.2 not supported.")
2410 def test_protocol_tlsv1_2(self):
2411 """Connecting to a TLSv1.2 server with various client options.
2412 Testing against older TLS versions."""
2413 if support.verbose:
2414 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002415 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002416 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2417 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2418 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2419 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002420 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2421 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002422 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2423 client_options=ssl.OP_NO_TLSv1_2)
2424
Alex Gaynore98205d2014-09-04 13:33:22 -07002425 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002426 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2427 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2428 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2429 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00002430
Antoine Pitrou3945c862010-04-28 21:11:01 +00002431 def test_starttls(self):
2432 """Switching from clear text to encrypted and back again."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002433 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 +00002434
Trent Nelsone41b0062008-04-08 23:47:30 +00002435 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00002436 ssl_version=ssl.PROTOCOL_TLSv1,
2437 starttls_server=True,
2438 chatty=True,
2439 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002440 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002441 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002442 s = socket.socket()
2443 s.setblocking(1)
2444 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002445 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002446 sys.stdout.write("\n")
2447 for indata in msgs:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002448 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002449 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002450 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002451 if wrapped:
2452 conn.write(indata)
2453 outdata = conn.read()
2454 else:
2455 s.send(indata)
2456 outdata = s.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002457 msg = outdata.strip().lower()
2458 if indata == b"STARTTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002459 # STARTTLS ok, switch to secure mode
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002460 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002461 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002462 " client: read %r from server, starting TLS...\n"
2463 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002464 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2465 wrapped = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002466 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002467 # ENDTLS ok, switch back to clear text
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002468 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002469 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002470 " client: read %r from server, ending TLS...\n"
2471 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002472 s = conn.unwrap()
2473 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00002474 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002475 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002476 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002477 " client: read %r from server\n" % msg)
2478 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002479 sys.stdout.write(" client: closing connection.\n")
2480 if wrapped:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002481 conn.write(b"over\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00002482 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002483 s.send(b"over\n")
2484 if wrapped:
2485 conn.close()
2486 else:
2487 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002488
Antoine Pitrou3945c862010-04-28 21:11:01 +00002489 def test_socketserver(self):
2490 """Using a SocketServer to create and manage SSL connections."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002491 server = make_https_server(self, certfile=CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00002492 # try to connect
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002493 if support.verbose:
2494 sys.stdout.write('\n')
2495 with open(CERTFILE, 'rb') as f:
2496 d1 = f.read()
2497 d2 = ''
2498 # now fetch the same data from the HTTPS server
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -06002499 url = 'https://localhost:%d/%s' % (
2500 server.port, os.path.split(CERTFILE)[1])
2501 context = ssl.create_default_context(cafile=CERTFILE)
Benjamin Petersonb0609ec2014-11-23 11:52:46 -06002502 f = urllib2.urlopen(url, context=context)
Bill Janssen296a59d2007-09-16 22:06:00 +00002503 try:
Bill Janssen296a59d2007-09-16 22:06:00 +00002504 dlen = f.info().getheader("content-length")
2505 if dlen and (int(dlen) > 0):
2506 d2 = f.read(int(dlen))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002507 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002508 sys.stdout.write(
2509 " client: read %d bytes from remote server '%s'\n"
2510 % (len(d2), server))
Bill Janssen296a59d2007-09-16 22:06:00 +00002511 finally:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002512 f.close()
2513 self.assertEqual(d1, d2)
Bill Janssen934b16d2008-06-28 22:19:33 +00002514
Antoine Pitrou3945c862010-04-28 21:11:01 +00002515 def test_asyncore_server(self):
2516 """Check the example asyncore integration."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002517 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00002518 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002519
2520 indata = b"FOO\n"
Bill Janssen934b16d2008-06-28 22:19:33 +00002521 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002522 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002523 s = ssl.wrap_socket(socket.socket())
2524 s.connect(('127.0.0.1', server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002525 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002526 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002527 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002528 s.write(indata)
2529 outdata = s.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002530 if support.verbose:
2531 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002532 if outdata != indata.lower():
2533 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002534 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2535 % (outdata[:20], len(outdata),
2536 indata[:20].lower(), len(indata)))
2537 s.write(b"over\n")
2538 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002539 sys.stdout.write(" client: closing connection.\n")
2540 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002541 if support.verbose:
2542 sys.stdout.write(" client: connection closed.\n")
Bill Janssen934b16d2008-06-28 22:19:33 +00002543
Antoine Pitrou3945c862010-04-28 21:11:01 +00002544 def test_recv_send(self):
2545 """Test recv(), send() and friends."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002546 if support.verbose:
Bill Janssen61c001a2008-09-08 16:37:24 +00002547 sys.stdout.write("\n")
2548
2549 server = ThreadedEchoServer(CERTFILE,
2550 certreqs=ssl.CERT_NONE,
2551 ssl_version=ssl.PROTOCOL_TLSv1,
2552 cacerts=CERTFILE,
2553 chatty=True,
2554 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002555 with server:
2556 s = ssl.wrap_socket(socket.socket(),
2557 server_side=False,
2558 certfile=CERTFILE,
2559 ca_certs=CERTFILE,
2560 cert_reqs=ssl.CERT_NONE,
2561 ssl_version=ssl.PROTOCOL_TLSv1)
2562 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00002563 # helper methods for standardising recv* method signatures
2564 def _recv_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002565 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002566 count = s.recv_into(b)
2567 return b[:count]
2568
2569 def _recvfrom_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002570 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002571 count, addr = s.recvfrom_into(b)
2572 return b[:count]
2573
2574 # (name, method, whether to expect success, *args)
2575 send_methods = [
2576 ('send', s.send, True, []),
2577 ('sendto', s.sendto, False, ["some.address"]),
2578 ('sendall', s.sendall, True, []),
2579 ]
2580 recv_methods = [
2581 ('recv', s.recv, True, []),
2582 ('recvfrom', s.recvfrom, False, ["some.address"]),
2583 ('recv_into', _recv_into, True, []),
2584 ('recvfrom_into', _recvfrom_into, False, []),
2585 ]
2586 data_prefix = u"PREFIX_"
2587
2588 for meth_name, send_meth, expect_success, args in send_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002589 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002590 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002591 send_meth(indata, *args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002592 outdata = s.read()
Bill Janssen61c001a2008-09-08 16:37:24 +00002593 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002594 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002595 "While sending with <<{name:s}>> bad data "
2596 "<<{outdata:r}>> ({nout:d}) received; "
2597 "expected <<{indata:r}>> ({nin:d})\n".format(
2598 name=meth_name, outdata=outdata[:20],
2599 nout=len(outdata),
2600 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002601 )
2602 )
2603 except ValueError as e:
2604 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002605 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002606 "Failed to send with method <<{name:s}>>; "
2607 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002608 )
2609 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002610 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002611 "Method <<{name:s}>> failed with unexpected "
2612 "exception message: {exp:s}\n".format(
2613 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002614 )
2615 )
2616
2617 for meth_name, recv_meth, expect_success, args in recv_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002618 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002619 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002620 s.send(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002621 outdata = recv_meth(*args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002622 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002623 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002624 "While receiving with <<{name:s}>> bad data "
2625 "<<{outdata:r}>> ({nout:d}) received; "
2626 "expected <<{indata:r}>> ({nin:d})\n".format(
2627 name=meth_name, outdata=outdata[:20],
2628 nout=len(outdata),
2629 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002630 )
2631 )
2632 except ValueError as e:
2633 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002634 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002635 "Failed to receive with method <<{name:s}>>; "
2636 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002637 )
2638 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002639 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002640 "Method <<{name:s}>> failed with unexpected "
2641 "exception message: {exp:s}\n".format(
2642 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002643 )
2644 )
2645 # consume data
2646 s.read()
2647
Martin Panterd524b702016-03-28 00:22:09 +00002648 # read(-1, buffer) is supported, even though read(-1) is not
Martin Panter8c6849b2016-07-11 00:17:13 +00002649 data = b"data"
Martin Panterb8089b42016-03-27 05:35:19 +00002650 s.send(data)
2651 buffer = bytearray(len(data))
2652 self.assertEqual(s.read(-1, buffer), len(data))
2653 self.assertEqual(buffer, data)
2654
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002655 s.write(b"over\n")
Martin Panterb8089b42016-03-27 05:35:19 +00002656
2657 self.assertRaises(ValueError, s.recv, -1)
2658 self.assertRaises(ValueError, s.read, -1)
2659
Bill Janssen61c001a2008-09-08 16:37:24 +00002660 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00002661
Martin Panter8c6849b2016-07-11 00:17:13 +00002662 def test_recv_zero(self):
2663 server = ThreadedEchoServer(CERTFILE)
2664 server.__enter__()
2665 self.addCleanup(server.__exit__, None, None)
2666 s = socket.create_connection((HOST, server.port))
2667 self.addCleanup(s.close)
2668 s = ssl.wrap_socket(s, suppress_ragged_eofs=False)
2669 self.addCleanup(s.close)
2670
2671 # recv/read(0) should return no data
2672 s.send(b"data")
2673 self.assertEqual(s.recv(0), b"")
2674 self.assertEqual(s.read(0), b"")
2675 self.assertEqual(s.read(), b"data")
2676
2677 # Should not block if the other end sends no data
2678 s.setblocking(False)
2679 self.assertEqual(s.recv(0), b"")
2680 self.assertEqual(s.recv_into(bytearray()), 0)
2681
Antoine Pitroufc69af12010-04-24 20:04:58 +00002682 def test_handshake_timeout(self):
2683 # Issue #5103: SSL handshake must respect the socket timeout
2684 server = socket.socket(socket.AF_INET)
2685 host = "127.0.0.1"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002686 port = support.bind_port(server)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002687 started = threading.Event()
2688 finish = False
2689
2690 def serve():
2691 server.listen(5)
2692 started.set()
2693 conns = []
2694 while not finish:
2695 r, w, e = select.select([server], [], [], 0.1)
2696 if server in r:
2697 # Let the socket hang around rather than having
2698 # it closed by garbage collection.
2699 conns.append(server.accept()[0])
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002700 for sock in conns:
2701 sock.close()
Antoine Pitroufc69af12010-04-24 20:04:58 +00002702
2703 t = threading.Thread(target=serve)
2704 t.start()
2705 started.wait()
2706
2707 try:
2708 try:
2709 c = socket.socket(socket.AF_INET)
2710 c.settimeout(0.2)
2711 c.connect((host, port))
2712 # Will attempt handshake and time out
2713 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2714 ssl.wrap_socket, c)
2715 finally:
2716 c.close()
2717 try:
2718 c = socket.socket(socket.AF_INET)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002719 c = ssl.wrap_socket(c)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002720 c.settimeout(0.2)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002721 # Will attempt handshake and time out
2722 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2723 c.connect, (host, port))
2724 finally:
2725 c.close()
2726 finally:
2727 finish = True
2728 t.join()
2729 server.close()
2730
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002731 def test_server_accept(self):
2732 # Issue #16357: accept() on a SSLSocket created through
2733 # SSLContext.wrap_socket().
2734 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2735 context.verify_mode = ssl.CERT_REQUIRED
2736 context.load_verify_locations(CERTFILE)
2737 context.load_cert_chain(CERTFILE)
2738 server = socket.socket(socket.AF_INET)
2739 host = "127.0.0.1"
2740 port = support.bind_port(server)
2741 server = context.wrap_socket(server, server_side=True)
2742
2743 evt = threading.Event()
2744 remote = [None]
2745 peer = [None]
2746 def serve():
2747 server.listen(5)
2748 # Block on the accept and wait on the connection to close.
2749 evt.set()
2750 remote[0], peer[0] = server.accept()
2751 remote[0].recv(1)
2752
2753 t = threading.Thread(target=serve)
2754 t.start()
2755 # Client wait until server setup and perform a connect.
2756 evt.wait()
2757 client = context.wrap_socket(socket.socket())
2758 client.connect((host, port))
2759 client_addr = client.getsockname()
2760 client.close()
2761 t.join()
2762 remote[0].close()
2763 server.close()
2764 # Sanity checks.
2765 self.assertIsInstance(remote[0], ssl.SSLSocket)
2766 self.assertEqual(peer[0], client_addr)
2767
2768 def test_getpeercert_enotconn(self):
2769 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2770 with closing(context.wrap_socket(socket.socket())) as sock:
2771 with self.assertRaises(socket.error) as cm:
2772 sock.getpeercert()
2773 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2774
2775 def test_do_handshake_enotconn(self):
2776 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2777 with closing(context.wrap_socket(socket.socket())) as sock:
2778 with self.assertRaises(socket.error) as cm:
2779 sock.do_handshake()
2780 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2781
Antoine Pitroud76088d2012-01-03 22:46:48 +01002782 def test_default_ciphers(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002783 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2784 try:
2785 # Force a set of weak ciphers on our client context
2786 context.set_ciphers("DES")
2787 except ssl.SSLError:
2788 self.skipTest("no DES cipher available")
Antoine Pitroud76088d2012-01-03 22:46:48 +01002789 with ThreadedEchoServer(CERTFILE,
2790 ssl_version=ssl.PROTOCOL_SSLv23,
2791 chatty=False) as server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002792 with closing(context.wrap_socket(socket.socket())) as s:
2793 with self.assertRaises(ssl.SSLError):
Antoine Pitroud76088d2012-01-03 22:46:48 +01002794 s.connect((HOST, server.port))
Antoine Pitroud76088d2012-01-03 22:46:48 +01002795 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2796
Alex Gaynore98205d2014-09-04 13:33:22 -07002797 def test_version_basic(self):
2798 """
2799 Basic tests for SSLSocket.version().
2800 More tests are done in the test_protocol_*() methods.
2801 """
2802 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2803 with ThreadedEchoServer(CERTFILE,
2804 ssl_version=ssl.PROTOCOL_TLSv1,
2805 chatty=False) as server:
2806 with closing(context.wrap_socket(socket.socket())) as s:
2807 self.assertIs(s.version(), None)
2808 s.connect((HOST, server.port))
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002809 self.assertEqual(s.version(), 'TLSv1')
Alex Gaynore98205d2014-09-04 13:33:22 -07002810 self.assertIs(s.version(), None)
2811
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002812 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2813 def test_default_ecdh_curve(self):
2814 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2815 # should be enabled by default on SSL contexts.
2816 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2817 context.load_cert_chain(CERTFILE)
2818 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2819 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2820 # our default cipher list should prefer ECDH-based ciphers
2821 # automatically.
2822 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2823 context.set_ciphers("ECCdraft:ECDH")
2824 with ThreadedEchoServer(context=context) as server:
2825 with closing(context.wrap_socket(socket.socket())) as s:
2826 s.connect((HOST, server.port))
2827 self.assertIn("ECDH", s.cipher()[0])
2828
2829 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2830 "'tls-unique' channel binding not available")
2831 def test_tls_unique_channel_binding(self):
2832 """Test tls-unique channel binding."""
2833 if support.verbose:
2834 sys.stdout.write("\n")
2835
2836 server = ThreadedEchoServer(CERTFILE,
2837 certreqs=ssl.CERT_NONE,
2838 ssl_version=ssl.PROTOCOL_TLSv1,
2839 cacerts=CERTFILE,
2840 chatty=True,
2841 connectionchatty=False)
2842 with server:
2843 s = ssl.wrap_socket(socket.socket(),
2844 server_side=False,
2845 certfile=CERTFILE,
2846 ca_certs=CERTFILE,
2847 cert_reqs=ssl.CERT_NONE,
2848 ssl_version=ssl.PROTOCOL_TLSv1)
2849 s.connect((HOST, server.port))
2850 # get the data
2851 cb_data = s.get_channel_binding("tls-unique")
2852 if support.verbose:
2853 sys.stdout.write(" got channel binding data: {0!r}\n"
2854 .format(cb_data))
2855
2856 # check if it is sane
2857 self.assertIsNotNone(cb_data)
2858 self.assertEqual(len(cb_data), 12) # True for TLSv1
2859
2860 # and compare with the peers version
2861 s.write(b"CB tls-unique\n")
2862 peer_data_repr = s.read().strip()
2863 self.assertEqual(peer_data_repr,
2864 repr(cb_data).encode("us-ascii"))
2865 s.close()
2866
2867 # now, again
2868 s = ssl.wrap_socket(socket.socket(),
2869 server_side=False,
2870 certfile=CERTFILE,
2871 ca_certs=CERTFILE,
2872 cert_reqs=ssl.CERT_NONE,
2873 ssl_version=ssl.PROTOCOL_TLSv1)
2874 s.connect((HOST, server.port))
2875 new_cb_data = s.get_channel_binding("tls-unique")
2876 if support.verbose:
2877 sys.stdout.write(" got another channel binding data: {0!r}\n"
2878 .format(new_cb_data))
2879 # is it really unique
2880 self.assertNotEqual(cb_data, new_cb_data)
2881 self.assertIsNotNone(cb_data)
2882 self.assertEqual(len(cb_data), 12) # True for TLSv1
2883 s.write(b"CB tls-unique\n")
2884 peer_data_repr = s.read().strip()
2885 self.assertEqual(peer_data_repr,
2886 repr(new_cb_data).encode("us-ascii"))
2887 s.close()
2888
2889 def test_compression(self):
2890 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2891 context.load_cert_chain(CERTFILE)
2892 stats = server_params_test(context, context,
2893 chatty=True, connectionchatty=True)
2894 if support.verbose:
2895 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2896 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2897
2898 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2899 "ssl.OP_NO_COMPRESSION needed for this test")
2900 def test_compression_disabled(self):
2901 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2902 context.load_cert_chain(CERTFILE)
2903 context.options |= ssl.OP_NO_COMPRESSION
2904 stats = server_params_test(context, context,
2905 chatty=True, connectionchatty=True)
2906 self.assertIs(stats['compression'], None)
2907
2908 def test_dh_params(self):
2909 # Check we can get a connection with ephemeral Diffie-Hellman
2910 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2911 context.load_cert_chain(CERTFILE)
2912 context.load_dh_params(DHFILE)
2913 context.set_ciphers("kEDH")
2914 stats = server_params_test(context, context,
2915 chatty=True, connectionchatty=True)
2916 cipher = stats["cipher"][0]
2917 parts = cipher.split("-")
2918 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2919 self.fail("Non-DH cipher: " + cipher[0])
2920
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002921 def test_selected_alpn_protocol(self):
2922 # selected_alpn_protocol() is None unless ALPN is used.
2923 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2924 context.load_cert_chain(CERTFILE)
2925 stats = server_params_test(context, context,
2926 chatty=True, connectionchatty=True)
2927 self.assertIs(stats['client_alpn_protocol'], None)
2928
2929 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
2930 def test_selected_alpn_protocol_if_server_uses_alpn(self):
2931 # selected_alpn_protocol() is None unless ALPN is used by the client.
2932 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2933 client_context.load_verify_locations(CERTFILE)
2934 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2935 server_context.load_cert_chain(CERTFILE)
2936 server_context.set_alpn_protocols(['foo', 'bar'])
2937 stats = server_params_test(client_context, server_context,
2938 chatty=True, connectionchatty=True)
2939 self.assertIs(stats['client_alpn_protocol'], None)
2940
2941 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
2942 def test_alpn_protocols(self):
2943 server_protocols = ['foo', 'bar', 'milkshake']
2944 protocol_tests = [
2945 (['foo', 'bar'], 'foo'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002946 (['bar', 'foo'], 'foo'),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002947 (['milkshake'], 'milkshake'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002948 (['http/3.0', 'http/4.0'], None)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002949 ]
2950 for client_protocols, expected in protocol_tests:
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002951 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002952 server_context.load_cert_chain(CERTFILE)
2953 server_context.set_alpn_protocols(server_protocols)
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002954 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002955 client_context.load_cert_chain(CERTFILE)
2956 client_context.set_alpn_protocols(client_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002957
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002958 try:
2959 stats = server_params_test(client_context,
2960 server_context,
2961 chatty=True,
2962 connectionchatty=True)
2963 except ssl.SSLError as e:
2964 stats = e
2965
2966 if expected is None and IS_OPENSSL_1_1:
2967 # OpenSSL 1.1.0 raises handshake error
2968 self.assertIsInstance(stats, ssl.SSLError)
2969 else:
2970 msg = "failed trying %s (s) and %s (c).\n" \
2971 "was expecting %s, but got %%s from the %%s" \
2972 % (str(server_protocols), str(client_protocols),
2973 str(expected))
2974 client_result = stats['client_alpn_protocol']
2975 self.assertEqual(client_result, expected,
2976 msg % (client_result, "client"))
2977 server_result = stats['server_alpn_protocols'][-1] \
2978 if len(stats['server_alpn_protocols']) else 'nothing'
2979 self.assertEqual(server_result, expected,
2980 msg % (server_result, "server"))
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002981
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002982 def test_selected_npn_protocol(self):
2983 # selected_npn_protocol() is None unless NPN is used
2984 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2985 context.load_cert_chain(CERTFILE)
2986 stats = server_params_test(context, context,
2987 chatty=True, connectionchatty=True)
2988 self.assertIs(stats['client_npn_protocol'], None)
2989
2990 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2991 def test_npn_protocols(self):
2992 server_protocols = ['http/1.1', 'spdy/2']
2993 protocol_tests = [
2994 (['http/1.1', 'spdy/2'], 'http/1.1'),
2995 (['spdy/2', 'http/1.1'], 'http/1.1'),
2996 (['spdy/2', 'test'], 'spdy/2'),
2997 (['abc', 'def'], 'abc')
2998 ]
2999 for client_protocols, expected in protocol_tests:
3000 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3001 server_context.load_cert_chain(CERTFILE)
3002 server_context.set_npn_protocols(server_protocols)
3003 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3004 client_context.load_cert_chain(CERTFILE)
3005 client_context.set_npn_protocols(client_protocols)
3006 stats = server_params_test(client_context, server_context,
3007 chatty=True, connectionchatty=True)
3008
3009 msg = "failed trying %s (s) and %s (c).\n" \
3010 "was expecting %s, but got %%s from the %%s" \
3011 % (str(server_protocols), str(client_protocols),
3012 str(expected))
3013 client_result = stats['client_npn_protocol']
3014 self.assertEqual(client_result, expected, msg % (client_result, "client"))
3015 server_result = stats['server_npn_protocols'][-1] \
3016 if len(stats['server_npn_protocols']) else 'nothing'
3017 self.assertEqual(server_result, expected, msg % (server_result, "server"))
3018
3019 def sni_contexts(self):
3020 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3021 server_context.load_cert_chain(SIGNED_CERTFILE)
3022 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3023 other_context.load_cert_chain(SIGNED_CERTFILE2)
3024 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3025 client_context.verify_mode = ssl.CERT_REQUIRED
3026 client_context.load_verify_locations(SIGNING_CA)
3027 return server_context, other_context, client_context
3028
3029 def check_common_name(self, stats, name):
3030 cert = stats['peercert']
3031 self.assertIn((('commonName', name),), cert['subject'])
3032
3033 @needs_sni
3034 def test_sni_callback(self):
3035 calls = []
3036 server_context, other_context, client_context = self.sni_contexts()
3037
3038 def servername_cb(ssl_sock, server_name, initial_context):
3039 calls.append((server_name, initial_context))
3040 if server_name is not None:
3041 ssl_sock.context = other_context
3042 server_context.set_servername_callback(servername_cb)
3043
3044 stats = server_params_test(client_context, server_context,
3045 chatty=True,
3046 sni_name='supermessage')
3047 # The hostname was fetched properly, and the certificate was
3048 # changed for the connection.
3049 self.assertEqual(calls, [("supermessage", server_context)])
3050 # CERTFILE4 was selected
3051 self.check_common_name(stats, 'fakehostname')
3052
3053 calls = []
3054 # The callback is called with server_name=None
3055 stats = server_params_test(client_context, server_context,
3056 chatty=True,
3057 sni_name=None)
3058 self.assertEqual(calls, [(None, server_context)])
3059 self.check_common_name(stats, 'localhost')
3060
3061 # Check disabling the callback
3062 calls = []
3063 server_context.set_servername_callback(None)
3064
3065 stats = server_params_test(client_context, server_context,
3066 chatty=True,
3067 sni_name='notfunny')
3068 # Certificate didn't change
3069 self.check_common_name(stats, 'localhost')
3070 self.assertEqual(calls, [])
3071
3072 @needs_sni
3073 def test_sni_callback_alert(self):
3074 # Returning a TLS alert is reflected to the connecting client
3075 server_context, other_context, client_context = self.sni_contexts()
3076
3077 def cb_returning_alert(ssl_sock, server_name, initial_context):
3078 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
3079 server_context.set_servername_callback(cb_returning_alert)
3080
3081 with self.assertRaises(ssl.SSLError) as cm:
3082 stats = server_params_test(client_context, server_context,
3083 chatty=False,
3084 sni_name='supermessage')
3085 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
3086
3087 @needs_sni
3088 def test_sni_callback_raising(self):
3089 # Raising fails the connection with a TLS handshake failure alert.
3090 server_context, other_context, client_context = self.sni_contexts()
3091
3092 def cb_raising(ssl_sock, server_name, initial_context):
Serhiy Storchaka5312a7f2015-01-31 11:27:06 +02003093 1.0/0.0
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003094 server_context.set_servername_callback(cb_raising)
3095
3096 with self.assertRaises(ssl.SSLError) as cm, \
3097 support.captured_stderr() as stderr:
3098 stats = server_params_test(client_context, server_context,
3099 chatty=False,
3100 sni_name='supermessage')
3101 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
3102 self.assertIn("ZeroDivisionError", stderr.getvalue())
3103
3104 @needs_sni
3105 def test_sni_callback_wrong_return_type(self):
3106 # Returning the wrong return type terminates the TLS connection
3107 # with an internal error alert.
3108 server_context, other_context, client_context = self.sni_contexts()
3109
3110 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
3111 return "foo"
3112 server_context.set_servername_callback(cb_wrong_return_type)
3113
3114 with self.assertRaises(ssl.SSLError) as cm, \
3115 support.captured_stderr() as stderr:
3116 stats = server_params_test(client_context, server_context,
3117 chatty=False,
3118 sni_name='supermessage')
3119 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
3120 self.assertIn("TypeError", stderr.getvalue())
3121
3122 def test_read_write_after_close_raises_valuerror(self):
3123 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3124 context.verify_mode = ssl.CERT_REQUIRED
3125 context.load_verify_locations(CERTFILE)
3126 context.load_cert_chain(CERTFILE)
3127 server = ThreadedEchoServer(context=context, chatty=False)
3128
3129 with server:
3130 s = context.wrap_socket(socket.socket())
3131 s.connect((HOST, server.port))
3132 s.close()
3133
3134 self.assertRaises(ValueError, s.read, 1024)
3135 self.assertRaises(ValueError, s.write, b'hello')
3136
Bill Janssen61c001a2008-09-08 16:37:24 +00003137
Neal Norwitz9eb9b102007-08-27 01:15:33 +00003138def test_main(verbose=False):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003139 if support.verbose:
3140 plats = {
3141 'Linux': platform.linux_distribution,
3142 'Mac': platform.mac_ver,
3143 'Windows': platform.win32_ver,
3144 }
3145 for name, func in plats.items():
3146 plat = func()
3147 if plat and plat[0]:
3148 plat = '%s %r' % (name, plat)
3149 break
3150 else:
3151 plat = repr(platform.platform())
3152 print("test_ssl: testing with %r %r" %
3153 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3154 print(" under %s" % plat)
3155 print(" HAS_SNI = %r" % ssl.HAS_SNI)
3156 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3157 try:
3158 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3159 except AttributeError:
3160 pass
Bill Janssen296a59d2007-09-16 22:06:00 +00003161
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003162 for filename in [
Martin Panter71202bb2016-01-15 00:25:29 +00003163 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003164 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
3165 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
3166 BADCERT, BADKEY, EMPTYCERT]:
3167 if not os.path.exists(filename):
3168 raise support.TestFailed("Can't read certificate file %r" % filename)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003169
Benjamin Peterson2f334562014-10-01 23:53:01 -04003170 tests = [ContextTests, BasicTests, BasicSocketTests, SSLErrorTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003171
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003172 if support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00003173 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00003174
Bill Janssen98d19da2007-09-10 21:51:02 +00003175 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003176 thread_info = support.threading_setup()
3177 if thread_info:
Bill Janssen934b16d2008-06-28 22:19:33 +00003178 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003179
Antoine Pitrou3945c862010-04-28 21:11:01 +00003180 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003181 support.run_unittest(*tests)
Antoine Pitrou3945c862010-04-28 21:11:01 +00003182 finally:
3183 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003184 support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003185
3186if __name__ == "__main__":
3187 test_main()