blob: e9723a75519c36be191de8e1287bb6a35f68c2d9 [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
Bill Janssen934b16d2008-06-28 22:19:33 +00007import asyncore
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00008import socket
Bill Janssen934b16d2008-06-28 22:19:33 +00009import select
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000010import time
Benjamin Petersondaeb9252014-08-20 14:14:50 -050011import datetime
Antoine Pitroub558f172010-04-23 23:25:45 +000012import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import os
Antoine Pitroub558f172010-04-23 23:25:45 +000014import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import pprint
Benjamin Petersondaeb9252014-08-20 14:14:50 -050016import tempfile
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -060017import urllib2
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000018import traceback
Antoine Pitroudfb299b2010-04-23 22:54:59 +000019import weakref
Antoine Pitroud75efd92010-08-04 17:38:33 +000020import platform
Benjamin Petersondaeb9252014-08-20 14:14:50 -050021import functools
22from contextlib import closing
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000023
Benjamin Petersondaeb9252014-08-20 14:14:50 -050024ssl = support.import_module("ssl")
Bill Janssen296a59d2007-09-16 22:06:00 +000025
Benjamin Petersondaeb9252014-08-20 14:14:50 -050026PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
27HOST = support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000028
Benjamin Petersondaeb9252014-08-20 14:14:50 -050029def data_file(*name):
30 return os.path.join(os.path.dirname(__file__), *name)
31
32# The custom key and certificate files used in test_ssl are generated
33# using Lib/test/make_ssl_certs.py.
34# Other certificates are simply fetched from the Internet servers they
35# are meant to authenticate.
36
37CERTFILE = data_file("keycert.pem")
38BYTES_CERTFILE = CERTFILE.encode(sys.getfilesystemencoding())
39ONLYCERT = data_file("ssl_cert.pem")
40ONLYKEY = data_file("ssl_key.pem")
41BYTES_ONLYCERT = ONLYCERT.encode(sys.getfilesystemencoding())
42BYTES_ONLYKEY = ONLYKEY.encode(sys.getfilesystemencoding())
43CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
44ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
45KEY_PASSWORD = "somepass"
46CAPATH = data_file("capath")
47BYTES_CAPATH = CAPATH.encode(sys.getfilesystemencoding())
48CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
49CAFILE_CACERT = data_file("capath", "5ed36f99.0")
50
51
52# empty CRL
53CRLFILE = data_file("revocation.crl")
54
55# Two keys and certs signed by the same CA (for SNI tests)
56SIGNED_CERTFILE = data_file("keycert3.pem")
57SIGNED_CERTFILE2 = data_file("keycert4.pem")
58SIGNING_CA = data_file("pycacert.pem")
59
Martin Panter71202bb2016-01-15 00:25:29 +000060REMOTE_HOST = "self-signed.pythontest.net"
61REMOTE_ROOT_CERT = data_file("selfsigned_pythontestdotnet.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050062
63EMPTYCERT = data_file("nullcert.pem")
64BADCERT = data_file("badcert.pem")
Martin Panterfd8e8502016-01-30 02:36:00 +000065NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050066BADKEY = data_file("badkey.pem")
67NOKIACERT = data_file("nokia.pem")
68NULLBYTECERT = data_file("nullbytecert.pem")
69
Benjamin Petersondf11d4c2015-04-02 00:04:06 -040070DHFILE = data_file("dh1024.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -050071BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding())
72
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000073
Neal Norwitz3e533c22007-08-27 01:03:18 +000074def handle_error(prefix):
75 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersondaeb9252014-08-20 14:14:50 -050076 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +000077 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000078
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000079
80class BasicTests(unittest.TestCase):
81
Antoine Pitrou3945c862010-04-28 21:11:01 +000082 def test_sslwrap_simple(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000083 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000084 try:
85 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
86 except IOError, e:
87 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
88 pass
89 else:
90 raise
91 try:
92 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
93 except IOError, e:
94 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
95 pass
96 else:
97 raise
Benjamin Peterson2f334562014-10-01 23:53:01 -040098
99
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500100def can_clear_options():
101 # 0.9.8m or higher
102 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
103
104def no_sslv2_implies_sslv3_hello():
105 # 0.9.7h or higher
106 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
107
108def have_verify_flags():
109 # 0.9.8 or higher
110 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
111
112def utc_offset(): #NOTE: ignore issues like #1647654
113 # local time = utc time + utc offset
114 if time.daylight and time.localtime().tm_isdst > 0:
115 return -time.altzone # seconds
116 return -time.timezone
117
118def asn1time(cert_time):
119 # Some versions of OpenSSL ignore seconds, see #18207
120 # 0.9.8.i
121 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
122 fmt = "%b %d %H:%M:%S %Y GMT"
123 dt = datetime.datetime.strptime(cert_time, fmt)
124 dt = dt.replace(second=0)
125 cert_time = dt.strftime(fmt)
126 # %d adds leading zero but ASN1_TIME_print() uses leading space
127 if cert_time[4] == "0":
128 cert_time = cert_time[:4] + " " + cert_time[5:]
129
130 return cert_time
Neal Norwitz3e533c22007-08-27 01:03:18 +0000131
Antoine Pitroud75efd92010-08-04 17:38:33 +0000132# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
133def skip_if_broken_ubuntu_ssl(func):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200134 if hasattr(ssl, 'PROTOCOL_SSLv2'):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200135 @functools.wraps(func)
136 def f(*args, **kwargs):
137 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500138 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
139 except ssl.SSLError:
Victor Stinnerb1241f92011-05-10 01:52:03 +0200140 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500141 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200142 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
143 return func(*args, **kwargs)
144 return f
145 else:
146 return func
Antoine Pitroud75efd92010-08-04 17:38:33 +0000147
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500148needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
149
Antoine Pitroud75efd92010-08-04 17:38:33 +0000150
151class BasicSocketTests(unittest.TestCase):
152
Antoine Pitrou3945c862010-04-28 21:11:01 +0000153 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000154 ssl.CERT_NONE
155 ssl.CERT_OPTIONAL
156 ssl.CERT_REQUIRED
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500157 ssl.OP_CIPHER_SERVER_PREFERENCE
158 ssl.OP_SINGLE_DH_USE
159 if ssl.HAS_ECDH:
160 ssl.OP_SINGLE_ECDH_USE
161 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
162 ssl.OP_NO_COMPRESSION
163 self.assertIn(ssl.HAS_SNI, {True, False})
164 self.assertIn(ssl.HAS_ECDH, {True, False})
165
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000166
Antoine Pitrou3945c862010-04-28 21:11:01 +0000167 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000168 v = ssl.RAND_status()
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500169 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000170 sys.stdout.write("\n RAND_status is %d (%s)\n"
171 % (v, (v and "sufficient randomness") or
172 "insufficient randomness"))
Victor Stinner7c906672015-01-06 13:53:37 +0100173 if hasattr(ssl, 'RAND_egd'):
174 self.assertRaises(TypeError, ssl.RAND_egd, 1)
175 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000176 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000177
Antoine Pitrou3945c862010-04-28 21:11:01 +0000178 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000179 # note that this uses an 'unofficial' function in _ssl.c,
180 # provided solely for this test, to exercise the certificate
181 # parsing code
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500182 p = ssl._ssl._test_decode_cert(CERTFILE)
183 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000184 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500185 self.assertEqual(p['issuer'],
186 ((('countryName', 'XY'),),
187 (('localityName', 'Castle Anthrax'),),
188 (('organizationName', 'Python Software Foundation'),),
189 (('commonName', 'localhost'),))
190 )
191 # Note the next three asserts will fail if the keys are regenerated
192 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
193 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
194 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200195 self.assertEqual(p['subject'],
Antoine Pitrou60982912013-02-16 21:39:28 +0100196 ((('countryName', 'XY'),),
197 (('localityName', 'Castle Anthrax'),),
198 (('organizationName', 'Python Software Foundation'),),
199 (('commonName', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200200 )
Antoine Pitrou60982912013-02-16 21:39:28 +0100201 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200202 # Issue #13034: the subjectAltName in some certificates
203 # (notably projects.developer.nokia.com:443) wasn't parsed
204 p = ssl._ssl._test_decode_cert(NOKIACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500205 if support.verbose:
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200206 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
207 self.assertEqual(p['subjectAltName'],
208 (('DNS', 'projects.developer.nokia.com'),
209 ('DNS', 'projects.forum.nokia.com'))
210 )
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500211 # extra OCSP and AIA fields
212 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
213 self.assertEqual(p['caIssuers'],
214 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
215 self.assertEqual(p['crlDistributionPoints'],
216 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000217
Christian Heimes88b174c2013-08-17 00:54:47 +0200218 def test_parse_cert_CVE_2013_4238(self):
219 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500220 if support.verbose:
Christian Heimes88b174c2013-08-17 00:54:47 +0200221 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
222 subject = ((('countryName', 'US'),),
223 (('stateOrProvinceName', 'Oregon'),),
224 (('localityName', 'Beaverton'),),
225 (('organizationName', 'Python Software Foundation'),),
226 (('organizationalUnitName', 'Python Core Development'),),
227 (('commonName', 'null.python.org\x00example.org'),),
228 (('emailAddress', 'python-dev@python.org'),))
229 self.assertEqual(p['subject'], subject)
230 self.assertEqual(p['issuer'], subject)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500231 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
Christian Heimesf869a942013-08-25 14:12:41 +0200232 san = (('DNS', 'altnull.python.org\x00example.com'),
233 ('email', 'null@python.org\x00user@example.org'),
234 ('URI', 'http://null.python.org\x00http://example.org'),
235 ('IP Address', '192.0.2.1'),
236 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
237 else:
238 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
239 san = (('DNS', 'altnull.python.org\x00example.com'),
240 ('email', 'null@python.org\x00user@example.org'),
241 ('URI', 'http://null.python.org\x00http://example.org'),
242 ('IP Address', '192.0.2.1'),
243 ('IP Address', '<invalid>'))
244
245 self.assertEqual(p['subjectAltName'], san)
Christian Heimes88b174c2013-08-17 00:54:47 +0200246
Antoine Pitrou3945c862010-04-28 21:11:01 +0000247 def test_DER_to_PEM(self):
Martin Panter71202bb2016-01-15 00:25:29 +0000248 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000249 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000250 d1 = ssl.PEM_cert_to_DER_cert(pem)
251 p2 = ssl.DER_cert_to_PEM_cert(d1)
252 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000253 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000254 if not p2.startswith(ssl.PEM_HEADER + '\n'):
255 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
256 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
257 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000258
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000259 def test_openssl_version(self):
260 n = ssl.OPENSSL_VERSION_NUMBER
261 t = ssl.OPENSSL_VERSION_INFO
262 s = ssl.OPENSSL_VERSION
263 self.assertIsInstance(n, (int, long))
264 self.assertIsInstance(t, tuple)
265 self.assertIsInstance(s, str)
266 # Some sanity checks follow
267 # >= 0.9
268 self.assertGreaterEqual(n, 0x900000)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400269 # < 3.0
270 self.assertLess(n, 0x30000000)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000271 major, minor, fix, patch, status = t
272 self.assertGreaterEqual(major, 0)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400273 self.assertLess(major, 3)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000274 self.assertGreaterEqual(minor, 0)
275 self.assertLess(minor, 256)
276 self.assertGreaterEqual(fix, 0)
277 self.assertLess(fix, 256)
278 self.assertGreaterEqual(patch, 0)
Ned Deilyfa119782015-02-05 17:19:11 +1100279 self.assertLessEqual(patch, 63)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000280 self.assertGreaterEqual(status, 0)
281 self.assertLessEqual(status, 15)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400282 # Version string as returned by {Open,Libre}SSL, the format might change
283 if "LibreSSL" in s:
284 self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
285 (s, t))
286 else:
287 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
288 (s, t))
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000289
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500290 @support.cpython_only
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000291 def test_refcycle(self):
292 # Issue #7943: an SSL object doesn't create reference cycles with
293 # itself.
294 s = socket.socket(socket.AF_INET)
295 ss = ssl.wrap_socket(s)
296 wr = weakref.ref(ss)
297 del ss
298 self.assertEqual(wr(), None)
299
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000300 def test_wrapped_unconnected(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500301 # Methods on an unconnected SSLSocket propagate the original
302 # socket.error raise by the underlying socket object.
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000303 s = socket.socket(socket.AF_INET)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500304 with closing(ssl.wrap_socket(s)) as ss:
305 self.assertRaises(socket.error, ss.recv, 1)
306 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
307 self.assertRaises(socket.error, ss.recvfrom, 1)
308 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
309 self.assertRaises(socket.error, ss.send, b'x')
310 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
311
312 def test_timeout(self):
313 # Issue #8524: when creating an SSL socket, the timeout of the
314 # original socket should be retained.
315 for timeout in (None, 0.0, 5.0):
316 s = socket.socket(socket.AF_INET)
317 s.settimeout(timeout)
318 with closing(ssl.wrap_socket(s)) as ss:
319 self.assertEqual(timeout, ss.gettimeout())
320
321 def test_errors(self):
322 sock = socket.socket()
323 self.assertRaisesRegexp(ValueError,
324 "certfile must be specified",
325 ssl.wrap_socket, sock, keyfile=CERTFILE)
326 self.assertRaisesRegexp(ValueError,
327 "certfile must be specified for server-side operations",
328 ssl.wrap_socket, sock, server_side=True)
329 self.assertRaisesRegexp(ValueError,
330 "certfile must be specified for server-side operations",
331 ssl.wrap_socket, sock, server_side=True, certfile="")
332 with closing(ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)) as s:
333 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
334 s.connect, (HOST, 8080))
335 with self.assertRaises(IOError) as cm:
336 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000337 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500338 self.assertEqual(cm.exception.errno, errno.ENOENT)
339 with self.assertRaises(IOError) as cm:
340 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000341 ssl.wrap_socket(sock,
342 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500343 self.assertEqual(cm.exception.errno, errno.ENOENT)
344 with self.assertRaises(IOError) as cm:
345 with closing(socket.socket()) as sock:
Martin Panterfd8e8502016-01-30 02:36:00 +0000346 ssl.wrap_socket(sock,
347 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500348 self.assertEqual(cm.exception.errno, errno.ENOENT)
349
Martin Panter886aba42016-02-01 21:58:11 +0000350 def bad_cert_test(self, certfile):
351 """Check that trying to use the given client certificate fails"""
352 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
353 certfile)
354 sock = socket.socket()
355 self.addCleanup(sock.close)
356 with self.assertRaises(ssl.SSLError):
357 ssl.wrap_socket(sock,
358 certfile=certfile,
359 ssl_version=ssl.PROTOCOL_TLSv1)
360
361 def test_empty_cert(self):
362 """Wrapping with an empty cert file"""
363 self.bad_cert_test("nullcert.pem")
364
365 def test_malformed_cert(self):
366 """Wrapping with a badly formatted certificate (syntax error)"""
367 self.bad_cert_test("badcert.pem")
368
369 def test_malformed_key(self):
370 """Wrapping with a badly formatted key (syntax error)"""
371 self.bad_cert_test("badkey.pem")
372
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500373 def test_match_hostname(self):
374 def ok(cert, hostname):
375 ssl.match_hostname(cert, hostname)
376 def fail(cert, hostname):
377 self.assertRaises(ssl.CertificateError,
378 ssl.match_hostname, cert, hostname)
379
380 cert = {'subject': ((('commonName', 'example.com'),),)}
381 ok(cert, 'example.com')
382 ok(cert, 'ExAmple.cOm')
383 fail(cert, 'www.example.com')
384 fail(cert, '.example.com')
385 fail(cert, 'example.org')
386 fail(cert, 'exampleXcom')
387
388 cert = {'subject': ((('commonName', '*.a.com'),),)}
389 ok(cert, 'foo.a.com')
390 fail(cert, 'bar.foo.a.com')
391 fail(cert, 'a.com')
392 fail(cert, 'Xa.com')
393 fail(cert, '.a.com')
394
395 # only match one left-most wildcard
396 cert = {'subject': ((('commonName', 'f*.com'),),)}
397 ok(cert, 'foo.com')
398 ok(cert, 'f.com')
399 fail(cert, 'bar.com')
400 fail(cert, 'foo.a.com')
401 fail(cert, 'bar.foo.com')
402
403 # NULL bytes are bad, CVE-2013-4073
404 cert = {'subject': ((('commonName',
405 'null.python.org\x00example.org'),),)}
406 ok(cert, 'null.python.org\x00example.org') # or raise an error?
407 fail(cert, 'example.org')
408 fail(cert, 'null.python.org')
409
410 # error cases with wildcards
411 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
412 fail(cert, 'bar.foo.a.com')
413 fail(cert, 'a.com')
414 fail(cert, 'Xa.com')
415 fail(cert, '.a.com')
416
417 cert = {'subject': ((('commonName', 'a.*.com'),),)}
418 fail(cert, 'a.foo.com')
419 fail(cert, 'a..com')
420 fail(cert, 'a.com')
421
422 # wildcard doesn't match IDNA prefix 'xn--'
423 idna = u'püthon.python.org'.encode("idna").decode("ascii")
424 cert = {'subject': ((('commonName', idna),),)}
425 ok(cert, idna)
426 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
427 fail(cert, idna)
428 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
429 fail(cert, idna)
430
431 # wildcard in first fragment and IDNA A-labels in sequent fragments
432 # are supported.
433 idna = u'www*.pythön.org'.encode("idna").decode("ascii")
434 cert = {'subject': ((('commonName', idna),),)}
435 ok(cert, u'www.pythön.org'.encode("idna").decode("ascii"))
436 ok(cert, u'www1.pythön.org'.encode("idna").decode("ascii"))
437 fail(cert, u'ftp.pythön.org'.encode("idna").decode("ascii"))
438 fail(cert, u'pythön.org'.encode("idna").decode("ascii"))
439
440 # Slightly fake real-world example
441 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
442 'subject': ((('commonName', 'linuxfrz.org'),),),
443 'subjectAltName': (('DNS', 'linuxfr.org'),
444 ('DNS', 'linuxfr.com'),
445 ('othername', '<unsupported>'))}
446 ok(cert, 'linuxfr.org')
447 ok(cert, 'linuxfr.com')
448 # Not a "DNS" entry
449 fail(cert, '<unsupported>')
450 # When there is a subjectAltName, commonName isn't used
451 fail(cert, 'linuxfrz.org')
452
453 # A pristine real-world example
454 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
455 'subject': ((('countryName', 'US'),),
456 (('stateOrProvinceName', 'California'),),
457 (('localityName', 'Mountain View'),),
458 (('organizationName', 'Google Inc'),),
459 (('commonName', 'mail.google.com'),))}
460 ok(cert, 'mail.google.com')
461 fail(cert, 'gmail.com')
462 # Only commonName is considered
463 fail(cert, 'California')
464
465 # Neither commonName nor subjectAltName
466 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
467 'subject': ((('countryName', 'US'),),
468 (('stateOrProvinceName', 'California'),),
469 (('localityName', 'Mountain View'),),
470 (('organizationName', 'Google Inc'),))}
471 fail(cert, 'mail.google.com')
472
473 # No DNS entry in subjectAltName but a commonName
474 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
475 'subject': ((('countryName', 'US'),),
476 (('stateOrProvinceName', 'California'),),
477 (('localityName', 'Mountain View'),),
478 (('commonName', 'mail.google.com'),)),
479 'subjectAltName': (('othername', 'blabla'), )}
480 ok(cert, 'mail.google.com')
481
482 # No DNS entry subjectAltName and no commonName
483 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
484 'subject': ((('countryName', 'US'),),
485 (('stateOrProvinceName', 'California'),),
486 (('localityName', 'Mountain View'),),
487 (('organizationName', 'Google Inc'),)),
488 'subjectAltName': (('othername', 'blabla'),)}
489 fail(cert, 'google.com')
490
491 # Empty cert / no cert
492 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
493 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
494
495 # Issue #17980: avoid denials of service by refusing more than one
496 # wildcard per fragment.
497 cert = {'subject': ((('commonName', 'a*b.com'),),)}
498 ok(cert, 'axxb.com')
499 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
500 fail(cert, 'axxb.com')
501 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
502 with self.assertRaises(ssl.CertificateError) as cm:
503 ssl.match_hostname(cert, 'axxbxxc.com')
504 self.assertIn("too many wildcards", str(cm.exception))
505
506 def test_server_side(self):
507 # server_hostname doesn't work for server sockets
508 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
509 with closing(socket.socket()) as sock:
510 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
511 server_hostname="some.hostname")
512
513 def test_unknown_channel_binding(self):
514 # should raise ValueError for unknown type
515 s = socket.socket(socket.AF_INET)
516 with closing(ssl.wrap_socket(s)) as ss:
517 with self.assertRaises(ValueError):
518 ss.get_channel_binding("unknown-type")
519
520 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
521 "'tls-unique' channel binding not available")
522 def test_tls_unique_channel_binding(self):
523 # unconnected should return None for known type
524 s = socket.socket(socket.AF_INET)
525 with closing(ssl.wrap_socket(s)) as ss:
526 self.assertIsNone(ss.get_channel_binding("tls-unique"))
527 # the same for server-side
528 s = socket.socket(socket.AF_INET)
529 with closing(ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)) as ss:
530 self.assertIsNone(ss.get_channel_binding("tls-unique"))
531
532 def test_get_default_verify_paths(self):
533 paths = ssl.get_default_verify_paths()
534 self.assertEqual(len(paths), 6)
535 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
536
537 with support.EnvironmentVarGuard() as env:
538 env["SSL_CERT_DIR"] = CAPATH
539 env["SSL_CERT_FILE"] = CERTFILE
540 paths = ssl.get_default_verify_paths()
541 self.assertEqual(paths.cafile, CERTFILE)
542 self.assertEqual(paths.capath, CAPATH)
543
544 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
545 def test_enum_certificates(self):
546 self.assertTrue(ssl.enum_certificates("CA"))
547 self.assertTrue(ssl.enum_certificates("ROOT"))
548
549 self.assertRaises(TypeError, ssl.enum_certificates)
550 self.assertRaises(WindowsError, ssl.enum_certificates, "")
551
552 trust_oids = set()
553 for storename in ("CA", "ROOT"):
554 store = ssl.enum_certificates(storename)
555 self.assertIsInstance(store, list)
556 for element in store:
557 self.assertIsInstance(element, tuple)
558 self.assertEqual(len(element), 3)
559 cert, enc, trust = element
560 self.assertIsInstance(cert, bytes)
561 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
562 self.assertIsInstance(trust, (set, bool))
563 if isinstance(trust, set):
564 trust_oids.update(trust)
565
566 serverAuth = "1.3.6.1.5.5.7.3.1"
567 self.assertIn(serverAuth, trust_oids)
568
569 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
570 def test_enum_crls(self):
571 self.assertTrue(ssl.enum_crls("CA"))
572 self.assertRaises(TypeError, ssl.enum_crls)
573 self.assertRaises(WindowsError, ssl.enum_crls, "")
574
575 crls = ssl.enum_crls("CA")
576 self.assertIsInstance(crls, list)
577 for element in crls:
578 self.assertIsInstance(element, tuple)
579 self.assertEqual(len(element), 2)
580 self.assertIsInstance(element[0], bytes)
581 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
582
583
584 def test_asn1object(self):
585 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
586 '1.3.6.1.5.5.7.3.1')
587
588 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
589 self.assertEqual(val, expected)
590 self.assertEqual(val.nid, 129)
591 self.assertEqual(val.shortname, 'serverAuth')
592 self.assertEqual(val.longname, 'TLS Web Server Authentication')
593 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
594 self.assertIsInstance(val, ssl._ASN1Object)
595 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
596
597 val = ssl._ASN1Object.fromnid(129)
598 self.assertEqual(val, expected)
599 self.assertIsInstance(val, ssl._ASN1Object)
600 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
601 with self.assertRaisesRegexp(ValueError, "unknown NID 100000"):
602 ssl._ASN1Object.fromnid(100000)
603 for i in range(1000):
604 try:
605 obj = ssl._ASN1Object.fromnid(i)
606 except ValueError:
607 pass
608 else:
609 self.assertIsInstance(obj.nid, int)
610 self.assertIsInstance(obj.shortname, str)
611 self.assertIsInstance(obj.longname, str)
612 self.assertIsInstance(obj.oid, (str, type(None)))
613
614 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
615 self.assertEqual(val, expected)
616 self.assertIsInstance(val, ssl._ASN1Object)
617 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
618 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
619 expected)
620 with self.assertRaisesRegexp(ValueError, "unknown object 'serverauth'"):
621 ssl._ASN1Object.fromname('serverauth')
622
623 def test_purpose_enum(self):
624 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
625 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
626 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
627 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
628 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
629 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
630 '1.3.6.1.5.5.7.3.1')
631
632 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
633 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
634 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
635 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
636 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
637 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
638 '1.3.6.1.5.5.7.3.2')
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000639
Antoine Pitrou63cc99d2013-12-28 17:26:33 +0100640 def test_unsupported_dtls(self):
641 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
642 self.addCleanup(s.close)
643 with self.assertRaises(NotImplementedError) as cx:
644 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
645 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500646 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
647 with self.assertRaises(NotImplementedError) as cx:
648 ctx.wrap_socket(s)
649 self.assertEqual(str(cx.exception), "only stream sockets are supported")
650
651 def cert_time_ok(self, timestring, timestamp):
652 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
653
654 def cert_time_fail(self, timestring):
655 with self.assertRaises(ValueError):
656 ssl.cert_time_to_seconds(timestring)
657
658 @unittest.skipUnless(utc_offset(),
659 'local time needs to be different from UTC')
660 def test_cert_time_to_seconds_timezone(self):
661 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
662 # results if local timezone is not UTC
663 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
664 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
665
666 def test_cert_time_to_seconds(self):
667 timestring = "Jan 5 09:34:43 2018 GMT"
668 ts = 1515144883.0
669 self.cert_time_ok(timestring, ts)
670 # accept keyword parameter, assert its name
671 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
672 # accept both %e and %d (space or zero generated by strftime)
673 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
674 # case-insensitive
675 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
676 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
677 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
678 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
679 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
680 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
681 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
682 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
683
684 newyear_ts = 1230768000.0
685 # leap seconds
686 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
687 # same timestamp
688 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
689
690 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
691 # allow 60th second (even if it is not a leap second)
692 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
693 # allow 2nd leap second for compatibility with time.strptime()
694 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
695 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
696
697 # no special treatement for the special value:
698 # 99991231235959Z (rfc 5280)
699 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
700
701 @support.run_with_locale('LC_ALL', '')
702 def test_cert_time_to_seconds_locale(self):
703 # `cert_time_to_seconds()` should be locale independent
704
705 def local_february_name():
706 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
707
708 if local_february_name().lower() == 'feb':
709 self.skipTest("locale-specific month name needs to be "
710 "different from C locale")
711
712 # locale-independent
713 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
714 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
715
716
717class ContextTests(unittest.TestCase):
718
719 @skip_if_broken_ubuntu_ssl
720 def test_constructor(self):
721 for protocol in PROTOCOLS:
722 ssl.SSLContext(protocol)
723 self.assertRaises(TypeError, ssl.SSLContext)
724 self.assertRaises(ValueError, ssl.SSLContext, -1)
725 self.assertRaises(ValueError, ssl.SSLContext, 42)
726
727 @skip_if_broken_ubuntu_ssl
728 def test_protocol(self):
729 for proto in PROTOCOLS:
730 ctx = ssl.SSLContext(proto)
731 self.assertEqual(ctx.protocol, proto)
732
733 def test_ciphers(self):
734 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
735 ctx.set_ciphers("ALL")
736 ctx.set_ciphers("DEFAULT")
737 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
738 ctx.set_ciphers("^$:,;?*'dorothyx")
739
740 @skip_if_broken_ubuntu_ssl
741 def test_options(self):
742 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800743 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500744 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
745 ctx.options)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800746 ctx.options |= ssl.OP_NO_TLSv1
747 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1,
748 ctx.options)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500749 if can_clear_options():
750 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
751 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
752 ctx.options)
753 ctx.options = 0
754 self.assertEqual(0, ctx.options)
755 else:
756 with self.assertRaises(ValueError):
757 ctx.options = 0
758
759 def test_verify_mode(self):
760 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
761 # Default value
762 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
763 ctx.verify_mode = ssl.CERT_OPTIONAL
764 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
765 ctx.verify_mode = ssl.CERT_REQUIRED
766 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
767 ctx.verify_mode = ssl.CERT_NONE
768 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
769 with self.assertRaises(TypeError):
770 ctx.verify_mode = None
771 with self.assertRaises(ValueError):
772 ctx.verify_mode = 42
773
774 @unittest.skipUnless(have_verify_flags(),
775 "verify_flags need OpenSSL > 0.9.8")
776 def test_verify_flags(self):
777 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson72ef9612015-03-04 22:49:41 -0500778 # default value
779 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
780 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500781 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
782 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
783 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
784 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
785 ctx.verify_flags = ssl.VERIFY_DEFAULT
786 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
787 # supports any value
788 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
789 self.assertEqual(ctx.verify_flags,
790 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
791 with self.assertRaises(TypeError):
792 ctx.verify_flags = None
793
794 def test_load_cert_chain(self):
795 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
796 # Combined key and cert in a single file
Benjamin Peterson04439fd2014-11-03 21:05:01 -0500797 ctx.load_cert_chain(CERTFILE, keyfile=None)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500798 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
799 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
800 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000801 ctx.load_cert_chain(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500802 self.assertEqual(cm.exception.errno, errno.ENOENT)
803 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
804 ctx.load_cert_chain(BADCERT)
805 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
806 ctx.load_cert_chain(EMPTYCERT)
807 # Separate key and cert
808 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
809 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
810 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
811 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
812 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
813 ctx.load_cert_chain(ONLYCERT)
814 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
815 ctx.load_cert_chain(ONLYKEY)
816 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
817 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
818 # Mismatching key and cert
819 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
820 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Martin Panter71202bb2016-01-15 00:25:29 +0000821 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500822 # Password protected key and cert
823 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
824 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
825 ctx.load_cert_chain(CERTFILE_PROTECTED,
826 password=bytearray(KEY_PASSWORD.encode()))
827 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
828 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
829 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
830 bytearray(KEY_PASSWORD.encode()))
831 with self.assertRaisesRegexp(TypeError, "should be a string"):
832 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
833 with self.assertRaises(ssl.SSLError):
834 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
835 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
836 # openssl has a fixed limit on the password buffer.
837 # PEM_BUFSIZE is generally set to 1kb.
838 # Return a string larger than this.
839 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
840 # Password callback
841 def getpass_unicode():
842 return KEY_PASSWORD
843 def getpass_bytes():
844 return KEY_PASSWORD.encode()
845 def getpass_bytearray():
846 return bytearray(KEY_PASSWORD.encode())
847 def getpass_badpass():
848 return "badpass"
849 def getpass_huge():
850 return b'a' * (1024 * 1024)
851 def getpass_bad_type():
852 return 9
853 def getpass_exception():
854 raise Exception('getpass error')
855 class GetPassCallable:
856 def __call__(self):
857 return KEY_PASSWORD
858 def getpass(self):
859 return KEY_PASSWORD
860 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
861 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
862 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
863 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
864 ctx.load_cert_chain(CERTFILE_PROTECTED,
865 password=GetPassCallable().getpass)
866 with self.assertRaises(ssl.SSLError):
867 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
868 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
869 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
870 with self.assertRaisesRegexp(TypeError, "must return a string"):
871 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
872 with self.assertRaisesRegexp(Exception, "getpass error"):
873 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
874 # Make sure the password function isn't called if it isn't needed
875 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
876
877 def test_load_verify_locations(self):
878 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
879 ctx.load_verify_locations(CERTFILE)
880 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
881 ctx.load_verify_locations(BYTES_CERTFILE)
882 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400883 ctx.load_verify_locations(cafile=BYTES_CERTFILE.decode('utf-8'))
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500884 self.assertRaises(TypeError, ctx.load_verify_locations)
885 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
886 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000887 ctx.load_verify_locations(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500888 self.assertEqual(cm.exception.errno, errno.ENOENT)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400889 with self.assertRaises(IOError):
890 ctx.load_verify_locations(u'')
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500891 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
892 ctx.load_verify_locations(BADCERT)
893 ctx.load_verify_locations(CERTFILE, CAPATH)
894 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
895
896 # Issue #10989: crash if the second argument type is invalid
897 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
898
899 def test_load_verify_cadata(self):
900 # test cadata
901 with open(CAFILE_CACERT) as f:
902 cacert_pem = f.read().decode("ascii")
903 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
904 with open(CAFILE_NEURONIO) as f:
905 neuronio_pem = f.read().decode("ascii")
906 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
907
908 # test PEM
909 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
910 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
911 ctx.load_verify_locations(cadata=cacert_pem)
912 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
913 ctx.load_verify_locations(cadata=neuronio_pem)
914 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
915 # cert already in hash table
916 ctx.load_verify_locations(cadata=neuronio_pem)
917 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
918
919 # combined
920 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
921 combined = "\n".join((cacert_pem, neuronio_pem))
922 ctx.load_verify_locations(cadata=combined)
923 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
924
925 # with junk around the certs
926 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
927 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
928 neuronio_pem, "tail"]
929 ctx.load_verify_locations(cadata="\n".join(combined))
930 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
931
932 # test DER
933 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
934 ctx.load_verify_locations(cadata=cacert_der)
935 ctx.load_verify_locations(cadata=neuronio_der)
936 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
937 # cert already in hash table
938 ctx.load_verify_locations(cadata=cacert_der)
939 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
940
941 # combined
942 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
943 combined = b"".join((cacert_der, neuronio_der))
944 ctx.load_verify_locations(cadata=combined)
945 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
946
947 # error cases
948 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
949 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
950
951 with self.assertRaisesRegexp(ssl.SSLError, "no start line"):
952 ctx.load_verify_locations(cadata=u"broken")
953 with self.assertRaisesRegexp(ssl.SSLError, "not enough data"):
954 ctx.load_verify_locations(cadata=b"broken")
955
956
957 def test_load_dh_params(self):
958 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
959 ctx.load_dh_params(DHFILE)
960 if os.name != 'nt':
961 ctx.load_dh_params(BYTES_DHFILE)
962 self.assertRaises(TypeError, ctx.load_dh_params)
963 self.assertRaises(TypeError, ctx.load_dh_params, None)
964 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000965 ctx.load_dh_params(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500966 self.assertEqual(cm.exception.errno, errno.ENOENT)
967 with self.assertRaises(ssl.SSLError) as cm:
968 ctx.load_dh_params(CERTFILE)
969
970 @skip_if_broken_ubuntu_ssl
971 def test_session_stats(self):
972 for proto in PROTOCOLS:
973 ctx = ssl.SSLContext(proto)
974 self.assertEqual(ctx.session_stats(), {
975 'number': 0,
976 'connect': 0,
977 'connect_good': 0,
978 'connect_renegotiate': 0,
979 'accept': 0,
980 'accept_good': 0,
981 'accept_renegotiate': 0,
982 'hits': 0,
983 'misses': 0,
984 'timeouts': 0,
985 'cache_full': 0,
986 })
987
988 def test_set_default_verify_paths(self):
989 # There's not much we can do to test that it acts as expected,
990 # so just check it doesn't crash or raise an exception.
991 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
992 ctx.set_default_verify_paths()
993
994 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
995 def test_set_ecdh_curve(self):
996 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
997 ctx.set_ecdh_curve("prime256v1")
998 ctx.set_ecdh_curve(b"prime256v1")
999 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1000 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1001 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1002 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1003
1004 @needs_sni
1005 def test_sni_callback(self):
1006 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1007
1008 # set_servername_callback expects a callable, or None
1009 self.assertRaises(TypeError, ctx.set_servername_callback)
1010 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1011 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1012 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1013
1014 def dummycallback(sock, servername, ctx):
1015 pass
1016 ctx.set_servername_callback(None)
1017 ctx.set_servername_callback(dummycallback)
1018
1019 @needs_sni
1020 def test_sni_callback_refcycle(self):
1021 # Reference cycles through the servername callback are detected
1022 # and cleared.
1023 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1024 def dummycallback(sock, servername, ctx, cycle=ctx):
1025 pass
1026 ctx.set_servername_callback(dummycallback)
1027 wr = weakref.ref(ctx)
1028 del ctx, dummycallback
1029 gc.collect()
1030 self.assertIs(wr(), None)
1031
1032 def test_cert_store_stats(self):
1033 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1034 self.assertEqual(ctx.cert_store_stats(),
1035 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1036 ctx.load_cert_chain(CERTFILE)
1037 self.assertEqual(ctx.cert_store_stats(),
1038 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1039 ctx.load_verify_locations(CERTFILE)
1040 self.assertEqual(ctx.cert_store_stats(),
1041 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panter71202bb2016-01-15 00:25:29 +00001042 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001043 self.assertEqual(ctx.cert_store_stats(),
1044 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1045
1046 def test_get_ca_certs(self):
1047 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1048 self.assertEqual(ctx.get_ca_certs(), [])
1049 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1050 ctx.load_verify_locations(CERTFILE)
1051 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panter71202bb2016-01-15 00:25:29 +00001052 # but CAFILE_CACERT is a CA cert
1053 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001054 self.assertEqual(ctx.get_ca_certs(),
1055 [{'issuer': ((('organizationName', 'Root CA'),),
1056 (('organizationalUnitName', 'http://www.cacert.org'),),
1057 (('commonName', 'CA Cert Signing Authority'),),
1058 (('emailAddress', 'support@cacert.org'),)),
1059 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1060 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1061 'serialNumber': '00',
1062 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
1063 'subject': ((('organizationName', 'Root CA'),),
1064 (('organizationalUnitName', 'http://www.cacert.org'),),
1065 (('commonName', 'CA Cert Signing Authority'),),
1066 (('emailAddress', 'support@cacert.org'),)),
1067 'version': 3}])
1068
Martin Panter71202bb2016-01-15 00:25:29 +00001069 with open(CAFILE_CACERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001070 pem = f.read()
1071 der = ssl.PEM_cert_to_DER_cert(pem)
1072 self.assertEqual(ctx.get_ca_certs(True), [der])
1073
1074 def test_load_default_certs(self):
1075 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1076 ctx.load_default_certs()
1077
1078 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1079 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1080 ctx.load_default_certs()
1081
1082 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1083 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1084
1085 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1086 self.assertRaises(TypeError, ctx.load_default_certs, None)
1087 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1088
Benjamin Petersona02ae252014-10-03 18:17:15 -04001089 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson0b30a2b2014-10-03 17:27:05 -04001090 def test_load_default_certs_env(self):
1091 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1092 with support.EnvironmentVarGuard() as env:
1093 env["SSL_CERT_DIR"] = CAPATH
1094 env["SSL_CERT_FILE"] = CERTFILE
1095 ctx.load_default_certs()
1096 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1097
Benjamin Petersona02ae252014-10-03 18:17:15 -04001098 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1099 def test_load_default_certs_env_windows(self):
1100 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1101 ctx.load_default_certs()
1102 stats = ctx.cert_store_stats()
1103
1104 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1105 with support.EnvironmentVarGuard() as env:
1106 env["SSL_CERT_DIR"] = CAPATH
1107 env["SSL_CERT_FILE"] = CERTFILE
1108 ctx.load_default_certs()
1109 stats["x509"] += 1
1110 self.assertEqual(ctx.cert_store_stats(), stats)
1111
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001112 def test_create_default_context(self):
1113 ctx = ssl.create_default_context()
1114 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1115 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1116 self.assertTrue(ctx.check_hostname)
1117 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1118 self.assertEqual(
1119 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1120 getattr(ssl, "OP_NO_COMPRESSION", 0),
1121 )
1122
1123 with open(SIGNING_CA) as f:
1124 cadata = f.read().decode("ascii")
1125 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1126 cadata=cadata)
1127 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1128 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1129 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1130 self.assertEqual(
1131 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1132 getattr(ssl, "OP_NO_COMPRESSION", 0),
1133 )
1134
1135 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
1136 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1137 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1138 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1139 self.assertEqual(
1140 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1141 getattr(ssl, "OP_NO_COMPRESSION", 0),
1142 )
1143 self.assertEqual(
1144 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1145 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1146 )
1147 self.assertEqual(
1148 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1149 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1150 )
1151
1152 def test__create_stdlib_context(self):
1153 ctx = ssl._create_stdlib_context()
1154 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1155 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1156 self.assertFalse(ctx.check_hostname)
1157 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1158
1159 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1160 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1161 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1162 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1163
1164 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
1165 cert_reqs=ssl.CERT_REQUIRED,
1166 check_hostname=True)
1167 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1168 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1169 self.assertTrue(ctx.check_hostname)
1170 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1171
1172 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1173 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1174 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1175 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1176
1177 def test_check_hostname(self):
1178 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1179 self.assertFalse(ctx.check_hostname)
1180
1181 # Requires CERT_REQUIRED or CERT_OPTIONAL
1182 with self.assertRaises(ValueError):
1183 ctx.check_hostname = True
1184 ctx.verify_mode = ssl.CERT_REQUIRED
1185 self.assertFalse(ctx.check_hostname)
1186 ctx.check_hostname = True
1187 self.assertTrue(ctx.check_hostname)
1188
1189 ctx.verify_mode = ssl.CERT_OPTIONAL
1190 ctx.check_hostname = True
1191 self.assertTrue(ctx.check_hostname)
1192
1193 # Cannot set CERT_NONE with check_hostname enabled
1194 with self.assertRaises(ValueError):
1195 ctx.verify_mode = ssl.CERT_NONE
1196 ctx.check_hostname = False
1197 self.assertFalse(ctx.check_hostname)
1198
1199
1200class SSLErrorTests(unittest.TestCase):
1201
1202 def test_str(self):
1203 # The str() of a SSLError doesn't include the errno
1204 e = ssl.SSLError(1, "foo")
1205 self.assertEqual(str(e), "foo")
1206 self.assertEqual(e.errno, 1)
1207 # Same for a subclass
1208 e = ssl.SSLZeroReturnError(1, "foo")
1209 self.assertEqual(str(e), "foo")
1210 self.assertEqual(e.errno, 1)
1211
1212 def test_lib_reason(self):
1213 # Test the library and reason attributes
1214 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1215 with self.assertRaises(ssl.SSLError) as cm:
1216 ctx.load_dh_params(CERTFILE)
1217 self.assertEqual(cm.exception.library, 'PEM')
1218 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1219 s = str(cm.exception)
1220 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1221
1222 def test_subclass(self):
1223 # Check that the appropriate SSLError subclass is raised
1224 # (this only tests one of them)
1225 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1226 with closing(socket.socket()) as s:
1227 s.bind(("127.0.0.1", 0))
1228 s.listen(5)
1229 c = socket.socket()
1230 c.connect(s.getsockname())
1231 c.setblocking(False)
1232 with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c:
1233 with self.assertRaises(ssl.SSLWantReadError) as cm:
1234 c.do_handshake()
1235 s = str(cm.exception)
1236 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1237 # For compatibility
1238 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
Antoine Pitrou63cc99d2013-12-28 17:26:33 +01001239
Antoine Pitrouf9de5342010-04-05 21:35:07 +00001240
Bill Janssen934b16d2008-06-28 22:19:33 +00001241class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +00001242
Antoine Pitrou3945c862010-04-28 21:11:01 +00001243 def test_connect(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001244 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001245 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1246 cert_reqs=ssl.CERT_NONE)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001247 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001248 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001249 self.assertEqual({}, s.getpeercert())
1250 finally:
1251 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001252
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001253 # this should fail because we have no verification certs
1254 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1255 cert_reqs=ssl.CERT_REQUIRED)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001256 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001257 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001258 s.close()
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001259
1260 # this should succeed because we specify the root cert
1261 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1262 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001263 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001264 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001265 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001266 self.assertTrue(s.getpeercert())
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001267 finally:
1268 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001269
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001270 def test_connect_ex(self):
1271 # Issue #11326: check connect_ex() implementation
Martin Panter71202bb2016-01-15 00:25:29 +00001272 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001273 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1274 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001275 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001276 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001277 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001278 self.assertTrue(s.getpeercert())
1279 finally:
1280 s.close()
1281
1282 def test_non_blocking_connect_ex(self):
1283 # Issue #11326: non-blocking connect_ex() should allow handshake
1284 # to proceed after the socket gets ready.
Martin Panter71202bb2016-01-15 00:25:29 +00001285 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001286 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1287 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001288 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001289 do_handshake_on_connect=False)
1290 try:
1291 s.setblocking(False)
Martin Panter71202bb2016-01-15 00:25:29 +00001292 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +00001293 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1294 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001295 # Wait for connect to finish
1296 select.select([], [s], [], 5.0)
1297 # Non-blocking handshake
1298 while True:
1299 try:
1300 s.do_handshake()
1301 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001302 except ssl.SSLWantReadError:
1303 select.select([s], [], [], 5.0)
1304 except ssl.SSLWantWriteError:
1305 select.select([], [s], [], 5.0)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001306 # SSL established
1307 self.assertTrue(s.getpeercert())
1308 finally:
1309 s.close()
1310
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001311 def test_timeout_connect_ex(self):
1312 # Issue #12065: on a timeout, connect_ex() should return the original
1313 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter71202bb2016-01-15 00:25:29 +00001314 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001315 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1316 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001317 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001318 do_handshake_on_connect=False)
1319 try:
1320 s.settimeout(0.0000001)
Martin Panter71202bb2016-01-15 00:25:29 +00001321 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001322 if rc == 0:
Martin Panter71202bb2016-01-15 00:25:29 +00001323 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001324 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1325 finally:
1326 s.close()
1327
1328 def test_connect_ex_error(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001329 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001330 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1331 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001332 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001333 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001334 rc = s.connect_ex((REMOTE_HOST, 444))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001335 # Issue #19919: Windows machines or VMs hosted on Windows
1336 # machines sometimes return EWOULDBLOCK.
Martin Panter71202bb2016-01-15 00:25:29 +00001337 errors = (
1338 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1339 errno.EWOULDBLOCK,
1340 )
1341 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001342 finally:
1343 s.close()
1344
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001345 def test_connect_with_context(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001346 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001347 # Same as test_connect, but with a separately created context
1348 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1349 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001350 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001351 try:
1352 self.assertEqual({}, s.getpeercert())
1353 finally:
1354 s.close()
1355 # Same with a server hostname
1356 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter71202bb2016-01-15 00:25:29 +00001357 server_hostname=REMOTE_HOST)
1358 s.connect((REMOTE_HOST, 443))
Benjamin Peterson31aa69e2014-11-23 20:13:31 -06001359 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001360 # This should fail because we have no verification certs
1361 ctx.verify_mode = ssl.CERT_REQUIRED
1362 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1363 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001364 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001365 s.close()
1366 # This should succeed because we specify the root cert
Martin Panter71202bb2016-01-15 00:25:29 +00001367 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001368 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001369 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001370 try:
1371 cert = s.getpeercert()
1372 self.assertTrue(cert)
1373 finally:
1374 s.close()
1375
1376 def test_connect_capath(self):
1377 # Verify server certificates using the `capath` argument
1378 # NOTE: the subject hashing algorithm has been changed between
1379 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1380 # contain both versions of each certificate (same content, different
1381 # filename) for this test to be portable across OpenSSL releases.
Martin Panter71202bb2016-01-15 00:25:29 +00001382 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001383 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1384 ctx.verify_mode = ssl.CERT_REQUIRED
1385 ctx.load_verify_locations(capath=CAPATH)
1386 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001387 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001388 try:
1389 cert = s.getpeercert()
1390 self.assertTrue(cert)
1391 finally:
1392 s.close()
1393 # Same with a bytes `capath` argument
1394 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1395 ctx.verify_mode = ssl.CERT_REQUIRED
1396 ctx.load_verify_locations(capath=BYTES_CAPATH)
1397 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001398 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001399 try:
1400 cert = s.getpeercert()
1401 self.assertTrue(cert)
1402 finally:
1403 s.close()
1404
1405 def test_connect_cadata(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001406 with open(REMOTE_ROOT_CERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001407 pem = f.read().decode('ascii')
1408 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panter71202bb2016-01-15 00:25:29 +00001409 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001410 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1411 ctx.verify_mode = ssl.CERT_REQUIRED
1412 ctx.load_verify_locations(cadata=pem)
1413 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001414 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001415 cert = s.getpeercert()
1416 self.assertTrue(cert)
1417
1418 # same with DER
1419 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1420 ctx.verify_mode = ssl.CERT_REQUIRED
1421 ctx.load_verify_locations(cadata=der)
1422 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001423 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001424 cert = s.getpeercert()
1425 self.assertTrue(cert)
1426
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001427 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1428 def test_makefile_close(self):
1429 # Issue #5238: creating a file-like object with makefile() shouldn't
1430 # delay closing the underlying "real socket" (here tested with its
1431 # file descriptor, hence skipping the test under Windows).
Martin Panter71202bb2016-01-15 00:25:29 +00001432 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001433 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001434 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001435 fd = ss.fileno()
1436 f = ss.makefile()
1437 f.close()
1438 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001439 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001440 # Closing the SSL socket should close the fd too
1441 ss.close()
1442 gc.collect()
1443 with self.assertRaises(OSError) as e:
1444 os.read(fd, 0)
1445 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +00001446
Antoine Pitrou3945c862010-04-28 21:11:01 +00001447 def test_non_blocking_handshake(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001448 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001449 s = socket.socket(socket.AF_INET)
Martin Panter71202bb2016-01-15 00:25:29 +00001450 s.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001451 s.setblocking(False)
1452 s = ssl.wrap_socket(s,
1453 cert_reqs=ssl.CERT_NONE,
1454 do_handshake_on_connect=False)
1455 count = 0
1456 while True:
1457 try:
1458 count += 1
1459 s.do_handshake()
1460 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001461 except ssl.SSLWantReadError:
1462 select.select([s], [], [])
1463 except ssl.SSLWantWriteError:
1464 select.select([], [s], [])
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001465 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001466 if support.verbose:
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001467 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +00001468
Antoine Pitrou3945c862010-04-28 21:11:01 +00001469 def test_get_server_certificate(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001470 def _test_get_server_certificate(host, port, cert=None):
1471 with support.transient_internet(host):
1472 pem = ssl.get_server_certificate((host, port))
1473 if not pem:
1474 self.fail("No server certificate on %s:%s!" % (host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001475
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001476 try:
1477 pem = ssl.get_server_certificate((host, port),
1478 ca_certs=CERTFILE)
1479 except ssl.SSLError as x:
1480 #should fail
1481 if support.verbose:
1482 sys.stdout.write("%s\n" % x)
1483 else:
1484 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001485
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001486 pem = ssl.get_server_certificate((host, port),
1487 ca_certs=cert)
1488 if not pem:
1489 self.fail("No server certificate on %s:%s!" % (host, port))
1490 if support.verbose:
1491 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1492
Martin Panter71202bb2016-01-15 00:25:29 +00001493 _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001494 if support.IPV6_ENABLED:
1495 _test_get_server_certificate('ipv6.google.com', 443)
1496
1497 def test_ciphers(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001498 remote = (REMOTE_HOST, 443)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001499 with support.transient_internet(remote[0]):
1500 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1501 cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s:
1502 s.connect(remote)
1503 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1504 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s:
1505 s.connect(remote)
1506 # Error checking can happen at instantiation or when connecting
1507 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
1508 with closing(socket.socket(socket.AF_INET)) as sock:
1509 s = ssl.wrap_socket(sock,
1510 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1511 s.connect(remote)
Bill Janssen296a59d2007-09-16 22:06:00 +00001512
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001513 def test_algorithms(self):
1514 # Issue #8484: all algorithms should be available when verifying a
1515 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +00001516 # SHA256 was added in OpenSSL 0.9.8
1517 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1518 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001519 # sha256.tbs-internet.com needs SNI to use the correct certificate
1520 if not ssl.HAS_SNI:
1521 self.skipTest("SNI needed for this test")
1522 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
Antoine Pitroud43245a2011-01-08 10:32:51 +00001523 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001524 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001525 with support.transient_internet("sha256.tbs-internet.com"):
1526 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1527 ctx.verify_mode = ssl.CERT_REQUIRED
1528 ctx.load_verify_locations(sha256_cert)
1529 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1530 server_hostname="sha256.tbs-internet.com")
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001531 try:
1532 s.connect(remote)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001533 if support.verbose:
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001534 sys.stdout.write("\nCipher with %r is %r\n" %
1535 (remote, s.cipher()))
1536 sys.stdout.write("Certificate is:\n%s\n" %
1537 pprint.pformat(s.getpeercert()))
1538 finally:
1539 s.close()
1540
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001541 def test_get_ca_certs_capath(self):
1542 # capath certs are loaded on request
Martin Panter71202bb2016-01-15 00:25:29 +00001543 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001544 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1545 ctx.verify_mode = ssl.CERT_REQUIRED
1546 ctx.load_verify_locations(capath=CAPATH)
1547 self.assertEqual(ctx.get_ca_certs(), [])
1548 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001549 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001550 try:
1551 cert = s.getpeercert()
1552 self.assertTrue(cert)
1553 finally:
1554 s.close()
1555 self.assertEqual(len(ctx.get_ca_certs()), 1)
1556
1557 @needs_sni
1558 def test_context_setget(self):
1559 # Check that the context of a connected socket can be replaced.
Martin Panter71202bb2016-01-15 00:25:29 +00001560 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001561 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1562 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1563 s = socket.socket(socket.AF_INET)
1564 with closing(ctx1.wrap_socket(s)) as ss:
Martin Panter71202bb2016-01-15 00:25:29 +00001565 ss.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001566 self.assertIs(ss.context, ctx1)
1567 self.assertIs(ss._sslobj.context, ctx1)
1568 ss.context = ctx2
1569 self.assertIs(ss.context, ctx2)
1570 self.assertIs(ss._sslobj.context, ctx2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001571
Bill Janssen98d19da2007-09-10 21:51:02 +00001572try:
1573 import threading
1574except ImportError:
1575 _have_threads = False
1576else:
Bill Janssen98d19da2007-09-10 21:51:02 +00001577 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001578
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001579 from test.ssl_servers import make_https_server
1580
Bill Janssen98d19da2007-09-10 21:51:02 +00001581 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001582
Bill Janssen98d19da2007-09-10 21:51:02 +00001583 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001584
Bill Janssen98d19da2007-09-10 21:51:02 +00001585 """A mildly complicated class, because we want it to work both
1586 with and without the SSL wrapper around the socket connection, so
1587 that we can test the STARTTLS functionality."""
1588
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001589 def __init__(self, server, connsock, addr):
Bill Janssen98d19da2007-09-10 21:51:02 +00001590 self.server = server
1591 self.running = False
1592 self.sock = connsock
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001593 self.addr = addr
Bill Janssen98d19da2007-09-10 21:51:02 +00001594 self.sock.setblocking(1)
1595 self.sslconn = None
1596 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001597 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001598
Antoine Pitrou3945c862010-04-28 21:11:01 +00001599 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001600 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001601 self.sslconn = self.server.context.wrap_socket(
1602 self.sock, server_side=True)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001603 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1604 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001605 except socket.error as e:
1606 # We treat ConnectionResetError as though it were an
1607 # SSLError - OpenSSL on Ubuntu abruptly closes the
1608 # connection when asked to use an unsupported protocol.
1609 #
Antoine Pitroudb187842010-04-27 10:32:58 +00001610 # XXX Various errors can have happened here, for example
1611 # a mismatching protocol version, an invalid certificate,
1612 # or a low-level bug. This should be made more discriminating.
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001613 if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET:
1614 raise
Antoine Pitroud76088d2012-01-03 22:46:48 +01001615 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +00001616 if self.server.chatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001617 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00001618 self.running = False
1619 self.server.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001620 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001621 return False
Bill Janssen98d19da2007-09-10 21:51:02 +00001622 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001623 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
1624 cert = self.sslconn.getpeercert()
1625 if support.verbose and self.server.chatty:
1626 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1627 cert_binary = self.sslconn.getpeercert(True)
1628 if support.verbose and self.server.chatty:
1629 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1630 cipher = self.sslconn.cipher()
1631 if support.verbose and self.server.chatty:
1632 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
1633 sys.stdout.write(" server: selected protocol is now "
1634 + str(self.sslconn.selected_npn_protocol()) + "\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001635 return True
1636
1637 def read(self):
1638 if self.sslconn:
1639 return self.sslconn.read()
1640 else:
1641 return self.sock.recv(1024)
1642
1643 def write(self, bytes):
1644 if self.sslconn:
1645 return self.sslconn.write(bytes)
1646 else:
1647 return self.sock.send(bytes)
1648
1649 def close(self):
1650 if self.sslconn:
1651 self.sslconn.close()
1652 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001653 self.sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001654
Antoine Pitrou3945c862010-04-28 21:11:01 +00001655 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001656 self.running = True
1657 if not self.server.starttls_server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001658 if not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +00001659 return
1660 while self.running:
1661 try:
1662 msg = self.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001663 stripped = msg.strip()
1664 if not stripped:
Bill Janssen98d19da2007-09-10 21:51:02 +00001665 # eof, so quit this handler
1666 self.running = False
1667 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001668 elif stripped == b'over':
1669 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001670 sys.stdout.write(" server: client closed connection\n")
1671 self.close()
1672 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001673 elif (self.server.starttls_server and
1674 stripped == b'STARTTLS'):
1675 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001676 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001677 self.write(b"OK\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001678 if not self.wrap_conn():
1679 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001680 elif (self.server.starttls_server and self.sslconn
1681 and stripped == b'ENDTLS'):
1682 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001683 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001684 self.write(b"OK\n")
1685 self.sock = self.sslconn.unwrap()
Bill Janssen39295c22008-08-12 16:31:21 +00001686 self.sslconn = None
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001687 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001688 sys.stdout.write(" server: connection is now unencrypted...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001689 elif stripped == b'CB tls-unique':
1690 if support.verbose and self.server.connectionchatty:
1691 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1692 data = self.sslconn.get_channel_binding("tls-unique")
1693 self.write(repr(data).encode("us-ascii") + b"\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001694 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001695 if (support.verbose and
Bill Janssen98d19da2007-09-10 21:51:02 +00001696 self.server.connectionchatty):
1697 ctype = (self.sslconn and "encrypted") or "unencrypted"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001698 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1699 % (msg, ctype, msg.lower(), ctype))
Bill Janssen98d19da2007-09-10 21:51:02 +00001700 self.write(msg.lower())
1701 except ssl.SSLError:
1702 if self.server.chatty:
1703 handle_error("Test server failure:\n")
1704 self.close()
1705 self.running = False
1706 # normally, we'd just stop here, but for the test
1707 # harness, we want to stop the server
1708 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +00001709
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001710 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +00001711 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +00001712 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001713 npn_protocols=None, alpn_protocols=None,
1714 ciphers=None, context=None):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001715 if context:
1716 self.context = context
1717 else:
1718 self.context = ssl.SSLContext(ssl_version
1719 if ssl_version is not None
1720 else ssl.PROTOCOL_TLSv1)
1721 self.context.verify_mode = (certreqs if certreqs is not None
1722 else ssl.CERT_NONE)
1723 if cacerts:
1724 self.context.load_verify_locations(cacerts)
1725 if certificate:
1726 self.context.load_cert_chain(certificate)
1727 if npn_protocols:
1728 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001729 if alpn_protocols:
1730 self.context.set_alpn_protocols(alpn_protocols)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001731 if ciphers:
1732 self.context.set_ciphers(ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +00001733 self.chatty = chatty
1734 self.connectionchatty = connectionchatty
1735 self.starttls_server = starttls_server
1736 self.sock = socket.socket()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001737 self.port = support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +00001738 self.flag = None
Bill Janssen98d19da2007-09-10 21:51:02 +00001739 self.active = False
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001740 self.selected_npn_protocols = []
1741 self.selected_alpn_protocols = []
Antoine Pitroud76088d2012-01-03 22:46:48 +01001742 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001743 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001744 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001745
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001746 def __enter__(self):
1747 self.start(threading.Event())
1748 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001749 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001750
1751 def __exit__(self, *args):
1752 self.stop()
1753 self.join()
1754
Antoine Pitrou3945c862010-04-28 21:11:01 +00001755 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +00001756 self.flag = flag
1757 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001758
Antoine Pitrou3945c862010-04-28 21:11:01 +00001759 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +00001760 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +00001761 self.sock.listen(5)
1762 self.active = True
1763 if self.flag:
1764 # signal an event
1765 self.flag.set()
1766 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001767 try:
Bill Janssen98d19da2007-09-10 21:51:02 +00001768 newconn, connaddr = self.sock.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001769 if support.verbose and self.chatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001770 sys.stdout.write(' server: new connection from '
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001771 + repr(connaddr) + '\n')
1772 handler = self.ConnectionHandler(self, newconn, connaddr)
Bill Janssen98d19da2007-09-10 21:51:02 +00001773 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +01001774 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +00001775 except socket.timeout:
1776 pass
1777 except KeyboardInterrupt:
1778 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +00001779 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001780
Antoine Pitrou3945c862010-04-28 21:11:01 +00001781 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001782 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001783
Bill Janssen934b16d2008-06-28 22:19:33 +00001784 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +00001785
Antoine Pitrou3945c862010-04-28 21:11:01 +00001786 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +00001787
Antoine Pitrou3945c862010-04-28 21:11:01 +00001788 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +00001789
1790 def __init__(self, conn, certfile):
Bill Janssen934b16d2008-06-28 22:19:33 +00001791 self.socket = ssl.wrap_socket(conn, server_side=True,
1792 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +00001793 do_handshake_on_connect=False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001794 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroufc69af12010-04-24 20:04:58 +00001795 self._ssl_accepting = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001796 self._do_ssl_handshake()
Bill Janssen934b16d2008-06-28 22:19:33 +00001797
1798 def readable(self):
1799 if isinstance(self.socket, ssl.SSLSocket):
1800 while self.socket.pending() > 0:
1801 self.handle_read_event()
1802 return True
1803
Antoine Pitroufc69af12010-04-24 20:04:58 +00001804 def _do_ssl_handshake(self):
1805 try:
1806 self.socket.do_handshake()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001807 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1808 return
1809 except ssl.SSLEOFError:
1810 return self.handle_close()
1811 except ssl.SSLError:
Antoine Pitroufc69af12010-04-24 20:04:58 +00001812 raise
1813 except socket.error, err:
1814 if err.args[0] == errno.ECONNABORTED:
1815 return self.handle_close()
1816 else:
1817 self._ssl_accepting = False
1818
Bill Janssen934b16d2008-06-28 22:19:33 +00001819 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +00001820 if self._ssl_accepting:
1821 self._do_ssl_handshake()
1822 else:
1823 data = self.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001824 if support.verbose:
1825 sys.stdout.write(" server: read %s from client\n" % repr(data))
1826 if not data:
1827 self.close()
1828 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001829 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +00001830
1831 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +00001832 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001833 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001834 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1835
1836 def handle_error(self):
1837 raise
1838
1839 def __init__(self, certfile):
1840 self.certfile = certfile
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001841 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1842 self.port = support.bind_port(sock, '')
1843 asyncore.dispatcher.__init__(self, sock)
Bill Janssen934b16d2008-06-28 22:19:33 +00001844 self.listen(5)
1845
1846 def handle_accept(self):
1847 sock_obj, addr = self.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001848 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001849 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1850 self.ConnectionHandler(sock_obj, self.certfile)
1851
1852 def handle_error(self):
1853 raise
1854
1855 def __init__(self, certfile):
1856 self.flag = None
1857 self.active = False
1858 self.server = self.EchoServer(certfile)
1859 self.port = self.server.port
1860 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001861 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +00001862
1863 def __str__(self):
1864 return "<%s %s>" % (self.__class__.__name__, self.server)
1865
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001866 def __enter__(self):
1867 self.start(threading.Event())
1868 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001869 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001870
1871 def __exit__(self, *args):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001872 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001873 sys.stdout.write(" cleanup: stopping server.\n")
1874 self.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001875 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001876 sys.stdout.write(" cleanup: joining server thread.\n")
1877 self.join()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001878 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001879 sys.stdout.write(" cleanup: successfully joined.\n")
1880
Antoine Pitrou3945c862010-04-28 21:11:01 +00001881 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +00001882 self.flag = flag
1883 threading.Thread.start(self)
1884
Antoine Pitrou3945c862010-04-28 21:11:01 +00001885 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001886 self.active = True
1887 if self.flag:
1888 self.flag.set()
1889 while self.active:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001890 try:
1891 asyncore.loop(1)
1892 except:
1893 pass
Bill Janssen934b16d2008-06-28 22:19:33 +00001894
Antoine Pitrou3945c862010-04-28 21:11:01 +00001895 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001896 self.active = False
1897 self.server.close()
1898
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001899 def server_params_test(client_context, server_context, indata=b"FOO\n",
1900 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001901 """
1902 Launch a server, connect a client to it and try various reads
1903 and writes.
1904 """
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001905 stats = {}
1906 server = ThreadedEchoServer(context=server_context,
Bill Janssen98d19da2007-09-10 21:51:02 +00001907 chatty=chatty,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001908 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001909 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001910 with closing(client_context.wrap_socket(socket.socket(),
1911 server_hostname=sni_name)) as s:
1912 s.connect((HOST, server.port))
1913 for arg in [indata, bytearray(indata), memoryview(indata)]:
1914 if connectionchatty:
1915 if support.verbose:
1916 sys.stdout.write(
1917 " client: sending %r...\n" % indata)
1918 s.write(arg)
1919 outdata = s.read()
1920 if connectionchatty:
1921 if support.verbose:
1922 sys.stdout.write(" client: read %r\n" % outdata)
1923 if outdata != indata.lower():
1924 raise AssertionError(
1925 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1926 % (outdata[:20], len(outdata),
1927 indata[:20].lower(), len(indata)))
1928 s.write(b"over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001929 if connectionchatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001930 if support.verbose:
1931 sys.stdout.write(" client: closing connection.\n")
1932 stats.update({
1933 'compression': s.compression(),
1934 'cipher': s.cipher(),
1935 'peercert': s.getpeercert(),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001936 'client_alpn_protocol': s.selected_alpn_protocol(),
Alex Gaynore98205d2014-09-04 13:33:22 -07001937 'client_npn_protocol': s.selected_npn_protocol(),
1938 'version': s.version(),
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001939 })
1940 s.close()
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001941 stats['server_alpn_protocols'] = server.selected_alpn_protocols
1942 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001943 return stats
Bill Janssen98d19da2007-09-10 21:51:02 +00001944
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001945 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1946 certsreqs=None, server_options=0, client_options=0):
Alex Gaynore98205d2014-09-04 13:33:22 -07001947 """
1948 Try to SSL-connect using *client_protocol* to *server_protocol*.
1949 If *expect_success* is true, assert that the connection succeeds,
1950 if it's false, assert that the connection fails.
1951 Also, if *expect_success* is a string, assert that it is the protocol
1952 version actually used by the connection.
1953 """
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00001954 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +00001955 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +00001956 certtype = {
1957 ssl.CERT_NONE: "CERT_NONE",
1958 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1959 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1960 }[certsreqs]
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001961 if support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001962 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +00001963 sys.stdout.write(formatstr %
1964 (ssl.get_protocol_name(client_protocol),
1965 ssl.get_protocol_name(server_protocol),
1966 certtype))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001967 client_context = ssl.SSLContext(client_protocol)
1968 client_context.options |= client_options
1969 server_context = ssl.SSLContext(server_protocol)
1970 server_context.options |= server_options
1971
1972 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1973 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1974 # starting from OpenSSL 1.0.0 (see issue #8322).
1975 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1976 client_context.set_ciphers("ALL")
1977
1978 for ctx in (client_context, server_context):
1979 ctx.verify_mode = certsreqs
1980 ctx.load_cert_chain(CERTFILE)
1981 ctx.load_verify_locations(CERTFILE)
Bill Janssen98d19da2007-09-10 21:51:02 +00001982 try:
Alex Gaynore98205d2014-09-04 13:33:22 -07001983 stats = server_params_test(client_context, server_context,
1984 chatty=False, connectionchatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00001985 # Protocol mismatch can result in either an SSLError, or a
1986 # "Connection reset by peer" error.
1987 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001988 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +00001989 raise
Antoine Pitroudb187842010-04-27 10:32:58 +00001990 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001991 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +00001992 raise
Bill Janssen98d19da2007-09-10 21:51:02 +00001993 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001994 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00001995 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +00001996 "Client protocol %s succeeded with server protocol %s!"
1997 % (ssl.get_protocol_name(client_protocol),
1998 ssl.get_protocol_name(server_protocol)))
Alex Gaynore98205d2014-09-04 13:33:22 -07001999 elif (expect_success is not True
2000 and expect_success != stats['version']):
2001 raise AssertionError("version mismatch: expected %r, got %r"
2002 % (expect_success, stats['version']))
Bill Janssen98d19da2007-09-10 21:51:02 +00002003
2004
Bill Janssen934b16d2008-06-28 22:19:33 +00002005 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +00002006
Antoine Pitroud75efd92010-08-04 17:38:33 +00002007 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002008 def test_echo(self):
2009 """Basic test of an SSL client connecting to a server"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002010 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002011 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002012 for protocol in PROTOCOLS:
2013 context = ssl.SSLContext(protocol)
2014 context.load_cert_chain(CERTFILE)
2015 server_params_test(context, context,
2016 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002017
Antoine Pitrou3945c862010-04-28 21:11:01 +00002018 def test_getpeercert(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002019 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002020 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002021 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2022 context.verify_mode = ssl.CERT_REQUIRED
2023 context.load_verify_locations(CERTFILE)
2024 context.load_cert_chain(CERTFILE)
2025 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002026 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002027 s = context.wrap_socket(socket.socket(),
2028 do_handshake_on_connect=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002029 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002030 # getpeercert() raise ValueError while the handshake isn't
2031 # done.
2032 with self.assertRaises(ValueError):
2033 s.getpeercert()
2034 s.do_handshake()
Antoine Pitroudb187842010-04-27 10:32:58 +00002035 cert = s.getpeercert()
2036 self.assertTrue(cert, "Can't get peer certificate.")
2037 cipher = s.cipher()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002038 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002039 sys.stdout.write(pprint.pformat(cert) + '\n')
2040 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2041 if 'subject' not in cert:
2042 self.fail("No subject field in certificate: %s." %
2043 pprint.pformat(cert))
2044 if ((('organizationName', 'Python Software Foundation'),)
2045 not in cert['subject']):
2046 self.fail(
2047 "Missing or invalid 'organizationName' field in certificate subject; "
2048 "should be 'Python Software Foundation'.")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002049 self.assertIn('notBefore', cert)
2050 self.assertIn('notAfter', cert)
2051 before = ssl.cert_time_to_seconds(cert['notBefore'])
2052 after = ssl.cert_time_to_seconds(cert['notAfter'])
2053 self.assertLess(before, after)
Antoine Pitroudb187842010-04-27 10:32:58 +00002054 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002055
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002056 @unittest.skipUnless(have_verify_flags(),
2057 "verify_flags need OpenSSL > 0.9.8")
2058 def test_crl_check(self):
2059 if support.verbose:
2060 sys.stdout.write("\n")
2061
2062 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2063 server_context.load_cert_chain(SIGNED_CERTFILE)
2064
2065 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2066 context.verify_mode = ssl.CERT_REQUIRED
2067 context.load_verify_locations(SIGNING_CA)
Benjamin Petersond86699f2015-03-04 23:18:48 -05002068 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2069 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002070
2071 # VERIFY_DEFAULT should pass
2072 server = ThreadedEchoServer(context=server_context, chatty=True)
2073 with server:
2074 with closing(context.wrap_socket(socket.socket())) as s:
2075 s.connect((HOST, server.port))
2076 cert = s.getpeercert()
2077 self.assertTrue(cert, "Can't get peer certificate.")
2078
2079 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
2080 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
2081
2082 server = ThreadedEchoServer(context=server_context, chatty=True)
2083 with server:
2084 with closing(context.wrap_socket(socket.socket())) as s:
2085 with self.assertRaisesRegexp(ssl.SSLError,
2086 "certificate verify failed"):
2087 s.connect((HOST, server.port))
2088
2089 # now load a CRL file. The CRL file is signed by the CA.
2090 context.load_verify_locations(CRLFILE)
2091
2092 server = ThreadedEchoServer(context=server_context, chatty=True)
2093 with server:
2094 with closing(context.wrap_socket(socket.socket())) as s:
2095 s.connect((HOST, server.port))
2096 cert = s.getpeercert()
2097 self.assertTrue(cert, "Can't get peer certificate.")
2098
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002099 def test_check_hostname(self):
2100 if support.verbose:
2101 sys.stdout.write("\n")
2102
2103 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2104 server_context.load_cert_chain(SIGNED_CERTFILE)
2105
2106 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2107 context.verify_mode = ssl.CERT_REQUIRED
2108 context.check_hostname = True
2109 context.load_verify_locations(SIGNING_CA)
2110
2111 # correct hostname should verify
2112 server = ThreadedEchoServer(context=server_context, chatty=True)
2113 with server:
2114 with closing(context.wrap_socket(socket.socket(),
2115 server_hostname="localhost")) as s:
2116 s.connect((HOST, server.port))
2117 cert = s.getpeercert()
2118 self.assertTrue(cert, "Can't get peer certificate.")
2119
2120 # incorrect hostname should raise an exception
2121 server = ThreadedEchoServer(context=server_context, chatty=True)
2122 with server:
2123 with closing(context.wrap_socket(socket.socket(),
2124 server_hostname="invalid")) as s:
2125 with self.assertRaisesRegexp(ssl.CertificateError,
2126 "hostname 'invalid' doesn't match u?'localhost'"):
2127 s.connect((HOST, server.port))
2128
2129 # missing server_hostname arg should cause an exception, too
2130 server = ThreadedEchoServer(context=server_context, chatty=True)
2131 with server:
2132 with closing(socket.socket()) as s:
2133 with self.assertRaisesRegexp(ValueError,
2134 "check_hostname requires server_hostname"):
2135 context.wrap_socket(s)
2136
Martin Panterfd8e8502016-01-30 02:36:00 +00002137 def test_wrong_cert(self):
Martin Panter886aba42016-02-01 21:58:11 +00002138 """Connecting when the server rejects the client's certificate
2139
2140 Launch a server with CERT_REQUIRED, and check that trying to
2141 connect to it with a wrong client certificate fails.
2142 """
2143 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
2144 "wrongcert.pem")
2145 server = ThreadedEchoServer(CERTFILE,
2146 certreqs=ssl.CERT_REQUIRED,
2147 cacerts=CERTFILE, chatty=False,
2148 connectionchatty=False)
2149 with server, \
2150 closing(socket.socket()) as sock, \
2151 closing(ssl.wrap_socket(sock,
2152 certfile=certfile,
2153 ssl_version=ssl.PROTOCOL_TLSv1)) as s:
2154 try:
2155 # Expect either an SSL error about the server rejecting
2156 # the connection, or a low-level connection reset (which
2157 # sometimes happens on Windows)
2158 s.connect((HOST, server.port))
2159 except ssl.SSLError as e:
2160 if support.verbose:
2161 sys.stdout.write("\nSSLError is %r\n" % e)
2162 except socket.error as e:
2163 if e.errno != errno.ECONNRESET:
2164 raise
2165 if support.verbose:
2166 sys.stdout.write("\nsocket.error is %r\n" % e)
2167 else:
2168 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +00002169
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002170 def test_rude_shutdown(self):
2171 """A brutal shutdown of an SSL server should raise an OSError
2172 in the client when attempting handshake.
2173 """
2174 listener_ready = threading.Event()
2175 listener_gone = threading.Event()
2176
2177 s = socket.socket()
2178 port = support.bind_port(s, HOST)
2179
2180 # `listener` runs in a thread. It sits in an accept() until
2181 # the main thread connects. Then it rudely closes the socket,
2182 # and sets Event `listener_gone` to let the main thread know
2183 # the socket is gone.
2184 def listener():
2185 s.listen(5)
2186 listener_ready.set()
2187 newsock, addr = s.accept()
2188 newsock.close()
2189 s.close()
2190 listener_gone.set()
2191
2192 def connector():
2193 listener_ready.wait()
2194 with closing(socket.socket()) as c:
2195 c.connect((HOST, port))
2196 listener_gone.wait()
2197 try:
2198 ssl_sock = ssl.wrap_socket(c)
Benjamin Petersone208b572014-08-20 14:49:08 -05002199 except socket.error:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002200 pass
2201 else:
2202 self.fail('connecting to closed SSL socket should have failed')
2203
2204 t = threading.Thread(target=listener)
2205 t.start()
2206 try:
2207 connector()
2208 finally:
2209 t.join()
2210
Antoine Pitroud75efd92010-08-04 17:38:33 +00002211 @skip_if_broken_ubuntu_ssl
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002212 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2213 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002214 def test_protocol_sslv2(self):
2215 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002216 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002217 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002218 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2219 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2220 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01002221 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002222 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2223 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002224 # SSLv23 client with specific SSL options
2225 if no_sslv2_implies_sslv3_hello():
2226 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2227 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2228 client_options=ssl.OP_NO_SSLv2)
2229 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2230 client_options=ssl.OP_NO_SSLv3)
2231 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2232 client_options=ssl.OP_NO_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00002233
Antoine Pitroud75efd92010-08-04 17:38:33 +00002234 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002235 def test_protocol_sslv23(self):
2236 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002237 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002238 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002239 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2240 try:
2241 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
2242 except socket.error as x:
2243 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2244 if support.verbose:
2245 sys.stdout.write(
2246 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2247 % str(x))
Benjamin Peterson60766c42014-12-05 21:59:35 -05002248 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002249 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002250 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Alex Gaynore98205d2014-09-04 13:33:22 -07002251 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Bill Janssen98d19da2007-09-10 21:51:02 +00002252
Benjamin Peterson60766c42014-12-05 21:59:35 -05002253 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002254 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002255 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Alex Gaynore98205d2014-09-04 13:33:22 -07002256 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00002257
Benjamin Peterson60766c42014-12-05 21:59:35 -05002258 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002259 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002260 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Alex Gaynore98205d2014-09-04 13:33:22 -07002261 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00002262
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002263 # Server with specific SSL options
Benjamin Peterson60766c42014-12-05 21:59:35 -05002264 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2265 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002266 server_options=ssl.OP_NO_SSLv3)
2267 # Will choose TLSv1
2268 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2269 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2270 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2271 server_options=ssl.OP_NO_TLSv1)
2272
2273
Antoine Pitroud75efd92010-08-04 17:38:33 +00002274 @skip_if_broken_ubuntu_ssl
Benjamin Peterson60766c42014-12-05 21:59:35 -05002275 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2276 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002277 def test_protocol_sslv3(self):
2278 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002279 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002280 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002281 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2282 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2283 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002284 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2285 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002286 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2287 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002288 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002289 if no_sslv2_implies_sslv3_hello():
2290 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002291 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2292 False, client_options=ssl.OP_NO_SSLv2)
Bill Janssen98d19da2007-09-10 21:51:02 +00002293
Antoine Pitroud75efd92010-08-04 17:38:33 +00002294 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002295 def test_protocol_tlsv1(self):
2296 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002297 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002298 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002299 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2300 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2301 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002302 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2303 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002304 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2305 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002306 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2307 client_options=ssl.OP_NO_TLSv1)
2308
2309 @skip_if_broken_ubuntu_ssl
2310 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2311 "TLS version 1.1 not supported.")
2312 def test_protocol_tlsv1_1(self):
2313 """Connecting to a TLSv1.1 server with various client options.
2314 Testing against older TLS versions."""
2315 if support.verbose:
2316 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002317 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002318 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2319 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002320 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2321 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002322 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2323 client_options=ssl.OP_NO_TLSv1_1)
2324
Alex Gaynore98205d2014-09-04 13:33:22 -07002325 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002326 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2327 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2328
2329
2330 @skip_if_broken_ubuntu_ssl
2331 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2332 "TLS version 1.2 not supported.")
2333 def test_protocol_tlsv1_2(self):
2334 """Connecting to a TLSv1.2 server with various client options.
2335 Testing against older TLS versions."""
2336 if support.verbose:
2337 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002338 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002339 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2340 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2341 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2342 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002343 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2344 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002345 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2346 client_options=ssl.OP_NO_TLSv1_2)
2347
Alex Gaynore98205d2014-09-04 13:33:22 -07002348 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002349 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2350 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2351 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2352 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00002353
Antoine Pitrou3945c862010-04-28 21:11:01 +00002354 def test_starttls(self):
2355 """Switching from clear text to encrypted and back again."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002356 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 +00002357
Trent Nelsone41b0062008-04-08 23:47:30 +00002358 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00002359 ssl_version=ssl.PROTOCOL_TLSv1,
2360 starttls_server=True,
2361 chatty=True,
2362 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002363 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002364 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002365 s = socket.socket()
2366 s.setblocking(1)
2367 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002368 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002369 sys.stdout.write("\n")
2370 for indata in msgs:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002371 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002372 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002373 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002374 if wrapped:
2375 conn.write(indata)
2376 outdata = conn.read()
2377 else:
2378 s.send(indata)
2379 outdata = s.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002380 msg = outdata.strip().lower()
2381 if indata == b"STARTTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002382 # STARTTLS ok, switch to secure mode
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002383 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002384 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002385 " client: read %r from server, starting TLS...\n"
2386 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002387 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2388 wrapped = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002389 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002390 # ENDTLS ok, switch back to clear text
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002391 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002392 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002393 " client: read %r from server, ending TLS...\n"
2394 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002395 s = conn.unwrap()
2396 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00002397 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002398 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002399 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002400 " client: read %r from server\n" % msg)
2401 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002402 sys.stdout.write(" client: closing connection.\n")
2403 if wrapped:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002404 conn.write(b"over\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00002405 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002406 s.send(b"over\n")
2407 if wrapped:
2408 conn.close()
2409 else:
2410 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002411
Antoine Pitrou3945c862010-04-28 21:11:01 +00002412 def test_socketserver(self):
2413 """Using a SocketServer to create and manage SSL connections."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002414 server = make_https_server(self, certfile=CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00002415 # try to connect
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002416 if support.verbose:
2417 sys.stdout.write('\n')
2418 with open(CERTFILE, 'rb') as f:
2419 d1 = f.read()
2420 d2 = ''
2421 # now fetch the same data from the HTTPS server
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -06002422 url = 'https://localhost:%d/%s' % (
2423 server.port, os.path.split(CERTFILE)[1])
2424 context = ssl.create_default_context(cafile=CERTFILE)
Benjamin Petersonb0609ec2014-11-23 11:52:46 -06002425 f = urllib2.urlopen(url, context=context)
Bill Janssen296a59d2007-09-16 22:06:00 +00002426 try:
Bill Janssen296a59d2007-09-16 22:06:00 +00002427 dlen = f.info().getheader("content-length")
2428 if dlen and (int(dlen) > 0):
2429 d2 = f.read(int(dlen))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002430 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002431 sys.stdout.write(
2432 " client: read %d bytes from remote server '%s'\n"
2433 % (len(d2), server))
Bill Janssen296a59d2007-09-16 22:06:00 +00002434 finally:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002435 f.close()
2436 self.assertEqual(d1, d2)
Bill Janssen934b16d2008-06-28 22:19:33 +00002437
Antoine Pitrou3945c862010-04-28 21:11:01 +00002438 def test_asyncore_server(self):
2439 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00002440 indata = "TEST MESSAGE of mixed case\n"
2441
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002442 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00002443 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002444
2445 indata = b"FOO\n"
Bill Janssen934b16d2008-06-28 22:19:33 +00002446 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002447 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002448 s = ssl.wrap_socket(socket.socket())
2449 s.connect(('127.0.0.1', server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002450 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002451 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002452 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002453 s.write(indata)
2454 outdata = s.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002455 if support.verbose:
2456 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002457 if outdata != indata.lower():
2458 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002459 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2460 % (outdata[:20], len(outdata),
2461 indata[:20].lower(), len(indata)))
2462 s.write(b"over\n")
2463 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002464 sys.stdout.write(" client: closing connection.\n")
2465 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002466 if support.verbose:
2467 sys.stdout.write(" client: connection closed.\n")
Bill Janssen934b16d2008-06-28 22:19:33 +00002468
Antoine Pitrou3945c862010-04-28 21:11:01 +00002469 def test_recv_send(self):
2470 """Test recv(), send() and friends."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002471 if support.verbose:
Bill Janssen61c001a2008-09-08 16:37:24 +00002472 sys.stdout.write("\n")
2473
2474 server = ThreadedEchoServer(CERTFILE,
2475 certreqs=ssl.CERT_NONE,
2476 ssl_version=ssl.PROTOCOL_TLSv1,
2477 cacerts=CERTFILE,
2478 chatty=True,
2479 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002480 with server:
2481 s = ssl.wrap_socket(socket.socket(),
2482 server_side=False,
2483 certfile=CERTFILE,
2484 ca_certs=CERTFILE,
2485 cert_reqs=ssl.CERT_NONE,
2486 ssl_version=ssl.PROTOCOL_TLSv1)
2487 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00002488 # helper methods for standardising recv* method signatures
2489 def _recv_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002490 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002491 count = s.recv_into(b)
2492 return b[:count]
2493
2494 def _recvfrom_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002495 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002496 count, addr = s.recvfrom_into(b)
2497 return b[:count]
2498
2499 # (name, method, whether to expect success, *args)
2500 send_methods = [
2501 ('send', s.send, True, []),
2502 ('sendto', s.sendto, False, ["some.address"]),
2503 ('sendall', s.sendall, True, []),
2504 ]
2505 recv_methods = [
2506 ('recv', s.recv, True, []),
2507 ('recvfrom', s.recvfrom, False, ["some.address"]),
2508 ('recv_into', _recv_into, True, []),
2509 ('recvfrom_into', _recvfrom_into, False, []),
2510 ]
2511 data_prefix = u"PREFIX_"
2512
2513 for meth_name, send_meth, expect_success, args in send_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002514 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002515 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002516 send_meth(indata, *args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002517 outdata = s.read()
Bill Janssen61c001a2008-09-08 16:37:24 +00002518 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002519 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002520 "While sending with <<{name:s}>> bad data "
2521 "<<{outdata:r}>> ({nout:d}) received; "
2522 "expected <<{indata:r}>> ({nin:d})\n".format(
2523 name=meth_name, outdata=outdata[:20],
2524 nout=len(outdata),
2525 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002526 )
2527 )
2528 except ValueError as e:
2529 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002530 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002531 "Failed to send with method <<{name:s}>>; "
2532 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002533 )
2534 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002535 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002536 "Method <<{name:s}>> failed with unexpected "
2537 "exception message: {exp:s}\n".format(
2538 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002539 )
2540 )
2541
2542 for meth_name, recv_meth, expect_success, args in recv_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002543 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002544 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002545 s.send(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002546 outdata = recv_meth(*args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002547 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002548 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002549 "While receiving with <<{name:s}>> bad data "
2550 "<<{outdata:r}>> ({nout:d}) received; "
2551 "expected <<{indata:r}>> ({nin:d})\n".format(
2552 name=meth_name, outdata=outdata[:20],
2553 nout=len(outdata),
2554 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002555 )
2556 )
2557 except ValueError as e:
2558 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002559 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002560 "Failed to receive with method <<{name:s}>>; "
2561 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002562 )
2563 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002564 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002565 "Method <<{name:s}>> failed with unexpected "
2566 "exception message: {exp:s}\n".format(
2567 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002568 )
2569 )
2570 # consume data
2571 s.read()
2572
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002573 s.write(b"over\n")
Bill Janssen61c001a2008-09-08 16:37:24 +00002574 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00002575
Antoine Pitroufc69af12010-04-24 20:04:58 +00002576 def test_handshake_timeout(self):
2577 # Issue #5103: SSL handshake must respect the socket timeout
2578 server = socket.socket(socket.AF_INET)
2579 host = "127.0.0.1"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002580 port = support.bind_port(server)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002581 started = threading.Event()
2582 finish = False
2583
2584 def serve():
2585 server.listen(5)
2586 started.set()
2587 conns = []
2588 while not finish:
2589 r, w, e = select.select([server], [], [], 0.1)
2590 if server in r:
2591 # Let the socket hang around rather than having
2592 # it closed by garbage collection.
2593 conns.append(server.accept()[0])
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002594 for sock in conns:
2595 sock.close()
Antoine Pitroufc69af12010-04-24 20:04:58 +00002596
2597 t = threading.Thread(target=serve)
2598 t.start()
2599 started.wait()
2600
2601 try:
2602 try:
2603 c = socket.socket(socket.AF_INET)
2604 c.settimeout(0.2)
2605 c.connect((host, port))
2606 # Will attempt handshake and time out
2607 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2608 ssl.wrap_socket, c)
2609 finally:
2610 c.close()
2611 try:
2612 c = socket.socket(socket.AF_INET)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002613 c = ssl.wrap_socket(c)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002614 c.settimeout(0.2)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002615 # Will attempt handshake and time out
2616 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2617 c.connect, (host, port))
2618 finally:
2619 c.close()
2620 finally:
2621 finish = True
2622 t.join()
2623 server.close()
2624
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002625 def test_server_accept(self):
2626 # Issue #16357: accept() on a SSLSocket created through
2627 # SSLContext.wrap_socket().
2628 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2629 context.verify_mode = ssl.CERT_REQUIRED
2630 context.load_verify_locations(CERTFILE)
2631 context.load_cert_chain(CERTFILE)
2632 server = socket.socket(socket.AF_INET)
2633 host = "127.0.0.1"
2634 port = support.bind_port(server)
2635 server = context.wrap_socket(server, server_side=True)
2636
2637 evt = threading.Event()
2638 remote = [None]
2639 peer = [None]
2640 def serve():
2641 server.listen(5)
2642 # Block on the accept and wait on the connection to close.
2643 evt.set()
2644 remote[0], peer[0] = server.accept()
2645 remote[0].recv(1)
2646
2647 t = threading.Thread(target=serve)
2648 t.start()
2649 # Client wait until server setup and perform a connect.
2650 evt.wait()
2651 client = context.wrap_socket(socket.socket())
2652 client.connect((host, port))
2653 client_addr = client.getsockname()
2654 client.close()
2655 t.join()
2656 remote[0].close()
2657 server.close()
2658 # Sanity checks.
2659 self.assertIsInstance(remote[0], ssl.SSLSocket)
2660 self.assertEqual(peer[0], client_addr)
2661
2662 def test_getpeercert_enotconn(self):
2663 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2664 with closing(context.wrap_socket(socket.socket())) as sock:
2665 with self.assertRaises(socket.error) as cm:
2666 sock.getpeercert()
2667 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2668
2669 def test_do_handshake_enotconn(self):
2670 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2671 with closing(context.wrap_socket(socket.socket())) as sock:
2672 with self.assertRaises(socket.error) as cm:
2673 sock.do_handshake()
2674 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2675
Antoine Pitroud76088d2012-01-03 22:46:48 +01002676 def test_default_ciphers(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002677 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2678 try:
2679 # Force a set of weak ciphers on our client context
2680 context.set_ciphers("DES")
2681 except ssl.SSLError:
2682 self.skipTest("no DES cipher available")
Antoine Pitroud76088d2012-01-03 22:46:48 +01002683 with ThreadedEchoServer(CERTFILE,
2684 ssl_version=ssl.PROTOCOL_SSLv23,
2685 chatty=False) as server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002686 with closing(context.wrap_socket(socket.socket())) as s:
2687 with self.assertRaises(ssl.SSLError):
Antoine Pitroud76088d2012-01-03 22:46:48 +01002688 s.connect((HOST, server.port))
Antoine Pitroud76088d2012-01-03 22:46:48 +01002689 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2690
Alex Gaynore98205d2014-09-04 13:33:22 -07002691 def test_version_basic(self):
2692 """
2693 Basic tests for SSLSocket.version().
2694 More tests are done in the test_protocol_*() methods.
2695 """
2696 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2697 with ThreadedEchoServer(CERTFILE,
2698 ssl_version=ssl.PROTOCOL_TLSv1,
2699 chatty=False) as server:
2700 with closing(context.wrap_socket(socket.socket())) as s:
2701 self.assertIs(s.version(), None)
2702 s.connect((HOST, server.port))
2703 self.assertEqual(s.version(), "TLSv1")
2704 self.assertIs(s.version(), None)
2705
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002706 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2707 def test_default_ecdh_curve(self):
2708 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2709 # should be enabled by default on SSL contexts.
2710 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2711 context.load_cert_chain(CERTFILE)
2712 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2713 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2714 # our default cipher list should prefer ECDH-based ciphers
2715 # automatically.
2716 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2717 context.set_ciphers("ECCdraft:ECDH")
2718 with ThreadedEchoServer(context=context) as server:
2719 with closing(context.wrap_socket(socket.socket())) as s:
2720 s.connect((HOST, server.port))
2721 self.assertIn("ECDH", s.cipher()[0])
2722
2723 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2724 "'tls-unique' channel binding not available")
2725 def test_tls_unique_channel_binding(self):
2726 """Test tls-unique channel binding."""
2727 if support.verbose:
2728 sys.stdout.write("\n")
2729
2730 server = ThreadedEchoServer(CERTFILE,
2731 certreqs=ssl.CERT_NONE,
2732 ssl_version=ssl.PROTOCOL_TLSv1,
2733 cacerts=CERTFILE,
2734 chatty=True,
2735 connectionchatty=False)
2736 with server:
2737 s = ssl.wrap_socket(socket.socket(),
2738 server_side=False,
2739 certfile=CERTFILE,
2740 ca_certs=CERTFILE,
2741 cert_reqs=ssl.CERT_NONE,
2742 ssl_version=ssl.PROTOCOL_TLSv1)
2743 s.connect((HOST, server.port))
2744 # get the data
2745 cb_data = s.get_channel_binding("tls-unique")
2746 if support.verbose:
2747 sys.stdout.write(" got channel binding data: {0!r}\n"
2748 .format(cb_data))
2749
2750 # check if it is sane
2751 self.assertIsNotNone(cb_data)
2752 self.assertEqual(len(cb_data), 12) # True for TLSv1
2753
2754 # and compare with the peers version
2755 s.write(b"CB tls-unique\n")
2756 peer_data_repr = s.read().strip()
2757 self.assertEqual(peer_data_repr,
2758 repr(cb_data).encode("us-ascii"))
2759 s.close()
2760
2761 # now, again
2762 s = ssl.wrap_socket(socket.socket(),
2763 server_side=False,
2764 certfile=CERTFILE,
2765 ca_certs=CERTFILE,
2766 cert_reqs=ssl.CERT_NONE,
2767 ssl_version=ssl.PROTOCOL_TLSv1)
2768 s.connect((HOST, server.port))
2769 new_cb_data = s.get_channel_binding("tls-unique")
2770 if support.verbose:
2771 sys.stdout.write(" got another channel binding data: {0!r}\n"
2772 .format(new_cb_data))
2773 # is it really unique
2774 self.assertNotEqual(cb_data, new_cb_data)
2775 self.assertIsNotNone(cb_data)
2776 self.assertEqual(len(cb_data), 12) # True for TLSv1
2777 s.write(b"CB tls-unique\n")
2778 peer_data_repr = s.read().strip()
2779 self.assertEqual(peer_data_repr,
2780 repr(new_cb_data).encode("us-ascii"))
2781 s.close()
2782
2783 def test_compression(self):
2784 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2785 context.load_cert_chain(CERTFILE)
2786 stats = server_params_test(context, context,
2787 chatty=True, connectionchatty=True)
2788 if support.verbose:
2789 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2790 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2791
2792 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2793 "ssl.OP_NO_COMPRESSION needed for this test")
2794 def test_compression_disabled(self):
2795 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2796 context.load_cert_chain(CERTFILE)
2797 context.options |= ssl.OP_NO_COMPRESSION
2798 stats = server_params_test(context, context,
2799 chatty=True, connectionchatty=True)
2800 self.assertIs(stats['compression'], None)
2801
2802 def test_dh_params(self):
2803 # Check we can get a connection with ephemeral Diffie-Hellman
2804 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2805 context.load_cert_chain(CERTFILE)
2806 context.load_dh_params(DHFILE)
2807 context.set_ciphers("kEDH")
2808 stats = server_params_test(context, context,
2809 chatty=True, connectionchatty=True)
2810 cipher = stats["cipher"][0]
2811 parts = cipher.split("-")
2812 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2813 self.fail("Non-DH cipher: " + cipher[0])
2814
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002815 def test_selected_alpn_protocol(self):
2816 # selected_alpn_protocol() is None unless ALPN is used.
2817 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2818 context.load_cert_chain(CERTFILE)
2819 stats = server_params_test(context, context,
2820 chatty=True, connectionchatty=True)
2821 self.assertIs(stats['client_alpn_protocol'], None)
2822
2823 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
2824 def test_selected_alpn_protocol_if_server_uses_alpn(self):
2825 # selected_alpn_protocol() is None unless ALPN is used by the client.
2826 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2827 client_context.load_verify_locations(CERTFILE)
2828 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2829 server_context.load_cert_chain(CERTFILE)
2830 server_context.set_alpn_protocols(['foo', 'bar'])
2831 stats = server_params_test(client_context, server_context,
2832 chatty=True, connectionchatty=True)
2833 self.assertIs(stats['client_alpn_protocol'], None)
2834
2835 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
2836 def test_alpn_protocols(self):
2837 server_protocols = ['foo', 'bar', 'milkshake']
2838 protocol_tests = [
2839 (['foo', 'bar'], 'foo'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002840 (['bar', 'foo'], 'foo'),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002841 (['milkshake'], 'milkshake'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002842 (['http/3.0', 'http/4.0'], None)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002843 ]
2844 for client_protocols, expected in protocol_tests:
2845 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2846 server_context.load_cert_chain(CERTFILE)
2847 server_context.set_alpn_protocols(server_protocols)
2848 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2849 client_context.load_cert_chain(CERTFILE)
2850 client_context.set_alpn_protocols(client_protocols)
2851 stats = server_params_test(client_context, server_context,
2852 chatty=True, connectionchatty=True)
2853
2854 msg = "failed trying %s (s) and %s (c).\n" \
2855 "was expecting %s, but got %%s from the %%s" \
2856 % (str(server_protocols), str(client_protocols),
2857 str(expected))
2858 client_result = stats['client_alpn_protocol']
2859 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2860 server_result = stats['server_alpn_protocols'][-1] \
2861 if len(stats['server_alpn_protocols']) else 'nothing'
2862 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2863
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002864 def test_selected_npn_protocol(self):
2865 # selected_npn_protocol() is None unless NPN is used
2866 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2867 context.load_cert_chain(CERTFILE)
2868 stats = server_params_test(context, context,
2869 chatty=True, connectionchatty=True)
2870 self.assertIs(stats['client_npn_protocol'], None)
2871
2872 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2873 def test_npn_protocols(self):
2874 server_protocols = ['http/1.1', 'spdy/2']
2875 protocol_tests = [
2876 (['http/1.1', 'spdy/2'], 'http/1.1'),
2877 (['spdy/2', 'http/1.1'], 'http/1.1'),
2878 (['spdy/2', 'test'], 'spdy/2'),
2879 (['abc', 'def'], 'abc')
2880 ]
2881 for client_protocols, expected in protocol_tests:
2882 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2883 server_context.load_cert_chain(CERTFILE)
2884 server_context.set_npn_protocols(server_protocols)
2885 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2886 client_context.load_cert_chain(CERTFILE)
2887 client_context.set_npn_protocols(client_protocols)
2888 stats = server_params_test(client_context, server_context,
2889 chatty=True, connectionchatty=True)
2890
2891 msg = "failed trying %s (s) and %s (c).\n" \
2892 "was expecting %s, but got %%s from the %%s" \
2893 % (str(server_protocols), str(client_protocols),
2894 str(expected))
2895 client_result = stats['client_npn_protocol']
2896 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2897 server_result = stats['server_npn_protocols'][-1] \
2898 if len(stats['server_npn_protocols']) else 'nothing'
2899 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2900
2901 def sni_contexts(self):
2902 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2903 server_context.load_cert_chain(SIGNED_CERTFILE)
2904 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2905 other_context.load_cert_chain(SIGNED_CERTFILE2)
2906 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2907 client_context.verify_mode = ssl.CERT_REQUIRED
2908 client_context.load_verify_locations(SIGNING_CA)
2909 return server_context, other_context, client_context
2910
2911 def check_common_name(self, stats, name):
2912 cert = stats['peercert']
2913 self.assertIn((('commonName', name),), cert['subject'])
2914
2915 @needs_sni
2916 def test_sni_callback(self):
2917 calls = []
2918 server_context, other_context, client_context = self.sni_contexts()
2919
2920 def servername_cb(ssl_sock, server_name, initial_context):
2921 calls.append((server_name, initial_context))
2922 if server_name is not None:
2923 ssl_sock.context = other_context
2924 server_context.set_servername_callback(servername_cb)
2925
2926 stats = server_params_test(client_context, server_context,
2927 chatty=True,
2928 sni_name='supermessage')
2929 # The hostname was fetched properly, and the certificate was
2930 # changed for the connection.
2931 self.assertEqual(calls, [("supermessage", server_context)])
2932 # CERTFILE4 was selected
2933 self.check_common_name(stats, 'fakehostname')
2934
2935 calls = []
2936 # The callback is called with server_name=None
2937 stats = server_params_test(client_context, server_context,
2938 chatty=True,
2939 sni_name=None)
2940 self.assertEqual(calls, [(None, server_context)])
2941 self.check_common_name(stats, 'localhost')
2942
2943 # Check disabling the callback
2944 calls = []
2945 server_context.set_servername_callback(None)
2946
2947 stats = server_params_test(client_context, server_context,
2948 chatty=True,
2949 sni_name='notfunny')
2950 # Certificate didn't change
2951 self.check_common_name(stats, 'localhost')
2952 self.assertEqual(calls, [])
2953
2954 @needs_sni
2955 def test_sni_callback_alert(self):
2956 # Returning a TLS alert is reflected to the connecting client
2957 server_context, other_context, client_context = self.sni_contexts()
2958
2959 def cb_returning_alert(ssl_sock, server_name, initial_context):
2960 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2961 server_context.set_servername_callback(cb_returning_alert)
2962
2963 with self.assertRaises(ssl.SSLError) as cm:
2964 stats = server_params_test(client_context, server_context,
2965 chatty=False,
2966 sni_name='supermessage')
2967 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2968
2969 @needs_sni
2970 def test_sni_callback_raising(self):
2971 # Raising fails the connection with a TLS handshake failure alert.
2972 server_context, other_context, client_context = self.sni_contexts()
2973
2974 def cb_raising(ssl_sock, server_name, initial_context):
Serhiy Storchaka5312a7f2015-01-31 11:27:06 +02002975 1.0/0.0
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002976 server_context.set_servername_callback(cb_raising)
2977
2978 with self.assertRaises(ssl.SSLError) as cm, \
2979 support.captured_stderr() as stderr:
2980 stats = server_params_test(client_context, server_context,
2981 chatty=False,
2982 sni_name='supermessage')
2983 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2984 self.assertIn("ZeroDivisionError", stderr.getvalue())
2985
2986 @needs_sni
2987 def test_sni_callback_wrong_return_type(self):
2988 # Returning the wrong return type terminates the TLS connection
2989 # with an internal error alert.
2990 server_context, other_context, client_context = self.sni_contexts()
2991
2992 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2993 return "foo"
2994 server_context.set_servername_callback(cb_wrong_return_type)
2995
2996 with self.assertRaises(ssl.SSLError) as cm, \
2997 support.captured_stderr() as stderr:
2998 stats = server_params_test(client_context, server_context,
2999 chatty=False,
3000 sni_name='supermessage')
3001 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
3002 self.assertIn("TypeError", stderr.getvalue())
3003
3004 def test_read_write_after_close_raises_valuerror(self):
3005 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3006 context.verify_mode = ssl.CERT_REQUIRED
3007 context.load_verify_locations(CERTFILE)
3008 context.load_cert_chain(CERTFILE)
3009 server = ThreadedEchoServer(context=context, chatty=False)
3010
3011 with server:
3012 s = context.wrap_socket(socket.socket())
3013 s.connect((HOST, server.port))
3014 s.close()
3015
3016 self.assertRaises(ValueError, s.read, 1024)
3017 self.assertRaises(ValueError, s.write, b'hello')
3018
Bill Janssen61c001a2008-09-08 16:37:24 +00003019
Neal Norwitz9eb9b102007-08-27 01:15:33 +00003020def test_main(verbose=False):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003021 if support.verbose:
3022 plats = {
3023 'Linux': platform.linux_distribution,
3024 'Mac': platform.mac_ver,
3025 'Windows': platform.win32_ver,
3026 }
3027 for name, func in plats.items():
3028 plat = func()
3029 if plat and plat[0]:
3030 plat = '%s %r' % (name, plat)
3031 break
3032 else:
3033 plat = repr(platform.platform())
3034 print("test_ssl: testing with %r %r" %
3035 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3036 print(" under %s" % plat)
3037 print(" HAS_SNI = %r" % ssl.HAS_SNI)
3038 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3039 try:
3040 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3041 except AttributeError:
3042 pass
Bill Janssen296a59d2007-09-16 22:06:00 +00003043
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003044 for filename in [
Martin Panter71202bb2016-01-15 00:25:29 +00003045 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003046 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
3047 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
3048 BADCERT, BADKEY, EMPTYCERT]:
3049 if not os.path.exists(filename):
3050 raise support.TestFailed("Can't read certificate file %r" % filename)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003051
Benjamin Peterson2f334562014-10-01 23:53:01 -04003052 tests = [ContextTests, BasicTests, BasicSocketTests, SSLErrorTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003053
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003054 if support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00003055 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00003056
Bill Janssen98d19da2007-09-10 21:51:02 +00003057 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003058 thread_info = support.threading_setup()
3059 if thread_info:
Bill Janssen934b16d2008-06-28 22:19:33 +00003060 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003061
Antoine Pitrou3945c862010-04-28 21:11:01 +00003062 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003063 support.run_unittest(*tests)
Antoine Pitrou3945c862010-04-28 21:11:01 +00003064 finally:
3065 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003066 support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003067
3068if __name__ == "__main__":
3069 test_main()