blob: f1d85dd0963a253288eb4e8dd49d168d2b33e639 [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")
63
Martin Panter71202bb2016-01-15 00:25:29 +000064REMOTE_HOST = "self-signed.pythontest.net"
65REMOTE_ROOT_CERT = data_file("selfsigned_pythontestdotnet.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050066
67EMPTYCERT = data_file("nullcert.pem")
68BADCERT = data_file("badcert.pem")
Martin Panterfd8e8502016-01-30 02:36:00 +000069NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050070BADKEY = data_file("badkey.pem")
71NOKIACERT = data_file("nokia.pem")
72NULLBYTECERT = data_file("nullbytecert.pem")
73
Benjamin Petersondf11d4c2015-04-02 00:04:06 -040074DHFILE = data_file("dh1024.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050075BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding())
76
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000077
Neal Norwitz3e533c22007-08-27 01:03:18 +000078def handle_error(prefix):
79 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersondaeb9252014-08-20 14:14:50 -050080 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +000081 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000082
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000083
84class BasicTests(unittest.TestCase):
85
Antoine Pitrou3945c862010-04-28 21:11:01 +000086 def test_sslwrap_simple(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000087 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000088 try:
89 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
90 except IOError, e:
91 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
92 pass
93 else:
94 raise
95 try:
96 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
97 except IOError, e:
98 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
99 pass
100 else:
101 raise
Benjamin Peterson2f334562014-10-01 23:53:01 -0400102
103
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500104def can_clear_options():
105 # 0.9.8m or higher
106 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
107
108def no_sslv2_implies_sslv3_hello():
109 # 0.9.7h or higher
110 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
111
112def have_verify_flags():
113 # 0.9.8 or higher
114 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
115
116def utc_offset(): #NOTE: ignore issues like #1647654
117 # local time = utc time + utc offset
118 if time.daylight and time.localtime().tm_isdst > 0:
119 return -time.altzone # seconds
120 return -time.timezone
121
122def asn1time(cert_time):
123 # Some versions of OpenSSL ignore seconds, see #18207
124 # 0.9.8.i
125 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
126 fmt = "%b %d %H:%M:%S %Y GMT"
127 dt = datetime.datetime.strptime(cert_time, fmt)
128 dt = dt.replace(second=0)
129 cert_time = dt.strftime(fmt)
130 # %d adds leading zero but ASN1_TIME_print() uses leading space
131 if cert_time[4] == "0":
132 cert_time = cert_time[:4] + " " + cert_time[5:]
133
134 return cert_time
Neal Norwitz3e533c22007-08-27 01:03:18 +0000135
Antoine Pitroud75efd92010-08-04 17:38:33 +0000136# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
137def skip_if_broken_ubuntu_ssl(func):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200138 if hasattr(ssl, 'PROTOCOL_SSLv2'):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200139 @functools.wraps(func)
140 def f(*args, **kwargs):
141 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500142 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
143 except ssl.SSLError:
Victor Stinnerb1241f92011-05-10 01:52:03 +0200144 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500145 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200146 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
147 return func(*args, **kwargs)
148 return f
149 else:
150 return func
Antoine Pitroud75efd92010-08-04 17:38:33 +0000151
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500152needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
153
Antoine Pitroud75efd92010-08-04 17:38:33 +0000154
155class BasicSocketTests(unittest.TestCase):
156
Antoine Pitrou3945c862010-04-28 21:11:01 +0000157 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000158 ssl.CERT_NONE
159 ssl.CERT_OPTIONAL
160 ssl.CERT_REQUIRED
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500161 ssl.OP_CIPHER_SERVER_PREFERENCE
162 ssl.OP_SINGLE_DH_USE
163 if ssl.HAS_ECDH:
164 ssl.OP_SINGLE_ECDH_USE
165 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
166 ssl.OP_NO_COMPRESSION
167 self.assertIn(ssl.HAS_SNI, {True, False})
168 self.assertIn(ssl.HAS_ECDH, {True, False})
169
Antoine Pitrou3945c862010-04-28 21:11:01 +0000170 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000171 v = ssl.RAND_status()
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500172 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000173 sys.stdout.write("\n RAND_status is %d (%s)\n"
174 % (v, (v and "sufficient randomness") or
175 "insufficient randomness"))
Victor Stinner7c906672015-01-06 13:53:37 +0100176 if hasattr(ssl, 'RAND_egd'):
177 self.assertRaises(TypeError, ssl.RAND_egd, 1)
178 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000179 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000180
Antoine Pitrou3945c862010-04-28 21:11:01 +0000181 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000182 # note that this uses an 'unofficial' function in _ssl.c,
183 # provided solely for this test, to exercise the certificate
184 # parsing code
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500185 p = ssl._ssl._test_decode_cert(CERTFILE)
186 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000187 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500188 self.assertEqual(p['issuer'],
189 ((('countryName', 'XY'),),
190 (('localityName', 'Castle Anthrax'),),
191 (('organizationName', 'Python Software Foundation'),),
192 (('commonName', 'localhost'),))
193 )
194 # Note the next three asserts will fail if the keys are regenerated
195 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
196 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
197 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200198 self.assertEqual(p['subject'],
Antoine Pitrou60982912013-02-16 21:39:28 +0100199 ((('countryName', 'XY'),),
200 (('localityName', 'Castle Anthrax'),),
201 (('organizationName', 'Python Software Foundation'),),
202 (('commonName', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200203 )
Antoine Pitrou60982912013-02-16 21:39:28 +0100204 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200205 # Issue #13034: the subjectAltName in some certificates
206 # (notably projects.developer.nokia.com:443) wasn't parsed
207 p = ssl._ssl._test_decode_cert(NOKIACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500208 if support.verbose:
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200209 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
210 self.assertEqual(p['subjectAltName'],
211 (('DNS', 'projects.developer.nokia.com'),
212 ('DNS', 'projects.forum.nokia.com'))
213 )
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500214 # extra OCSP and AIA fields
215 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
216 self.assertEqual(p['caIssuers'],
217 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
218 self.assertEqual(p['crlDistributionPoints'],
219 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000220
Christian Heimes88b174c2013-08-17 00:54:47 +0200221 def test_parse_cert_CVE_2013_4238(self):
222 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500223 if support.verbose:
Christian Heimes88b174c2013-08-17 00:54:47 +0200224 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
225 subject = ((('countryName', 'US'),),
226 (('stateOrProvinceName', 'Oregon'),),
227 (('localityName', 'Beaverton'),),
228 (('organizationName', 'Python Software Foundation'),),
229 (('organizationalUnitName', 'Python Core Development'),),
230 (('commonName', 'null.python.org\x00example.org'),),
231 (('emailAddress', 'python-dev@python.org'),))
232 self.assertEqual(p['subject'], subject)
233 self.assertEqual(p['issuer'], subject)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500234 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
Christian Heimesf869a942013-08-25 14:12:41 +0200235 san = (('DNS', 'altnull.python.org\x00example.com'),
236 ('email', 'null@python.org\x00user@example.org'),
237 ('URI', 'http://null.python.org\x00http://example.org'),
238 ('IP Address', '192.0.2.1'),
239 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
240 else:
241 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
242 san = (('DNS', 'altnull.python.org\x00example.com'),
243 ('email', 'null@python.org\x00user@example.org'),
244 ('URI', 'http://null.python.org\x00http://example.org'),
245 ('IP Address', '192.0.2.1'),
246 ('IP Address', '<invalid>'))
247
248 self.assertEqual(p['subjectAltName'], san)
Christian Heimes88b174c2013-08-17 00:54:47 +0200249
Antoine Pitrou3945c862010-04-28 21:11:01 +0000250 def test_DER_to_PEM(self):
Martin Panter71202bb2016-01-15 00:25:29 +0000251 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000252 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000253 d1 = ssl.PEM_cert_to_DER_cert(pem)
254 p2 = ssl.DER_cert_to_PEM_cert(d1)
255 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000256 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000257 if not p2.startswith(ssl.PEM_HEADER + '\n'):
258 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
259 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
260 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000261
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000262 def test_openssl_version(self):
263 n = ssl.OPENSSL_VERSION_NUMBER
264 t = ssl.OPENSSL_VERSION_INFO
265 s = ssl.OPENSSL_VERSION
266 self.assertIsInstance(n, (int, long))
267 self.assertIsInstance(t, tuple)
268 self.assertIsInstance(s, str)
269 # Some sanity checks follow
270 # >= 0.9
271 self.assertGreaterEqual(n, 0x900000)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400272 # < 3.0
273 self.assertLess(n, 0x30000000)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000274 major, minor, fix, patch, status = t
275 self.assertGreaterEqual(major, 0)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400276 self.assertLess(major, 3)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000277 self.assertGreaterEqual(minor, 0)
278 self.assertLess(minor, 256)
279 self.assertGreaterEqual(fix, 0)
280 self.assertLess(fix, 256)
281 self.assertGreaterEqual(patch, 0)
Ned Deilyfa119782015-02-05 17:19:11 +1100282 self.assertLessEqual(patch, 63)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000283 self.assertGreaterEqual(status, 0)
284 self.assertLessEqual(status, 15)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400285 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimesc2fc7c42016-09-05 23:37:13 +0200286 if IS_LIBRESSL:
287 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
288 (s, t, hex(n)))
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400289 else:
290 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
291 (s, t))
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000292
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500293 @support.cpython_only
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000294 def test_refcycle(self):
295 # Issue #7943: an SSL object doesn't create reference cycles with
296 # itself.
297 s = socket.socket(socket.AF_INET)
298 ss = ssl.wrap_socket(s)
299 wr = weakref.ref(ss)
300 del ss
301 self.assertEqual(wr(), None)
302
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000303 def test_wrapped_unconnected(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500304 # Methods on an unconnected SSLSocket propagate the original
305 # socket.error raise by the underlying socket object.
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000306 s = socket.socket(socket.AF_INET)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500307 with closing(ssl.wrap_socket(s)) as ss:
308 self.assertRaises(socket.error, ss.recv, 1)
309 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
310 self.assertRaises(socket.error, ss.recvfrom, 1)
311 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
312 self.assertRaises(socket.error, ss.send, b'x')
313 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
314
315 def test_timeout(self):
316 # Issue #8524: when creating an SSL socket, the timeout of the
317 # original socket should be retained.
318 for timeout in (None, 0.0, 5.0):
319 s = socket.socket(socket.AF_INET)
320 s.settimeout(timeout)
321 with closing(ssl.wrap_socket(s)) as ss:
322 self.assertEqual(timeout, ss.gettimeout())
323
324 def test_errors(self):
325 sock = socket.socket()
326 self.assertRaisesRegexp(ValueError,
327 "certfile must be specified",
328 ssl.wrap_socket, sock, keyfile=CERTFILE)
329 self.assertRaisesRegexp(ValueError,
330 "certfile must be specified for server-side operations",
331 ssl.wrap_socket, sock, server_side=True)
332 self.assertRaisesRegexp(ValueError,
333 "certfile must be specified for server-side operations",
334 ssl.wrap_socket, sock, server_side=True, certfile="")
335 with closing(ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)) as s:
336 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
337 s.connect, (HOST, 8080))
338 with self.assertRaises(IOError) as cm:
339 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000340 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500341 self.assertEqual(cm.exception.errno, errno.ENOENT)
342 with self.assertRaises(IOError) as cm:
343 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000344 ssl.wrap_socket(sock,
345 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500346 self.assertEqual(cm.exception.errno, errno.ENOENT)
347 with self.assertRaises(IOError) as cm:
348 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000349 ssl.wrap_socket(sock,
350 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500351 self.assertEqual(cm.exception.errno, errno.ENOENT)
352
Martin Panter886aba42016-02-01 21:58:11 +0000353 def bad_cert_test(self, certfile):
354 """Check that trying to use the given client certificate fails"""
355 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
356 certfile)
357 sock = socket.socket()
358 self.addCleanup(sock.close)
359 with self.assertRaises(ssl.SSLError):
360 ssl.wrap_socket(sock,
361 certfile=certfile,
362 ssl_version=ssl.PROTOCOL_TLSv1)
363
364 def test_empty_cert(self):
365 """Wrapping with an empty cert file"""
366 self.bad_cert_test("nullcert.pem")
367
368 def test_malformed_cert(self):
369 """Wrapping with a badly formatted certificate (syntax error)"""
370 self.bad_cert_test("badcert.pem")
371
372 def test_malformed_key(self):
373 """Wrapping with a badly formatted key (syntax error)"""
374 self.bad_cert_test("badkey.pem")
375
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500376 def test_match_hostname(self):
377 def ok(cert, hostname):
378 ssl.match_hostname(cert, hostname)
379 def fail(cert, hostname):
380 self.assertRaises(ssl.CertificateError,
381 ssl.match_hostname, cert, hostname)
382
383 cert = {'subject': ((('commonName', 'example.com'),),)}
384 ok(cert, 'example.com')
385 ok(cert, 'ExAmple.cOm')
386 fail(cert, 'www.example.com')
387 fail(cert, '.example.com')
388 fail(cert, 'example.org')
389 fail(cert, 'exampleXcom')
390
391 cert = {'subject': ((('commonName', '*.a.com'),),)}
392 ok(cert, 'foo.a.com')
393 fail(cert, 'bar.foo.a.com')
394 fail(cert, 'a.com')
395 fail(cert, 'Xa.com')
396 fail(cert, '.a.com')
397
398 # only match one left-most wildcard
399 cert = {'subject': ((('commonName', 'f*.com'),),)}
400 ok(cert, 'foo.com')
401 ok(cert, 'f.com')
402 fail(cert, 'bar.com')
403 fail(cert, 'foo.a.com')
404 fail(cert, 'bar.foo.com')
405
406 # NULL bytes are bad, CVE-2013-4073
407 cert = {'subject': ((('commonName',
408 'null.python.org\x00example.org'),),)}
409 ok(cert, 'null.python.org\x00example.org') # or raise an error?
410 fail(cert, 'example.org')
411 fail(cert, 'null.python.org')
412
413 # error cases with wildcards
414 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
415 fail(cert, 'bar.foo.a.com')
416 fail(cert, 'a.com')
417 fail(cert, 'Xa.com')
418 fail(cert, '.a.com')
419
420 cert = {'subject': ((('commonName', 'a.*.com'),),)}
421 fail(cert, 'a.foo.com')
422 fail(cert, 'a..com')
423 fail(cert, 'a.com')
424
425 # wildcard doesn't match IDNA prefix 'xn--'
426 idna = u'püthon.python.org'.encode("idna").decode("ascii")
427 cert = {'subject': ((('commonName', idna),),)}
428 ok(cert, idna)
429 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
430 fail(cert, idna)
431 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
432 fail(cert, idna)
433
434 # wildcard in first fragment and IDNA A-labels in sequent fragments
435 # are supported.
436 idna = u'www*.pythön.org'.encode("idna").decode("ascii")
437 cert = {'subject': ((('commonName', idna),),)}
438 ok(cert, u'www.pythön.org'.encode("idna").decode("ascii"))
439 ok(cert, u'www1.pythön.org'.encode("idna").decode("ascii"))
440 fail(cert, u'ftp.pythön.org'.encode("idna").decode("ascii"))
441 fail(cert, u'pythön.org'.encode("idna").decode("ascii"))
442
443 # Slightly fake real-world example
444 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
445 'subject': ((('commonName', 'linuxfrz.org'),),),
446 'subjectAltName': (('DNS', 'linuxfr.org'),
447 ('DNS', 'linuxfr.com'),
448 ('othername', '<unsupported>'))}
449 ok(cert, 'linuxfr.org')
450 ok(cert, 'linuxfr.com')
451 # Not a "DNS" entry
452 fail(cert, '<unsupported>')
453 # When there is a subjectAltName, commonName isn't used
454 fail(cert, 'linuxfrz.org')
455
456 # A pristine real-world example
457 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
458 'subject': ((('countryName', 'US'),),
459 (('stateOrProvinceName', 'California'),),
460 (('localityName', 'Mountain View'),),
461 (('organizationName', 'Google Inc'),),
462 (('commonName', 'mail.google.com'),))}
463 ok(cert, 'mail.google.com')
464 fail(cert, 'gmail.com')
465 # Only commonName is considered
466 fail(cert, 'California')
467
468 # Neither commonName nor subjectAltName
469 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
470 'subject': ((('countryName', 'US'),),
471 (('stateOrProvinceName', 'California'),),
472 (('localityName', 'Mountain View'),),
473 (('organizationName', 'Google Inc'),))}
474 fail(cert, 'mail.google.com')
475
476 # No DNS entry in subjectAltName but a commonName
477 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
478 'subject': ((('countryName', 'US'),),
479 (('stateOrProvinceName', 'California'),),
480 (('localityName', 'Mountain View'),),
481 (('commonName', 'mail.google.com'),)),
482 'subjectAltName': (('othername', 'blabla'), )}
483 ok(cert, 'mail.google.com')
484
485 # No DNS entry subjectAltName and no commonName
486 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
487 'subject': ((('countryName', 'US'),),
488 (('stateOrProvinceName', 'California'),),
489 (('localityName', 'Mountain View'),),
490 (('organizationName', 'Google Inc'),)),
491 'subjectAltName': (('othername', 'blabla'),)}
492 fail(cert, 'google.com')
493
494 # Empty cert / no cert
495 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
496 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
497
498 # Issue #17980: avoid denials of service by refusing more than one
499 # wildcard per fragment.
500 cert = {'subject': ((('commonName', 'a*b.com'),),)}
501 ok(cert, 'axxb.com')
502 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
503 fail(cert, 'axxb.com')
504 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
505 with self.assertRaises(ssl.CertificateError) as cm:
506 ssl.match_hostname(cert, 'axxbxxc.com')
507 self.assertIn("too many wildcards", str(cm.exception))
508
509 def test_server_side(self):
510 # server_hostname doesn't work for server sockets
511 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
512 with closing(socket.socket()) as sock:
513 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
514 server_hostname="some.hostname")
515
516 def test_unknown_channel_binding(self):
517 # should raise ValueError for unknown type
518 s = socket.socket(socket.AF_INET)
519 with closing(ssl.wrap_socket(s)) as ss:
520 with self.assertRaises(ValueError):
521 ss.get_channel_binding("unknown-type")
522
523 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
524 "'tls-unique' channel binding not available")
525 def test_tls_unique_channel_binding(self):
526 # unconnected should return None for known type
527 s = socket.socket(socket.AF_INET)
528 with closing(ssl.wrap_socket(s)) as ss:
529 self.assertIsNone(ss.get_channel_binding("tls-unique"))
530 # the same for server-side
531 s = socket.socket(socket.AF_INET)
532 with closing(ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)) as ss:
533 self.assertIsNone(ss.get_channel_binding("tls-unique"))
534
535 def test_get_default_verify_paths(self):
536 paths = ssl.get_default_verify_paths()
537 self.assertEqual(len(paths), 6)
538 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
539
540 with support.EnvironmentVarGuard() as env:
541 env["SSL_CERT_DIR"] = CAPATH
542 env["SSL_CERT_FILE"] = CERTFILE
543 paths = ssl.get_default_verify_paths()
544 self.assertEqual(paths.cafile, CERTFILE)
545 self.assertEqual(paths.capath, CAPATH)
546
547 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
548 def test_enum_certificates(self):
549 self.assertTrue(ssl.enum_certificates("CA"))
550 self.assertTrue(ssl.enum_certificates("ROOT"))
551
552 self.assertRaises(TypeError, ssl.enum_certificates)
553 self.assertRaises(WindowsError, ssl.enum_certificates, "")
554
555 trust_oids = set()
556 for storename in ("CA", "ROOT"):
557 store = ssl.enum_certificates(storename)
558 self.assertIsInstance(store, list)
559 for element in store:
560 self.assertIsInstance(element, tuple)
561 self.assertEqual(len(element), 3)
562 cert, enc, trust = element
563 self.assertIsInstance(cert, bytes)
564 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
565 self.assertIsInstance(trust, (set, bool))
566 if isinstance(trust, set):
567 trust_oids.update(trust)
568
569 serverAuth = "1.3.6.1.5.5.7.3.1"
570 self.assertIn(serverAuth, trust_oids)
571
572 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
573 def test_enum_crls(self):
574 self.assertTrue(ssl.enum_crls("CA"))
575 self.assertRaises(TypeError, ssl.enum_crls)
576 self.assertRaises(WindowsError, ssl.enum_crls, "")
577
578 crls = ssl.enum_crls("CA")
579 self.assertIsInstance(crls, list)
580 for element in crls:
581 self.assertIsInstance(element, tuple)
582 self.assertEqual(len(element), 2)
583 self.assertIsInstance(element[0], bytes)
584 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
585
586
587 def test_asn1object(self):
588 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
589 '1.3.6.1.5.5.7.3.1')
590
591 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
592 self.assertEqual(val, expected)
593 self.assertEqual(val.nid, 129)
594 self.assertEqual(val.shortname, 'serverAuth')
595 self.assertEqual(val.longname, 'TLS Web Server Authentication')
596 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
597 self.assertIsInstance(val, ssl._ASN1Object)
598 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
599
600 val = ssl._ASN1Object.fromnid(129)
601 self.assertEqual(val, expected)
602 self.assertIsInstance(val, ssl._ASN1Object)
603 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
604 with self.assertRaisesRegexp(ValueError, "unknown NID 100000"):
605 ssl._ASN1Object.fromnid(100000)
606 for i in range(1000):
607 try:
608 obj = ssl._ASN1Object.fromnid(i)
609 except ValueError:
610 pass
611 else:
612 self.assertIsInstance(obj.nid, int)
613 self.assertIsInstance(obj.shortname, str)
614 self.assertIsInstance(obj.longname, str)
615 self.assertIsInstance(obj.oid, (str, type(None)))
616
617 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
618 self.assertEqual(val, expected)
619 self.assertIsInstance(val, ssl._ASN1Object)
620 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
621 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
622 expected)
623 with self.assertRaisesRegexp(ValueError, "unknown object 'serverauth'"):
624 ssl._ASN1Object.fromname('serverauth')
625
626 def test_purpose_enum(self):
627 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
628 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
629 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
630 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
631 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
632 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
633 '1.3.6.1.5.5.7.3.1')
634
635 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
636 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
637 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
638 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
639 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
640 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
641 '1.3.6.1.5.5.7.3.2')
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000642
Antoine Pitrou63cc99d2013-12-28 17:26:33 +0100643 def test_unsupported_dtls(self):
644 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
645 self.addCleanup(s.close)
646 with self.assertRaises(NotImplementedError) as cx:
647 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
648 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500649 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
650 with self.assertRaises(NotImplementedError) as cx:
651 ctx.wrap_socket(s)
652 self.assertEqual(str(cx.exception), "only stream sockets are supported")
653
654 def cert_time_ok(self, timestring, timestamp):
655 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
656
657 def cert_time_fail(self, timestring):
658 with self.assertRaises(ValueError):
659 ssl.cert_time_to_seconds(timestring)
660
661 @unittest.skipUnless(utc_offset(),
662 'local time needs to be different from UTC')
663 def test_cert_time_to_seconds_timezone(self):
664 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
665 # results if local timezone is not UTC
666 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
667 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
668
669 def test_cert_time_to_seconds(self):
670 timestring = "Jan 5 09:34:43 2018 GMT"
671 ts = 1515144883.0
672 self.cert_time_ok(timestring, ts)
673 # accept keyword parameter, assert its name
674 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
675 # accept both %e and %d (space or zero generated by strftime)
676 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
677 # case-insensitive
678 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
679 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
680 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
681 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
682 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
683 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
684 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
685 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
686
687 newyear_ts = 1230768000.0
688 # leap seconds
689 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
690 # same timestamp
691 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
692
693 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
694 # allow 60th second (even if it is not a leap second)
695 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
696 # allow 2nd leap second for compatibility with time.strptime()
697 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
698 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
699
700 # no special treatement for the special value:
701 # 99991231235959Z (rfc 5280)
702 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
703
704 @support.run_with_locale('LC_ALL', '')
705 def test_cert_time_to_seconds_locale(self):
706 # `cert_time_to_seconds()` should be locale independent
707
708 def local_february_name():
709 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
710
711 if local_february_name().lower() == 'feb':
712 self.skipTest("locale-specific month name needs to be "
713 "different from C locale")
714
715 # locale-independent
716 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
717 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
718
719
720class ContextTests(unittest.TestCase):
721
722 @skip_if_broken_ubuntu_ssl
723 def test_constructor(self):
724 for protocol in PROTOCOLS:
725 ssl.SSLContext(protocol)
726 self.assertRaises(TypeError, ssl.SSLContext)
727 self.assertRaises(ValueError, ssl.SSLContext, -1)
728 self.assertRaises(ValueError, ssl.SSLContext, 42)
729
730 @skip_if_broken_ubuntu_ssl
731 def test_protocol(self):
732 for proto in PROTOCOLS:
733 ctx = ssl.SSLContext(proto)
734 self.assertEqual(ctx.protocol, proto)
735
736 def test_ciphers(self):
737 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
738 ctx.set_ciphers("ALL")
739 ctx.set_ciphers("DEFAULT")
740 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
741 ctx.set_ciphers("^$:,;?*'dorothyx")
742
743 @skip_if_broken_ubuntu_ssl
744 def test_options(self):
745 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800746 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimesc2fc7c42016-09-05 23:37:13 +0200747 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
748 if not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0):
749 default |= ssl.OP_NO_COMPRESSION
750 self.assertEqual(default, ctx.options)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800751 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimesc2fc7c42016-09-05 23:37:13 +0200752 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500753 if can_clear_options():
Christian Heimesc2fc7c42016-09-05 23:37:13 +0200754 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
755 self.assertEqual(default, ctx.options)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500756 ctx.options = 0
757 self.assertEqual(0, ctx.options)
758 else:
759 with self.assertRaises(ValueError):
760 ctx.options = 0
761
762 def test_verify_mode(self):
763 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
764 # Default value
765 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
766 ctx.verify_mode = ssl.CERT_OPTIONAL
767 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
768 ctx.verify_mode = ssl.CERT_REQUIRED
769 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
770 ctx.verify_mode = ssl.CERT_NONE
771 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
772 with self.assertRaises(TypeError):
773 ctx.verify_mode = None
774 with self.assertRaises(ValueError):
775 ctx.verify_mode = 42
776
777 @unittest.skipUnless(have_verify_flags(),
778 "verify_flags need OpenSSL > 0.9.8")
779 def test_verify_flags(self):
780 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson72ef9612015-03-04 22:49:41 -0500781 # default value
782 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
783 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500784 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
785 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
786 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
787 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
788 ctx.verify_flags = ssl.VERIFY_DEFAULT
789 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
790 # supports any value
791 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
792 self.assertEqual(ctx.verify_flags,
793 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
794 with self.assertRaises(TypeError):
795 ctx.verify_flags = None
796
797 def test_load_cert_chain(self):
798 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
799 # Combined key and cert in a single file
Benjamin Peterson04439fd2014-11-03 21:05:01 -0500800 ctx.load_cert_chain(CERTFILE, keyfile=None)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500801 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
802 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
803 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000804 ctx.load_cert_chain(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500805 self.assertEqual(cm.exception.errno, errno.ENOENT)
806 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
807 ctx.load_cert_chain(BADCERT)
808 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
809 ctx.load_cert_chain(EMPTYCERT)
810 # Separate key and cert
811 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
812 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
813 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
814 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
815 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
816 ctx.load_cert_chain(ONLYCERT)
817 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
818 ctx.load_cert_chain(ONLYKEY)
819 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
820 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
821 # Mismatching key and cert
822 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
823 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Martin Panter71202bb2016-01-15 00:25:29 +0000824 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500825 # Password protected key and cert
826 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
827 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
828 ctx.load_cert_chain(CERTFILE_PROTECTED,
829 password=bytearray(KEY_PASSWORD.encode()))
830 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
831 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
832 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
833 bytearray(KEY_PASSWORD.encode()))
834 with self.assertRaisesRegexp(TypeError, "should be a string"):
835 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
836 with self.assertRaises(ssl.SSLError):
837 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
838 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
839 # openssl has a fixed limit on the password buffer.
840 # PEM_BUFSIZE is generally set to 1kb.
841 # Return a string larger than this.
842 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
843 # Password callback
844 def getpass_unicode():
845 return KEY_PASSWORD
846 def getpass_bytes():
847 return KEY_PASSWORD.encode()
848 def getpass_bytearray():
849 return bytearray(KEY_PASSWORD.encode())
850 def getpass_badpass():
851 return "badpass"
852 def getpass_huge():
853 return b'a' * (1024 * 1024)
854 def getpass_bad_type():
855 return 9
856 def getpass_exception():
857 raise Exception('getpass error')
858 class GetPassCallable:
859 def __call__(self):
860 return KEY_PASSWORD
861 def getpass(self):
862 return KEY_PASSWORD
863 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
864 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
865 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
866 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
867 ctx.load_cert_chain(CERTFILE_PROTECTED,
868 password=GetPassCallable().getpass)
869 with self.assertRaises(ssl.SSLError):
870 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
871 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
872 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
873 with self.assertRaisesRegexp(TypeError, "must return a string"):
874 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
875 with self.assertRaisesRegexp(Exception, "getpass error"):
876 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
877 # Make sure the password function isn't called if it isn't needed
878 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
879
880 def test_load_verify_locations(self):
881 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
882 ctx.load_verify_locations(CERTFILE)
883 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
884 ctx.load_verify_locations(BYTES_CERTFILE)
885 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400886 ctx.load_verify_locations(cafile=BYTES_CERTFILE.decode('utf-8'))
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500887 self.assertRaises(TypeError, ctx.load_verify_locations)
888 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
889 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000890 ctx.load_verify_locations(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500891 self.assertEqual(cm.exception.errno, errno.ENOENT)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400892 with self.assertRaises(IOError):
893 ctx.load_verify_locations(u'')
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500894 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
895 ctx.load_verify_locations(BADCERT)
896 ctx.load_verify_locations(CERTFILE, CAPATH)
897 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
898
899 # Issue #10989: crash if the second argument type is invalid
900 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
901
902 def test_load_verify_cadata(self):
903 # test cadata
904 with open(CAFILE_CACERT) as f:
905 cacert_pem = f.read().decode("ascii")
906 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
907 with open(CAFILE_NEURONIO) as f:
908 neuronio_pem = f.read().decode("ascii")
909 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
910
911 # test PEM
912 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
913 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
914 ctx.load_verify_locations(cadata=cacert_pem)
915 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
916 ctx.load_verify_locations(cadata=neuronio_pem)
917 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
918 # cert already in hash table
919 ctx.load_verify_locations(cadata=neuronio_pem)
920 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
921
922 # combined
923 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
924 combined = "\n".join((cacert_pem, neuronio_pem))
925 ctx.load_verify_locations(cadata=combined)
926 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
927
928 # with junk around the certs
929 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
930 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
931 neuronio_pem, "tail"]
932 ctx.load_verify_locations(cadata="\n".join(combined))
933 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
934
935 # test DER
936 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
937 ctx.load_verify_locations(cadata=cacert_der)
938 ctx.load_verify_locations(cadata=neuronio_der)
939 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
940 # cert already in hash table
941 ctx.load_verify_locations(cadata=cacert_der)
942 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
943
944 # combined
945 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
946 combined = b"".join((cacert_der, neuronio_der))
947 ctx.load_verify_locations(cadata=combined)
948 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
949
950 # error cases
951 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
952 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
953
954 with self.assertRaisesRegexp(ssl.SSLError, "no start line"):
955 ctx.load_verify_locations(cadata=u"broken")
956 with self.assertRaisesRegexp(ssl.SSLError, "not enough data"):
957 ctx.load_verify_locations(cadata=b"broken")
958
959
960 def test_load_dh_params(self):
961 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
962 ctx.load_dh_params(DHFILE)
963 if os.name != 'nt':
964 ctx.load_dh_params(BYTES_DHFILE)
965 self.assertRaises(TypeError, ctx.load_dh_params)
966 self.assertRaises(TypeError, ctx.load_dh_params, None)
967 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000968 ctx.load_dh_params(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500969 self.assertEqual(cm.exception.errno, errno.ENOENT)
970 with self.assertRaises(ssl.SSLError) as cm:
971 ctx.load_dh_params(CERTFILE)
972
973 @skip_if_broken_ubuntu_ssl
974 def test_session_stats(self):
975 for proto in PROTOCOLS:
976 ctx = ssl.SSLContext(proto)
977 self.assertEqual(ctx.session_stats(), {
978 'number': 0,
979 'connect': 0,
980 'connect_good': 0,
981 'connect_renegotiate': 0,
982 'accept': 0,
983 'accept_good': 0,
984 'accept_renegotiate': 0,
985 'hits': 0,
986 'misses': 0,
987 'timeouts': 0,
988 'cache_full': 0,
989 })
990
991 def test_set_default_verify_paths(self):
992 # There's not much we can do to test that it acts as expected,
993 # so just check it doesn't crash or raise an exception.
994 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
995 ctx.set_default_verify_paths()
996
997 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
998 def test_set_ecdh_curve(self):
999 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1000 ctx.set_ecdh_curve("prime256v1")
1001 ctx.set_ecdh_curve(b"prime256v1")
1002 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1003 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1004 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1005 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1006
1007 @needs_sni
1008 def test_sni_callback(self):
1009 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1010
1011 # set_servername_callback expects a callable, or None
1012 self.assertRaises(TypeError, ctx.set_servername_callback)
1013 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1014 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1015 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1016
1017 def dummycallback(sock, servername, ctx):
1018 pass
1019 ctx.set_servername_callback(None)
1020 ctx.set_servername_callback(dummycallback)
1021
1022 @needs_sni
1023 def test_sni_callback_refcycle(self):
1024 # Reference cycles through the servername callback are detected
1025 # and cleared.
1026 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1027 def dummycallback(sock, servername, ctx, cycle=ctx):
1028 pass
1029 ctx.set_servername_callback(dummycallback)
1030 wr = weakref.ref(ctx)
1031 del ctx, dummycallback
1032 gc.collect()
1033 self.assertIs(wr(), None)
1034
1035 def test_cert_store_stats(self):
1036 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1037 self.assertEqual(ctx.cert_store_stats(),
1038 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1039 ctx.load_cert_chain(CERTFILE)
1040 self.assertEqual(ctx.cert_store_stats(),
1041 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1042 ctx.load_verify_locations(CERTFILE)
1043 self.assertEqual(ctx.cert_store_stats(),
1044 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panter71202bb2016-01-15 00:25:29 +00001045 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001046 self.assertEqual(ctx.cert_store_stats(),
1047 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1048
1049 def test_get_ca_certs(self):
1050 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1051 self.assertEqual(ctx.get_ca_certs(), [])
1052 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1053 ctx.load_verify_locations(CERTFILE)
1054 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panter71202bb2016-01-15 00:25:29 +00001055 # but CAFILE_CACERT is a CA cert
1056 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001057 self.assertEqual(ctx.get_ca_certs(),
1058 [{'issuer': ((('organizationName', 'Root CA'),),
1059 (('organizationalUnitName', 'http://www.cacert.org'),),
1060 (('commonName', 'CA Cert Signing Authority'),),
1061 (('emailAddress', 'support@cacert.org'),)),
1062 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1063 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1064 'serialNumber': '00',
1065 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
1066 'subject': ((('organizationName', 'Root CA'),),
1067 (('organizationalUnitName', 'http://www.cacert.org'),),
1068 (('commonName', 'CA Cert Signing Authority'),),
1069 (('emailAddress', 'support@cacert.org'),)),
1070 'version': 3}])
1071
Martin Panter71202bb2016-01-15 00:25:29 +00001072 with open(CAFILE_CACERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001073 pem = f.read()
1074 der = ssl.PEM_cert_to_DER_cert(pem)
1075 self.assertEqual(ctx.get_ca_certs(True), [der])
1076
1077 def test_load_default_certs(self):
1078 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1079 ctx.load_default_certs()
1080
1081 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1082 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1083 ctx.load_default_certs()
1084
1085 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1086 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1087
1088 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1089 self.assertRaises(TypeError, ctx.load_default_certs, None)
1090 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1091
Benjamin Petersona02ae252014-10-03 18:17:15 -04001092 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimesc2fc7c42016-09-05 23:37:13 +02001093 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson0b30a2b2014-10-03 17:27:05 -04001094 def test_load_default_certs_env(self):
1095 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1096 with support.EnvironmentVarGuard() as env:
1097 env["SSL_CERT_DIR"] = CAPATH
1098 env["SSL_CERT_FILE"] = CERTFILE
1099 ctx.load_default_certs()
1100 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1101
Benjamin Petersona02ae252014-10-03 18:17:15 -04001102 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1103 def test_load_default_certs_env_windows(self):
1104 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1105 ctx.load_default_certs()
1106 stats = ctx.cert_store_stats()
1107
1108 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1109 with support.EnvironmentVarGuard() as env:
1110 env["SSL_CERT_DIR"] = CAPATH
1111 env["SSL_CERT_FILE"] = CERTFILE
1112 ctx.load_default_certs()
1113 stats["x509"] += 1
1114 self.assertEqual(ctx.cert_store_stats(), stats)
1115
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001116 def test_create_default_context(self):
1117 ctx = ssl.create_default_context()
1118 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1119 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1120 self.assertTrue(ctx.check_hostname)
1121 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1122 self.assertEqual(
1123 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1124 getattr(ssl, "OP_NO_COMPRESSION", 0),
1125 )
1126
1127 with open(SIGNING_CA) as f:
1128 cadata = f.read().decode("ascii")
1129 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1130 cadata=cadata)
1131 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1132 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1133 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1134 self.assertEqual(
1135 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1136 getattr(ssl, "OP_NO_COMPRESSION", 0),
1137 )
1138
1139 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
1140 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1141 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1142 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1143 self.assertEqual(
1144 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1145 getattr(ssl, "OP_NO_COMPRESSION", 0),
1146 )
1147 self.assertEqual(
1148 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1149 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1150 )
1151 self.assertEqual(
1152 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1153 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1154 )
1155
1156 def test__create_stdlib_context(self):
1157 ctx = ssl._create_stdlib_context()
1158 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1159 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1160 self.assertFalse(ctx.check_hostname)
1161 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1162
1163 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1164 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1165 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1166 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1167
1168 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
1169 cert_reqs=ssl.CERT_REQUIRED,
1170 check_hostname=True)
1171 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1172 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1173 self.assertTrue(ctx.check_hostname)
1174 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1175
1176 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1177 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1178 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1179 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1180
Nick Coghlandbcd4572016-03-20 22:39:15 +10001181 def test__https_verify_certificates(self):
1182 # Unit test to check the contect factory mapping
1183 # The factories themselves are tested above
1184 # This test will fail by design if run under PYTHONHTTPSVERIFY=0
1185 # (as will various test_httplib tests)
1186
1187 # Uses a fresh SSL module to avoid affecting the real one
1188 local_ssl = support.import_fresh_module("ssl")
1189 # Certificate verification is enabled by default
1190 self.assertIs(local_ssl._create_default_https_context,
1191 local_ssl.create_default_context)
1192 # Turn default verification off
1193 local_ssl._https_verify_certificates(enable=False)
1194 self.assertIs(local_ssl._create_default_https_context,
1195 local_ssl._create_unverified_context)
1196 # And back on
1197 local_ssl._https_verify_certificates(enable=True)
1198 self.assertIs(local_ssl._create_default_https_context,
1199 local_ssl.create_default_context)
1200 # The default behaviour is to enable
1201 local_ssl._https_verify_certificates(enable=False)
1202 local_ssl._https_verify_certificates()
1203 self.assertIs(local_ssl._create_default_https_context,
1204 local_ssl.create_default_context)
1205
1206 def test__https_verify_envvar(self):
1207 # Unit test to check the PYTHONHTTPSVERIFY handling
1208 # Need to use a subprocess so it can still be run under -E
1209 https_is_verified = """import ssl, sys; \
1210 status = "Error: _create_default_https_context does not verify certs" \
1211 if ssl._create_default_https_context is \
1212 ssl._create_unverified_context \
1213 else None; \
1214 sys.exit(status)"""
1215 https_is_not_verified = """import ssl, sys; \
1216 status = "Error: _create_default_https_context verifies certs" \
1217 if ssl._create_default_https_context is \
1218 ssl.create_default_context \
1219 else None; \
1220 sys.exit(status)"""
1221 extra_env = {}
1222 # Omitting it leaves verification on
1223 assert_python_ok("-c", https_is_verified, **extra_env)
1224 # Setting it to zero turns verification off
1225 extra_env[ssl._https_verify_envvar] = "0"
1226 assert_python_ok("-c", https_is_not_verified, **extra_env)
1227 # Any other value should also leave it on
1228 for setting in ("", "1", "enabled", "foo"):
1229 extra_env[ssl._https_verify_envvar] = setting
1230 assert_python_ok("-c", https_is_verified, **extra_env)
1231
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001232 def test_check_hostname(self):
1233 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1234 self.assertFalse(ctx.check_hostname)
1235
1236 # Requires CERT_REQUIRED or CERT_OPTIONAL
1237 with self.assertRaises(ValueError):
1238 ctx.check_hostname = True
1239 ctx.verify_mode = ssl.CERT_REQUIRED
1240 self.assertFalse(ctx.check_hostname)
1241 ctx.check_hostname = True
1242 self.assertTrue(ctx.check_hostname)
1243
1244 ctx.verify_mode = ssl.CERT_OPTIONAL
1245 ctx.check_hostname = True
1246 self.assertTrue(ctx.check_hostname)
1247
1248 # Cannot set CERT_NONE with check_hostname enabled
1249 with self.assertRaises(ValueError):
1250 ctx.verify_mode = ssl.CERT_NONE
1251 ctx.check_hostname = False
1252 self.assertFalse(ctx.check_hostname)
1253
1254
1255class SSLErrorTests(unittest.TestCase):
1256
1257 def test_str(self):
1258 # The str() of a SSLError doesn't include the errno
1259 e = ssl.SSLError(1, "foo")
1260 self.assertEqual(str(e), "foo")
1261 self.assertEqual(e.errno, 1)
1262 # Same for a subclass
1263 e = ssl.SSLZeroReturnError(1, "foo")
1264 self.assertEqual(str(e), "foo")
1265 self.assertEqual(e.errno, 1)
1266
1267 def test_lib_reason(self):
1268 # Test the library and reason attributes
1269 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1270 with self.assertRaises(ssl.SSLError) as cm:
1271 ctx.load_dh_params(CERTFILE)
1272 self.assertEqual(cm.exception.library, 'PEM')
1273 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1274 s = str(cm.exception)
1275 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1276
1277 def test_subclass(self):
1278 # Check that the appropriate SSLError subclass is raised
1279 # (this only tests one of them)
1280 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1281 with closing(socket.socket()) as s:
1282 s.bind(("127.0.0.1", 0))
1283 s.listen(5)
1284 c = socket.socket()
1285 c.connect(s.getsockname())
1286 c.setblocking(False)
1287 with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c:
1288 with self.assertRaises(ssl.SSLWantReadError) as cm:
1289 c.do_handshake()
1290 s = str(cm.exception)
1291 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1292 # For compatibility
1293 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
Antoine Pitrou63cc99d2013-12-28 17:26:33 +01001294
Antoine Pitrouf9de5342010-04-05 21:35:07 +00001295
Bill Janssen934b16d2008-06-28 22:19:33 +00001296class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +00001297
Antoine Pitrou3945c862010-04-28 21:11:01 +00001298 def test_connect(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001299 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001300 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1301 cert_reqs=ssl.CERT_NONE)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001302 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001303 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001304 self.assertEqual({}, s.getpeercert())
1305 finally:
1306 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001307
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001308 # this should fail because we have no verification certs
1309 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1310 cert_reqs=ssl.CERT_REQUIRED)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001311 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001312 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001313 s.close()
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001314
1315 # this should succeed because we specify the root cert
1316 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1317 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001318 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001319 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001320 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001321 self.assertTrue(s.getpeercert())
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001322 finally:
1323 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001324
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001325 def test_connect_ex(self):
1326 # Issue #11326: check connect_ex() implementation
Martin Panter71202bb2016-01-15 00:25:29 +00001327 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001328 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1329 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001330 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001331 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001332 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001333 self.assertTrue(s.getpeercert())
1334 finally:
1335 s.close()
1336
1337 def test_non_blocking_connect_ex(self):
1338 # Issue #11326: non-blocking connect_ex() should allow handshake
1339 # to proceed after the socket gets ready.
Martin Panter71202bb2016-01-15 00:25:29 +00001340 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001341 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1342 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001343 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001344 do_handshake_on_connect=False)
1345 try:
1346 s.setblocking(False)
Martin Panter71202bb2016-01-15 00:25:29 +00001347 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +00001348 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1349 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001350 # Wait for connect to finish
1351 select.select([], [s], [], 5.0)
1352 # Non-blocking handshake
1353 while True:
1354 try:
1355 s.do_handshake()
1356 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001357 except ssl.SSLWantReadError:
1358 select.select([s], [], [], 5.0)
1359 except ssl.SSLWantWriteError:
1360 select.select([], [s], [], 5.0)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001361 # SSL established
1362 self.assertTrue(s.getpeercert())
1363 finally:
1364 s.close()
1365
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001366 def test_timeout_connect_ex(self):
1367 # Issue #12065: on a timeout, connect_ex() should return the original
1368 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter71202bb2016-01-15 00:25:29 +00001369 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001370 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1371 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001372 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001373 do_handshake_on_connect=False)
1374 try:
1375 s.settimeout(0.0000001)
Martin Panter71202bb2016-01-15 00:25:29 +00001376 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001377 if rc == 0:
Martin Panter71202bb2016-01-15 00:25:29 +00001378 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001379 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1380 finally:
1381 s.close()
1382
1383 def test_connect_ex_error(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001384 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001385 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1386 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001387 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001388 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001389 rc = s.connect_ex((REMOTE_HOST, 444))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001390 # Issue #19919: Windows machines or VMs hosted on Windows
1391 # machines sometimes return EWOULDBLOCK.
Martin Panter71202bb2016-01-15 00:25:29 +00001392 errors = (
1393 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1394 errno.EWOULDBLOCK,
1395 )
1396 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001397 finally:
1398 s.close()
1399
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001400 def test_connect_with_context(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001401 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001402 # Same as test_connect, but with a separately created context
1403 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1404 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001405 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001406 try:
1407 self.assertEqual({}, s.getpeercert())
1408 finally:
1409 s.close()
1410 # Same with a server hostname
1411 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter71202bb2016-01-15 00:25:29 +00001412 server_hostname=REMOTE_HOST)
1413 s.connect((REMOTE_HOST, 443))
Benjamin Peterson31aa69e2014-11-23 20:13:31 -06001414 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001415 # This should fail because we have no verification certs
1416 ctx.verify_mode = ssl.CERT_REQUIRED
1417 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1418 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001419 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001420 s.close()
1421 # This should succeed because we specify the root cert
Martin Panter71202bb2016-01-15 00:25:29 +00001422 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001423 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001424 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001425 try:
1426 cert = s.getpeercert()
1427 self.assertTrue(cert)
1428 finally:
1429 s.close()
1430
1431 def test_connect_capath(self):
1432 # Verify server certificates using the `capath` argument
1433 # NOTE: the subject hashing algorithm has been changed between
1434 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1435 # contain both versions of each certificate (same content, different
1436 # filename) for this test to be portable across OpenSSL releases.
Martin Panter71202bb2016-01-15 00:25:29 +00001437 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001438 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1439 ctx.verify_mode = ssl.CERT_REQUIRED
1440 ctx.load_verify_locations(capath=CAPATH)
1441 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001442 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001443 try:
1444 cert = s.getpeercert()
1445 self.assertTrue(cert)
1446 finally:
1447 s.close()
1448 # Same with a bytes `capath` argument
1449 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1450 ctx.verify_mode = ssl.CERT_REQUIRED
1451 ctx.load_verify_locations(capath=BYTES_CAPATH)
1452 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001453 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001454 try:
1455 cert = s.getpeercert()
1456 self.assertTrue(cert)
1457 finally:
1458 s.close()
1459
1460 def test_connect_cadata(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001461 with open(REMOTE_ROOT_CERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001462 pem = f.read().decode('ascii')
1463 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panter71202bb2016-01-15 00:25:29 +00001464 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001465 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1466 ctx.verify_mode = ssl.CERT_REQUIRED
1467 ctx.load_verify_locations(cadata=pem)
1468 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001469 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001470 cert = s.getpeercert()
1471 self.assertTrue(cert)
1472
1473 # same with DER
1474 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1475 ctx.verify_mode = ssl.CERT_REQUIRED
1476 ctx.load_verify_locations(cadata=der)
1477 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001478 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001479 cert = s.getpeercert()
1480 self.assertTrue(cert)
1481
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001482 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1483 def test_makefile_close(self):
1484 # Issue #5238: creating a file-like object with makefile() shouldn't
1485 # delay closing the underlying "real socket" (here tested with its
1486 # file descriptor, hence skipping the test under Windows).
Martin Panter71202bb2016-01-15 00:25:29 +00001487 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001488 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001489 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001490 fd = ss.fileno()
1491 f = ss.makefile()
1492 f.close()
1493 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001494 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001495 # Closing the SSL socket should close the fd too
1496 ss.close()
1497 gc.collect()
1498 with self.assertRaises(OSError) as e:
1499 os.read(fd, 0)
1500 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +00001501
Antoine Pitrou3945c862010-04-28 21:11:01 +00001502 def test_non_blocking_handshake(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001503 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001504 s = socket.socket(socket.AF_INET)
Martin Panter71202bb2016-01-15 00:25:29 +00001505 s.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001506 s.setblocking(False)
1507 s = ssl.wrap_socket(s,
1508 cert_reqs=ssl.CERT_NONE,
1509 do_handshake_on_connect=False)
1510 count = 0
1511 while True:
1512 try:
1513 count += 1
1514 s.do_handshake()
1515 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001516 except ssl.SSLWantReadError:
1517 select.select([s], [], [])
1518 except ssl.SSLWantWriteError:
1519 select.select([], [s], [])
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001520 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001521 if support.verbose:
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001522 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +00001523
Antoine Pitrou3945c862010-04-28 21:11:01 +00001524 def test_get_server_certificate(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001525 def _test_get_server_certificate(host, port, cert=None):
1526 with support.transient_internet(host):
1527 pem = ssl.get_server_certificate((host, port))
1528 if not pem:
1529 self.fail("No server certificate on %s:%s!" % (host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001530
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001531 try:
1532 pem = ssl.get_server_certificate((host, port),
1533 ca_certs=CERTFILE)
1534 except ssl.SSLError as x:
1535 #should fail
1536 if support.verbose:
1537 sys.stdout.write("%s\n" % x)
1538 else:
1539 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001540 pem = ssl.get_server_certificate((host, port),
1541 ca_certs=cert)
1542 if not pem:
1543 self.fail("No server certificate on %s:%s!" % (host, port))
1544 if support.verbose:
1545 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1546
Martin Panter71202bb2016-01-15 00:25:29 +00001547 _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001548 if support.IPV6_ENABLED:
1549 _test_get_server_certificate('ipv6.google.com', 443)
1550
1551 def test_ciphers(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001552 remote = (REMOTE_HOST, 443)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001553 with support.transient_internet(remote[0]):
1554 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1555 cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s:
1556 s.connect(remote)
1557 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1558 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s:
1559 s.connect(remote)
1560 # Error checking can happen at instantiation or when connecting
1561 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
1562 with closing(socket.socket(socket.AF_INET)) as sock:
1563 s = ssl.wrap_socket(sock,
1564 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1565 s.connect(remote)
Bill Janssen296a59d2007-09-16 22:06:00 +00001566
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001567 def test_algorithms(self):
1568 # Issue #8484: all algorithms should be available when verifying a
1569 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +00001570 # SHA256 was added in OpenSSL 0.9.8
1571 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1572 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001573 # sha256.tbs-internet.com needs SNI to use the correct certificate
1574 if not ssl.HAS_SNI:
1575 self.skipTest("SNI needed for this test")
1576 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
Antoine Pitroud43245a2011-01-08 10:32:51 +00001577 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001578 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001579 with support.transient_internet("sha256.tbs-internet.com"):
1580 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1581 ctx.verify_mode = ssl.CERT_REQUIRED
1582 ctx.load_verify_locations(sha256_cert)
1583 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1584 server_hostname="sha256.tbs-internet.com")
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001585 try:
1586 s.connect(remote)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001587 if support.verbose:
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001588 sys.stdout.write("\nCipher with %r is %r\n" %
1589 (remote, s.cipher()))
1590 sys.stdout.write("Certificate is:\n%s\n" %
1591 pprint.pformat(s.getpeercert()))
1592 finally:
1593 s.close()
1594
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001595 def test_get_ca_certs_capath(self):
1596 # capath certs are loaded on request
Martin Panter71202bb2016-01-15 00:25:29 +00001597 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001598 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1599 ctx.verify_mode = ssl.CERT_REQUIRED
1600 ctx.load_verify_locations(capath=CAPATH)
1601 self.assertEqual(ctx.get_ca_certs(), [])
1602 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001603 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001604 try:
1605 cert = s.getpeercert()
1606 self.assertTrue(cert)
1607 finally:
1608 s.close()
1609 self.assertEqual(len(ctx.get_ca_certs()), 1)
1610
1611 @needs_sni
1612 def test_context_setget(self):
1613 # Check that the context of a connected socket can be replaced.
Martin Panter71202bb2016-01-15 00:25:29 +00001614 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001615 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1616 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1617 s = socket.socket(socket.AF_INET)
1618 with closing(ctx1.wrap_socket(s)) as ss:
Martin Panter71202bb2016-01-15 00:25:29 +00001619 ss.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001620 self.assertIs(ss.context, ctx1)
1621 self.assertIs(ss._sslobj.context, ctx1)
1622 ss.context = ctx2
1623 self.assertIs(ss.context, ctx2)
1624 self.assertIs(ss._sslobj.context, ctx2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001625
Bill Janssen98d19da2007-09-10 21:51:02 +00001626try:
1627 import threading
1628except ImportError:
1629 _have_threads = False
1630else:
Bill Janssen98d19da2007-09-10 21:51:02 +00001631 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001632
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001633 from test.ssl_servers import make_https_server
1634
Bill Janssen98d19da2007-09-10 21:51:02 +00001635 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001636
Bill Janssen98d19da2007-09-10 21:51:02 +00001637 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001638
Bill Janssen98d19da2007-09-10 21:51:02 +00001639 """A mildly complicated class, because we want it to work both
1640 with and without the SSL wrapper around the socket connection, so
1641 that we can test the STARTTLS functionality."""
1642
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001643 def __init__(self, server, connsock, addr):
Bill Janssen98d19da2007-09-10 21:51:02 +00001644 self.server = server
1645 self.running = False
1646 self.sock = connsock
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001647 self.addr = addr
Bill Janssen98d19da2007-09-10 21:51:02 +00001648 self.sock.setblocking(1)
1649 self.sslconn = None
1650 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001651 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001652
Antoine Pitrou3945c862010-04-28 21:11:01 +00001653 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001654 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001655 self.sslconn = self.server.context.wrap_socket(
1656 self.sock, server_side=True)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001657 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1658 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001659 except socket.error as e:
1660 # We treat ConnectionResetError as though it were an
1661 # SSLError - OpenSSL on Ubuntu abruptly closes the
1662 # connection when asked to use an unsupported protocol.
1663 #
Antoine Pitroudb187842010-04-27 10:32:58 +00001664 # XXX Various errors can have happened here, for example
1665 # a mismatching protocol version, an invalid certificate,
1666 # or a low-level bug. This should be made more discriminating.
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001667 if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET:
1668 raise
Antoine Pitroud76088d2012-01-03 22:46:48 +01001669 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +00001670 if self.server.chatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001671 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00001672 self.running = False
1673 self.server.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001674 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001675 return False
Bill Janssen98d19da2007-09-10 21:51:02 +00001676 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001677 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
1678 cert = self.sslconn.getpeercert()
1679 if support.verbose and self.server.chatty:
1680 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1681 cert_binary = self.sslconn.getpeercert(True)
1682 if support.verbose and self.server.chatty:
1683 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1684 cipher = self.sslconn.cipher()
1685 if support.verbose and self.server.chatty:
1686 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
1687 sys.stdout.write(" server: selected protocol is now "
1688 + str(self.sslconn.selected_npn_protocol()) + "\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001689 return True
1690
1691 def read(self):
1692 if self.sslconn:
1693 return self.sslconn.read()
1694 else:
1695 return self.sock.recv(1024)
1696
1697 def write(self, bytes):
1698 if self.sslconn:
1699 return self.sslconn.write(bytes)
1700 else:
1701 return self.sock.send(bytes)
1702
1703 def close(self):
1704 if self.sslconn:
1705 self.sslconn.close()
1706 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001707 self.sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001708
Antoine Pitrou3945c862010-04-28 21:11:01 +00001709 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001710 self.running = True
1711 if not self.server.starttls_server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001712 if not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +00001713 return
1714 while self.running:
1715 try:
1716 msg = self.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001717 stripped = msg.strip()
1718 if not stripped:
Bill Janssen98d19da2007-09-10 21:51:02 +00001719 # eof, so quit this handler
1720 self.running = False
1721 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001722 elif stripped == b'over':
1723 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001724 sys.stdout.write(" server: client closed connection\n")
1725 self.close()
1726 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001727 elif (self.server.starttls_server and
1728 stripped == b'STARTTLS'):
1729 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001730 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001731 self.write(b"OK\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001732 if not self.wrap_conn():
1733 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001734 elif (self.server.starttls_server and self.sslconn
1735 and stripped == b'ENDTLS'):
1736 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001737 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001738 self.write(b"OK\n")
1739 self.sock = self.sslconn.unwrap()
Bill Janssen39295c22008-08-12 16:31:21 +00001740 self.sslconn = None
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001741 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001742 sys.stdout.write(" server: connection is now unencrypted...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001743 elif stripped == b'CB tls-unique':
1744 if support.verbose and self.server.connectionchatty:
1745 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1746 data = self.sslconn.get_channel_binding("tls-unique")
1747 self.write(repr(data).encode("us-ascii") + b"\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001748 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001749 if (support.verbose and
Bill Janssen98d19da2007-09-10 21:51:02 +00001750 self.server.connectionchatty):
1751 ctype = (self.sslconn and "encrypted") or "unencrypted"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001752 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1753 % (msg, ctype, msg.lower(), ctype))
Bill Janssen98d19da2007-09-10 21:51:02 +00001754 self.write(msg.lower())
1755 except ssl.SSLError:
1756 if self.server.chatty:
1757 handle_error("Test server failure:\n")
1758 self.close()
1759 self.running = False
1760 # normally, we'd just stop here, but for the test
1761 # harness, we want to stop the server
1762 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +00001763
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001764 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +00001765 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +00001766 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001767 npn_protocols=None, alpn_protocols=None,
1768 ciphers=None, context=None):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001769 if context:
1770 self.context = context
1771 else:
1772 self.context = ssl.SSLContext(ssl_version
1773 if ssl_version is not None
1774 else ssl.PROTOCOL_TLSv1)
1775 self.context.verify_mode = (certreqs if certreqs is not None
1776 else ssl.CERT_NONE)
1777 if cacerts:
1778 self.context.load_verify_locations(cacerts)
1779 if certificate:
1780 self.context.load_cert_chain(certificate)
1781 if npn_protocols:
1782 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001783 if alpn_protocols:
1784 self.context.set_alpn_protocols(alpn_protocols)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001785 if ciphers:
1786 self.context.set_ciphers(ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +00001787 self.chatty = chatty
1788 self.connectionchatty = connectionchatty
1789 self.starttls_server = starttls_server
1790 self.sock = socket.socket()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001791 self.port = support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +00001792 self.flag = None
Bill Janssen98d19da2007-09-10 21:51:02 +00001793 self.active = False
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001794 self.selected_npn_protocols = []
1795 self.selected_alpn_protocols = []
Antoine Pitroud76088d2012-01-03 22:46:48 +01001796 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001797 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001798 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001799
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001800 def __enter__(self):
1801 self.start(threading.Event())
1802 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001803 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001804
1805 def __exit__(self, *args):
1806 self.stop()
1807 self.join()
1808
Antoine Pitrou3945c862010-04-28 21:11:01 +00001809 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +00001810 self.flag = flag
1811 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001812
Antoine Pitrou3945c862010-04-28 21:11:01 +00001813 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +00001814 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +00001815 self.sock.listen(5)
1816 self.active = True
1817 if self.flag:
1818 # signal an event
1819 self.flag.set()
1820 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001821 try:
Bill Janssen98d19da2007-09-10 21:51:02 +00001822 newconn, connaddr = self.sock.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001823 if support.verbose and self.chatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001824 sys.stdout.write(' server: new connection from '
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001825 + repr(connaddr) + '\n')
1826 handler = self.ConnectionHandler(self, newconn, connaddr)
Bill Janssen98d19da2007-09-10 21:51:02 +00001827 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +01001828 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +00001829 except socket.timeout:
1830 pass
1831 except KeyboardInterrupt:
1832 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +00001833 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001834
Antoine Pitrou3945c862010-04-28 21:11:01 +00001835 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001836 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001837
Bill Janssen934b16d2008-06-28 22:19:33 +00001838 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +00001839
Antoine Pitrou3945c862010-04-28 21:11:01 +00001840 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +00001841
Antoine Pitrou3945c862010-04-28 21:11:01 +00001842 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +00001843
1844 def __init__(self, conn, certfile):
Bill Janssen934b16d2008-06-28 22:19:33 +00001845 self.socket = ssl.wrap_socket(conn, server_side=True,
1846 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +00001847 do_handshake_on_connect=False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001848 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroufc69af12010-04-24 20:04:58 +00001849 self._ssl_accepting = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001850 self._do_ssl_handshake()
Bill Janssen934b16d2008-06-28 22:19:33 +00001851
1852 def readable(self):
1853 if isinstance(self.socket, ssl.SSLSocket):
1854 while self.socket.pending() > 0:
1855 self.handle_read_event()
1856 return True
1857
Antoine Pitroufc69af12010-04-24 20:04:58 +00001858 def _do_ssl_handshake(self):
1859 try:
1860 self.socket.do_handshake()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001861 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1862 return
1863 except ssl.SSLEOFError:
1864 return self.handle_close()
1865 except ssl.SSLError:
Antoine Pitroufc69af12010-04-24 20:04:58 +00001866 raise
1867 except socket.error, err:
1868 if err.args[0] == errno.ECONNABORTED:
1869 return self.handle_close()
1870 else:
1871 self._ssl_accepting = False
1872
Bill Janssen934b16d2008-06-28 22:19:33 +00001873 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +00001874 if self._ssl_accepting:
1875 self._do_ssl_handshake()
1876 else:
1877 data = self.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001878 if support.verbose:
1879 sys.stdout.write(" server: read %s from client\n" % repr(data))
1880 if not data:
1881 self.close()
1882 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001883 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +00001884
1885 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +00001886 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001887 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001888 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1889
1890 def handle_error(self):
1891 raise
1892
1893 def __init__(self, certfile):
1894 self.certfile = certfile
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001895 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1896 self.port = support.bind_port(sock, '')
1897 asyncore.dispatcher.__init__(self, sock)
Bill Janssen934b16d2008-06-28 22:19:33 +00001898 self.listen(5)
1899
1900 def handle_accept(self):
1901 sock_obj, addr = self.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001902 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001903 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1904 self.ConnectionHandler(sock_obj, self.certfile)
1905
1906 def handle_error(self):
1907 raise
1908
1909 def __init__(self, certfile):
1910 self.flag = None
1911 self.active = False
1912 self.server = self.EchoServer(certfile)
1913 self.port = self.server.port
1914 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001915 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +00001916
1917 def __str__(self):
1918 return "<%s %s>" % (self.__class__.__name__, self.server)
1919
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001920 def __enter__(self):
1921 self.start(threading.Event())
1922 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001923 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001924
1925 def __exit__(self, *args):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001926 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001927 sys.stdout.write(" cleanup: stopping server.\n")
1928 self.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001929 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001930 sys.stdout.write(" cleanup: joining server thread.\n")
1931 self.join()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001932 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001933 sys.stdout.write(" cleanup: successfully joined.\n")
1934
Antoine Pitrou3945c862010-04-28 21:11:01 +00001935 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +00001936 self.flag = flag
1937 threading.Thread.start(self)
1938
Antoine Pitrou3945c862010-04-28 21:11:01 +00001939 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001940 self.active = True
1941 if self.flag:
1942 self.flag.set()
1943 while self.active:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001944 try:
1945 asyncore.loop(1)
1946 except:
1947 pass
Bill Janssen934b16d2008-06-28 22:19:33 +00001948
Antoine Pitrou3945c862010-04-28 21:11:01 +00001949 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001950 self.active = False
1951 self.server.close()
1952
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001953 def server_params_test(client_context, server_context, indata=b"FOO\n",
1954 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001955 """
1956 Launch a server, connect a client to it and try various reads
1957 and writes.
1958 """
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001959 stats = {}
1960 server = ThreadedEchoServer(context=server_context,
Bill Janssen98d19da2007-09-10 21:51:02 +00001961 chatty=chatty,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001962 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001963 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001964 with closing(client_context.wrap_socket(socket.socket(),
1965 server_hostname=sni_name)) as s:
1966 s.connect((HOST, server.port))
1967 for arg in [indata, bytearray(indata), memoryview(indata)]:
1968 if connectionchatty:
1969 if support.verbose:
1970 sys.stdout.write(
1971 " client: sending %r...\n" % indata)
1972 s.write(arg)
1973 outdata = s.read()
1974 if connectionchatty:
1975 if support.verbose:
1976 sys.stdout.write(" client: read %r\n" % outdata)
1977 if outdata != indata.lower():
1978 raise AssertionError(
1979 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1980 % (outdata[:20], len(outdata),
1981 indata[:20].lower(), len(indata)))
1982 s.write(b"over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001983 if connectionchatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001984 if support.verbose:
1985 sys.stdout.write(" client: closing connection.\n")
1986 stats.update({
1987 'compression': s.compression(),
1988 'cipher': s.cipher(),
1989 'peercert': s.getpeercert(),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001990 'client_alpn_protocol': s.selected_alpn_protocol(),
Alex Gaynore98205d2014-09-04 13:33:22 -07001991 'client_npn_protocol': s.selected_npn_protocol(),
1992 'version': s.version(),
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001993 })
1994 s.close()
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001995 stats['server_alpn_protocols'] = server.selected_alpn_protocols
1996 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001997 return stats
Bill Janssen98d19da2007-09-10 21:51:02 +00001998
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001999 def try_protocol_combo(server_protocol, client_protocol, expect_success,
2000 certsreqs=None, server_options=0, client_options=0):
Alex Gaynore98205d2014-09-04 13:33:22 -07002001 """
2002 Try to SSL-connect using *client_protocol* to *server_protocol*.
2003 If *expect_success* is true, assert that the connection succeeds,
2004 if it's false, assert that the connection fails.
2005 Also, if *expect_success* is a string, assert that it is the protocol
2006 version actually used by the connection.
2007 """
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00002008 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +00002009 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +00002010 certtype = {
2011 ssl.CERT_NONE: "CERT_NONE",
2012 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2013 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2014 }[certsreqs]
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002015 if support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002016 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +00002017 sys.stdout.write(formatstr %
2018 (ssl.get_protocol_name(client_protocol),
2019 ssl.get_protocol_name(server_protocol),
2020 certtype))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002021 client_context = ssl.SSLContext(client_protocol)
2022 client_context.options |= client_options
2023 server_context = ssl.SSLContext(server_protocol)
2024 server_context.options |= server_options
2025
2026 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2027 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2028 # starting from OpenSSL 1.0.0 (see issue #8322).
2029 if client_context.protocol == ssl.PROTOCOL_SSLv23:
2030 client_context.set_ciphers("ALL")
2031
2032 for ctx in (client_context, server_context):
2033 ctx.verify_mode = certsreqs
2034 ctx.load_cert_chain(CERTFILE)
2035 ctx.load_verify_locations(CERTFILE)
Bill Janssen98d19da2007-09-10 21:51:02 +00002036 try:
Alex Gaynore98205d2014-09-04 13:33:22 -07002037 stats = server_params_test(client_context, server_context,
2038 chatty=False, connectionchatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002039 # Protocol mismatch can result in either an SSLError, or a
2040 # "Connection reset by peer" error.
2041 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002042 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +00002043 raise
Antoine Pitroudb187842010-04-27 10:32:58 +00002044 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002045 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +00002046 raise
Bill Janssen98d19da2007-09-10 21:51:02 +00002047 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +00002048 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00002049 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +00002050 "Client protocol %s succeeded with server protocol %s!"
2051 % (ssl.get_protocol_name(client_protocol),
2052 ssl.get_protocol_name(server_protocol)))
Alex Gaynore98205d2014-09-04 13:33:22 -07002053 elif (expect_success is not True
2054 and expect_success != stats['version']):
2055 raise AssertionError("version mismatch: expected %r, got %r"
2056 % (expect_success, stats['version']))
Bill Janssen98d19da2007-09-10 21:51:02 +00002057
2058
Bill Janssen934b16d2008-06-28 22:19:33 +00002059 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +00002060
Antoine Pitroud75efd92010-08-04 17:38:33 +00002061 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002062 def test_echo(self):
2063 """Basic test of an SSL client connecting to a server"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002064 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002065 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002066 for protocol in PROTOCOLS:
2067 context = ssl.SSLContext(protocol)
2068 context.load_cert_chain(CERTFILE)
2069 server_params_test(context, context,
2070 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002071
Antoine Pitrou3945c862010-04-28 21:11:01 +00002072 def test_getpeercert(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002073 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002074 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002075 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2076 context.verify_mode = ssl.CERT_REQUIRED
2077 context.load_verify_locations(CERTFILE)
2078 context.load_cert_chain(CERTFILE)
2079 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002080 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002081 s = context.wrap_socket(socket.socket(),
2082 do_handshake_on_connect=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002083 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002084 # getpeercert() raise ValueError while the handshake isn't
2085 # done.
2086 with self.assertRaises(ValueError):
2087 s.getpeercert()
2088 s.do_handshake()
Antoine Pitroudb187842010-04-27 10:32:58 +00002089 cert = s.getpeercert()
2090 self.assertTrue(cert, "Can't get peer certificate.")
2091 cipher = s.cipher()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002092 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002093 sys.stdout.write(pprint.pformat(cert) + '\n')
2094 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2095 if 'subject' not in cert:
2096 self.fail("No subject field in certificate: %s." %
2097 pprint.pformat(cert))
2098 if ((('organizationName', 'Python Software Foundation'),)
2099 not in cert['subject']):
2100 self.fail(
2101 "Missing or invalid 'organizationName' field in certificate subject; "
2102 "should be 'Python Software Foundation'.")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002103 self.assertIn('notBefore', cert)
2104 self.assertIn('notAfter', cert)
2105 before = ssl.cert_time_to_seconds(cert['notBefore'])
2106 after = ssl.cert_time_to_seconds(cert['notAfter'])
2107 self.assertLess(before, after)
Antoine Pitroudb187842010-04-27 10:32:58 +00002108 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002109
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002110 @unittest.skipUnless(have_verify_flags(),
2111 "verify_flags need OpenSSL > 0.9.8")
2112 def test_crl_check(self):
2113 if support.verbose:
2114 sys.stdout.write("\n")
2115
2116 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2117 server_context.load_cert_chain(SIGNED_CERTFILE)
2118
2119 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2120 context.verify_mode = ssl.CERT_REQUIRED
2121 context.load_verify_locations(SIGNING_CA)
Benjamin Petersond86699f2015-03-04 23:18:48 -05002122 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2123 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002124
2125 # VERIFY_DEFAULT should pass
2126 server = ThreadedEchoServer(context=server_context, chatty=True)
2127 with server:
2128 with closing(context.wrap_socket(socket.socket())) as s:
2129 s.connect((HOST, server.port))
2130 cert = s.getpeercert()
2131 self.assertTrue(cert, "Can't get peer certificate.")
2132
2133 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
2134 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
2135
2136 server = ThreadedEchoServer(context=server_context, chatty=True)
2137 with server:
2138 with closing(context.wrap_socket(socket.socket())) as s:
2139 with self.assertRaisesRegexp(ssl.SSLError,
2140 "certificate verify failed"):
2141 s.connect((HOST, server.port))
2142
2143 # now load a CRL file. The CRL file is signed by the CA.
2144 context.load_verify_locations(CRLFILE)
2145
2146 server = ThreadedEchoServer(context=server_context, chatty=True)
2147 with server:
2148 with closing(context.wrap_socket(socket.socket())) as s:
2149 s.connect((HOST, server.port))
2150 cert = s.getpeercert()
2151 self.assertTrue(cert, "Can't get peer certificate.")
2152
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002153 def test_check_hostname(self):
2154 if support.verbose:
2155 sys.stdout.write("\n")
2156
2157 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2158 server_context.load_cert_chain(SIGNED_CERTFILE)
2159
2160 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2161 context.verify_mode = ssl.CERT_REQUIRED
2162 context.check_hostname = True
2163 context.load_verify_locations(SIGNING_CA)
2164
2165 # correct hostname should verify
2166 server = ThreadedEchoServer(context=server_context, chatty=True)
2167 with server:
2168 with closing(context.wrap_socket(socket.socket(),
2169 server_hostname="localhost")) as s:
2170 s.connect((HOST, server.port))
2171 cert = s.getpeercert()
2172 self.assertTrue(cert, "Can't get peer certificate.")
2173
2174 # incorrect hostname should raise an exception
2175 server = ThreadedEchoServer(context=server_context, chatty=True)
2176 with server:
2177 with closing(context.wrap_socket(socket.socket(),
2178 server_hostname="invalid")) as s:
2179 with self.assertRaisesRegexp(ssl.CertificateError,
2180 "hostname 'invalid' doesn't match u?'localhost'"):
2181 s.connect((HOST, server.port))
2182
2183 # missing server_hostname arg should cause an exception, too
2184 server = ThreadedEchoServer(context=server_context, chatty=True)
2185 with server:
2186 with closing(socket.socket()) as s:
2187 with self.assertRaisesRegexp(ValueError,
2188 "check_hostname requires server_hostname"):
2189 context.wrap_socket(s)
2190
Martin Panterfd8e8502016-01-30 02:36:00 +00002191 def test_wrong_cert(self):
Martin Panter886aba42016-02-01 21:58:11 +00002192 """Connecting when the server rejects the client's certificate
2193
2194 Launch a server with CERT_REQUIRED, and check that trying to
2195 connect to it with a wrong client certificate fails.
2196 """
2197 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
2198 "wrongcert.pem")
2199 server = ThreadedEchoServer(CERTFILE,
2200 certreqs=ssl.CERT_REQUIRED,
2201 cacerts=CERTFILE, chatty=False,
2202 connectionchatty=False)
2203 with server, \
2204 closing(socket.socket()) as sock, \
2205 closing(ssl.wrap_socket(sock,
2206 certfile=certfile,
2207 ssl_version=ssl.PROTOCOL_TLSv1)) as s:
2208 try:
2209 # Expect either an SSL error about the server rejecting
2210 # the connection, or a low-level connection reset (which
2211 # sometimes happens on Windows)
2212 s.connect((HOST, server.port))
2213 except ssl.SSLError as e:
2214 if support.verbose:
2215 sys.stdout.write("\nSSLError is %r\n" % e)
2216 except socket.error as e:
2217 if e.errno != errno.ECONNRESET:
2218 raise
2219 if support.verbose:
2220 sys.stdout.write("\nsocket.error is %r\n" % e)
2221 else:
2222 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +00002223
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002224 def test_rude_shutdown(self):
2225 """A brutal shutdown of an SSL server should raise an OSError
2226 in the client when attempting handshake.
2227 """
2228 listener_ready = threading.Event()
2229 listener_gone = threading.Event()
2230
2231 s = socket.socket()
2232 port = support.bind_port(s, HOST)
2233
2234 # `listener` runs in a thread. It sits in an accept() until
2235 # the main thread connects. Then it rudely closes the socket,
2236 # and sets Event `listener_gone` to let the main thread know
2237 # the socket is gone.
2238 def listener():
2239 s.listen(5)
2240 listener_ready.set()
2241 newsock, addr = s.accept()
2242 newsock.close()
2243 s.close()
2244 listener_gone.set()
2245
2246 def connector():
2247 listener_ready.wait()
2248 with closing(socket.socket()) as c:
2249 c.connect((HOST, port))
2250 listener_gone.wait()
2251 try:
2252 ssl_sock = ssl.wrap_socket(c)
Benjamin Petersone208b572014-08-20 14:49:08 -05002253 except socket.error:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002254 pass
2255 else:
2256 self.fail('connecting to closed SSL socket should have failed')
2257
2258 t = threading.Thread(target=listener)
2259 t.start()
2260 try:
2261 connector()
2262 finally:
2263 t.join()
2264
Antoine Pitroud75efd92010-08-04 17:38:33 +00002265 @skip_if_broken_ubuntu_ssl
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002266 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2267 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002268 def test_protocol_sslv2(self):
2269 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002270 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002271 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002272 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2273 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2274 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01002275 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002276 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2277 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002278 # SSLv23 client with specific SSL options
2279 if no_sslv2_implies_sslv3_hello():
2280 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2281 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2282 client_options=ssl.OP_NO_SSLv2)
2283 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2284 client_options=ssl.OP_NO_SSLv3)
2285 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2286 client_options=ssl.OP_NO_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00002287
Antoine Pitroud75efd92010-08-04 17:38:33 +00002288 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002289 def test_protocol_sslv23(self):
2290 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002291 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002292 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002293 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2294 try:
2295 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
2296 except socket.error as x:
2297 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2298 if support.verbose:
2299 sys.stdout.write(
2300 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2301 % str(x))
Benjamin Peterson60766c42014-12-05 21:59:35 -05002302 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002303 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002304 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Alex Gaynore98205d2014-09-04 13:33:22 -07002305 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Bill Janssen98d19da2007-09-10 21:51:02 +00002306
Benjamin Peterson60766c42014-12-05 21:59:35 -05002307 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002308 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002309 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Alex Gaynore98205d2014-09-04 13:33:22 -07002310 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00002311
Benjamin Peterson60766c42014-12-05 21:59:35 -05002312 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002313 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002314 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Alex Gaynore98205d2014-09-04 13:33:22 -07002315 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00002316
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002317 # Server with specific SSL options
Benjamin Peterson60766c42014-12-05 21:59:35 -05002318 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2319 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002320 server_options=ssl.OP_NO_SSLv3)
2321 # Will choose TLSv1
2322 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2323 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2324 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2325 server_options=ssl.OP_NO_TLSv1)
2326
2327
Antoine Pitroud75efd92010-08-04 17:38:33 +00002328 @skip_if_broken_ubuntu_ssl
Benjamin Peterson60766c42014-12-05 21:59:35 -05002329 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2330 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002331 def test_protocol_sslv3(self):
2332 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002333 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002334 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002335 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2336 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2337 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002338 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2339 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002340 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2341 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002342 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002343 if no_sslv2_implies_sslv3_hello():
2344 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002345 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2346 False, client_options=ssl.OP_NO_SSLv2)
Bill Janssen98d19da2007-09-10 21:51:02 +00002347
Antoine Pitroud75efd92010-08-04 17:38:33 +00002348 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002349 def test_protocol_tlsv1(self):
2350 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002351 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002352 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002353 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2354 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2355 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002356 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2357 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002358 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2359 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002360 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2361 client_options=ssl.OP_NO_TLSv1)
2362
2363 @skip_if_broken_ubuntu_ssl
2364 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2365 "TLS version 1.1 not supported.")
2366 def test_protocol_tlsv1_1(self):
2367 """Connecting to a TLSv1.1 server with various client options.
2368 Testing against older TLS versions."""
2369 if support.verbose:
2370 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002371 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002372 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2373 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002374 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2375 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002376 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2377 client_options=ssl.OP_NO_TLSv1_1)
2378
Alex Gaynore98205d2014-09-04 13:33:22 -07002379 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002380 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2381 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2382
2383
2384 @skip_if_broken_ubuntu_ssl
2385 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2386 "TLS version 1.2 not supported.")
2387 def test_protocol_tlsv1_2(self):
2388 """Connecting to a TLSv1.2 server with various client options.
2389 Testing against older TLS versions."""
2390 if support.verbose:
2391 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002392 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002393 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2394 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2395 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2396 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002397 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2398 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002399 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2400 client_options=ssl.OP_NO_TLSv1_2)
2401
Alex Gaynore98205d2014-09-04 13:33:22 -07002402 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002403 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2404 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2405 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2406 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00002407
Antoine Pitrou3945c862010-04-28 21:11:01 +00002408 def test_starttls(self):
2409 """Switching from clear text to encrypted and back again."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002410 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 +00002411
Trent Nelsone41b0062008-04-08 23:47:30 +00002412 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00002413 ssl_version=ssl.PROTOCOL_TLSv1,
2414 starttls_server=True,
2415 chatty=True,
2416 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002417 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002418 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002419 s = socket.socket()
2420 s.setblocking(1)
2421 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002422 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002423 sys.stdout.write("\n")
2424 for indata in msgs:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002425 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002426 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002427 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002428 if wrapped:
2429 conn.write(indata)
2430 outdata = conn.read()
2431 else:
2432 s.send(indata)
2433 outdata = s.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002434 msg = outdata.strip().lower()
2435 if indata == b"STARTTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002436 # STARTTLS ok, switch to secure mode
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002437 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002438 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002439 " client: read %r from server, starting TLS...\n"
2440 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002441 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2442 wrapped = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002443 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002444 # ENDTLS ok, switch back to clear text
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002445 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002446 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002447 " client: read %r from server, ending TLS...\n"
2448 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002449 s = conn.unwrap()
2450 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00002451 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002452 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002453 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002454 " client: read %r from server\n" % msg)
2455 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002456 sys.stdout.write(" client: closing connection.\n")
2457 if wrapped:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002458 conn.write(b"over\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00002459 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002460 s.send(b"over\n")
2461 if wrapped:
2462 conn.close()
2463 else:
2464 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002465
Antoine Pitrou3945c862010-04-28 21:11:01 +00002466 def test_socketserver(self):
2467 """Using a SocketServer to create and manage SSL connections."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002468 server = make_https_server(self, certfile=CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00002469 # try to connect
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002470 if support.verbose:
2471 sys.stdout.write('\n')
2472 with open(CERTFILE, 'rb') as f:
2473 d1 = f.read()
2474 d2 = ''
2475 # now fetch the same data from the HTTPS server
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -06002476 url = 'https://localhost:%d/%s' % (
2477 server.port, os.path.split(CERTFILE)[1])
2478 context = ssl.create_default_context(cafile=CERTFILE)
Benjamin Petersonb0609ec2014-11-23 11:52:46 -06002479 f = urllib2.urlopen(url, context=context)
Bill Janssen296a59d2007-09-16 22:06:00 +00002480 try:
Bill Janssen296a59d2007-09-16 22:06:00 +00002481 dlen = f.info().getheader("content-length")
2482 if dlen and (int(dlen) > 0):
2483 d2 = f.read(int(dlen))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002484 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002485 sys.stdout.write(
2486 " client: read %d bytes from remote server '%s'\n"
2487 % (len(d2), server))
Bill Janssen296a59d2007-09-16 22:06:00 +00002488 finally:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002489 f.close()
2490 self.assertEqual(d1, d2)
Bill Janssen934b16d2008-06-28 22:19:33 +00002491
Antoine Pitrou3945c862010-04-28 21:11:01 +00002492 def test_asyncore_server(self):
2493 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00002494 indata = "TEST MESSAGE of mixed case\n"
2495
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002496 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00002497 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002498
2499 indata = b"FOO\n"
Bill Janssen934b16d2008-06-28 22:19:33 +00002500 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002501 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002502 s = ssl.wrap_socket(socket.socket())
2503 s.connect(('127.0.0.1', server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002504 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002505 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002506 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002507 s.write(indata)
2508 outdata = s.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002509 if support.verbose:
2510 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002511 if outdata != indata.lower():
2512 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002513 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2514 % (outdata[:20], len(outdata),
2515 indata[:20].lower(), len(indata)))
2516 s.write(b"over\n")
2517 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002518 sys.stdout.write(" client: closing connection.\n")
2519 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002520 if support.verbose:
2521 sys.stdout.write(" client: connection closed.\n")
Bill Janssen934b16d2008-06-28 22:19:33 +00002522
Antoine Pitrou3945c862010-04-28 21:11:01 +00002523 def test_recv_send(self):
2524 """Test recv(), send() and friends."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002525 if support.verbose:
Bill Janssen61c001a2008-09-08 16:37:24 +00002526 sys.stdout.write("\n")
2527
2528 server = ThreadedEchoServer(CERTFILE,
2529 certreqs=ssl.CERT_NONE,
2530 ssl_version=ssl.PROTOCOL_TLSv1,
2531 cacerts=CERTFILE,
2532 chatty=True,
2533 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002534 with server:
2535 s = ssl.wrap_socket(socket.socket(),
2536 server_side=False,
2537 certfile=CERTFILE,
2538 ca_certs=CERTFILE,
2539 cert_reqs=ssl.CERT_NONE,
2540 ssl_version=ssl.PROTOCOL_TLSv1)
2541 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00002542 # helper methods for standardising recv* method signatures
2543 def _recv_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002544 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002545 count = s.recv_into(b)
2546 return b[:count]
2547
2548 def _recvfrom_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002549 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002550 count, addr = s.recvfrom_into(b)
2551 return b[:count]
2552
2553 # (name, method, whether to expect success, *args)
2554 send_methods = [
2555 ('send', s.send, True, []),
2556 ('sendto', s.sendto, False, ["some.address"]),
2557 ('sendall', s.sendall, True, []),
2558 ]
2559 recv_methods = [
2560 ('recv', s.recv, True, []),
2561 ('recvfrom', s.recvfrom, False, ["some.address"]),
2562 ('recv_into', _recv_into, True, []),
2563 ('recvfrom_into', _recvfrom_into, False, []),
2564 ]
2565 data_prefix = u"PREFIX_"
2566
2567 for meth_name, send_meth, expect_success, args in send_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002568 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002569 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002570 send_meth(indata, *args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002571 outdata = s.read()
Bill Janssen61c001a2008-09-08 16:37:24 +00002572 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002573 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002574 "While sending with <<{name:s}>> bad data "
2575 "<<{outdata:r}>> ({nout:d}) received; "
2576 "expected <<{indata:r}>> ({nin:d})\n".format(
2577 name=meth_name, outdata=outdata[:20],
2578 nout=len(outdata),
2579 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002580 )
2581 )
2582 except ValueError as e:
2583 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002584 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002585 "Failed to send with method <<{name:s}>>; "
2586 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002587 )
2588 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002589 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002590 "Method <<{name:s}>> failed with unexpected "
2591 "exception message: {exp:s}\n".format(
2592 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002593 )
2594 )
2595
2596 for meth_name, recv_meth, expect_success, args in recv_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002597 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002598 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002599 s.send(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002600 outdata = recv_meth(*args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002601 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002602 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002603 "While receiving with <<{name:s}>> bad data "
2604 "<<{outdata:r}>> ({nout:d}) received; "
2605 "expected <<{indata:r}>> ({nin:d})\n".format(
2606 name=meth_name, outdata=outdata[:20],
2607 nout=len(outdata),
2608 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002609 )
2610 )
2611 except ValueError as e:
2612 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002613 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002614 "Failed to receive with method <<{name:s}>>; "
2615 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002616 )
2617 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002618 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002619 "Method <<{name:s}>> failed with unexpected "
2620 "exception message: {exp:s}\n".format(
2621 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002622 )
2623 )
2624 # consume data
2625 s.read()
2626
Martin Panterd524b702016-03-28 00:22:09 +00002627 # read(-1, buffer) is supported, even though read(-1) is not
Martin Panter8c6849b2016-07-11 00:17:13 +00002628 data = b"data"
Martin Panterb8089b42016-03-27 05:35:19 +00002629 s.send(data)
2630 buffer = bytearray(len(data))
2631 self.assertEqual(s.read(-1, buffer), len(data))
2632 self.assertEqual(buffer, data)
2633
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002634 s.write(b"over\n")
Martin Panterb8089b42016-03-27 05:35:19 +00002635
2636 self.assertRaises(ValueError, s.recv, -1)
2637 self.assertRaises(ValueError, s.read, -1)
2638
Bill Janssen61c001a2008-09-08 16:37:24 +00002639 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00002640
Martin Panter8c6849b2016-07-11 00:17:13 +00002641 def test_recv_zero(self):
2642 server = ThreadedEchoServer(CERTFILE)
2643 server.__enter__()
2644 self.addCleanup(server.__exit__, None, None)
2645 s = socket.create_connection((HOST, server.port))
2646 self.addCleanup(s.close)
2647 s = ssl.wrap_socket(s, suppress_ragged_eofs=False)
2648 self.addCleanup(s.close)
2649
2650 # recv/read(0) should return no data
2651 s.send(b"data")
2652 self.assertEqual(s.recv(0), b"")
2653 self.assertEqual(s.read(0), b"")
2654 self.assertEqual(s.read(), b"data")
2655
2656 # Should not block if the other end sends no data
2657 s.setblocking(False)
2658 self.assertEqual(s.recv(0), b"")
2659 self.assertEqual(s.recv_into(bytearray()), 0)
2660
Antoine Pitroufc69af12010-04-24 20:04:58 +00002661 def test_handshake_timeout(self):
2662 # Issue #5103: SSL handshake must respect the socket timeout
2663 server = socket.socket(socket.AF_INET)
2664 host = "127.0.0.1"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002665 port = support.bind_port(server)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002666 started = threading.Event()
2667 finish = False
2668
2669 def serve():
2670 server.listen(5)
2671 started.set()
2672 conns = []
2673 while not finish:
2674 r, w, e = select.select([server], [], [], 0.1)
2675 if server in r:
2676 # Let the socket hang around rather than having
2677 # it closed by garbage collection.
2678 conns.append(server.accept()[0])
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002679 for sock in conns:
2680 sock.close()
Antoine Pitroufc69af12010-04-24 20:04:58 +00002681
2682 t = threading.Thread(target=serve)
2683 t.start()
2684 started.wait()
2685
2686 try:
2687 try:
2688 c = socket.socket(socket.AF_INET)
2689 c.settimeout(0.2)
2690 c.connect((host, port))
2691 # Will attempt handshake and time out
2692 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2693 ssl.wrap_socket, c)
2694 finally:
2695 c.close()
2696 try:
2697 c = socket.socket(socket.AF_INET)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002698 c = ssl.wrap_socket(c)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002699 c.settimeout(0.2)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002700 # Will attempt handshake and time out
2701 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2702 c.connect, (host, port))
2703 finally:
2704 c.close()
2705 finally:
2706 finish = True
2707 t.join()
2708 server.close()
2709
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002710 def test_server_accept(self):
2711 # Issue #16357: accept() on a SSLSocket created through
2712 # SSLContext.wrap_socket().
2713 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2714 context.verify_mode = ssl.CERT_REQUIRED
2715 context.load_verify_locations(CERTFILE)
2716 context.load_cert_chain(CERTFILE)
2717 server = socket.socket(socket.AF_INET)
2718 host = "127.0.0.1"
2719 port = support.bind_port(server)
2720 server = context.wrap_socket(server, server_side=True)
2721
2722 evt = threading.Event()
2723 remote = [None]
2724 peer = [None]
2725 def serve():
2726 server.listen(5)
2727 # Block on the accept and wait on the connection to close.
2728 evt.set()
2729 remote[0], peer[0] = server.accept()
2730 remote[0].recv(1)
2731
2732 t = threading.Thread(target=serve)
2733 t.start()
2734 # Client wait until server setup and perform a connect.
2735 evt.wait()
2736 client = context.wrap_socket(socket.socket())
2737 client.connect((host, port))
2738 client_addr = client.getsockname()
2739 client.close()
2740 t.join()
2741 remote[0].close()
2742 server.close()
2743 # Sanity checks.
2744 self.assertIsInstance(remote[0], ssl.SSLSocket)
2745 self.assertEqual(peer[0], client_addr)
2746
2747 def test_getpeercert_enotconn(self):
2748 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2749 with closing(context.wrap_socket(socket.socket())) as sock:
2750 with self.assertRaises(socket.error) as cm:
2751 sock.getpeercert()
2752 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2753
2754 def test_do_handshake_enotconn(self):
2755 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2756 with closing(context.wrap_socket(socket.socket())) as sock:
2757 with self.assertRaises(socket.error) as cm:
2758 sock.do_handshake()
2759 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2760
Antoine Pitroud76088d2012-01-03 22:46:48 +01002761 def test_default_ciphers(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002762 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2763 try:
2764 # Force a set of weak ciphers on our client context
2765 context.set_ciphers("DES")
2766 except ssl.SSLError:
2767 self.skipTest("no DES cipher available")
Antoine Pitroud76088d2012-01-03 22:46:48 +01002768 with ThreadedEchoServer(CERTFILE,
2769 ssl_version=ssl.PROTOCOL_SSLv23,
2770 chatty=False) as server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002771 with closing(context.wrap_socket(socket.socket())) as s:
2772 with self.assertRaises(ssl.SSLError):
Antoine Pitroud76088d2012-01-03 22:46:48 +01002773 s.connect((HOST, server.port))
Antoine Pitroud76088d2012-01-03 22:46:48 +01002774 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2775
Alex Gaynore98205d2014-09-04 13:33:22 -07002776 def test_version_basic(self):
2777 """
2778 Basic tests for SSLSocket.version().
2779 More tests are done in the test_protocol_*() methods.
2780 """
2781 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2782 with ThreadedEchoServer(CERTFILE,
2783 ssl_version=ssl.PROTOCOL_TLSv1,
2784 chatty=False) as server:
2785 with closing(context.wrap_socket(socket.socket())) as s:
2786 self.assertIs(s.version(), None)
2787 s.connect((HOST, server.port))
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002788 self.assertEqual(s.version(), 'TLSv1')
Alex Gaynore98205d2014-09-04 13:33:22 -07002789 self.assertIs(s.version(), None)
2790
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002791 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2792 def test_default_ecdh_curve(self):
2793 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2794 # should be enabled by default on SSL contexts.
2795 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2796 context.load_cert_chain(CERTFILE)
2797 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2798 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2799 # our default cipher list should prefer ECDH-based ciphers
2800 # automatically.
2801 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2802 context.set_ciphers("ECCdraft:ECDH")
2803 with ThreadedEchoServer(context=context) as server:
2804 with closing(context.wrap_socket(socket.socket())) as s:
2805 s.connect((HOST, server.port))
2806 self.assertIn("ECDH", s.cipher()[0])
2807
2808 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2809 "'tls-unique' channel binding not available")
2810 def test_tls_unique_channel_binding(self):
2811 """Test tls-unique channel binding."""
2812 if support.verbose:
2813 sys.stdout.write("\n")
2814
2815 server = ThreadedEchoServer(CERTFILE,
2816 certreqs=ssl.CERT_NONE,
2817 ssl_version=ssl.PROTOCOL_TLSv1,
2818 cacerts=CERTFILE,
2819 chatty=True,
2820 connectionchatty=False)
2821 with server:
2822 s = ssl.wrap_socket(socket.socket(),
2823 server_side=False,
2824 certfile=CERTFILE,
2825 ca_certs=CERTFILE,
2826 cert_reqs=ssl.CERT_NONE,
2827 ssl_version=ssl.PROTOCOL_TLSv1)
2828 s.connect((HOST, server.port))
2829 # get the data
2830 cb_data = s.get_channel_binding("tls-unique")
2831 if support.verbose:
2832 sys.stdout.write(" got channel binding data: {0!r}\n"
2833 .format(cb_data))
2834
2835 # check if it is sane
2836 self.assertIsNotNone(cb_data)
2837 self.assertEqual(len(cb_data), 12) # True for TLSv1
2838
2839 # and compare with the peers version
2840 s.write(b"CB tls-unique\n")
2841 peer_data_repr = s.read().strip()
2842 self.assertEqual(peer_data_repr,
2843 repr(cb_data).encode("us-ascii"))
2844 s.close()
2845
2846 # now, again
2847 s = ssl.wrap_socket(socket.socket(),
2848 server_side=False,
2849 certfile=CERTFILE,
2850 ca_certs=CERTFILE,
2851 cert_reqs=ssl.CERT_NONE,
2852 ssl_version=ssl.PROTOCOL_TLSv1)
2853 s.connect((HOST, server.port))
2854 new_cb_data = s.get_channel_binding("tls-unique")
2855 if support.verbose:
2856 sys.stdout.write(" got another channel binding data: {0!r}\n"
2857 .format(new_cb_data))
2858 # is it really unique
2859 self.assertNotEqual(cb_data, new_cb_data)
2860 self.assertIsNotNone(cb_data)
2861 self.assertEqual(len(cb_data), 12) # True for TLSv1
2862 s.write(b"CB tls-unique\n")
2863 peer_data_repr = s.read().strip()
2864 self.assertEqual(peer_data_repr,
2865 repr(new_cb_data).encode("us-ascii"))
2866 s.close()
2867
2868 def test_compression(self):
2869 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2870 context.load_cert_chain(CERTFILE)
2871 stats = server_params_test(context, context,
2872 chatty=True, connectionchatty=True)
2873 if support.verbose:
2874 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2875 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2876
2877 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2878 "ssl.OP_NO_COMPRESSION needed for this test")
2879 def test_compression_disabled(self):
2880 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2881 context.load_cert_chain(CERTFILE)
2882 context.options |= ssl.OP_NO_COMPRESSION
2883 stats = server_params_test(context, context,
2884 chatty=True, connectionchatty=True)
2885 self.assertIs(stats['compression'], None)
2886
2887 def test_dh_params(self):
2888 # Check we can get a connection with ephemeral Diffie-Hellman
2889 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2890 context.load_cert_chain(CERTFILE)
2891 context.load_dh_params(DHFILE)
2892 context.set_ciphers("kEDH")
2893 stats = server_params_test(context, context,
2894 chatty=True, connectionchatty=True)
2895 cipher = stats["cipher"][0]
2896 parts = cipher.split("-")
2897 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2898 self.fail("Non-DH cipher: " + cipher[0])
2899
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002900 def test_selected_alpn_protocol(self):
2901 # selected_alpn_protocol() is None unless ALPN is used.
2902 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2903 context.load_cert_chain(CERTFILE)
2904 stats = server_params_test(context, context,
2905 chatty=True, connectionchatty=True)
2906 self.assertIs(stats['client_alpn_protocol'], None)
2907
2908 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
2909 def test_selected_alpn_protocol_if_server_uses_alpn(self):
2910 # selected_alpn_protocol() is None unless ALPN is used by the client.
2911 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2912 client_context.load_verify_locations(CERTFILE)
2913 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2914 server_context.load_cert_chain(CERTFILE)
2915 server_context.set_alpn_protocols(['foo', 'bar'])
2916 stats = server_params_test(client_context, server_context,
2917 chatty=True, connectionchatty=True)
2918 self.assertIs(stats['client_alpn_protocol'], None)
2919
2920 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
2921 def test_alpn_protocols(self):
2922 server_protocols = ['foo', 'bar', 'milkshake']
2923 protocol_tests = [
2924 (['foo', 'bar'], 'foo'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002925 (['bar', 'foo'], 'foo'),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002926 (['milkshake'], 'milkshake'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002927 (['http/3.0', 'http/4.0'], None)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002928 ]
2929 for client_protocols, expected in protocol_tests:
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002930 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002931 server_context.load_cert_chain(CERTFILE)
2932 server_context.set_alpn_protocols(server_protocols)
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002933 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002934 client_context.load_cert_chain(CERTFILE)
2935 client_context.set_alpn_protocols(client_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002936
Christian Heimesc2fc7c42016-09-05 23:37:13 +02002937 try:
2938 stats = server_params_test(client_context,
2939 server_context,
2940 chatty=True,
2941 connectionchatty=True)
2942 except ssl.SSLError as e:
2943 stats = e
2944
2945 if expected is None and IS_OPENSSL_1_1:
2946 # OpenSSL 1.1.0 raises handshake error
2947 self.assertIsInstance(stats, ssl.SSLError)
2948 else:
2949 msg = "failed trying %s (s) and %s (c).\n" \
2950 "was expecting %s, but got %%s from the %%s" \
2951 % (str(server_protocols), str(client_protocols),
2952 str(expected))
2953 client_result = stats['client_alpn_protocol']
2954 self.assertEqual(client_result, expected,
2955 msg % (client_result, "client"))
2956 server_result = stats['server_alpn_protocols'][-1] \
2957 if len(stats['server_alpn_protocols']) else 'nothing'
2958 self.assertEqual(server_result, expected,
2959 msg % (server_result, "server"))
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002960
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002961 def test_selected_npn_protocol(self):
2962 # selected_npn_protocol() is None unless NPN is used
2963 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2964 context.load_cert_chain(CERTFILE)
2965 stats = server_params_test(context, context,
2966 chatty=True, connectionchatty=True)
2967 self.assertIs(stats['client_npn_protocol'], None)
2968
2969 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2970 def test_npn_protocols(self):
2971 server_protocols = ['http/1.1', 'spdy/2']
2972 protocol_tests = [
2973 (['http/1.1', 'spdy/2'], 'http/1.1'),
2974 (['spdy/2', 'http/1.1'], 'http/1.1'),
2975 (['spdy/2', 'test'], 'spdy/2'),
2976 (['abc', 'def'], 'abc')
2977 ]
2978 for client_protocols, expected in protocol_tests:
2979 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2980 server_context.load_cert_chain(CERTFILE)
2981 server_context.set_npn_protocols(server_protocols)
2982 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2983 client_context.load_cert_chain(CERTFILE)
2984 client_context.set_npn_protocols(client_protocols)
2985 stats = server_params_test(client_context, server_context,
2986 chatty=True, connectionchatty=True)
2987
2988 msg = "failed trying %s (s) and %s (c).\n" \
2989 "was expecting %s, but got %%s from the %%s" \
2990 % (str(server_protocols), str(client_protocols),
2991 str(expected))
2992 client_result = stats['client_npn_protocol']
2993 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2994 server_result = stats['server_npn_protocols'][-1] \
2995 if len(stats['server_npn_protocols']) else 'nothing'
2996 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2997
2998 def sni_contexts(self):
2999 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3000 server_context.load_cert_chain(SIGNED_CERTFILE)
3001 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3002 other_context.load_cert_chain(SIGNED_CERTFILE2)
3003 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3004 client_context.verify_mode = ssl.CERT_REQUIRED
3005 client_context.load_verify_locations(SIGNING_CA)
3006 return server_context, other_context, client_context
3007
3008 def check_common_name(self, stats, name):
3009 cert = stats['peercert']
3010 self.assertIn((('commonName', name),), cert['subject'])
3011
3012 @needs_sni
3013 def test_sni_callback(self):
3014 calls = []
3015 server_context, other_context, client_context = self.sni_contexts()
3016
3017 def servername_cb(ssl_sock, server_name, initial_context):
3018 calls.append((server_name, initial_context))
3019 if server_name is not None:
3020 ssl_sock.context = other_context
3021 server_context.set_servername_callback(servername_cb)
3022
3023 stats = server_params_test(client_context, server_context,
3024 chatty=True,
3025 sni_name='supermessage')
3026 # The hostname was fetched properly, and the certificate was
3027 # changed for the connection.
3028 self.assertEqual(calls, [("supermessage", server_context)])
3029 # CERTFILE4 was selected
3030 self.check_common_name(stats, 'fakehostname')
3031
3032 calls = []
3033 # The callback is called with server_name=None
3034 stats = server_params_test(client_context, server_context,
3035 chatty=True,
3036 sni_name=None)
3037 self.assertEqual(calls, [(None, server_context)])
3038 self.check_common_name(stats, 'localhost')
3039
3040 # Check disabling the callback
3041 calls = []
3042 server_context.set_servername_callback(None)
3043
3044 stats = server_params_test(client_context, server_context,
3045 chatty=True,
3046 sni_name='notfunny')
3047 # Certificate didn't change
3048 self.check_common_name(stats, 'localhost')
3049 self.assertEqual(calls, [])
3050
3051 @needs_sni
3052 def test_sni_callback_alert(self):
3053 # Returning a TLS alert is reflected to the connecting client
3054 server_context, other_context, client_context = self.sni_contexts()
3055
3056 def cb_returning_alert(ssl_sock, server_name, initial_context):
3057 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
3058 server_context.set_servername_callback(cb_returning_alert)
3059
3060 with self.assertRaises(ssl.SSLError) as cm:
3061 stats = server_params_test(client_context, server_context,
3062 chatty=False,
3063 sni_name='supermessage')
3064 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
3065
3066 @needs_sni
3067 def test_sni_callback_raising(self):
3068 # Raising fails the connection with a TLS handshake failure alert.
3069 server_context, other_context, client_context = self.sni_contexts()
3070
3071 def cb_raising(ssl_sock, server_name, initial_context):
Serhiy Storchaka5312a7f2015-01-31 11:27:06 +02003072 1.0/0.0
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003073 server_context.set_servername_callback(cb_raising)
3074
3075 with self.assertRaises(ssl.SSLError) as cm, \
3076 support.captured_stderr() as stderr:
3077 stats = server_params_test(client_context, server_context,
3078 chatty=False,
3079 sni_name='supermessage')
3080 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
3081 self.assertIn("ZeroDivisionError", stderr.getvalue())
3082
3083 @needs_sni
3084 def test_sni_callback_wrong_return_type(self):
3085 # Returning the wrong return type terminates the TLS connection
3086 # with an internal error alert.
3087 server_context, other_context, client_context = self.sni_contexts()
3088
3089 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
3090 return "foo"
3091 server_context.set_servername_callback(cb_wrong_return_type)
3092
3093 with self.assertRaises(ssl.SSLError) as cm, \
3094 support.captured_stderr() as stderr:
3095 stats = server_params_test(client_context, server_context,
3096 chatty=False,
3097 sni_name='supermessage')
3098 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
3099 self.assertIn("TypeError", stderr.getvalue())
3100
3101 def test_read_write_after_close_raises_valuerror(self):
3102 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3103 context.verify_mode = ssl.CERT_REQUIRED
3104 context.load_verify_locations(CERTFILE)
3105 context.load_cert_chain(CERTFILE)
3106 server = ThreadedEchoServer(context=context, chatty=False)
3107
3108 with server:
3109 s = context.wrap_socket(socket.socket())
3110 s.connect((HOST, server.port))
3111 s.close()
3112
3113 self.assertRaises(ValueError, s.read, 1024)
3114 self.assertRaises(ValueError, s.write, b'hello')
3115
Bill Janssen61c001a2008-09-08 16:37:24 +00003116
Neal Norwitz9eb9b102007-08-27 01:15:33 +00003117def test_main(verbose=False):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003118 if support.verbose:
3119 plats = {
3120 'Linux': platform.linux_distribution,
3121 'Mac': platform.mac_ver,
3122 'Windows': platform.win32_ver,
3123 }
3124 for name, func in plats.items():
3125 plat = func()
3126 if plat and plat[0]:
3127 plat = '%s %r' % (name, plat)
3128 break
3129 else:
3130 plat = repr(platform.platform())
3131 print("test_ssl: testing with %r %r" %
3132 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3133 print(" under %s" % plat)
3134 print(" HAS_SNI = %r" % ssl.HAS_SNI)
3135 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3136 try:
3137 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3138 except AttributeError:
3139 pass
Bill Janssen296a59d2007-09-16 22:06:00 +00003140
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003141 for filename in [
Martin Panter71202bb2016-01-15 00:25:29 +00003142 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003143 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
3144 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
3145 BADCERT, BADKEY, EMPTYCERT]:
3146 if not os.path.exists(filename):
3147 raise support.TestFailed("Can't read certificate file %r" % filename)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003148
Benjamin Peterson2f334562014-10-01 23:53:01 -04003149 tests = [ContextTests, BasicTests, BasicSocketTests, SSLErrorTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003150
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003151 if support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00003152 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00003153
Bill Janssen98d19da2007-09-10 21:51:02 +00003154 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003155 thread_info = support.threading_setup()
3156 if thread_info:
Bill Janssen934b16d2008-06-28 22:19:33 +00003157 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003158
Antoine Pitrou3945c862010-04-28 21:11:01 +00003159 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003160 support.run_unittest(*tests)
Antoine Pitrou3945c862010-04-28 21:11:01 +00003161 finally:
3162 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003163 support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003164
3165if __name__ == "__main__":
3166 test_main()