blob: d283c53771cf9fc7186468693ffae1a92b8cf458 [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
350 def test_match_hostname(self):
351 def ok(cert, hostname):
352 ssl.match_hostname(cert, hostname)
353 def fail(cert, hostname):
354 self.assertRaises(ssl.CertificateError,
355 ssl.match_hostname, cert, hostname)
356
357 cert = {'subject': ((('commonName', 'example.com'),),)}
358 ok(cert, 'example.com')
359 ok(cert, 'ExAmple.cOm')
360 fail(cert, 'www.example.com')
361 fail(cert, '.example.com')
362 fail(cert, 'example.org')
363 fail(cert, 'exampleXcom')
364
365 cert = {'subject': ((('commonName', '*.a.com'),),)}
366 ok(cert, 'foo.a.com')
367 fail(cert, 'bar.foo.a.com')
368 fail(cert, 'a.com')
369 fail(cert, 'Xa.com')
370 fail(cert, '.a.com')
371
372 # only match one left-most wildcard
373 cert = {'subject': ((('commonName', 'f*.com'),),)}
374 ok(cert, 'foo.com')
375 ok(cert, 'f.com')
376 fail(cert, 'bar.com')
377 fail(cert, 'foo.a.com')
378 fail(cert, 'bar.foo.com')
379
380 # NULL bytes are bad, CVE-2013-4073
381 cert = {'subject': ((('commonName',
382 'null.python.org\x00example.org'),),)}
383 ok(cert, 'null.python.org\x00example.org') # or raise an error?
384 fail(cert, 'example.org')
385 fail(cert, 'null.python.org')
386
387 # error cases with wildcards
388 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
389 fail(cert, 'bar.foo.a.com')
390 fail(cert, 'a.com')
391 fail(cert, 'Xa.com')
392 fail(cert, '.a.com')
393
394 cert = {'subject': ((('commonName', 'a.*.com'),),)}
395 fail(cert, 'a.foo.com')
396 fail(cert, 'a..com')
397 fail(cert, 'a.com')
398
399 # wildcard doesn't match IDNA prefix 'xn--'
400 idna = u'püthon.python.org'.encode("idna").decode("ascii")
401 cert = {'subject': ((('commonName', idna),),)}
402 ok(cert, idna)
403 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
404 fail(cert, idna)
405 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
406 fail(cert, idna)
407
408 # wildcard in first fragment and IDNA A-labels in sequent fragments
409 # are supported.
410 idna = u'www*.pythön.org'.encode("idna").decode("ascii")
411 cert = {'subject': ((('commonName', idna),),)}
412 ok(cert, u'www.pythön.org'.encode("idna").decode("ascii"))
413 ok(cert, u'www1.pythön.org'.encode("idna").decode("ascii"))
414 fail(cert, u'ftp.pythön.org'.encode("idna").decode("ascii"))
415 fail(cert, u'pythön.org'.encode("idna").decode("ascii"))
416
417 # Slightly fake real-world example
418 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
419 'subject': ((('commonName', 'linuxfrz.org'),),),
420 'subjectAltName': (('DNS', 'linuxfr.org'),
421 ('DNS', 'linuxfr.com'),
422 ('othername', '<unsupported>'))}
423 ok(cert, 'linuxfr.org')
424 ok(cert, 'linuxfr.com')
425 # Not a "DNS" entry
426 fail(cert, '<unsupported>')
427 # When there is a subjectAltName, commonName isn't used
428 fail(cert, 'linuxfrz.org')
429
430 # A pristine real-world example
431 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
432 'subject': ((('countryName', 'US'),),
433 (('stateOrProvinceName', 'California'),),
434 (('localityName', 'Mountain View'),),
435 (('organizationName', 'Google Inc'),),
436 (('commonName', 'mail.google.com'),))}
437 ok(cert, 'mail.google.com')
438 fail(cert, 'gmail.com')
439 # Only commonName is considered
440 fail(cert, 'California')
441
442 # Neither commonName nor subjectAltName
443 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
444 'subject': ((('countryName', 'US'),),
445 (('stateOrProvinceName', 'California'),),
446 (('localityName', 'Mountain View'),),
447 (('organizationName', 'Google Inc'),))}
448 fail(cert, 'mail.google.com')
449
450 # No DNS entry in subjectAltName but a commonName
451 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
452 'subject': ((('countryName', 'US'),),
453 (('stateOrProvinceName', 'California'),),
454 (('localityName', 'Mountain View'),),
455 (('commonName', 'mail.google.com'),)),
456 'subjectAltName': (('othername', 'blabla'), )}
457 ok(cert, 'mail.google.com')
458
459 # No DNS entry subjectAltName and no commonName
460 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
461 'subject': ((('countryName', 'US'),),
462 (('stateOrProvinceName', 'California'),),
463 (('localityName', 'Mountain View'),),
464 (('organizationName', 'Google Inc'),)),
465 'subjectAltName': (('othername', 'blabla'),)}
466 fail(cert, 'google.com')
467
468 # Empty cert / no cert
469 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
470 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
471
472 # Issue #17980: avoid denials of service by refusing more than one
473 # wildcard per fragment.
474 cert = {'subject': ((('commonName', 'a*b.com'),),)}
475 ok(cert, 'axxb.com')
476 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
477 fail(cert, 'axxb.com')
478 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
479 with self.assertRaises(ssl.CertificateError) as cm:
480 ssl.match_hostname(cert, 'axxbxxc.com')
481 self.assertIn("too many wildcards", str(cm.exception))
482
483 def test_server_side(self):
484 # server_hostname doesn't work for server sockets
485 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
486 with closing(socket.socket()) as sock:
487 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
488 server_hostname="some.hostname")
489
490 def test_unknown_channel_binding(self):
491 # should raise ValueError for unknown type
492 s = socket.socket(socket.AF_INET)
493 with closing(ssl.wrap_socket(s)) as ss:
494 with self.assertRaises(ValueError):
495 ss.get_channel_binding("unknown-type")
496
497 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
498 "'tls-unique' channel binding not available")
499 def test_tls_unique_channel_binding(self):
500 # unconnected should return None for known type
501 s = socket.socket(socket.AF_INET)
502 with closing(ssl.wrap_socket(s)) as ss:
503 self.assertIsNone(ss.get_channel_binding("tls-unique"))
504 # the same for server-side
505 s = socket.socket(socket.AF_INET)
506 with closing(ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)) as ss:
507 self.assertIsNone(ss.get_channel_binding("tls-unique"))
508
509 def test_get_default_verify_paths(self):
510 paths = ssl.get_default_verify_paths()
511 self.assertEqual(len(paths), 6)
512 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
513
514 with support.EnvironmentVarGuard() as env:
515 env["SSL_CERT_DIR"] = CAPATH
516 env["SSL_CERT_FILE"] = CERTFILE
517 paths = ssl.get_default_verify_paths()
518 self.assertEqual(paths.cafile, CERTFILE)
519 self.assertEqual(paths.capath, CAPATH)
520
521 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
522 def test_enum_certificates(self):
523 self.assertTrue(ssl.enum_certificates("CA"))
524 self.assertTrue(ssl.enum_certificates("ROOT"))
525
526 self.assertRaises(TypeError, ssl.enum_certificates)
527 self.assertRaises(WindowsError, ssl.enum_certificates, "")
528
529 trust_oids = set()
530 for storename in ("CA", "ROOT"):
531 store = ssl.enum_certificates(storename)
532 self.assertIsInstance(store, list)
533 for element in store:
534 self.assertIsInstance(element, tuple)
535 self.assertEqual(len(element), 3)
536 cert, enc, trust = element
537 self.assertIsInstance(cert, bytes)
538 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
539 self.assertIsInstance(trust, (set, bool))
540 if isinstance(trust, set):
541 trust_oids.update(trust)
542
543 serverAuth = "1.3.6.1.5.5.7.3.1"
544 self.assertIn(serverAuth, trust_oids)
545
546 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
547 def test_enum_crls(self):
548 self.assertTrue(ssl.enum_crls("CA"))
549 self.assertRaises(TypeError, ssl.enum_crls)
550 self.assertRaises(WindowsError, ssl.enum_crls, "")
551
552 crls = ssl.enum_crls("CA")
553 self.assertIsInstance(crls, list)
554 for element in crls:
555 self.assertIsInstance(element, tuple)
556 self.assertEqual(len(element), 2)
557 self.assertIsInstance(element[0], bytes)
558 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
559
560
561 def test_asn1object(self):
562 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
563 '1.3.6.1.5.5.7.3.1')
564
565 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
566 self.assertEqual(val, expected)
567 self.assertEqual(val.nid, 129)
568 self.assertEqual(val.shortname, 'serverAuth')
569 self.assertEqual(val.longname, 'TLS Web Server Authentication')
570 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
571 self.assertIsInstance(val, ssl._ASN1Object)
572 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
573
574 val = ssl._ASN1Object.fromnid(129)
575 self.assertEqual(val, expected)
576 self.assertIsInstance(val, ssl._ASN1Object)
577 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
578 with self.assertRaisesRegexp(ValueError, "unknown NID 100000"):
579 ssl._ASN1Object.fromnid(100000)
580 for i in range(1000):
581 try:
582 obj = ssl._ASN1Object.fromnid(i)
583 except ValueError:
584 pass
585 else:
586 self.assertIsInstance(obj.nid, int)
587 self.assertIsInstance(obj.shortname, str)
588 self.assertIsInstance(obj.longname, str)
589 self.assertIsInstance(obj.oid, (str, type(None)))
590
591 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
592 self.assertEqual(val, expected)
593 self.assertIsInstance(val, ssl._ASN1Object)
594 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
595 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
596 expected)
597 with self.assertRaisesRegexp(ValueError, "unknown object 'serverauth'"):
598 ssl._ASN1Object.fromname('serverauth')
599
600 def test_purpose_enum(self):
601 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
602 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
603 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
604 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
605 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
606 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
607 '1.3.6.1.5.5.7.3.1')
608
609 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
610 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
611 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
612 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
613 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
614 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
615 '1.3.6.1.5.5.7.3.2')
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000616
Antoine Pitrou63cc99d2013-12-28 17:26:33 +0100617 def test_unsupported_dtls(self):
618 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
619 self.addCleanup(s.close)
620 with self.assertRaises(NotImplementedError) as cx:
621 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
622 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500623 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
624 with self.assertRaises(NotImplementedError) as cx:
625 ctx.wrap_socket(s)
626 self.assertEqual(str(cx.exception), "only stream sockets are supported")
627
628 def cert_time_ok(self, timestring, timestamp):
629 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
630
631 def cert_time_fail(self, timestring):
632 with self.assertRaises(ValueError):
633 ssl.cert_time_to_seconds(timestring)
634
635 @unittest.skipUnless(utc_offset(),
636 'local time needs to be different from UTC')
637 def test_cert_time_to_seconds_timezone(self):
638 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
639 # results if local timezone is not UTC
640 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
641 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
642
643 def test_cert_time_to_seconds(self):
644 timestring = "Jan 5 09:34:43 2018 GMT"
645 ts = 1515144883.0
646 self.cert_time_ok(timestring, ts)
647 # accept keyword parameter, assert its name
648 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
649 # accept both %e and %d (space or zero generated by strftime)
650 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
651 # case-insensitive
652 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
653 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
654 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
655 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
656 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
657 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
658 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
659 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
660
661 newyear_ts = 1230768000.0
662 # leap seconds
663 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
664 # same timestamp
665 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
666
667 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
668 # allow 60th second (even if it is not a leap second)
669 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
670 # allow 2nd leap second for compatibility with time.strptime()
671 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
672 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
673
674 # no special treatement for the special value:
675 # 99991231235959Z (rfc 5280)
676 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
677
678 @support.run_with_locale('LC_ALL', '')
679 def test_cert_time_to_seconds_locale(self):
680 # `cert_time_to_seconds()` should be locale independent
681
682 def local_february_name():
683 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
684
685 if local_february_name().lower() == 'feb':
686 self.skipTest("locale-specific month name needs to be "
687 "different from C locale")
688
689 # locale-independent
690 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
691 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
692
693
694class ContextTests(unittest.TestCase):
695
696 @skip_if_broken_ubuntu_ssl
697 def test_constructor(self):
698 for protocol in PROTOCOLS:
699 ssl.SSLContext(protocol)
700 self.assertRaises(TypeError, ssl.SSLContext)
701 self.assertRaises(ValueError, ssl.SSLContext, -1)
702 self.assertRaises(ValueError, ssl.SSLContext, 42)
703
704 @skip_if_broken_ubuntu_ssl
705 def test_protocol(self):
706 for proto in PROTOCOLS:
707 ctx = ssl.SSLContext(proto)
708 self.assertEqual(ctx.protocol, proto)
709
710 def test_ciphers(self):
711 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
712 ctx.set_ciphers("ALL")
713 ctx.set_ciphers("DEFAULT")
714 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
715 ctx.set_ciphers("^$:,;?*'dorothyx")
716
717 @skip_if_broken_ubuntu_ssl
718 def test_options(self):
719 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800720 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500721 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
722 ctx.options)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800723 ctx.options |= ssl.OP_NO_TLSv1
724 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1,
725 ctx.options)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500726 if can_clear_options():
727 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
728 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
729 ctx.options)
730 ctx.options = 0
731 self.assertEqual(0, ctx.options)
732 else:
733 with self.assertRaises(ValueError):
734 ctx.options = 0
735
736 def test_verify_mode(self):
737 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
738 # Default value
739 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
740 ctx.verify_mode = ssl.CERT_OPTIONAL
741 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
742 ctx.verify_mode = ssl.CERT_REQUIRED
743 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
744 ctx.verify_mode = ssl.CERT_NONE
745 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
746 with self.assertRaises(TypeError):
747 ctx.verify_mode = None
748 with self.assertRaises(ValueError):
749 ctx.verify_mode = 42
750
751 @unittest.skipUnless(have_verify_flags(),
752 "verify_flags need OpenSSL > 0.9.8")
753 def test_verify_flags(self):
754 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson72ef9612015-03-04 22:49:41 -0500755 # default value
756 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
757 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500758 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
759 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
760 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
761 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
762 ctx.verify_flags = ssl.VERIFY_DEFAULT
763 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
764 # supports any value
765 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
766 self.assertEqual(ctx.verify_flags,
767 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
768 with self.assertRaises(TypeError):
769 ctx.verify_flags = None
770
771 def test_load_cert_chain(self):
772 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
773 # Combined key and cert in a single file
Benjamin Peterson04439fd2014-11-03 21:05:01 -0500774 ctx.load_cert_chain(CERTFILE, keyfile=None)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500775 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
776 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
777 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000778 ctx.load_cert_chain(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500779 self.assertEqual(cm.exception.errno, errno.ENOENT)
780 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
781 ctx.load_cert_chain(BADCERT)
782 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
783 ctx.load_cert_chain(EMPTYCERT)
784 # Separate key and cert
785 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
786 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
787 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
788 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
789 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
790 ctx.load_cert_chain(ONLYCERT)
791 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
792 ctx.load_cert_chain(ONLYKEY)
793 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
794 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
795 # Mismatching key and cert
796 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
797 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Martin Panter71202bb2016-01-15 00:25:29 +0000798 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500799 # Password protected key and cert
800 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
801 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
802 ctx.load_cert_chain(CERTFILE_PROTECTED,
803 password=bytearray(KEY_PASSWORD.encode()))
804 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
805 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
806 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
807 bytearray(KEY_PASSWORD.encode()))
808 with self.assertRaisesRegexp(TypeError, "should be a string"):
809 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
810 with self.assertRaises(ssl.SSLError):
811 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
812 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
813 # openssl has a fixed limit on the password buffer.
814 # PEM_BUFSIZE is generally set to 1kb.
815 # Return a string larger than this.
816 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
817 # Password callback
818 def getpass_unicode():
819 return KEY_PASSWORD
820 def getpass_bytes():
821 return KEY_PASSWORD.encode()
822 def getpass_bytearray():
823 return bytearray(KEY_PASSWORD.encode())
824 def getpass_badpass():
825 return "badpass"
826 def getpass_huge():
827 return b'a' * (1024 * 1024)
828 def getpass_bad_type():
829 return 9
830 def getpass_exception():
831 raise Exception('getpass error')
832 class GetPassCallable:
833 def __call__(self):
834 return KEY_PASSWORD
835 def getpass(self):
836 return KEY_PASSWORD
837 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
838 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
839 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
840 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
841 ctx.load_cert_chain(CERTFILE_PROTECTED,
842 password=GetPassCallable().getpass)
843 with self.assertRaises(ssl.SSLError):
844 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
845 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
846 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
847 with self.assertRaisesRegexp(TypeError, "must return a string"):
848 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
849 with self.assertRaisesRegexp(Exception, "getpass error"):
850 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
851 # Make sure the password function isn't called if it isn't needed
852 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
853
854 def test_load_verify_locations(self):
855 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
856 ctx.load_verify_locations(CERTFILE)
857 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
858 ctx.load_verify_locations(BYTES_CERTFILE)
859 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400860 ctx.load_verify_locations(cafile=BYTES_CERTFILE.decode('utf-8'))
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500861 self.assertRaises(TypeError, ctx.load_verify_locations)
862 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
863 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000864 ctx.load_verify_locations(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500865 self.assertEqual(cm.exception.errno, errno.ENOENT)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400866 with self.assertRaises(IOError):
867 ctx.load_verify_locations(u'')
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500868 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
869 ctx.load_verify_locations(BADCERT)
870 ctx.load_verify_locations(CERTFILE, CAPATH)
871 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
872
873 # Issue #10989: crash if the second argument type is invalid
874 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
875
876 def test_load_verify_cadata(self):
877 # test cadata
878 with open(CAFILE_CACERT) as f:
879 cacert_pem = f.read().decode("ascii")
880 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
881 with open(CAFILE_NEURONIO) as f:
882 neuronio_pem = f.read().decode("ascii")
883 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
884
885 # test PEM
886 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
887 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
888 ctx.load_verify_locations(cadata=cacert_pem)
889 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
890 ctx.load_verify_locations(cadata=neuronio_pem)
891 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
892 # cert already in hash table
893 ctx.load_verify_locations(cadata=neuronio_pem)
894 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
895
896 # combined
897 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
898 combined = "\n".join((cacert_pem, neuronio_pem))
899 ctx.load_verify_locations(cadata=combined)
900 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
901
902 # with junk around the certs
903 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
904 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
905 neuronio_pem, "tail"]
906 ctx.load_verify_locations(cadata="\n".join(combined))
907 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
908
909 # test DER
910 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
911 ctx.load_verify_locations(cadata=cacert_der)
912 ctx.load_verify_locations(cadata=neuronio_der)
913 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
914 # cert already in hash table
915 ctx.load_verify_locations(cadata=cacert_der)
916 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
917
918 # combined
919 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
920 combined = b"".join((cacert_der, neuronio_der))
921 ctx.load_verify_locations(cadata=combined)
922 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
923
924 # error cases
925 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
926 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
927
928 with self.assertRaisesRegexp(ssl.SSLError, "no start line"):
929 ctx.load_verify_locations(cadata=u"broken")
930 with self.assertRaisesRegexp(ssl.SSLError, "not enough data"):
931 ctx.load_verify_locations(cadata=b"broken")
932
933
934 def test_load_dh_params(self):
935 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
936 ctx.load_dh_params(DHFILE)
937 if os.name != 'nt':
938 ctx.load_dh_params(BYTES_DHFILE)
939 self.assertRaises(TypeError, ctx.load_dh_params)
940 self.assertRaises(TypeError, ctx.load_dh_params, None)
941 with self.assertRaises(IOError) as cm:
Martin Panterfd8e8502016-01-30 02:36:00 +0000942 ctx.load_dh_params(NONEXISTINGCERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500943 self.assertEqual(cm.exception.errno, errno.ENOENT)
944 with self.assertRaises(ssl.SSLError) as cm:
945 ctx.load_dh_params(CERTFILE)
946
947 @skip_if_broken_ubuntu_ssl
948 def test_session_stats(self):
949 for proto in PROTOCOLS:
950 ctx = ssl.SSLContext(proto)
951 self.assertEqual(ctx.session_stats(), {
952 'number': 0,
953 'connect': 0,
954 'connect_good': 0,
955 'connect_renegotiate': 0,
956 'accept': 0,
957 'accept_good': 0,
958 'accept_renegotiate': 0,
959 'hits': 0,
960 'misses': 0,
961 'timeouts': 0,
962 'cache_full': 0,
963 })
964
965 def test_set_default_verify_paths(self):
966 # There's not much we can do to test that it acts as expected,
967 # so just check it doesn't crash or raise an exception.
968 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
969 ctx.set_default_verify_paths()
970
971 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
972 def test_set_ecdh_curve(self):
973 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
974 ctx.set_ecdh_curve("prime256v1")
975 ctx.set_ecdh_curve(b"prime256v1")
976 self.assertRaises(TypeError, ctx.set_ecdh_curve)
977 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
978 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
979 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
980
981 @needs_sni
982 def test_sni_callback(self):
983 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
984
985 # set_servername_callback expects a callable, or None
986 self.assertRaises(TypeError, ctx.set_servername_callback)
987 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
988 self.assertRaises(TypeError, ctx.set_servername_callback, "")
989 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
990
991 def dummycallback(sock, servername, ctx):
992 pass
993 ctx.set_servername_callback(None)
994 ctx.set_servername_callback(dummycallback)
995
996 @needs_sni
997 def test_sni_callback_refcycle(self):
998 # Reference cycles through the servername callback are detected
999 # and cleared.
1000 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1001 def dummycallback(sock, servername, ctx, cycle=ctx):
1002 pass
1003 ctx.set_servername_callback(dummycallback)
1004 wr = weakref.ref(ctx)
1005 del ctx, dummycallback
1006 gc.collect()
1007 self.assertIs(wr(), None)
1008
1009 def test_cert_store_stats(self):
1010 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1011 self.assertEqual(ctx.cert_store_stats(),
1012 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1013 ctx.load_cert_chain(CERTFILE)
1014 self.assertEqual(ctx.cert_store_stats(),
1015 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1016 ctx.load_verify_locations(CERTFILE)
1017 self.assertEqual(ctx.cert_store_stats(),
1018 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panter71202bb2016-01-15 00:25:29 +00001019 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001020 self.assertEqual(ctx.cert_store_stats(),
1021 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1022
1023 def test_get_ca_certs(self):
1024 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1025 self.assertEqual(ctx.get_ca_certs(), [])
1026 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1027 ctx.load_verify_locations(CERTFILE)
1028 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panter71202bb2016-01-15 00:25:29 +00001029 # but CAFILE_CACERT is a CA cert
1030 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001031 self.assertEqual(ctx.get_ca_certs(),
1032 [{'issuer': ((('organizationName', 'Root CA'),),
1033 (('organizationalUnitName', 'http://www.cacert.org'),),
1034 (('commonName', 'CA Cert Signing Authority'),),
1035 (('emailAddress', 'support@cacert.org'),)),
1036 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1037 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1038 'serialNumber': '00',
1039 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
1040 'subject': ((('organizationName', 'Root CA'),),
1041 (('organizationalUnitName', 'http://www.cacert.org'),),
1042 (('commonName', 'CA Cert Signing Authority'),),
1043 (('emailAddress', 'support@cacert.org'),)),
1044 'version': 3}])
1045
Martin Panter71202bb2016-01-15 00:25:29 +00001046 with open(CAFILE_CACERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001047 pem = f.read()
1048 der = ssl.PEM_cert_to_DER_cert(pem)
1049 self.assertEqual(ctx.get_ca_certs(True), [der])
1050
1051 def test_load_default_certs(self):
1052 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1053 ctx.load_default_certs()
1054
1055 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1056 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1057 ctx.load_default_certs()
1058
1059 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1060 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1061
1062 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1063 self.assertRaises(TypeError, ctx.load_default_certs, None)
1064 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1065
Benjamin Petersona02ae252014-10-03 18:17:15 -04001066 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson0b30a2b2014-10-03 17:27:05 -04001067 def test_load_default_certs_env(self):
1068 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1069 with support.EnvironmentVarGuard() as env:
1070 env["SSL_CERT_DIR"] = CAPATH
1071 env["SSL_CERT_FILE"] = CERTFILE
1072 ctx.load_default_certs()
1073 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1074
Benjamin Petersona02ae252014-10-03 18:17:15 -04001075 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1076 def test_load_default_certs_env_windows(self):
1077 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1078 ctx.load_default_certs()
1079 stats = ctx.cert_store_stats()
1080
1081 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1082 with support.EnvironmentVarGuard() as env:
1083 env["SSL_CERT_DIR"] = CAPATH
1084 env["SSL_CERT_FILE"] = CERTFILE
1085 ctx.load_default_certs()
1086 stats["x509"] += 1
1087 self.assertEqual(ctx.cert_store_stats(), stats)
1088
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001089 def test_create_default_context(self):
1090 ctx = ssl.create_default_context()
1091 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1092 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1093 self.assertTrue(ctx.check_hostname)
1094 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1095 self.assertEqual(
1096 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1097 getattr(ssl, "OP_NO_COMPRESSION", 0),
1098 )
1099
1100 with open(SIGNING_CA) as f:
1101 cadata = f.read().decode("ascii")
1102 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1103 cadata=cadata)
1104 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1105 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1106 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1107 self.assertEqual(
1108 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1109 getattr(ssl, "OP_NO_COMPRESSION", 0),
1110 )
1111
1112 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
1113 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1114 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1115 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1116 self.assertEqual(
1117 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1118 getattr(ssl, "OP_NO_COMPRESSION", 0),
1119 )
1120 self.assertEqual(
1121 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1122 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1123 )
1124 self.assertEqual(
1125 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1126 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1127 )
1128
1129 def test__create_stdlib_context(self):
1130 ctx = ssl._create_stdlib_context()
1131 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1132 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1133 self.assertFalse(ctx.check_hostname)
1134 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1135
1136 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1137 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1138 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1139 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1140
1141 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
1142 cert_reqs=ssl.CERT_REQUIRED,
1143 check_hostname=True)
1144 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1145 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1146 self.assertTrue(ctx.check_hostname)
1147 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1148
1149 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1150 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1151 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1152 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1153
1154 def test_check_hostname(self):
1155 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1156 self.assertFalse(ctx.check_hostname)
1157
1158 # Requires CERT_REQUIRED or CERT_OPTIONAL
1159 with self.assertRaises(ValueError):
1160 ctx.check_hostname = True
1161 ctx.verify_mode = ssl.CERT_REQUIRED
1162 self.assertFalse(ctx.check_hostname)
1163 ctx.check_hostname = True
1164 self.assertTrue(ctx.check_hostname)
1165
1166 ctx.verify_mode = ssl.CERT_OPTIONAL
1167 ctx.check_hostname = True
1168 self.assertTrue(ctx.check_hostname)
1169
1170 # Cannot set CERT_NONE with check_hostname enabled
1171 with self.assertRaises(ValueError):
1172 ctx.verify_mode = ssl.CERT_NONE
1173 ctx.check_hostname = False
1174 self.assertFalse(ctx.check_hostname)
1175
1176
1177class SSLErrorTests(unittest.TestCase):
1178
1179 def test_str(self):
1180 # The str() of a SSLError doesn't include the errno
1181 e = ssl.SSLError(1, "foo")
1182 self.assertEqual(str(e), "foo")
1183 self.assertEqual(e.errno, 1)
1184 # Same for a subclass
1185 e = ssl.SSLZeroReturnError(1, "foo")
1186 self.assertEqual(str(e), "foo")
1187 self.assertEqual(e.errno, 1)
1188
1189 def test_lib_reason(self):
1190 # Test the library and reason attributes
1191 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1192 with self.assertRaises(ssl.SSLError) as cm:
1193 ctx.load_dh_params(CERTFILE)
1194 self.assertEqual(cm.exception.library, 'PEM')
1195 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1196 s = str(cm.exception)
1197 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1198
1199 def test_subclass(self):
1200 # Check that the appropriate SSLError subclass is raised
1201 # (this only tests one of them)
1202 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1203 with closing(socket.socket()) as s:
1204 s.bind(("127.0.0.1", 0))
1205 s.listen(5)
1206 c = socket.socket()
1207 c.connect(s.getsockname())
1208 c.setblocking(False)
1209 with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c:
1210 with self.assertRaises(ssl.SSLWantReadError) as cm:
1211 c.do_handshake()
1212 s = str(cm.exception)
1213 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1214 # For compatibility
1215 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
Antoine Pitrou63cc99d2013-12-28 17:26:33 +01001216
Antoine Pitrouf9de5342010-04-05 21:35:07 +00001217
Bill Janssen934b16d2008-06-28 22:19:33 +00001218class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +00001219
Antoine Pitrou3945c862010-04-28 21:11:01 +00001220 def test_connect(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001221 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001222 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1223 cert_reqs=ssl.CERT_NONE)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001224 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001225 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001226 self.assertEqual({}, s.getpeercert())
1227 finally:
1228 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001229
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001230 # this should fail because we have no verification certs
1231 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1232 cert_reqs=ssl.CERT_REQUIRED)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001233 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001234 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001235 s.close()
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001236
1237 # this should succeed because we specify the root cert
1238 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1239 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001240 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001241 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001242 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001243 self.assertTrue(s.getpeercert())
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001244 finally:
1245 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001246
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001247 def test_connect_ex(self):
1248 # Issue #11326: check connect_ex() implementation
Martin Panter71202bb2016-01-15 00:25:29 +00001249 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001250 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1251 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001252 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001253 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001254 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001255 self.assertTrue(s.getpeercert())
1256 finally:
1257 s.close()
1258
1259 def test_non_blocking_connect_ex(self):
1260 # Issue #11326: non-blocking connect_ex() should allow handshake
1261 # to proceed after the socket gets ready.
Martin Panter71202bb2016-01-15 00:25:29 +00001262 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001263 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1264 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001265 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001266 do_handshake_on_connect=False)
1267 try:
1268 s.setblocking(False)
Martin Panter71202bb2016-01-15 00:25:29 +00001269 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +00001270 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1271 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001272 # Wait for connect to finish
1273 select.select([], [s], [], 5.0)
1274 # Non-blocking handshake
1275 while True:
1276 try:
1277 s.do_handshake()
1278 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001279 except ssl.SSLWantReadError:
1280 select.select([s], [], [], 5.0)
1281 except ssl.SSLWantWriteError:
1282 select.select([], [s], [], 5.0)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001283 # SSL established
1284 self.assertTrue(s.getpeercert())
1285 finally:
1286 s.close()
1287
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001288 def test_timeout_connect_ex(self):
1289 # Issue #12065: on a timeout, connect_ex() should return the original
1290 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter71202bb2016-01-15 00:25:29 +00001291 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001292 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1293 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001294 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001295 do_handshake_on_connect=False)
1296 try:
1297 s.settimeout(0.0000001)
Martin Panter71202bb2016-01-15 00:25:29 +00001298 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001299 if rc == 0:
Martin Panter71202bb2016-01-15 00:25:29 +00001300 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001301 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1302 finally:
1303 s.close()
1304
1305 def test_connect_ex_error(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001306 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001307 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1308 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001309 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001310 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001311 rc = s.connect_ex((REMOTE_HOST, 444))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001312 # Issue #19919: Windows machines or VMs hosted on Windows
1313 # machines sometimes return EWOULDBLOCK.
Martin Panter71202bb2016-01-15 00:25:29 +00001314 errors = (
1315 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1316 errno.EWOULDBLOCK,
1317 )
1318 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001319 finally:
1320 s.close()
1321
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001322 def test_connect_with_context(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001323 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001324 # Same as test_connect, but with a separately created context
1325 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1326 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001327 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001328 try:
1329 self.assertEqual({}, s.getpeercert())
1330 finally:
1331 s.close()
1332 # Same with a server hostname
1333 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter71202bb2016-01-15 00:25:29 +00001334 server_hostname=REMOTE_HOST)
1335 s.connect((REMOTE_HOST, 443))
Benjamin Peterson31aa69e2014-11-23 20:13:31 -06001336 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001337 # This should fail because we have no verification certs
1338 ctx.verify_mode = ssl.CERT_REQUIRED
1339 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1340 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001341 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001342 s.close()
1343 # This should succeed because we specify the root cert
Martin Panter71202bb2016-01-15 00:25:29 +00001344 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001345 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001346 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001347 try:
1348 cert = s.getpeercert()
1349 self.assertTrue(cert)
1350 finally:
1351 s.close()
1352
1353 def test_connect_capath(self):
1354 # Verify server certificates using the `capath` argument
1355 # NOTE: the subject hashing algorithm has been changed between
1356 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1357 # contain both versions of each certificate (same content, different
1358 # filename) for this test to be portable across OpenSSL releases.
Martin Panter71202bb2016-01-15 00:25:29 +00001359 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001360 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1361 ctx.verify_mode = ssl.CERT_REQUIRED
1362 ctx.load_verify_locations(capath=CAPATH)
1363 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001364 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001365 try:
1366 cert = s.getpeercert()
1367 self.assertTrue(cert)
1368 finally:
1369 s.close()
1370 # Same with a bytes `capath` argument
1371 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1372 ctx.verify_mode = ssl.CERT_REQUIRED
1373 ctx.load_verify_locations(capath=BYTES_CAPATH)
1374 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001375 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001376 try:
1377 cert = s.getpeercert()
1378 self.assertTrue(cert)
1379 finally:
1380 s.close()
1381
1382 def test_connect_cadata(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001383 with open(REMOTE_ROOT_CERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001384 pem = f.read().decode('ascii')
1385 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panter71202bb2016-01-15 00:25:29 +00001386 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001387 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1388 ctx.verify_mode = ssl.CERT_REQUIRED
1389 ctx.load_verify_locations(cadata=pem)
1390 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001391 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001392 cert = s.getpeercert()
1393 self.assertTrue(cert)
1394
1395 # same with DER
1396 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1397 ctx.verify_mode = ssl.CERT_REQUIRED
1398 ctx.load_verify_locations(cadata=der)
1399 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001400 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001401 cert = s.getpeercert()
1402 self.assertTrue(cert)
1403
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001404 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1405 def test_makefile_close(self):
1406 # Issue #5238: creating a file-like object with makefile() shouldn't
1407 # delay closing the underlying "real socket" (here tested with its
1408 # file descriptor, hence skipping the test under Windows).
Martin Panter71202bb2016-01-15 00:25:29 +00001409 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001410 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001411 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001412 fd = ss.fileno()
1413 f = ss.makefile()
1414 f.close()
1415 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001416 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001417 # Closing the SSL socket should close the fd too
1418 ss.close()
1419 gc.collect()
1420 with self.assertRaises(OSError) as e:
1421 os.read(fd, 0)
1422 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +00001423
Antoine Pitrou3945c862010-04-28 21:11:01 +00001424 def test_non_blocking_handshake(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001425 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001426 s = socket.socket(socket.AF_INET)
Martin Panter71202bb2016-01-15 00:25:29 +00001427 s.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001428 s.setblocking(False)
1429 s = ssl.wrap_socket(s,
1430 cert_reqs=ssl.CERT_NONE,
1431 do_handshake_on_connect=False)
1432 count = 0
1433 while True:
1434 try:
1435 count += 1
1436 s.do_handshake()
1437 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001438 except ssl.SSLWantReadError:
1439 select.select([s], [], [])
1440 except ssl.SSLWantWriteError:
1441 select.select([], [s], [])
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001442 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001443 if support.verbose:
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001444 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +00001445
Antoine Pitrou3945c862010-04-28 21:11:01 +00001446 def test_get_server_certificate(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001447 def _test_get_server_certificate(host, port, cert=None):
1448 with support.transient_internet(host):
1449 pem = ssl.get_server_certificate((host, port))
1450 if not pem:
1451 self.fail("No server certificate on %s:%s!" % (host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001452
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001453 try:
1454 pem = ssl.get_server_certificate((host, port),
1455 ca_certs=CERTFILE)
1456 except ssl.SSLError as x:
1457 #should fail
1458 if support.verbose:
1459 sys.stdout.write("%s\n" % x)
1460 else:
1461 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001462
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001463 pem = ssl.get_server_certificate((host, port),
1464 ca_certs=cert)
1465 if not pem:
1466 self.fail("No server certificate on %s:%s!" % (host, port))
1467 if support.verbose:
1468 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1469
Martin Panter71202bb2016-01-15 00:25:29 +00001470 _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001471 if support.IPV6_ENABLED:
1472 _test_get_server_certificate('ipv6.google.com', 443)
1473
1474 def test_ciphers(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001475 remote = (REMOTE_HOST, 443)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001476 with support.transient_internet(remote[0]):
1477 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1478 cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s:
1479 s.connect(remote)
1480 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1481 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s:
1482 s.connect(remote)
1483 # Error checking can happen at instantiation or when connecting
1484 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
1485 with closing(socket.socket(socket.AF_INET)) as sock:
1486 s = ssl.wrap_socket(sock,
1487 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1488 s.connect(remote)
Bill Janssen296a59d2007-09-16 22:06:00 +00001489
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001490 def test_algorithms(self):
1491 # Issue #8484: all algorithms should be available when verifying a
1492 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +00001493 # SHA256 was added in OpenSSL 0.9.8
1494 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1495 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001496 # sha256.tbs-internet.com needs SNI to use the correct certificate
1497 if not ssl.HAS_SNI:
1498 self.skipTest("SNI needed for this test")
1499 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
Antoine Pitroud43245a2011-01-08 10:32:51 +00001500 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001501 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001502 with support.transient_internet("sha256.tbs-internet.com"):
1503 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1504 ctx.verify_mode = ssl.CERT_REQUIRED
1505 ctx.load_verify_locations(sha256_cert)
1506 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1507 server_hostname="sha256.tbs-internet.com")
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001508 try:
1509 s.connect(remote)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001510 if support.verbose:
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001511 sys.stdout.write("\nCipher with %r is %r\n" %
1512 (remote, s.cipher()))
1513 sys.stdout.write("Certificate is:\n%s\n" %
1514 pprint.pformat(s.getpeercert()))
1515 finally:
1516 s.close()
1517
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001518 def test_get_ca_certs_capath(self):
1519 # capath certs are loaded on request
Martin Panter71202bb2016-01-15 00:25:29 +00001520 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001521 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1522 ctx.verify_mode = ssl.CERT_REQUIRED
1523 ctx.load_verify_locations(capath=CAPATH)
1524 self.assertEqual(ctx.get_ca_certs(), [])
1525 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001526 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001527 try:
1528 cert = s.getpeercert()
1529 self.assertTrue(cert)
1530 finally:
1531 s.close()
1532 self.assertEqual(len(ctx.get_ca_certs()), 1)
1533
1534 @needs_sni
1535 def test_context_setget(self):
1536 # Check that the context of a connected socket can be replaced.
Martin Panter71202bb2016-01-15 00:25:29 +00001537 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001538 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1539 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1540 s = socket.socket(socket.AF_INET)
1541 with closing(ctx1.wrap_socket(s)) as ss:
Martin Panter71202bb2016-01-15 00:25:29 +00001542 ss.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001543 self.assertIs(ss.context, ctx1)
1544 self.assertIs(ss._sslobj.context, ctx1)
1545 ss.context = ctx2
1546 self.assertIs(ss.context, ctx2)
1547 self.assertIs(ss._sslobj.context, ctx2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001548
Bill Janssen98d19da2007-09-10 21:51:02 +00001549try:
1550 import threading
1551except ImportError:
1552 _have_threads = False
1553else:
Bill Janssen98d19da2007-09-10 21:51:02 +00001554 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001555
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001556 from test.ssl_servers import make_https_server
1557
Bill Janssen98d19da2007-09-10 21:51:02 +00001558 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001559
Bill Janssen98d19da2007-09-10 21:51:02 +00001560 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001561
Bill Janssen98d19da2007-09-10 21:51:02 +00001562 """A mildly complicated class, because we want it to work both
1563 with and without the SSL wrapper around the socket connection, so
1564 that we can test the STARTTLS functionality."""
1565
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001566 def __init__(self, server, connsock, addr):
Bill Janssen98d19da2007-09-10 21:51:02 +00001567 self.server = server
1568 self.running = False
1569 self.sock = connsock
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001570 self.addr = addr
Bill Janssen98d19da2007-09-10 21:51:02 +00001571 self.sock.setblocking(1)
1572 self.sslconn = None
1573 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001574 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001575
Antoine Pitrou3945c862010-04-28 21:11:01 +00001576 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001577 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001578 self.sslconn = self.server.context.wrap_socket(
1579 self.sock, server_side=True)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001580 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1581 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001582 except socket.error as e:
1583 # We treat ConnectionResetError as though it were an
1584 # SSLError - OpenSSL on Ubuntu abruptly closes the
1585 # connection when asked to use an unsupported protocol.
1586 #
Antoine Pitroudb187842010-04-27 10:32:58 +00001587 # XXX Various errors can have happened here, for example
1588 # a mismatching protocol version, an invalid certificate,
1589 # or a low-level bug. This should be made more discriminating.
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001590 if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET:
1591 raise
Antoine Pitroud76088d2012-01-03 22:46:48 +01001592 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +00001593 if self.server.chatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001594 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00001595 self.running = False
1596 self.server.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001597 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001598 return False
Bill Janssen98d19da2007-09-10 21:51:02 +00001599 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001600 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
1601 cert = self.sslconn.getpeercert()
1602 if support.verbose and self.server.chatty:
1603 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1604 cert_binary = self.sslconn.getpeercert(True)
1605 if support.verbose and self.server.chatty:
1606 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1607 cipher = self.sslconn.cipher()
1608 if support.verbose and self.server.chatty:
1609 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
1610 sys.stdout.write(" server: selected protocol is now "
1611 + str(self.sslconn.selected_npn_protocol()) + "\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001612 return True
1613
1614 def read(self):
1615 if self.sslconn:
1616 return self.sslconn.read()
1617 else:
1618 return self.sock.recv(1024)
1619
1620 def write(self, bytes):
1621 if self.sslconn:
1622 return self.sslconn.write(bytes)
1623 else:
1624 return self.sock.send(bytes)
1625
1626 def close(self):
1627 if self.sslconn:
1628 self.sslconn.close()
1629 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001630 self.sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001631
Antoine Pitrou3945c862010-04-28 21:11:01 +00001632 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001633 self.running = True
1634 if not self.server.starttls_server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001635 if not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +00001636 return
1637 while self.running:
1638 try:
1639 msg = self.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001640 stripped = msg.strip()
1641 if not stripped:
Bill Janssen98d19da2007-09-10 21:51:02 +00001642 # eof, so quit this handler
1643 self.running = False
1644 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001645 elif stripped == b'over':
1646 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001647 sys.stdout.write(" server: client closed connection\n")
1648 self.close()
1649 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001650 elif (self.server.starttls_server and
1651 stripped == b'STARTTLS'):
1652 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001653 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001654 self.write(b"OK\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001655 if not self.wrap_conn():
1656 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001657 elif (self.server.starttls_server and self.sslconn
1658 and stripped == b'ENDTLS'):
1659 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001660 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001661 self.write(b"OK\n")
1662 self.sock = self.sslconn.unwrap()
Bill Janssen39295c22008-08-12 16:31:21 +00001663 self.sslconn = None
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001664 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001665 sys.stdout.write(" server: connection is now unencrypted...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001666 elif stripped == b'CB tls-unique':
1667 if support.verbose and self.server.connectionchatty:
1668 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1669 data = self.sslconn.get_channel_binding("tls-unique")
1670 self.write(repr(data).encode("us-ascii") + b"\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001671 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001672 if (support.verbose and
Bill Janssen98d19da2007-09-10 21:51:02 +00001673 self.server.connectionchatty):
1674 ctype = (self.sslconn and "encrypted") or "unencrypted"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001675 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1676 % (msg, ctype, msg.lower(), ctype))
Bill Janssen98d19da2007-09-10 21:51:02 +00001677 self.write(msg.lower())
1678 except ssl.SSLError:
1679 if self.server.chatty:
1680 handle_error("Test server failure:\n")
1681 self.close()
1682 self.running = False
1683 # normally, we'd just stop here, but for the test
1684 # harness, we want to stop the server
1685 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +00001686
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001687 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +00001688 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +00001689 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001690 npn_protocols=None, alpn_protocols=None,
1691 ciphers=None, context=None):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001692 if context:
1693 self.context = context
1694 else:
1695 self.context = ssl.SSLContext(ssl_version
1696 if ssl_version is not None
1697 else ssl.PROTOCOL_TLSv1)
1698 self.context.verify_mode = (certreqs if certreqs is not None
1699 else ssl.CERT_NONE)
1700 if cacerts:
1701 self.context.load_verify_locations(cacerts)
1702 if certificate:
1703 self.context.load_cert_chain(certificate)
1704 if npn_protocols:
1705 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001706 if alpn_protocols:
1707 self.context.set_alpn_protocols(alpn_protocols)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001708 if ciphers:
1709 self.context.set_ciphers(ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +00001710 self.chatty = chatty
1711 self.connectionchatty = connectionchatty
1712 self.starttls_server = starttls_server
1713 self.sock = socket.socket()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001714 self.port = support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +00001715 self.flag = None
Bill Janssen98d19da2007-09-10 21:51:02 +00001716 self.active = False
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001717 self.selected_npn_protocols = []
1718 self.selected_alpn_protocols = []
Antoine Pitroud76088d2012-01-03 22:46:48 +01001719 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001720 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001721 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001722
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001723 def __enter__(self):
1724 self.start(threading.Event())
1725 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001726 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001727
1728 def __exit__(self, *args):
1729 self.stop()
1730 self.join()
1731
Antoine Pitrou3945c862010-04-28 21:11:01 +00001732 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +00001733 self.flag = flag
1734 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001735
Antoine Pitrou3945c862010-04-28 21:11:01 +00001736 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +00001737 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +00001738 self.sock.listen(5)
1739 self.active = True
1740 if self.flag:
1741 # signal an event
1742 self.flag.set()
1743 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001744 try:
Bill Janssen98d19da2007-09-10 21:51:02 +00001745 newconn, connaddr = self.sock.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001746 if support.verbose and self.chatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001747 sys.stdout.write(' server: new connection from '
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001748 + repr(connaddr) + '\n')
1749 handler = self.ConnectionHandler(self, newconn, connaddr)
Bill Janssen98d19da2007-09-10 21:51:02 +00001750 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +01001751 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +00001752 except socket.timeout:
1753 pass
1754 except KeyboardInterrupt:
1755 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +00001756 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001757
Antoine Pitrou3945c862010-04-28 21:11:01 +00001758 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001759 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001760
Bill Janssen934b16d2008-06-28 22:19:33 +00001761 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +00001762
Antoine Pitrou3945c862010-04-28 21:11:01 +00001763 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +00001764
Antoine Pitrou3945c862010-04-28 21:11:01 +00001765 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +00001766
1767 def __init__(self, conn, certfile):
Bill Janssen934b16d2008-06-28 22:19:33 +00001768 self.socket = ssl.wrap_socket(conn, server_side=True,
1769 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +00001770 do_handshake_on_connect=False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001771 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroufc69af12010-04-24 20:04:58 +00001772 self._ssl_accepting = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001773 self._do_ssl_handshake()
Bill Janssen934b16d2008-06-28 22:19:33 +00001774
1775 def readable(self):
1776 if isinstance(self.socket, ssl.SSLSocket):
1777 while self.socket.pending() > 0:
1778 self.handle_read_event()
1779 return True
1780
Antoine Pitroufc69af12010-04-24 20:04:58 +00001781 def _do_ssl_handshake(self):
1782 try:
1783 self.socket.do_handshake()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001784 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1785 return
1786 except ssl.SSLEOFError:
1787 return self.handle_close()
1788 except ssl.SSLError:
Antoine Pitroufc69af12010-04-24 20:04:58 +00001789 raise
1790 except socket.error, err:
1791 if err.args[0] == errno.ECONNABORTED:
1792 return self.handle_close()
1793 else:
1794 self._ssl_accepting = False
1795
Bill Janssen934b16d2008-06-28 22:19:33 +00001796 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +00001797 if self._ssl_accepting:
1798 self._do_ssl_handshake()
1799 else:
1800 data = self.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001801 if support.verbose:
1802 sys.stdout.write(" server: read %s from client\n" % repr(data))
1803 if not data:
1804 self.close()
1805 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001806 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +00001807
1808 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +00001809 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001810 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001811 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1812
1813 def handle_error(self):
1814 raise
1815
1816 def __init__(self, certfile):
1817 self.certfile = certfile
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001818 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1819 self.port = support.bind_port(sock, '')
1820 asyncore.dispatcher.__init__(self, sock)
Bill Janssen934b16d2008-06-28 22:19:33 +00001821 self.listen(5)
1822
1823 def handle_accept(self):
1824 sock_obj, addr = self.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001825 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001826 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1827 self.ConnectionHandler(sock_obj, self.certfile)
1828
1829 def handle_error(self):
1830 raise
1831
1832 def __init__(self, certfile):
1833 self.flag = None
1834 self.active = False
1835 self.server = self.EchoServer(certfile)
1836 self.port = self.server.port
1837 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001838 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +00001839
1840 def __str__(self):
1841 return "<%s %s>" % (self.__class__.__name__, self.server)
1842
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001843 def __enter__(self):
1844 self.start(threading.Event())
1845 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001846 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001847
1848 def __exit__(self, *args):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001849 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001850 sys.stdout.write(" cleanup: stopping server.\n")
1851 self.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001852 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001853 sys.stdout.write(" cleanup: joining server thread.\n")
1854 self.join()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001855 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001856 sys.stdout.write(" cleanup: successfully joined.\n")
1857
Antoine Pitrou3945c862010-04-28 21:11:01 +00001858 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +00001859 self.flag = flag
1860 threading.Thread.start(self)
1861
Antoine Pitrou3945c862010-04-28 21:11:01 +00001862 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001863 self.active = True
1864 if self.flag:
1865 self.flag.set()
1866 while self.active:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001867 try:
1868 asyncore.loop(1)
1869 except:
1870 pass
Bill Janssen934b16d2008-06-28 22:19:33 +00001871
Antoine Pitrou3945c862010-04-28 21:11:01 +00001872 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001873 self.active = False
1874 self.server.close()
1875
Antoine Pitrou3945c862010-04-28 21:11:01 +00001876 def bad_cert_test(certfile):
1877 """
1878 Launch a server with CERT_REQUIRED, and check that trying to
1879 connect to it with the given client certificate fails.
1880 """
Trent Nelsone41b0062008-04-08 23:47:30 +00001881 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001882 certreqs=ssl.CERT_REQUIRED,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001883 cacerts=CERTFILE, chatty=False,
1884 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001885 with server:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001886 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001887 with closing(socket.socket()) as sock:
1888 s = ssl.wrap_socket(sock,
1889 certfile=certfile,
1890 ssl_version=ssl.PROTOCOL_TLSv1)
1891 s.connect((HOST, server.port))
1892 except ssl.SSLError as x:
1893 if support.verbose:
1894 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
1895 except OSError as x:
1896 if support.verbose:
1897 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Bill Janssen98d19da2007-09-10 21:51:02 +00001898 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00001899 raise AssertionError("Use of invalid cert should have failed!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001900
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001901 def server_params_test(client_context, server_context, indata=b"FOO\n",
1902 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001903 """
1904 Launch a server, connect a client to it and try various reads
1905 and writes.
1906 """
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001907 stats = {}
1908 server = ThreadedEchoServer(context=server_context,
Bill Janssen98d19da2007-09-10 21:51:02 +00001909 chatty=chatty,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001910 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001911 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001912 with closing(client_context.wrap_socket(socket.socket(),
1913 server_hostname=sni_name)) as s:
1914 s.connect((HOST, server.port))
1915 for arg in [indata, bytearray(indata), memoryview(indata)]:
1916 if connectionchatty:
1917 if support.verbose:
1918 sys.stdout.write(
1919 " client: sending %r...\n" % indata)
1920 s.write(arg)
1921 outdata = s.read()
1922 if connectionchatty:
1923 if support.verbose:
1924 sys.stdout.write(" client: read %r\n" % outdata)
1925 if outdata != indata.lower():
1926 raise AssertionError(
1927 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1928 % (outdata[:20], len(outdata),
1929 indata[:20].lower(), len(indata)))
1930 s.write(b"over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001931 if connectionchatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001932 if support.verbose:
1933 sys.stdout.write(" client: closing connection.\n")
1934 stats.update({
1935 'compression': s.compression(),
1936 'cipher': s.cipher(),
1937 'peercert': s.getpeercert(),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001938 'client_alpn_protocol': s.selected_alpn_protocol(),
Alex Gaynore98205d2014-09-04 13:33:22 -07001939 'client_npn_protocol': s.selected_npn_protocol(),
1940 'version': s.version(),
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001941 })
1942 s.close()
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001943 stats['server_alpn_protocols'] = server.selected_alpn_protocols
1944 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001945 return stats
Bill Janssen98d19da2007-09-10 21:51:02 +00001946
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001947 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1948 certsreqs=None, server_options=0, client_options=0):
Alex Gaynore98205d2014-09-04 13:33:22 -07001949 """
1950 Try to SSL-connect using *client_protocol* to *server_protocol*.
1951 If *expect_success* is true, assert that the connection succeeds,
1952 if it's false, assert that the connection fails.
1953 Also, if *expect_success* is a string, assert that it is the protocol
1954 version actually used by the connection.
1955 """
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00001956 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +00001957 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +00001958 certtype = {
1959 ssl.CERT_NONE: "CERT_NONE",
1960 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1961 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1962 }[certsreqs]
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001963 if support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001964 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +00001965 sys.stdout.write(formatstr %
1966 (ssl.get_protocol_name(client_protocol),
1967 ssl.get_protocol_name(server_protocol),
1968 certtype))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001969 client_context = ssl.SSLContext(client_protocol)
1970 client_context.options |= client_options
1971 server_context = ssl.SSLContext(server_protocol)
1972 server_context.options |= server_options
1973
1974 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1975 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1976 # starting from OpenSSL 1.0.0 (see issue #8322).
1977 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1978 client_context.set_ciphers("ALL")
1979
1980 for ctx in (client_context, server_context):
1981 ctx.verify_mode = certsreqs
1982 ctx.load_cert_chain(CERTFILE)
1983 ctx.load_verify_locations(CERTFILE)
Bill Janssen98d19da2007-09-10 21:51:02 +00001984 try:
Alex Gaynore98205d2014-09-04 13:33:22 -07001985 stats = server_params_test(client_context, server_context,
1986 chatty=False, connectionchatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00001987 # Protocol mismatch can result in either an SSLError, or a
1988 # "Connection reset by peer" error.
1989 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001990 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +00001991 raise
Antoine Pitroudb187842010-04-27 10:32:58 +00001992 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001993 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +00001994 raise
Bill Janssen98d19da2007-09-10 21:51:02 +00001995 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001996 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00001997 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +00001998 "Client protocol %s succeeded with server protocol %s!"
1999 % (ssl.get_protocol_name(client_protocol),
2000 ssl.get_protocol_name(server_protocol)))
Alex Gaynore98205d2014-09-04 13:33:22 -07002001 elif (expect_success is not True
2002 and expect_success != stats['version']):
2003 raise AssertionError("version mismatch: expected %r, got %r"
2004 % (expect_success, stats['version']))
Bill Janssen98d19da2007-09-10 21:51:02 +00002005
2006
Bill Janssen934b16d2008-06-28 22:19:33 +00002007 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +00002008
Antoine Pitroud75efd92010-08-04 17:38:33 +00002009 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002010 def test_echo(self):
2011 """Basic test of an SSL client connecting to a server"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002012 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002013 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002014 for protocol in PROTOCOLS:
2015 context = ssl.SSLContext(protocol)
2016 context.load_cert_chain(CERTFILE)
2017 server_params_test(context, context,
2018 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002019
Antoine Pitrou3945c862010-04-28 21:11:01 +00002020 def test_getpeercert(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002021 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002022 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002023 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2024 context.verify_mode = ssl.CERT_REQUIRED
2025 context.load_verify_locations(CERTFILE)
2026 context.load_cert_chain(CERTFILE)
2027 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002028 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002029 s = context.wrap_socket(socket.socket(),
2030 do_handshake_on_connect=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002031 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002032 # getpeercert() raise ValueError while the handshake isn't
2033 # done.
2034 with self.assertRaises(ValueError):
2035 s.getpeercert()
2036 s.do_handshake()
Antoine Pitroudb187842010-04-27 10:32:58 +00002037 cert = s.getpeercert()
2038 self.assertTrue(cert, "Can't get peer certificate.")
2039 cipher = s.cipher()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002040 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002041 sys.stdout.write(pprint.pformat(cert) + '\n')
2042 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2043 if 'subject' not in cert:
2044 self.fail("No subject field in certificate: %s." %
2045 pprint.pformat(cert))
2046 if ((('organizationName', 'Python Software Foundation'),)
2047 not in cert['subject']):
2048 self.fail(
2049 "Missing or invalid 'organizationName' field in certificate subject; "
2050 "should be 'Python Software Foundation'.")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002051 self.assertIn('notBefore', cert)
2052 self.assertIn('notAfter', cert)
2053 before = ssl.cert_time_to_seconds(cert['notBefore'])
2054 after = ssl.cert_time_to_seconds(cert['notAfter'])
2055 self.assertLess(before, after)
Antoine Pitroudb187842010-04-27 10:32:58 +00002056 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002057
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002058 @unittest.skipUnless(have_verify_flags(),
2059 "verify_flags need OpenSSL > 0.9.8")
2060 def test_crl_check(self):
2061 if support.verbose:
2062 sys.stdout.write("\n")
2063
2064 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2065 server_context.load_cert_chain(SIGNED_CERTFILE)
2066
2067 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2068 context.verify_mode = ssl.CERT_REQUIRED
2069 context.load_verify_locations(SIGNING_CA)
Benjamin Petersond86699f2015-03-04 23:18:48 -05002070 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2071 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002072
2073 # VERIFY_DEFAULT should pass
2074 server = ThreadedEchoServer(context=server_context, chatty=True)
2075 with server:
2076 with closing(context.wrap_socket(socket.socket())) as s:
2077 s.connect((HOST, server.port))
2078 cert = s.getpeercert()
2079 self.assertTrue(cert, "Can't get peer certificate.")
2080
2081 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
2082 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
2083
2084 server = ThreadedEchoServer(context=server_context, chatty=True)
2085 with server:
2086 with closing(context.wrap_socket(socket.socket())) as s:
2087 with self.assertRaisesRegexp(ssl.SSLError,
2088 "certificate verify failed"):
2089 s.connect((HOST, server.port))
2090
2091 # now load a CRL file. The CRL file is signed by the CA.
2092 context.load_verify_locations(CRLFILE)
2093
2094 server = ThreadedEchoServer(context=server_context, chatty=True)
2095 with server:
2096 with closing(context.wrap_socket(socket.socket())) as s:
2097 s.connect((HOST, server.port))
2098 cert = s.getpeercert()
2099 self.assertTrue(cert, "Can't get peer certificate.")
2100
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002101 def test_check_hostname(self):
2102 if support.verbose:
2103 sys.stdout.write("\n")
2104
2105 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2106 server_context.load_cert_chain(SIGNED_CERTFILE)
2107
2108 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2109 context.verify_mode = ssl.CERT_REQUIRED
2110 context.check_hostname = True
2111 context.load_verify_locations(SIGNING_CA)
2112
2113 # correct hostname should verify
2114 server = ThreadedEchoServer(context=server_context, chatty=True)
2115 with server:
2116 with closing(context.wrap_socket(socket.socket(),
2117 server_hostname="localhost")) as s:
2118 s.connect((HOST, server.port))
2119 cert = s.getpeercert()
2120 self.assertTrue(cert, "Can't get peer certificate.")
2121
2122 # incorrect hostname should raise an exception
2123 server = ThreadedEchoServer(context=server_context, chatty=True)
2124 with server:
2125 with closing(context.wrap_socket(socket.socket(),
2126 server_hostname="invalid")) as s:
2127 with self.assertRaisesRegexp(ssl.CertificateError,
2128 "hostname 'invalid' doesn't match u?'localhost'"):
2129 s.connect((HOST, server.port))
2130
2131 # missing server_hostname arg should cause an exception, too
2132 server = ThreadedEchoServer(context=server_context, chatty=True)
2133 with server:
2134 with closing(socket.socket()) as s:
2135 with self.assertRaisesRegexp(ValueError,
2136 "check_hostname requires server_hostname"):
2137 context.wrap_socket(s)
2138
Antoine Pitrou3945c862010-04-28 21:11:01 +00002139 def test_empty_cert(self):
2140 """Connecting with an empty cert file"""
2141 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2142 "nullcert.pem"))
2143 def test_malformed_cert(self):
2144 """Connecting with a badly formatted certificate (syntax error)"""
2145 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2146 "badcert.pem"))
Martin Panterfd8e8502016-01-30 02:36:00 +00002147 def test_wrong_cert(self):
2148 """Connecting with a cert file not matching the server"""
Antoine Pitrou3945c862010-04-28 21:11:01 +00002149 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2150 "wrongcert.pem"))
2151 def test_malformed_key(self):
2152 """Connecting with a badly formatted key (syntax error)"""
2153 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2154 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +00002155
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002156 def test_rude_shutdown(self):
2157 """A brutal shutdown of an SSL server should raise an OSError
2158 in the client when attempting handshake.
2159 """
2160 listener_ready = threading.Event()
2161 listener_gone = threading.Event()
2162
2163 s = socket.socket()
2164 port = support.bind_port(s, HOST)
2165
2166 # `listener` runs in a thread. It sits in an accept() until
2167 # the main thread connects. Then it rudely closes the socket,
2168 # and sets Event `listener_gone` to let the main thread know
2169 # the socket is gone.
2170 def listener():
2171 s.listen(5)
2172 listener_ready.set()
2173 newsock, addr = s.accept()
2174 newsock.close()
2175 s.close()
2176 listener_gone.set()
2177
2178 def connector():
2179 listener_ready.wait()
2180 with closing(socket.socket()) as c:
2181 c.connect((HOST, port))
2182 listener_gone.wait()
2183 try:
2184 ssl_sock = ssl.wrap_socket(c)
Benjamin Petersone208b572014-08-20 14:49:08 -05002185 except socket.error:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002186 pass
2187 else:
2188 self.fail('connecting to closed SSL socket should have failed')
2189
2190 t = threading.Thread(target=listener)
2191 t.start()
2192 try:
2193 connector()
2194 finally:
2195 t.join()
2196
Antoine Pitroud75efd92010-08-04 17:38:33 +00002197 @skip_if_broken_ubuntu_ssl
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002198 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2199 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002200 def test_protocol_sslv2(self):
2201 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002202 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002203 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002204 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2205 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2206 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01002207 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002208 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2209 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002210 # SSLv23 client with specific SSL options
2211 if no_sslv2_implies_sslv3_hello():
2212 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2213 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2214 client_options=ssl.OP_NO_SSLv2)
2215 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2216 client_options=ssl.OP_NO_SSLv3)
2217 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2218 client_options=ssl.OP_NO_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00002219
Antoine Pitroud75efd92010-08-04 17:38:33 +00002220 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002221 def test_protocol_sslv23(self):
2222 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002223 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002224 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002225 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2226 try:
2227 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
2228 except socket.error as x:
2229 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2230 if support.verbose:
2231 sys.stdout.write(
2232 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2233 % str(x))
Benjamin Peterson60766c42014-12-05 21:59:35 -05002234 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002235 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002236 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Alex Gaynore98205d2014-09-04 13:33:22 -07002237 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Bill Janssen98d19da2007-09-10 21:51:02 +00002238
Benjamin Peterson60766c42014-12-05 21:59:35 -05002239 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002240 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002241 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Alex Gaynore98205d2014-09-04 13:33:22 -07002242 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00002243
Benjamin Peterson60766c42014-12-05 21:59:35 -05002244 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002245 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002246 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Alex Gaynore98205d2014-09-04 13:33:22 -07002247 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00002248
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002249 # Server with specific SSL options
Benjamin Peterson60766c42014-12-05 21:59:35 -05002250 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2251 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002252 server_options=ssl.OP_NO_SSLv3)
2253 # Will choose TLSv1
2254 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2255 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2256 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2257 server_options=ssl.OP_NO_TLSv1)
2258
2259
Antoine Pitroud75efd92010-08-04 17:38:33 +00002260 @skip_if_broken_ubuntu_ssl
Benjamin Peterson60766c42014-12-05 21:59:35 -05002261 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2262 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002263 def test_protocol_sslv3(self):
2264 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002265 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002266 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002267 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2268 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2269 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002270 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2271 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002272 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2273 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002274 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002275 if no_sslv2_implies_sslv3_hello():
2276 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002277 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2278 False, client_options=ssl.OP_NO_SSLv2)
Bill Janssen98d19da2007-09-10 21:51:02 +00002279
Antoine Pitroud75efd92010-08-04 17:38:33 +00002280 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002281 def test_protocol_tlsv1(self):
2282 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002283 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002284 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002285 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2286 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2287 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002288 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2289 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002290 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2291 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002292 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2293 client_options=ssl.OP_NO_TLSv1)
2294
2295 @skip_if_broken_ubuntu_ssl
2296 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2297 "TLS version 1.1 not supported.")
2298 def test_protocol_tlsv1_1(self):
2299 """Connecting to a TLSv1.1 server with various client options.
2300 Testing against older TLS versions."""
2301 if support.verbose:
2302 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002303 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002304 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2305 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002306 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2307 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002308 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2309 client_options=ssl.OP_NO_TLSv1_1)
2310
Alex Gaynore98205d2014-09-04 13:33:22 -07002311 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002312 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2313 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2314
2315
2316 @skip_if_broken_ubuntu_ssl
2317 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2318 "TLS version 1.2 not supported.")
2319 def test_protocol_tlsv1_2(self):
2320 """Connecting to a TLSv1.2 server with various client options.
2321 Testing against older TLS versions."""
2322 if support.verbose:
2323 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002324 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002325 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2326 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2327 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2328 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002329 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2330 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002331 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2332 client_options=ssl.OP_NO_TLSv1_2)
2333
Alex Gaynore98205d2014-09-04 13:33:22 -07002334 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002335 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2336 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2337 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2338 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00002339
Antoine Pitrou3945c862010-04-28 21:11:01 +00002340 def test_starttls(self):
2341 """Switching from clear text to encrypted and back again."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002342 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 +00002343
Trent Nelsone41b0062008-04-08 23:47:30 +00002344 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00002345 ssl_version=ssl.PROTOCOL_TLSv1,
2346 starttls_server=True,
2347 chatty=True,
2348 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002349 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002350 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002351 s = socket.socket()
2352 s.setblocking(1)
2353 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002354 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002355 sys.stdout.write("\n")
2356 for indata in msgs:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002357 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002358 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002359 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002360 if wrapped:
2361 conn.write(indata)
2362 outdata = conn.read()
2363 else:
2364 s.send(indata)
2365 outdata = s.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002366 msg = outdata.strip().lower()
2367 if indata == b"STARTTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002368 # STARTTLS ok, switch to secure mode
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002369 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002370 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002371 " client: read %r from server, starting TLS...\n"
2372 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002373 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2374 wrapped = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002375 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002376 # ENDTLS ok, switch back to clear text
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002377 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002378 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002379 " client: read %r from server, ending TLS...\n"
2380 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002381 s = conn.unwrap()
2382 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00002383 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002384 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002385 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002386 " client: read %r from server\n" % msg)
2387 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002388 sys.stdout.write(" client: closing connection.\n")
2389 if wrapped:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002390 conn.write(b"over\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00002391 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002392 s.send(b"over\n")
2393 if wrapped:
2394 conn.close()
2395 else:
2396 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002397
Antoine Pitrou3945c862010-04-28 21:11:01 +00002398 def test_socketserver(self):
2399 """Using a SocketServer to create and manage SSL connections."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002400 server = make_https_server(self, certfile=CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00002401 # try to connect
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002402 if support.verbose:
2403 sys.stdout.write('\n')
2404 with open(CERTFILE, 'rb') as f:
2405 d1 = f.read()
2406 d2 = ''
2407 # now fetch the same data from the HTTPS server
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -06002408 url = 'https://localhost:%d/%s' % (
2409 server.port, os.path.split(CERTFILE)[1])
2410 context = ssl.create_default_context(cafile=CERTFILE)
Benjamin Petersonb0609ec2014-11-23 11:52:46 -06002411 f = urllib2.urlopen(url, context=context)
Bill Janssen296a59d2007-09-16 22:06:00 +00002412 try:
Bill Janssen296a59d2007-09-16 22:06:00 +00002413 dlen = f.info().getheader("content-length")
2414 if dlen and (int(dlen) > 0):
2415 d2 = f.read(int(dlen))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002416 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002417 sys.stdout.write(
2418 " client: read %d bytes from remote server '%s'\n"
2419 % (len(d2), server))
Bill Janssen296a59d2007-09-16 22:06:00 +00002420 finally:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002421 f.close()
2422 self.assertEqual(d1, d2)
Bill Janssen934b16d2008-06-28 22:19:33 +00002423
Antoine Pitrou3945c862010-04-28 21:11:01 +00002424 def test_asyncore_server(self):
2425 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00002426 indata = "TEST MESSAGE of mixed case\n"
2427
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002428 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00002429 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002430
2431 indata = b"FOO\n"
Bill Janssen934b16d2008-06-28 22:19:33 +00002432 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002433 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002434 s = ssl.wrap_socket(socket.socket())
2435 s.connect(('127.0.0.1', server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002436 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002437 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002438 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002439 s.write(indata)
2440 outdata = s.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002441 if support.verbose:
2442 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002443 if outdata != indata.lower():
2444 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002445 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2446 % (outdata[:20], len(outdata),
2447 indata[:20].lower(), len(indata)))
2448 s.write(b"over\n")
2449 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002450 sys.stdout.write(" client: closing connection.\n")
2451 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002452 if support.verbose:
2453 sys.stdout.write(" client: connection closed.\n")
Bill Janssen934b16d2008-06-28 22:19:33 +00002454
Antoine Pitrou3945c862010-04-28 21:11:01 +00002455 def test_recv_send(self):
2456 """Test recv(), send() and friends."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002457 if support.verbose:
Bill Janssen61c001a2008-09-08 16:37:24 +00002458 sys.stdout.write("\n")
2459
2460 server = ThreadedEchoServer(CERTFILE,
2461 certreqs=ssl.CERT_NONE,
2462 ssl_version=ssl.PROTOCOL_TLSv1,
2463 cacerts=CERTFILE,
2464 chatty=True,
2465 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002466 with server:
2467 s = ssl.wrap_socket(socket.socket(),
2468 server_side=False,
2469 certfile=CERTFILE,
2470 ca_certs=CERTFILE,
2471 cert_reqs=ssl.CERT_NONE,
2472 ssl_version=ssl.PROTOCOL_TLSv1)
2473 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00002474 # helper methods for standardising recv* method signatures
2475 def _recv_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002476 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002477 count = s.recv_into(b)
2478 return b[:count]
2479
2480 def _recvfrom_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002481 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002482 count, addr = s.recvfrom_into(b)
2483 return b[:count]
2484
2485 # (name, method, whether to expect success, *args)
2486 send_methods = [
2487 ('send', s.send, True, []),
2488 ('sendto', s.sendto, False, ["some.address"]),
2489 ('sendall', s.sendall, True, []),
2490 ]
2491 recv_methods = [
2492 ('recv', s.recv, True, []),
2493 ('recvfrom', s.recvfrom, False, ["some.address"]),
2494 ('recv_into', _recv_into, True, []),
2495 ('recvfrom_into', _recvfrom_into, False, []),
2496 ]
2497 data_prefix = u"PREFIX_"
2498
2499 for meth_name, send_meth, expect_success, args in send_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002500 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002501 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002502 send_meth(indata, *args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002503 outdata = s.read()
Bill Janssen61c001a2008-09-08 16:37:24 +00002504 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002505 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002506 "While sending with <<{name:s}>> bad data "
2507 "<<{outdata:r}>> ({nout:d}) received; "
2508 "expected <<{indata:r}>> ({nin:d})\n".format(
2509 name=meth_name, outdata=outdata[:20],
2510 nout=len(outdata),
2511 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002512 )
2513 )
2514 except ValueError as e:
2515 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002516 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002517 "Failed to send with method <<{name:s}>>; "
2518 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002519 )
2520 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002521 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002522 "Method <<{name:s}>> failed with unexpected "
2523 "exception message: {exp:s}\n".format(
2524 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002525 )
2526 )
2527
2528 for meth_name, recv_meth, expect_success, args in recv_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002529 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002530 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002531 s.send(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002532 outdata = recv_meth(*args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002533 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002534 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002535 "While receiving with <<{name:s}>> bad data "
2536 "<<{outdata:r}>> ({nout:d}) received; "
2537 "expected <<{indata:r}>> ({nin:d})\n".format(
2538 name=meth_name, outdata=outdata[:20],
2539 nout=len(outdata),
2540 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002541 )
2542 )
2543 except ValueError as e:
2544 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002545 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002546 "Failed to receive with method <<{name:s}>>; "
2547 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002548 )
2549 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002550 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002551 "Method <<{name:s}>> failed with unexpected "
2552 "exception message: {exp:s}\n".format(
2553 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002554 )
2555 )
2556 # consume data
2557 s.read()
2558
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002559 s.write(b"over\n")
Bill Janssen61c001a2008-09-08 16:37:24 +00002560 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00002561
Antoine Pitroufc69af12010-04-24 20:04:58 +00002562 def test_handshake_timeout(self):
2563 # Issue #5103: SSL handshake must respect the socket timeout
2564 server = socket.socket(socket.AF_INET)
2565 host = "127.0.0.1"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002566 port = support.bind_port(server)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002567 started = threading.Event()
2568 finish = False
2569
2570 def serve():
2571 server.listen(5)
2572 started.set()
2573 conns = []
2574 while not finish:
2575 r, w, e = select.select([server], [], [], 0.1)
2576 if server in r:
2577 # Let the socket hang around rather than having
2578 # it closed by garbage collection.
2579 conns.append(server.accept()[0])
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002580 for sock in conns:
2581 sock.close()
Antoine Pitroufc69af12010-04-24 20:04:58 +00002582
2583 t = threading.Thread(target=serve)
2584 t.start()
2585 started.wait()
2586
2587 try:
2588 try:
2589 c = socket.socket(socket.AF_INET)
2590 c.settimeout(0.2)
2591 c.connect((host, port))
2592 # Will attempt handshake and time out
2593 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2594 ssl.wrap_socket, c)
2595 finally:
2596 c.close()
2597 try:
2598 c = socket.socket(socket.AF_INET)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002599 c = ssl.wrap_socket(c)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002600 c.settimeout(0.2)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002601 # Will attempt handshake and time out
2602 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2603 c.connect, (host, port))
2604 finally:
2605 c.close()
2606 finally:
2607 finish = True
2608 t.join()
2609 server.close()
2610
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002611 def test_server_accept(self):
2612 # Issue #16357: accept() on a SSLSocket created through
2613 # SSLContext.wrap_socket().
2614 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2615 context.verify_mode = ssl.CERT_REQUIRED
2616 context.load_verify_locations(CERTFILE)
2617 context.load_cert_chain(CERTFILE)
2618 server = socket.socket(socket.AF_INET)
2619 host = "127.0.0.1"
2620 port = support.bind_port(server)
2621 server = context.wrap_socket(server, server_side=True)
2622
2623 evt = threading.Event()
2624 remote = [None]
2625 peer = [None]
2626 def serve():
2627 server.listen(5)
2628 # Block on the accept and wait on the connection to close.
2629 evt.set()
2630 remote[0], peer[0] = server.accept()
2631 remote[0].recv(1)
2632
2633 t = threading.Thread(target=serve)
2634 t.start()
2635 # Client wait until server setup and perform a connect.
2636 evt.wait()
2637 client = context.wrap_socket(socket.socket())
2638 client.connect((host, port))
2639 client_addr = client.getsockname()
2640 client.close()
2641 t.join()
2642 remote[0].close()
2643 server.close()
2644 # Sanity checks.
2645 self.assertIsInstance(remote[0], ssl.SSLSocket)
2646 self.assertEqual(peer[0], client_addr)
2647
2648 def test_getpeercert_enotconn(self):
2649 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2650 with closing(context.wrap_socket(socket.socket())) as sock:
2651 with self.assertRaises(socket.error) as cm:
2652 sock.getpeercert()
2653 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2654
2655 def test_do_handshake_enotconn(self):
2656 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2657 with closing(context.wrap_socket(socket.socket())) as sock:
2658 with self.assertRaises(socket.error) as cm:
2659 sock.do_handshake()
2660 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2661
Antoine Pitroud76088d2012-01-03 22:46:48 +01002662 def test_default_ciphers(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002663 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2664 try:
2665 # Force a set of weak ciphers on our client context
2666 context.set_ciphers("DES")
2667 except ssl.SSLError:
2668 self.skipTest("no DES cipher available")
Antoine Pitroud76088d2012-01-03 22:46:48 +01002669 with ThreadedEchoServer(CERTFILE,
2670 ssl_version=ssl.PROTOCOL_SSLv23,
2671 chatty=False) as server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002672 with closing(context.wrap_socket(socket.socket())) as s:
2673 with self.assertRaises(ssl.SSLError):
Antoine Pitroud76088d2012-01-03 22:46:48 +01002674 s.connect((HOST, server.port))
Antoine Pitroud76088d2012-01-03 22:46:48 +01002675 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2676
Alex Gaynore98205d2014-09-04 13:33:22 -07002677 def test_version_basic(self):
2678 """
2679 Basic tests for SSLSocket.version().
2680 More tests are done in the test_protocol_*() methods.
2681 """
2682 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2683 with ThreadedEchoServer(CERTFILE,
2684 ssl_version=ssl.PROTOCOL_TLSv1,
2685 chatty=False) as server:
2686 with closing(context.wrap_socket(socket.socket())) as s:
2687 self.assertIs(s.version(), None)
2688 s.connect((HOST, server.port))
2689 self.assertEqual(s.version(), "TLSv1")
2690 self.assertIs(s.version(), None)
2691
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002692 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2693 def test_default_ecdh_curve(self):
2694 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2695 # should be enabled by default on SSL contexts.
2696 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2697 context.load_cert_chain(CERTFILE)
2698 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2699 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2700 # our default cipher list should prefer ECDH-based ciphers
2701 # automatically.
2702 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2703 context.set_ciphers("ECCdraft:ECDH")
2704 with ThreadedEchoServer(context=context) as server:
2705 with closing(context.wrap_socket(socket.socket())) as s:
2706 s.connect((HOST, server.port))
2707 self.assertIn("ECDH", s.cipher()[0])
2708
2709 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2710 "'tls-unique' channel binding not available")
2711 def test_tls_unique_channel_binding(self):
2712 """Test tls-unique channel binding."""
2713 if support.verbose:
2714 sys.stdout.write("\n")
2715
2716 server = ThreadedEchoServer(CERTFILE,
2717 certreqs=ssl.CERT_NONE,
2718 ssl_version=ssl.PROTOCOL_TLSv1,
2719 cacerts=CERTFILE,
2720 chatty=True,
2721 connectionchatty=False)
2722 with server:
2723 s = ssl.wrap_socket(socket.socket(),
2724 server_side=False,
2725 certfile=CERTFILE,
2726 ca_certs=CERTFILE,
2727 cert_reqs=ssl.CERT_NONE,
2728 ssl_version=ssl.PROTOCOL_TLSv1)
2729 s.connect((HOST, server.port))
2730 # get the data
2731 cb_data = s.get_channel_binding("tls-unique")
2732 if support.verbose:
2733 sys.stdout.write(" got channel binding data: {0!r}\n"
2734 .format(cb_data))
2735
2736 # check if it is sane
2737 self.assertIsNotNone(cb_data)
2738 self.assertEqual(len(cb_data), 12) # True for TLSv1
2739
2740 # and compare with the peers version
2741 s.write(b"CB tls-unique\n")
2742 peer_data_repr = s.read().strip()
2743 self.assertEqual(peer_data_repr,
2744 repr(cb_data).encode("us-ascii"))
2745 s.close()
2746
2747 # now, again
2748 s = ssl.wrap_socket(socket.socket(),
2749 server_side=False,
2750 certfile=CERTFILE,
2751 ca_certs=CERTFILE,
2752 cert_reqs=ssl.CERT_NONE,
2753 ssl_version=ssl.PROTOCOL_TLSv1)
2754 s.connect((HOST, server.port))
2755 new_cb_data = s.get_channel_binding("tls-unique")
2756 if support.verbose:
2757 sys.stdout.write(" got another channel binding data: {0!r}\n"
2758 .format(new_cb_data))
2759 # is it really unique
2760 self.assertNotEqual(cb_data, new_cb_data)
2761 self.assertIsNotNone(cb_data)
2762 self.assertEqual(len(cb_data), 12) # True for TLSv1
2763 s.write(b"CB tls-unique\n")
2764 peer_data_repr = s.read().strip()
2765 self.assertEqual(peer_data_repr,
2766 repr(new_cb_data).encode("us-ascii"))
2767 s.close()
2768
2769 def test_compression(self):
2770 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2771 context.load_cert_chain(CERTFILE)
2772 stats = server_params_test(context, context,
2773 chatty=True, connectionchatty=True)
2774 if support.verbose:
2775 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2776 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2777
2778 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2779 "ssl.OP_NO_COMPRESSION needed for this test")
2780 def test_compression_disabled(self):
2781 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2782 context.load_cert_chain(CERTFILE)
2783 context.options |= ssl.OP_NO_COMPRESSION
2784 stats = server_params_test(context, context,
2785 chatty=True, connectionchatty=True)
2786 self.assertIs(stats['compression'], None)
2787
2788 def test_dh_params(self):
2789 # Check we can get a connection with ephemeral Diffie-Hellman
2790 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2791 context.load_cert_chain(CERTFILE)
2792 context.load_dh_params(DHFILE)
2793 context.set_ciphers("kEDH")
2794 stats = server_params_test(context, context,
2795 chatty=True, connectionchatty=True)
2796 cipher = stats["cipher"][0]
2797 parts = cipher.split("-")
2798 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2799 self.fail("Non-DH cipher: " + cipher[0])
2800
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002801 def test_selected_alpn_protocol(self):
2802 # selected_alpn_protocol() is None unless ALPN is used.
2803 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2804 context.load_cert_chain(CERTFILE)
2805 stats = server_params_test(context, context,
2806 chatty=True, connectionchatty=True)
2807 self.assertIs(stats['client_alpn_protocol'], None)
2808
2809 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
2810 def test_selected_alpn_protocol_if_server_uses_alpn(self):
2811 # selected_alpn_protocol() is None unless ALPN is used by the client.
2812 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2813 client_context.load_verify_locations(CERTFILE)
2814 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2815 server_context.load_cert_chain(CERTFILE)
2816 server_context.set_alpn_protocols(['foo', 'bar'])
2817 stats = server_params_test(client_context, server_context,
2818 chatty=True, connectionchatty=True)
2819 self.assertIs(stats['client_alpn_protocol'], None)
2820
2821 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
2822 def test_alpn_protocols(self):
2823 server_protocols = ['foo', 'bar', 'milkshake']
2824 protocol_tests = [
2825 (['foo', 'bar'], 'foo'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002826 (['bar', 'foo'], 'foo'),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002827 (['milkshake'], 'milkshake'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002828 (['http/3.0', 'http/4.0'], None)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002829 ]
2830 for client_protocols, expected in protocol_tests:
2831 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2832 server_context.load_cert_chain(CERTFILE)
2833 server_context.set_alpn_protocols(server_protocols)
2834 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2835 client_context.load_cert_chain(CERTFILE)
2836 client_context.set_alpn_protocols(client_protocols)
2837 stats = server_params_test(client_context, server_context,
2838 chatty=True, connectionchatty=True)
2839
2840 msg = "failed trying %s (s) and %s (c).\n" \
2841 "was expecting %s, but got %%s from the %%s" \
2842 % (str(server_protocols), str(client_protocols),
2843 str(expected))
2844 client_result = stats['client_alpn_protocol']
2845 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2846 server_result = stats['server_alpn_protocols'][-1] \
2847 if len(stats['server_alpn_protocols']) else 'nothing'
2848 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2849
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002850 def test_selected_npn_protocol(self):
2851 # selected_npn_protocol() is None unless NPN is used
2852 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2853 context.load_cert_chain(CERTFILE)
2854 stats = server_params_test(context, context,
2855 chatty=True, connectionchatty=True)
2856 self.assertIs(stats['client_npn_protocol'], None)
2857
2858 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2859 def test_npn_protocols(self):
2860 server_protocols = ['http/1.1', 'spdy/2']
2861 protocol_tests = [
2862 (['http/1.1', 'spdy/2'], 'http/1.1'),
2863 (['spdy/2', 'http/1.1'], 'http/1.1'),
2864 (['spdy/2', 'test'], 'spdy/2'),
2865 (['abc', 'def'], 'abc')
2866 ]
2867 for client_protocols, expected in protocol_tests:
2868 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2869 server_context.load_cert_chain(CERTFILE)
2870 server_context.set_npn_protocols(server_protocols)
2871 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2872 client_context.load_cert_chain(CERTFILE)
2873 client_context.set_npn_protocols(client_protocols)
2874 stats = server_params_test(client_context, server_context,
2875 chatty=True, connectionchatty=True)
2876
2877 msg = "failed trying %s (s) and %s (c).\n" \
2878 "was expecting %s, but got %%s from the %%s" \
2879 % (str(server_protocols), str(client_protocols),
2880 str(expected))
2881 client_result = stats['client_npn_protocol']
2882 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2883 server_result = stats['server_npn_protocols'][-1] \
2884 if len(stats['server_npn_protocols']) else 'nothing'
2885 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2886
2887 def sni_contexts(self):
2888 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2889 server_context.load_cert_chain(SIGNED_CERTFILE)
2890 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2891 other_context.load_cert_chain(SIGNED_CERTFILE2)
2892 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2893 client_context.verify_mode = ssl.CERT_REQUIRED
2894 client_context.load_verify_locations(SIGNING_CA)
2895 return server_context, other_context, client_context
2896
2897 def check_common_name(self, stats, name):
2898 cert = stats['peercert']
2899 self.assertIn((('commonName', name),), cert['subject'])
2900
2901 @needs_sni
2902 def test_sni_callback(self):
2903 calls = []
2904 server_context, other_context, client_context = self.sni_contexts()
2905
2906 def servername_cb(ssl_sock, server_name, initial_context):
2907 calls.append((server_name, initial_context))
2908 if server_name is not None:
2909 ssl_sock.context = other_context
2910 server_context.set_servername_callback(servername_cb)
2911
2912 stats = server_params_test(client_context, server_context,
2913 chatty=True,
2914 sni_name='supermessage')
2915 # The hostname was fetched properly, and the certificate was
2916 # changed for the connection.
2917 self.assertEqual(calls, [("supermessage", server_context)])
2918 # CERTFILE4 was selected
2919 self.check_common_name(stats, 'fakehostname')
2920
2921 calls = []
2922 # The callback is called with server_name=None
2923 stats = server_params_test(client_context, server_context,
2924 chatty=True,
2925 sni_name=None)
2926 self.assertEqual(calls, [(None, server_context)])
2927 self.check_common_name(stats, 'localhost')
2928
2929 # Check disabling the callback
2930 calls = []
2931 server_context.set_servername_callback(None)
2932
2933 stats = server_params_test(client_context, server_context,
2934 chatty=True,
2935 sni_name='notfunny')
2936 # Certificate didn't change
2937 self.check_common_name(stats, 'localhost')
2938 self.assertEqual(calls, [])
2939
2940 @needs_sni
2941 def test_sni_callback_alert(self):
2942 # Returning a TLS alert is reflected to the connecting client
2943 server_context, other_context, client_context = self.sni_contexts()
2944
2945 def cb_returning_alert(ssl_sock, server_name, initial_context):
2946 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2947 server_context.set_servername_callback(cb_returning_alert)
2948
2949 with self.assertRaises(ssl.SSLError) as cm:
2950 stats = server_params_test(client_context, server_context,
2951 chatty=False,
2952 sni_name='supermessage')
2953 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2954
2955 @needs_sni
2956 def test_sni_callback_raising(self):
2957 # Raising fails the connection with a TLS handshake failure alert.
2958 server_context, other_context, client_context = self.sni_contexts()
2959
2960 def cb_raising(ssl_sock, server_name, initial_context):
Serhiy Storchaka5312a7f2015-01-31 11:27:06 +02002961 1.0/0.0
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002962 server_context.set_servername_callback(cb_raising)
2963
2964 with self.assertRaises(ssl.SSLError) as cm, \
2965 support.captured_stderr() as stderr:
2966 stats = server_params_test(client_context, server_context,
2967 chatty=False,
2968 sni_name='supermessage')
2969 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2970 self.assertIn("ZeroDivisionError", stderr.getvalue())
2971
2972 @needs_sni
2973 def test_sni_callback_wrong_return_type(self):
2974 # Returning the wrong return type terminates the TLS connection
2975 # with an internal error alert.
2976 server_context, other_context, client_context = self.sni_contexts()
2977
2978 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2979 return "foo"
2980 server_context.set_servername_callback(cb_wrong_return_type)
2981
2982 with self.assertRaises(ssl.SSLError) as cm, \
2983 support.captured_stderr() as stderr:
2984 stats = server_params_test(client_context, server_context,
2985 chatty=False,
2986 sni_name='supermessage')
2987 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2988 self.assertIn("TypeError", stderr.getvalue())
2989
2990 def test_read_write_after_close_raises_valuerror(self):
2991 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2992 context.verify_mode = ssl.CERT_REQUIRED
2993 context.load_verify_locations(CERTFILE)
2994 context.load_cert_chain(CERTFILE)
2995 server = ThreadedEchoServer(context=context, chatty=False)
2996
2997 with server:
2998 s = context.wrap_socket(socket.socket())
2999 s.connect((HOST, server.port))
3000 s.close()
3001
3002 self.assertRaises(ValueError, s.read, 1024)
3003 self.assertRaises(ValueError, s.write, b'hello')
3004
Bill Janssen61c001a2008-09-08 16:37:24 +00003005
Neal Norwitz9eb9b102007-08-27 01:15:33 +00003006def test_main(verbose=False):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003007 if support.verbose:
3008 plats = {
3009 'Linux': platform.linux_distribution,
3010 'Mac': platform.mac_ver,
3011 'Windows': platform.win32_ver,
3012 }
3013 for name, func in plats.items():
3014 plat = func()
3015 if plat and plat[0]:
3016 plat = '%s %r' % (name, plat)
3017 break
3018 else:
3019 plat = repr(platform.platform())
3020 print("test_ssl: testing with %r %r" %
3021 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3022 print(" under %s" % plat)
3023 print(" HAS_SNI = %r" % ssl.HAS_SNI)
3024 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3025 try:
3026 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3027 except AttributeError:
3028 pass
Bill Janssen296a59d2007-09-16 22:06:00 +00003029
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003030 for filename in [
Martin Panter71202bb2016-01-15 00:25:29 +00003031 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003032 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
3033 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
3034 BADCERT, BADKEY, EMPTYCERT]:
3035 if not os.path.exists(filename):
3036 raise support.TestFailed("Can't read certificate file %r" % filename)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003037
Benjamin Peterson2f334562014-10-01 23:53:01 -04003038 tests = [ContextTests, BasicTests, BasicSocketTests, SSLErrorTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003039
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003040 if support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00003041 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00003042
Bill Janssen98d19da2007-09-10 21:51:02 +00003043 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003044 thread_info = support.threading_setup()
3045 if thread_info:
Bill Janssen934b16d2008-06-28 22:19:33 +00003046 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003047
Antoine Pitrou3945c862010-04-28 21:11:01 +00003048 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003049 support.run_unittest(*tests)
Antoine Pitrou3945c862010-04-28 21:11:01 +00003050 finally:
3051 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003052 support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003053
3054if __name__ == "__main__":
3055 test_main()