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