blob: 05efaba7a3ff114a5c68e180b5303af7db1c8cdb [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")
65WRONGCERT = data_file("XXXnonexisting.pem")
66BADKEY = 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:
337 ssl.wrap_socket(sock, certfile=WRONGCERT)
338 self.assertEqual(cm.exception.errno, errno.ENOENT)
339 with self.assertRaises(IOError) as cm:
340 with closing(socket.socket()) as sock:
341 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
342 self.assertEqual(cm.exception.errno, errno.ENOENT)
343 with self.assertRaises(IOError) as cm:
344 with closing(socket.socket()) as sock:
345 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
346 self.assertEqual(cm.exception.errno, errno.ENOENT)
347
348 def test_match_hostname(self):
349 def ok(cert, hostname):
350 ssl.match_hostname(cert, hostname)
351 def fail(cert, hostname):
352 self.assertRaises(ssl.CertificateError,
353 ssl.match_hostname, cert, hostname)
354
355 cert = {'subject': ((('commonName', 'example.com'),),)}
356 ok(cert, 'example.com')
357 ok(cert, 'ExAmple.cOm')
358 fail(cert, 'www.example.com')
359 fail(cert, '.example.com')
360 fail(cert, 'example.org')
361 fail(cert, 'exampleXcom')
362
363 cert = {'subject': ((('commonName', '*.a.com'),),)}
364 ok(cert, 'foo.a.com')
365 fail(cert, 'bar.foo.a.com')
366 fail(cert, 'a.com')
367 fail(cert, 'Xa.com')
368 fail(cert, '.a.com')
369
370 # only match one left-most wildcard
371 cert = {'subject': ((('commonName', 'f*.com'),),)}
372 ok(cert, 'foo.com')
373 ok(cert, 'f.com')
374 fail(cert, 'bar.com')
375 fail(cert, 'foo.a.com')
376 fail(cert, 'bar.foo.com')
377
378 # NULL bytes are bad, CVE-2013-4073
379 cert = {'subject': ((('commonName',
380 'null.python.org\x00example.org'),),)}
381 ok(cert, 'null.python.org\x00example.org') # or raise an error?
382 fail(cert, 'example.org')
383 fail(cert, 'null.python.org')
384
385 # error cases with wildcards
386 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
387 fail(cert, 'bar.foo.a.com')
388 fail(cert, 'a.com')
389 fail(cert, 'Xa.com')
390 fail(cert, '.a.com')
391
392 cert = {'subject': ((('commonName', 'a.*.com'),),)}
393 fail(cert, 'a.foo.com')
394 fail(cert, 'a..com')
395 fail(cert, 'a.com')
396
397 # wildcard doesn't match IDNA prefix 'xn--'
398 idna = u'püthon.python.org'.encode("idna").decode("ascii")
399 cert = {'subject': ((('commonName', idna),),)}
400 ok(cert, idna)
401 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
402 fail(cert, idna)
403 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
404 fail(cert, idna)
405
406 # wildcard in first fragment and IDNA A-labels in sequent fragments
407 # are supported.
408 idna = u'www*.pythön.org'.encode("idna").decode("ascii")
409 cert = {'subject': ((('commonName', idna),),)}
410 ok(cert, u'www.pythön.org'.encode("idna").decode("ascii"))
411 ok(cert, u'www1.pythön.org'.encode("idna").decode("ascii"))
412 fail(cert, u'ftp.pythön.org'.encode("idna").decode("ascii"))
413 fail(cert, u'pythön.org'.encode("idna").decode("ascii"))
414
415 # Slightly fake real-world example
416 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
417 'subject': ((('commonName', 'linuxfrz.org'),),),
418 'subjectAltName': (('DNS', 'linuxfr.org'),
419 ('DNS', 'linuxfr.com'),
420 ('othername', '<unsupported>'))}
421 ok(cert, 'linuxfr.org')
422 ok(cert, 'linuxfr.com')
423 # Not a "DNS" entry
424 fail(cert, '<unsupported>')
425 # When there is a subjectAltName, commonName isn't used
426 fail(cert, 'linuxfrz.org')
427
428 # A pristine real-world example
429 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
430 'subject': ((('countryName', 'US'),),
431 (('stateOrProvinceName', 'California'),),
432 (('localityName', 'Mountain View'),),
433 (('organizationName', 'Google Inc'),),
434 (('commonName', 'mail.google.com'),))}
435 ok(cert, 'mail.google.com')
436 fail(cert, 'gmail.com')
437 # Only commonName is considered
438 fail(cert, 'California')
439
440 # Neither commonName nor subjectAltName
441 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
442 'subject': ((('countryName', 'US'),),
443 (('stateOrProvinceName', 'California'),),
444 (('localityName', 'Mountain View'),),
445 (('organizationName', 'Google Inc'),))}
446 fail(cert, 'mail.google.com')
447
448 # No DNS entry in subjectAltName but a commonName
449 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
450 'subject': ((('countryName', 'US'),),
451 (('stateOrProvinceName', 'California'),),
452 (('localityName', 'Mountain View'),),
453 (('commonName', 'mail.google.com'),)),
454 'subjectAltName': (('othername', 'blabla'), )}
455 ok(cert, 'mail.google.com')
456
457 # No DNS entry subjectAltName and no commonName
458 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
459 'subject': ((('countryName', 'US'),),
460 (('stateOrProvinceName', 'California'),),
461 (('localityName', 'Mountain View'),),
462 (('organizationName', 'Google Inc'),)),
463 'subjectAltName': (('othername', 'blabla'),)}
464 fail(cert, 'google.com')
465
466 # Empty cert / no cert
467 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
468 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
469
470 # Issue #17980: avoid denials of service by refusing more than one
471 # wildcard per fragment.
472 cert = {'subject': ((('commonName', 'a*b.com'),),)}
473 ok(cert, 'axxb.com')
474 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
475 fail(cert, 'axxb.com')
476 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
477 with self.assertRaises(ssl.CertificateError) as cm:
478 ssl.match_hostname(cert, 'axxbxxc.com')
479 self.assertIn("too many wildcards", str(cm.exception))
480
481 def test_server_side(self):
482 # server_hostname doesn't work for server sockets
483 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
484 with closing(socket.socket()) as sock:
485 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
486 server_hostname="some.hostname")
487
488 def test_unknown_channel_binding(self):
489 # should raise ValueError for unknown type
490 s = socket.socket(socket.AF_INET)
491 with closing(ssl.wrap_socket(s)) as ss:
492 with self.assertRaises(ValueError):
493 ss.get_channel_binding("unknown-type")
494
495 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
496 "'tls-unique' channel binding not available")
497 def test_tls_unique_channel_binding(self):
498 # unconnected should return None for known type
499 s = socket.socket(socket.AF_INET)
500 with closing(ssl.wrap_socket(s)) as ss:
501 self.assertIsNone(ss.get_channel_binding("tls-unique"))
502 # the same for server-side
503 s = socket.socket(socket.AF_INET)
504 with closing(ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)) as ss:
505 self.assertIsNone(ss.get_channel_binding("tls-unique"))
506
507 def test_get_default_verify_paths(self):
508 paths = ssl.get_default_verify_paths()
509 self.assertEqual(len(paths), 6)
510 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
511
512 with support.EnvironmentVarGuard() as env:
513 env["SSL_CERT_DIR"] = CAPATH
514 env["SSL_CERT_FILE"] = CERTFILE
515 paths = ssl.get_default_verify_paths()
516 self.assertEqual(paths.cafile, CERTFILE)
517 self.assertEqual(paths.capath, CAPATH)
518
519 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
520 def test_enum_certificates(self):
521 self.assertTrue(ssl.enum_certificates("CA"))
522 self.assertTrue(ssl.enum_certificates("ROOT"))
523
524 self.assertRaises(TypeError, ssl.enum_certificates)
525 self.assertRaises(WindowsError, ssl.enum_certificates, "")
526
527 trust_oids = set()
528 for storename in ("CA", "ROOT"):
529 store = ssl.enum_certificates(storename)
530 self.assertIsInstance(store, list)
531 for element in store:
532 self.assertIsInstance(element, tuple)
533 self.assertEqual(len(element), 3)
534 cert, enc, trust = element
535 self.assertIsInstance(cert, bytes)
536 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
537 self.assertIsInstance(trust, (set, bool))
538 if isinstance(trust, set):
539 trust_oids.update(trust)
540
541 serverAuth = "1.3.6.1.5.5.7.3.1"
542 self.assertIn(serverAuth, trust_oids)
543
544 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
545 def test_enum_crls(self):
546 self.assertTrue(ssl.enum_crls("CA"))
547 self.assertRaises(TypeError, ssl.enum_crls)
548 self.assertRaises(WindowsError, ssl.enum_crls, "")
549
550 crls = ssl.enum_crls("CA")
551 self.assertIsInstance(crls, list)
552 for element in crls:
553 self.assertIsInstance(element, tuple)
554 self.assertEqual(len(element), 2)
555 self.assertIsInstance(element[0], bytes)
556 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
557
558
559 def test_asn1object(self):
560 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
561 '1.3.6.1.5.5.7.3.1')
562
563 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
564 self.assertEqual(val, expected)
565 self.assertEqual(val.nid, 129)
566 self.assertEqual(val.shortname, 'serverAuth')
567 self.assertEqual(val.longname, 'TLS Web Server Authentication')
568 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
569 self.assertIsInstance(val, ssl._ASN1Object)
570 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
571
572 val = ssl._ASN1Object.fromnid(129)
573 self.assertEqual(val, expected)
574 self.assertIsInstance(val, ssl._ASN1Object)
575 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
576 with self.assertRaisesRegexp(ValueError, "unknown NID 100000"):
577 ssl._ASN1Object.fromnid(100000)
578 for i in range(1000):
579 try:
580 obj = ssl._ASN1Object.fromnid(i)
581 except ValueError:
582 pass
583 else:
584 self.assertIsInstance(obj.nid, int)
585 self.assertIsInstance(obj.shortname, str)
586 self.assertIsInstance(obj.longname, str)
587 self.assertIsInstance(obj.oid, (str, type(None)))
588
589 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
590 self.assertEqual(val, expected)
591 self.assertIsInstance(val, ssl._ASN1Object)
592 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
593 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
594 expected)
595 with self.assertRaisesRegexp(ValueError, "unknown object 'serverauth'"):
596 ssl._ASN1Object.fromname('serverauth')
597
598 def test_purpose_enum(self):
599 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
600 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
601 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
602 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
603 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
604 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
605 '1.3.6.1.5.5.7.3.1')
606
607 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
608 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
609 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
610 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
611 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
612 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
613 '1.3.6.1.5.5.7.3.2')
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000614
Antoine Pitrou63cc99d2013-12-28 17:26:33 +0100615 def test_unsupported_dtls(self):
616 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
617 self.addCleanup(s.close)
618 with self.assertRaises(NotImplementedError) as cx:
619 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
620 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500621 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
622 with self.assertRaises(NotImplementedError) as cx:
623 ctx.wrap_socket(s)
624 self.assertEqual(str(cx.exception), "only stream sockets are supported")
625
626 def cert_time_ok(self, timestring, timestamp):
627 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
628
629 def cert_time_fail(self, timestring):
630 with self.assertRaises(ValueError):
631 ssl.cert_time_to_seconds(timestring)
632
633 @unittest.skipUnless(utc_offset(),
634 'local time needs to be different from UTC')
635 def test_cert_time_to_seconds_timezone(self):
636 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
637 # results if local timezone is not UTC
638 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
639 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
640
641 def test_cert_time_to_seconds(self):
642 timestring = "Jan 5 09:34:43 2018 GMT"
643 ts = 1515144883.0
644 self.cert_time_ok(timestring, ts)
645 # accept keyword parameter, assert its name
646 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
647 # accept both %e and %d (space or zero generated by strftime)
648 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
649 # case-insensitive
650 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
651 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
652 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
653 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
654 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
655 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
656 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
657 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
658
659 newyear_ts = 1230768000.0
660 # leap seconds
661 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
662 # same timestamp
663 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
664
665 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
666 # allow 60th second (even if it is not a leap second)
667 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
668 # allow 2nd leap second for compatibility with time.strptime()
669 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
670 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
671
672 # no special treatement for the special value:
673 # 99991231235959Z (rfc 5280)
674 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
675
676 @support.run_with_locale('LC_ALL', '')
677 def test_cert_time_to_seconds_locale(self):
678 # `cert_time_to_seconds()` should be locale independent
679
680 def local_february_name():
681 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
682
683 if local_february_name().lower() == 'feb':
684 self.skipTest("locale-specific month name needs to be "
685 "different from C locale")
686
687 # locale-independent
688 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
689 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
690
691
692class ContextTests(unittest.TestCase):
693
694 @skip_if_broken_ubuntu_ssl
695 def test_constructor(self):
696 for protocol in PROTOCOLS:
697 ssl.SSLContext(protocol)
698 self.assertRaises(TypeError, ssl.SSLContext)
699 self.assertRaises(ValueError, ssl.SSLContext, -1)
700 self.assertRaises(ValueError, ssl.SSLContext, 42)
701
702 @skip_if_broken_ubuntu_ssl
703 def test_protocol(self):
704 for proto in PROTOCOLS:
705 ctx = ssl.SSLContext(proto)
706 self.assertEqual(ctx.protocol, proto)
707
708 def test_ciphers(self):
709 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
710 ctx.set_ciphers("ALL")
711 ctx.set_ciphers("DEFAULT")
712 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
713 ctx.set_ciphers("^$:,;?*'dorothyx")
714
715 @skip_if_broken_ubuntu_ssl
716 def test_options(self):
717 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800718 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500719 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
720 ctx.options)
Benjamin Peterson10aaca92015-11-11 22:38:41 -0800721 ctx.options |= ssl.OP_NO_TLSv1
722 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1,
723 ctx.options)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500724 if can_clear_options():
725 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
726 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
727 ctx.options)
728 ctx.options = 0
729 self.assertEqual(0, ctx.options)
730 else:
731 with self.assertRaises(ValueError):
732 ctx.options = 0
733
734 def test_verify_mode(self):
735 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
736 # Default value
737 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
738 ctx.verify_mode = ssl.CERT_OPTIONAL
739 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
740 ctx.verify_mode = ssl.CERT_REQUIRED
741 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
742 ctx.verify_mode = ssl.CERT_NONE
743 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
744 with self.assertRaises(TypeError):
745 ctx.verify_mode = None
746 with self.assertRaises(ValueError):
747 ctx.verify_mode = 42
748
749 @unittest.skipUnless(have_verify_flags(),
750 "verify_flags need OpenSSL > 0.9.8")
751 def test_verify_flags(self):
752 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson72ef9612015-03-04 22:49:41 -0500753 # default value
754 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
755 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500756 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
757 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
758 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
759 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
760 ctx.verify_flags = ssl.VERIFY_DEFAULT
761 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
762 # supports any value
763 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
764 self.assertEqual(ctx.verify_flags,
765 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
766 with self.assertRaises(TypeError):
767 ctx.verify_flags = None
768
769 def test_load_cert_chain(self):
770 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
771 # Combined key and cert in a single file
Benjamin Peterson04439fd2014-11-03 21:05:01 -0500772 ctx.load_cert_chain(CERTFILE, keyfile=None)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500773 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
774 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
775 with self.assertRaises(IOError) as cm:
776 ctx.load_cert_chain(WRONGCERT)
777 self.assertEqual(cm.exception.errno, errno.ENOENT)
778 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
779 ctx.load_cert_chain(BADCERT)
780 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
781 ctx.load_cert_chain(EMPTYCERT)
782 # Separate key and cert
783 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
784 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
785 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
786 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
787 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
788 ctx.load_cert_chain(ONLYCERT)
789 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
790 ctx.load_cert_chain(ONLYKEY)
791 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
792 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
793 # Mismatching key and cert
794 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
795 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Martin Panter71202bb2016-01-15 00:25:29 +0000796 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500797 # Password protected key and cert
798 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
799 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
800 ctx.load_cert_chain(CERTFILE_PROTECTED,
801 password=bytearray(KEY_PASSWORD.encode()))
802 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
803 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
804 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
805 bytearray(KEY_PASSWORD.encode()))
806 with self.assertRaisesRegexp(TypeError, "should be a string"):
807 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
808 with self.assertRaises(ssl.SSLError):
809 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
810 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
811 # openssl has a fixed limit on the password buffer.
812 # PEM_BUFSIZE is generally set to 1kb.
813 # Return a string larger than this.
814 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
815 # Password callback
816 def getpass_unicode():
817 return KEY_PASSWORD
818 def getpass_bytes():
819 return KEY_PASSWORD.encode()
820 def getpass_bytearray():
821 return bytearray(KEY_PASSWORD.encode())
822 def getpass_badpass():
823 return "badpass"
824 def getpass_huge():
825 return b'a' * (1024 * 1024)
826 def getpass_bad_type():
827 return 9
828 def getpass_exception():
829 raise Exception('getpass error')
830 class GetPassCallable:
831 def __call__(self):
832 return KEY_PASSWORD
833 def getpass(self):
834 return KEY_PASSWORD
835 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
836 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
837 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
838 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
839 ctx.load_cert_chain(CERTFILE_PROTECTED,
840 password=GetPassCallable().getpass)
841 with self.assertRaises(ssl.SSLError):
842 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
843 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
844 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
845 with self.assertRaisesRegexp(TypeError, "must return a string"):
846 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
847 with self.assertRaisesRegexp(Exception, "getpass error"):
848 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
849 # Make sure the password function isn't called if it isn't needed
850 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
851
852 def test_load_verify_locations(self):
853 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
854 ctx.load_verify_locations(CERTFILE)
855 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
856 ctx.load_verify_locations(BYTES_CERTFILE)
857 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400858 ctx.load_verify_locations(cafile=BYTES_CERTFILE.decode('utf-8'))
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500859 self.assertRaises(TypeError, ctx.load_verify_locations)
860 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
861 with self.assertRaises(IOError) as cm:
862 ctx.load_verify_locations(WRONGCERT)
863 self.assertEqual(cm.exception.errno, errno.ENOENT)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400864 with self.assertRaises(IOError):
865 ctx.load_verify_locations(u'')
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500866 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
867 ctx.load_verify_locations(BADCERT)
868 ctx.load_verify_locations(CERTFILE, CAPATH)
869 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
870
871 # Issue #10989: crash if the second argument type is invalid
872 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
873
874 def test_load_verify_cadata(self):
875 # test cadata
876 with open(CAFILE_CACERT) as f:
877 cacert_pem = f.read().decode("ascii")
878 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
879 with open(CAFILE_NEURONIO) as f:
880 neuronio_pem = f.read().decode("ascii")
881 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
882
883 # test PEM
884 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
885 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
886 ctx.load_verify_locations(cadata=cacert_pem)
887 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
888 ctx.load_verify_locations(cadata=neuronio_pem)
889 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
890 # cert already in hash table
891 ctx.load_verify_locations(cadata=neuronio_pem)
892 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
893
894 # combined
895 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
896 combined = "\n".join((cacert_pem, neuronio_pem))
897 ctx.load_verify_locations(cadata=combined)
898 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
899
900 # with junk around the certs
901 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
902 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
903 neuronio_pem, "tail"]
904 ctx.load_verify_locations(cadata="\n".join(combined))
905 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
906
907 # test DER
908 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
909 ctx.load_verify_locations(cadata=cacert_der)
910 ctx.load_verify_locations(cadata=neuronio_der)
911 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
912 # cert already in hash table
913 ctx.load_verify_locations(cadata=cacert_der)
914 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
915
916 # combined
917 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
918 combined = b"".join((cacert_der, neuronio_der))
919 ctx.load_verify_locations(cadata=combined)
920 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
921
922 # error cases
923 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
924 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
925
926 with self.assertRaisesRegexp(ssl.SSLError, "no start line"):
927 ctx.load_verify_locations(cadata=u"broken")
928 with self.assertRaisesRegexp(ssl.SSLError, "not enough data"):
929 ctx.load_verify_locations(cadata=b"broken")
930
931
932 def test_load_dh_params(self):
933 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
934 ctx.load_dh_params(DHFILE)
935 if os.name != 'nt':
936 ctx.load_dh_params(BYTES_DHFILE)
937 self.assertRaises(TypeError, ctx.load_dh_params)
938 self.assertRaises(TypeError, ctx.load_dh_params, None)
939 with self.assertRaises(IOError) as cm:
940 ctx.load_dh_params(WRONGCERT)
941 self.assertEqual(cm.exception.errno, errno.ENOENT)
942 with self.assertRaises(ssl.SSLError) as cm:
943 ctx.load_dh_params(CERTFILE)
944
945 @skip_if_broken_ubuntu_ssl
946 def test_session_stats(self):
947 for proto in PROTOCOLS:
948 ctx = ssl.SSLContext(proto)
949 self.assertEqual(ctx.session_stats(), {
950 'number': 0,
951 'connect': 0,
952 'connect_good': 0,
953 'connect_renegotiate': 0,
954 'accept': 0,
955 'accept_good': 0,
956 'accept_renegotiate': 0,
957 'hits': 0,
958 'misses': 0,
959 'timeouts': 0,
960 'cache_full': 0,
961 })
962
963 def test_set_default_verify_paths(self):
964 # There's not much we can do to test that it acts as expected,
965 # so just check it doesn't crash or raise an exception.
966 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
967 ctx.set_default_verify_paths()
968
969 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
970 def test_set_ecdh_curve(self):
971 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
972 ctx.set_ecdh_curve("prime256v1")
973 ctx.set_ecdh_curve(b"prime256v1")
974 self.assertRaises(TypeError, ctx.set_ecdh_curve)
975 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
976 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
977 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
978
979 @needs_sni
980 def test_sni_callback(self):
981 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
982
983 # set_servername_callback expects a callable, or None
984 self.assertRaises(TypeError, ctx.set_servername_callback)
985 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
986 self.assertRaises(TypeError, ctx.set_servername_callback, "")
987 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
988
989 def dummycallback(sock, servername, ctx):
990 pass
991 ctx.set_servername_callback(None)
992 ctx.set_servername_callback(dummycallback)
993
994 @needs_sni
995 def test_sni_callback_refcycle(self):
996 # Reference cycles through the servername callback are detected
997 # and cleared.
998 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
999 def dummycallback(sock, servername, ctx, cycle=ctx):
1000 pass
1001 ctx.set_servername_callback(dummycallback)
1002 wr = weakref.ref(ctx)
1003 del ctx, dummycallback
1004 gc.collect()
1005 self.assertIs(wr(), None)
1006
1007 def test_cert_store_stats(self):
1008 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1009 self.assertEqual(ctx.cert_store_stats(),
1010 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1011 ctx.load_cert_chain(CERTFILE)
1012 self.assertEqual(ctx.cert_store_stats(),
1013 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1014 ctx.load_verify_locations(CERTFILE)
1015 self.assertEqual(ctx.cert_store_stats(),
1016 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panter71202bb2016-01-15 00:25:29 +00001017 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001018 self.assertEqual(ctx.cert_store_stats(),
1019 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1020
1021 def test_get_ca_certs(self):
1022 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1023 self.assertEqual(ctx.get_ca_certs(), [])
1024 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1025 ctx.load_verify_locations(CERTFILE)
1026 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panter71202bb2016-01-15 00:25:29 +00001027 # but CAFILE_CACERT is a CA cert
1028 ctx.load_verify_locations(CAFILE_CACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001029 self.assertEqual(ctx.get_ca_certs(),
1030 [{'issuer': ((('organizationName', 'Root CA'),),
1031 (('organizationalUnitName', 'http://www.cacert.org'),),
1032 (('commonName', 'CA Cert Signing Authority'),),
1033 (('emailAddress', 'support@cacert.org'),)),
1034 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1035 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1036 'serialNumber': '00',
1037 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
1038 'subject': ((('organizationName', 'Root CA'),),
1039 (('organizationalUnitName', 'http://www.cacert.org'),),
1040 (('commonName', 'CA Cert Signing Authority'),),
1041 (('emailAddress', 'support@cacert.org'),)),
1042 'version': 3}])
1043
Martin Panter71202bb2016-01-15 00:25:29 +00001044 with open(CAFILE_CACERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001045 pem = f.read()
1046 der = ssl.PEM_cert_to_DER_cert(pem)
1047 self.assertEqual(ctx.get_ca_certs(True), [der])
1048
1049 def test_load_default_certs(self):
1050 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1051 ctx.load_default_certs()
1052
1053 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1054 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1055 ctx.load_default_certs()
1056
1057 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1058 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1059
1060 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1061 self.assertRaises(TypeError, ctx.load_default_certs, None)
1062 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1063
Benjamin Petersona02ae252014-10-03 18:17:15 -04001064 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson0b30a2b2014-10-03 17:27:05 -04001065 def test_load_default_certs_env(self):
1066 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1067 with support.EnvironmentVarGuard() as env:
1068 env["SSL_CERT_DIR"] = CAPATH
1069 env["SSL_CERT_FILE"] = CERTFILE
1070 ctx.load_default_certs()
1071 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1072
Benjamin Petersona02ae252014-10-03 18:17:15 -04001073 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1074 def test_load_default_certs_env_windows(self):
1075 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1076 ctx.load_default_certs()
1077 stats = ctx.cert_store_stats()
1078
1079 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1080 with support.EnvironmentVarGuard() as env:
1081 env["SSL_CERT_DIR"] = CAPATH
1082 env["SSL_CERT_FILE"] = CERTFILE
1083 ctx.load_default_certs()
1084 stats["x509"] += 1
1085 self.assertEqual(ctx.cert_store_stats(), stats)
1086
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001087 def test_create_default_context(self):
1088 ctx = ssl.create_default_context()
1089 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1090 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1091 self.assertTrue(ctx.check_hostname)
1092 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1093 self.assertEqual(
1094 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1095 getattr(ssl, "OP_NO_COMPRESSION", 0),
1096 )
1097
1098 with open(SIGNING_CA) as f:
1099 cadata = f.read().decode("ascii")
1100 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1101 cadata=cadata)
1102 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1103 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1104 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1105 self.assertEqual(
1106 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1107 getattr(ssl, "OP_NO_COMPRESSION", 0),
1108 )
1109
1110 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
1111 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1112 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1113 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1114 self.assertEqual(
1115 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1116 getattr(ssl, "OP_NO_COMPRESSION", 0),
1117 )
1118 self.assertEqual(
1119 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1120 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1121 )
1122 self.assertEqual(
1123 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1124 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1125 )
1126
1127 def test__create_stdlib_context(self):
1128 ctx = ssl._create_stdlib_context()
1129 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1130 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1131 self.assertFalse(ctx.check_hostname)
1132 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1133
1134 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1135 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1136 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1137 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1138
1139 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
1140 cert_reqs=ssl.CERT_REQUIRED,
1141 check_hostname=True)
1142 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1143 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1144 self.assertTrue(ctx.check_hostname)
1145 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1146
1147 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1148 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1149 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1150 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1151
1152 def test_check_hostname(self):
1153 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1154 self.assertFalse(ctx.check_hostname)
1155
1156 # Requires CERT_REQUIRED or CERT_OPTIONAL
1157 with self.assertRaises(ValueError):
1158 ctx.check_hostname = True
1159 ctx.verify_mode = ssl.CERT_REQUIRED
1160 self.assertFalse(ctx.check_hostname)
1161 ctx.check_hostname = True
1162 self.assertTrue(ctx.check_hostname)
1163
1164 ctx.verify_mode = ssl.CERT_OPTIONAL
1165 ctx.check_hostname = True
1166 self.assertTrue(ctx.check_hostname)
1167
1168 # Cannot set CERT_NONE with check_hostname enabled
1169 with self.assertRaises(ValueError):
1170 ctx.verify_mode = ssl.CERT_NONE
1171 ctx.check_hostname = False
1172 self.assertFalse(ctx.check_hostname)
1173
1174
1175class SSLErrorTests(unittest.TestCase):
1176
1177 def test_str(self):
1178 # The str() of a SSLError doesn't include the errno
1179 e = ssl.SSLError(1, "foo")
1180 self.assertEqual(str(e), "foo")
1181 self.assertEqual(e.errno, 1)
1182 # Same for a subclass
1183 e = ssl.SSLZeroReturnError(1, "foo")
1184 self.assertEqual(str(e), "foo")
1185 self.assertEqual(e.errno, 1)
1186
1187 def test_lib_reason(self):
1188 # Test the library and reason attributes
1189 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1190 with self.assertRaises(ssl.SSLError) as cm:
1191 ctx.load_dh_params(CERTFILE)
1192 self.assertEqual(cm.exception.library, 'PEM')
1193 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1194 s = str(cm.exception)
1195 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1196
1197 def test_subclass(self):
1198 # Check that the appropriate SSLError subclass is raised
1199 # (this only tests one of them)
1200 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1201 with closing(socket.socket()) as s:
1202 s.bind(("127.0.0.1", 0))
1203 s.listen(5)
1204 c = socket.socket()
1205 c.connect(s.getsockname())
1206 c.setblocking(False)
1207 with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c:
1208 with self.assertRaises(ssl.SSLWantReadError) as cm:
1209 c.do_handshake()
1210 s = str(cm.exception)
1211 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1212 # For compatibility
1213 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
Antoine Pitrou63cc99d2013-12-28 17:26:33 +01001214
Antoine Pitrouf9de5342010-04-05 21:35:07 +00001215
Bill Janssen934b16d2008-06-28 22:19:33 +00001216class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +00001217
Antoine Pitrou3945c862010-04-28 21:11:01 +00001218 def test_connect(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001219 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001220 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1221 cert_reqs=ssl.CERT_NONE)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001222 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001223 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001224 self.assertEqual({}, s.getpeercert())
1225 finally:
1226 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001227
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001228 # this should fail because we have no verification certs
1229 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1230 cert_reqs=ssl.CERT_REQUIRED)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001231 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001232 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001233 s.close()
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001234
1235 # this should succeed because we specify the root cert
1236 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1237 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001238 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001239 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001240 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001241 self.assertTrue(s.getpeercert())
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001242 finally:
1243 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001244
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001245 def test_connect_ex(self):
1246 # Issue #11326: check connect_ex() implementation
Martin Panter71202bb2016-01-15 00:25:29 +00001247 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001248 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1249 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001250 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001251 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001252 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001253 self.assertTrue(s.getpeercert())
1254 finally:
1255 s.close()
1256
1257 def test_non_blocking_connect_ex(self):
1258 # Issue #11326: non-blocking connect_ex() should allow handshake
1259 # to proceed after the socket gets ready.
Martin Panter71202bb2016-01-15 00:25:29 +00001260 with support.transient_internet(REMOTE_HOST):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001261 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1262 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001263 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001264 do_handshake_on_connect=False)
1265 try:
1266 s.setblocking(False)
Martin Panter71202bb2016-01-15 00:25:29 +00001267 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +00001268 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1269 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001270 # Wait for connect to finish
1271 select.select([], [s], [], 5.0)
1272 # Non-blocking handshake
1273 while True:
1274 try:
1275 s.do_handshake()
1276 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001277 except ssl.SSLWantReadError:
1278 select.select([s], [], [], 5.0)
1279 except ssl.SSLWantWriteError:
1280 select.select([], [s], [], 5.0)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001281 # SSL established
1282 self.assertTrue(s.getpeercert())
1283 finally:
1284 s.close()
1285
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001286 def test_timeout_connect_ex(self):
1287 # Issue #12065: on a timeout, connect_ex() should return the original
1288 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter71202bb2016-01-15 00:25:29 +00001289 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001290 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1291 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001292 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001293 do_handshake_on_connect=False)
1294 try:
1295 s.settimeout(0.0000001)
Martin Panter71202bb2016-01-15 00:25:29 +00001296 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001297 if rc == 0:
Martin Panter71202bb2016-01-15 00:25:29 +00001298 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001299 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1300 finally:
1301 s.close()
1302
1303 def test_connect_ex_error(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001304 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001305 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1306 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter71202bb2016-01-15 00:25:29 +00001307 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001308 try:
Martin Panter71202bb2016-01-15 00:25:29 +00001309 rc = s.connect_ex((REMOTE_HOST, 444))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001310 # Issue #19919: Windows machines or VMs hosted on Windows
1311 # machines sometimes return EWOULDBLOCK.
Martin Panter71202bb2016-01-15 00:25:29 +00001312 errors = (
1313 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1314 errno.EWOULDBLOCK,
1315 )
1316 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001317 finally:
1318 s.close()
1319
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001320 def test_connect_with_context(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001321 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001322 # Same as test_connect, but with a separately created context
1323 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1324 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001325 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001326 try:
1327 self.assertEqual({}, s.getpeercert())
1328 finally:
1329 s.close()
1330 # Same with a server hostname
1331 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter71202bb2016-01-15 00:25:29 +00001332 server_hostname=REMOTE_HOST)
1333 s.connect((REMOTE_HOST, 443))
Benjamin Peterson31aa69e2014-11-23 20:13:31 -06001334 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001335 # This should fail because we have no verification certs
1336 ctx.verify_mode = ssl.CERT_REQUIRED
1337 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1338 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
Martin Panter71202bb2016-01-15 00:25:29 +00001339 s.connect, (REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001340 s.close()
1341 # This should succeed because we specify the root cert
Martin Panter71202bb2016-01-15 00:25:29 +00001342 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001343 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001344 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001345 try:
1346 cert = s.getpeercert()
1347 self.assertTrue(cert)
1348 finally:
1349 s.close()
1350
1351 def test_connect_capath(self):
1352 # Verify server certificates using the `capath` argument
1353 # NOTE: the subject hashing algorithm has been changed between
1354 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1355 # contain both versions of each certificate (same content, different
1356 # filename) for this test to be portable across OpenSSL releases.
Martin Panter71202bb2016-01-15 00:25:29 +00001357 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001358 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1359 ctx.verify_mode = ssl.CERT_REQUIRED
1360 ctx.load_verify_locations(capath=CAPATH)
1361 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001362 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001363 try:
1364 cert = s.getpeercert()
1365 self.assertTrue(cert)
1366 finally:
1367 s.close()
1368 # Same with a bytes `capath` argument
1369 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1370 ctx.verify_mode = ssl.CERT_REQUIRED
1371 ctx.load_verify_locations(capath=BYTES_CAPATH)
1372 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001373 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001374 try:
1375 cert = s.getpeercert()
1376 self.assertTrue(cert)
1377 finally:
1378 s.close()
1379
1380 def test_connect_cadata(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001381 with open(REMOTE_ROOT_CERT) as f:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001382 pem = f.read().decode('ascii')
1383 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panter71202bb2016-01-15 00:25:29 +00001384 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001385 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1386 ctx.verify_mode = ssl.CERT_REQUIRED
1387 ctx.load_verify_locations(cadata=pem)
1388 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001389 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001390 cert = s.getpeercert()
1391 self.assertTrue(cert)
1392
1393 # same with DER
1394 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1395 ctx.verify_mode = ssl.CERT_REQUIRED
1396 ctx.load_verify_locations(cadata=der)
1397 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
Martin Panter71202bb2016-01-15 00:25:29 +00001398 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001399 cert = s.getpeercert()
1400 self.assertTrue(cert)
1401
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001402 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1403 def test_makefile_close(self):
1404 # Issue #5238: creating a file-like object with makefile() shouldn't
1405 # delay closing the underlying "real socket" (here tested with its
1406 # file descriptor, hence skipping the test under Windows).
Martin Panter71202bb2016-01-15 00:25:29 +00001407 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001408 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001409 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001410 fd = ss.fileno()
1411 f = ss.makefile()
1412 f.close()
1413 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001414 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001415 # Closing the SSL socket should close the fd too
1416 ss.close()
1417 gc.collect()
1418 with self.assertRaises(OSError) as e:
1419 os.read(fd, 0)
1420 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +00001421
Antoine Pitrou3945c862010-04-28 21:11:01 +00001422 def test_non_blocking_handshake(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001423 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001424 s = socket.socket(socket.AF_INET)
Martin Panter71202bb2016-01-15 00:25:29 +00001425 s.connect((REMOTE_HOST, 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001426 s.setblocking(False)
1427 s = ssl.wrap_socket(s,
1428 cert_reqs=ssl.CERT_NONE,
1429 do_handshake_on_connect=False)
1430 count = 0
1431 while True:
1432 try:
1433 count += 1
1434 s.do_handshake()
1435 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001436 except ssl.SSLWantReadError:
1437 select.select([s], [], [])
1438 except ssl.SSLWantWriteError:
1439 select.select([], [s], [])
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001440 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001441 if support.verbose:
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001442 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +00001443
Antoine Pitrou3945c862010-04-28 21:11:01 +00001444 def test_get_server_certificate(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001445 def _test_get_server_certificate(host, port, cert=None):
1446 with support.transient_internet(host):
1447 pem = ssl.get_server_certificate((host, port))
1448 if not pem:
1449 self.fail("No server certificate on %s:%s!" % (host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001450
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001451 try:
1452 pem = ssl.get_server_certificate((host, port),
1453 ca_certs=CERTFILE)
1454 except ssl.SSLError as x:
1455 #should fail
1456 if support.verbose:
1457 sys.stdout.write("%s\n" % x)
1458 else:
1459 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001460
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001461 pem = ssl.get_server_certificate((host, port),
1462 ca_certs=cert)
1463 if not pem:
1464 self.fail("No server certificate on %s:%s!" % (host, port))
1465 if support.verbose:
1466 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1467
Martin Panter71202bb2016-01-15 00:25:29 +00001468 _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001469 if support.IPV6_ENABLED:
1470 _test_get_server_certificate('ipv6.google.com', 443)
1471
1472 def test_ciphers(self):
Martin Panter71202bb2016-01-15 00:25:29 +00001473 remote = (REMOTE_HOST, 443)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001474 with support.transient_internet(remote[0]):
1475 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1476 cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s:
1477 s.connect(remote)
1478 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1479 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s:
1480 s.connect(remote)
1481 # Error checking can happen at instantiation or when connecting
1482 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
1483 with closing(socket.socket(socket.AF_INET)) as sock:
1484 s = ssl.wrap_socket(sock,
1485 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1486 s.connect(remote)
Bill Janssen296a59d2007-09-16 22:06:00 +00001487
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001488 def test_algorithms(self):
1489 # Issue #8484: all algorithms should be available when verifying a
1490 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +00001491 # SHA256 was added in OpenSSL 0.9.8
1492 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1493 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001494 # sha256.tbs-internet.com needs SNI to use the correct certificate
1495 if not ssl.HAS_SNI:
1496 self.skipTest("SNI needed for this test")
1497 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
Antoine Pitroud43245a2011-01-08 10:32:51 +00001498 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001499 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001500 with support.transient_internet("sha256.tbs-internet.com"):
1501 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1502 ctx.verify_mode = ssl.CERT_REQUIRED
1503 ctx.load_verify_locations(sha256_cert)
1504 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1505 server_hostname="sha256.tbs-internet.com")
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001506 try:
1507 s.connect(remote)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001508 if support.verbose:
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001509 sys.stdout.write("\nCipher with %r is %r\n" %
1510 (remote, s.cipher()))
1511 sys.stdout.write("Certificate is:\n%s\n" %
1512 pprint.pformat(s.getpeercert()))
1513 finally:
1514 s.close()
1515
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001516 def test_get_ca_certs_capath(self):
1517 # capath certs are loaded on request
Martin Panter71202bb2016-01-15 00:25:29 +00001518 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001519 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1520 ctx.verify_mode = ssl.CERT_REQUIRED
1521 ctx.load_verify_locations(capath=CAPATH)
1522 self.assertEqual(ctx.get_ca_certs(), [])
1523 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter71202bb2016-01-15 00:25:29 +00001524 s.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001525 try:
1526 cert = s.getpeercert()
1527 self.assertTrue(cert)
1528 finally:
1529 s.close()
1530 self.assertEqual(len(ctx.get_ca_certs()), 1)
1531
1532 @needs_sni
1533 def test_context_setget(self):
1534 # Check that the context of a connected socket can be replaced.
Martin Panter71202bb2016-01-15 00:25:29 +00001535 with support.transient_internet(REMOTE_HOST):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001536 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1537 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1538 s = socket.socket(socket.AF_INET)
1539 with closing(ctx1.wrap_socket(s)) as ss:
Martin Panter71202bb2016-01-15 00:25:29 +00001540 ss.connect((REMOTE_HOST, 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001541 self.assertIs(ss.context, ctx1)
1542 self.assertIs(ss._sslobj.context, ctx1)
1543 ss.context = ctx2
1544 self.assertIs(ss.context, ctx2)
1545 self.assertIs(ss._sslobj.context, ctx2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001546
Bill Janssen98d19da2007-09-10 21:51:02 +00001547try:
1548 import threading
1549except ImportError:
1550 _have_threads = False
1551else:
Bill Janssen98d19da2007-09-10 21:51:02 +00001552 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001553
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001554 from test.ssl_servers import make_https_server
1555
Bill Janssen98d19da2007-09-10 21:51:02 +00001556 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001557
Bill Janssen98d19da2007-09-10 21:51:02 +00001558 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001559
Bill Janssen98d19da2007-09-10 21:51:02 +00001560 """A mildly complicated class, because we want it to work both
1561 with and without the SSL wrapper around the socket connection, so
1562 that we can test the STARTTLS functionality."""
1563
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001564 def __init__(self, server, connsock, addr):
Bill Janssen98d19da2007-09-10 21:51:02 +00001565 self.server = server
1566 self.running = False
1567 self.sock = connsock
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001568 self.addr = addr
Bill Janssen98d19da2007-09-10 21:51:02 +00001569 self.sock.setblocking(1)
1570 self.sslconn = None
1571 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001572 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001573
Antoine Pitrou3945c862010-04-28 21:11:01 +00001574 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001575 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001576 self.sslconn = self.server.context.wrap_socket(
1577 self.sock, server_side=True)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001578 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1579 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001580 except socket.error as e:
1581 # We treat ConnectionResetError as though it were an
1582 # SSLError - OpenSSL on Ubuntu abruptly closes the
1583 # connection when asked to use an unsupported protocol.
1584 #
Antoine Pitroudb187842010-04-27 10:32:58 +00001585 # XXX Various errors can have happened here, for example
1586 # a mismatching protocol version, an invalid certificate,
1587 # or a low-level bug. This should be made more discriminating.
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001588 if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET:
1589 raise
Antoine Pitroud76088d2012-01-03 22:46:48 +01001590 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +00001591 if self.server.chatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001592 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00001593 self.running = False
1594 self.server.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001595 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001596 return False
Bill Janssen98d19da2007-09-10 21:51:02 +00001597 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001598 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
1599 cert = self.sslconn.getpeercert()
1600 if support.verbose and self.server.chatty:
1601 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1602 cert_binary = self.sslconn.getpeercert(True)
1603 if support.verbose and self.server.chatty:
1604 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1605 cipher = self.sslconn.cipher()
1606 if support.verbose and self.server.chatty:
1607 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
1608 sys.stdout.write(" server: selected protocol is now "
1609 + str(self.sslconn.selected_npn_protocol()) + "\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001610 return True
1611
1612 def read(self):
1613 if self.sslconn:
1614 return self.sslconn.read()
1615 else:
1616 return self.sock.recv(1024)
1617
1618 def write(self, bytes):
1619 if self.sslconn:
1620 return self.sslconn.write(bytes)
1621 else:
1622 return self.sock.send(bytes)
1623
1624 def close(self):
1625 if self.sslconn:
1626 self.sslconn.close()
1627 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001628 self.sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001629
Antoine Pitrou3945c862010-04-28 21:11:01 +00001630 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001631 self.running = True
1632 if not self.server.starttls_server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001633 if not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +00001634 return
1635 while self.running:
1636 try:
1637 msg = self.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001638 stripped = msg.strip()
1639 if not stripped:
Bill Janssen98d19da2007-09-10 21:51:02 +00001640 # eof, so quit this handler
1641 self.running = False
1642 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001643 elif stripped == b'over':
1644 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001645 sys.stdout.write(" server: client closed connection\n")
1646 self.close()
1647 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001648 elif (self.server.starttls_server and
1649 stripped == b'STARTTLS'):
1650 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001651 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001652 self.write(b"OK\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001653 if not self.wrap_conn():
1654 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001655 elif (self.server.starttls_server and self.sslconn
1656 and stripped == b'ENDTLS'):
1657 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001658 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001659 self.write(b"OK\n")
1660 self.sock = self.sslconn.unwrap()
Bill Janssen39295c22008-08-12 16:31:21 +00001661 self.sslconn = None
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001662 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001663 sys.stdout.write(" server: connection is now unencrypted...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001664 elif stripped == b'CB tls-unique':
1665 if support.verbose and self.server.connectionchatty:
1666 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1667 data = self.sslconn.get_channel_binding("tls-unique")
1668 self.write(repr(data).encode("us-ascii") + b"\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001669 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001670 if (support.verbose and
Bill Janssen98d19da2007-09-10 21:51:02 +00001671 self.server.connectionchatty):
1672 ctype = (self.sslconn and "encrypted") or "unencrypted"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001673 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1674 % (msg, ctype, msg.lower(), ctype))
Bill Janssen98d19da2007-09-10 21:51:02 +00001675 self.write(msg.lower())
1676 except ssl.SSLError:
1677 if self.server.chatty:
1678 handle_error("Test server failure:\n")
1679 self.close()
1680 self.running = False
1681 # normally, we'd just stop here, but for the test
1682 # harness, we want to stop the server
1683 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +00001684
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001685 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +00001686 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +00001687 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001688 npn_protocols=None, alpn_protocols=None,
1689 ciphers=None, context=None):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001690 if context:
1691 self.context = context
1692 else:
1693 self.context = ssl.SSLContext(ssl_version
1694 if ssl_version is not None
1695 else ssl.PROTOCOL_TLSv1)
1696 self.context.verify_mode = (certreqs if certreqs is not None
1697 else ssl.CERT_NONE)
1698 if cacerts:
1699 self.context.load_verify_locations(cacerts)
1700 if certificate:
1701 self.context.load_cert_chain(certificate)
1702 if npn_protocols:
1703 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001704 if alpn_protocols:
1705 self.context.set_alpn_protocols(alpn_protocols)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001706 if ciphers:
1707 self.context.set_ciphers(ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +00001708 self.chatty = chatty
1709 self.connectionchatty = connectionchatty
1710 self.starttls_server = starttls_server
1711 self.sock = socket.socket()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001712 self.port = support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +00001713 self.flag = None
Bill Janssen98d19da2007-09-10 21:51:02 +00001714 self.active = False
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001715 self.selected_npn_protocols = []
1716 self.selected_alpn_protocols = []
Antoine Pitroud76088d2012-01-03 22:46:48 +01001717 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001718 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001719 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001720
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001721 def __enter__(self):
1722 self.start(threading.Event())
1723 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001724 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001725
1726 def __exit__(self, *args):
1727 self.stop()
1728 self.join()
1729
Antoine Pitrou3945c862010-04-28 21:11:01 +00001730 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +00001731 self.flag = flag
1732 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001733
Antoine Pitrou3945c862010-04-28 21:11:01 +00001734 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +00001735 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +00001736 self.sock.listen(5)
1737 self.active = True
1738 if self.flag:
1739 # signal an event
1740 self.flag.set()
1741 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001742 try:
Bill Janssen98d19da2007-09-10 21:51:02 +00001743 newconn, connaddr = self.sock.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001744 if support.verbose and self.chatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001745 sys.stdout.write(' server: new connection from '
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001746 + repr(connaddr) + '\n')
1747 handler = self.ConnectionHandler(self, newconn, connaddr)
Bill Janssen98d19da2007-09-10 21:51:02 +00001748 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +01001749 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +00001750 except socket.timeout:
1751 pass
1752 except KeyboardInterrupt:
1753 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +00001754 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001755
Antoine Pitrou3945c862010-04-28 21:11:01 +00001756 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001757 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001758
Bill Janssen934b16d2008-06-28 22:19:33 +00001759 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +00001760
Antoine Pitrou3945c862010-04-28 21:11:01 +00001761 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +00001762
Antoine Pitrou3945c862010-04-28 21:11:01 +00001763 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +00001764
1765 def __init__(self, conn, certfile):
Bill Janssen934b16d2008-06-28 22:19:33 +00001766 self.socket = ssl.wrap_socket(conn, server_side=True,
1767 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +00001768 do_handshake_on_connect=False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001769 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroufc69af12010-04-24 20:04:58 +00001770 self._ssl_accepting = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001771 self._do_ssl_handshake()
Bill Janssen934b16d2008-06-28 22:19:33 +00001772
1773 def readable(self):
1774 if isinstance(self.socket, ssl.SSLSocket):
1775 while self.socket.pending() > 0:
1776 self.handle_read_event()
1777 return True
1778
Antoine Pitroufc69af12010-04-24 20:04:58 +00001779 def _do_ssl_handshake(self):
1780 try:
1781 self.socket.do_handshake()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001782 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1783 return
1784 except ssl.SSLEOFError:
1785 return self.handle_close()
1786 except ssl.SSLError:
Antoine Pitroufc69af12010-04-24 20:04:58 +00001787 raise
1788 except socket.error, err:
1789 if err.args[0] == errno.ECONNABORTED:
1790 return self.handle_close()
1791 else:
1792 self._ssl_accepting = False
1793
Bill Janssen934b16d2008-06-28 22:19:33 +00001794 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +00001795 if self._ssl_accepting:
1796 self._do_ssl_handshake()
1797 else:
1798 data = self.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001799 if support.verbose:
1800 sys.stdout.write(" server: read %s from client\n" % repr(data))
1801 if not data:
1802 self.close()
1803 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001804 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +00001805
1806 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +00001807 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001808 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001809 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1810
1811 def handle_error(self):
1812 raise
1813
1814 def __init__(self, certfile):
1815 self.certfile = certfile
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001816 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1817 self.port = support.bind_port(sock, '')
1818 asyncore.dispatcher.__init__(self, sock)
Bill Janssen934b16d2008-06-28 22:19:33 +00001819 self.listen(5)
1820
1821 def handle_accept(self):
1822 sock_obj, addr = self.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001823 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001824 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1825 self.ConnectionHandler(sock_obj, self.certfile)
1826
1827 def handle_error(self):
1828 raise
1829
1830 def __init__(self, certfile):
1831 self.flag = None
1832 self.active = False
1833 self.server = self.EchoServer(certfile)
1834 self.port = self.server.port
1835 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001836 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +00001837
1838 def __str__(self):
1839 return "<%s %s>" % (self.__class__.__name__, self.server)
1840
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001841 def __enter__(self):
1842 self.start(threading.Event())
1843 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001844 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001845
1846 def __exit__(self, *args):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001847 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001848 sys.stdout.write(" cleanup: stopping server.\n")
1849 self.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001850 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001851 sys.stdout.write(" cleanup: joining server thread.\n")
1852 self.join()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001853 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001854 sys.stdout.write(" cleanup: successfully joined.\n")
1855
Antoine Pitrou3945c862010-04-28 21:11:01 +00001856 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +00001857 self.flag = flag
1858 threading.Thread.start(self)
1859
Antoine Pitrou3945c862010-04-28 21:11:01 +00001860 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001861 self.active = True
1862 if self.flag:
1863 self.flag.set()
1864 while self.active:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001865 try:
1866 asyncore.loop(1)
1867 except:
1868 pass
Bill Janssen934b16d2008-06-28 22:19:33 +00001869
Antoine Pitrou3945c862010-04-28 21:11:01 +00001870 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001871 self.active = False
1872 self.server.close()
1873
Antoine Pitrou3945c862010-04-28 21:11:01 +00001874 def bad_cert_test(certfile):
1875 """
1876 Launch a server with CERT_REQUIRED, and check that trying to
1877 connect to it with the given client certificate fails.
1878 """
Trent Nelsone41b0062008-04-08 23:47:30 +00001879 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001880 certreqs=ssl.CERT_REQUIRED,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001881 cacerts=CERTFILE, chatty=False,
1882 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001883 with server:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001884 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001885 with closing(socket.socket()) as sock:
1886 s = ssl.wrap_socket(sock,
1887 certfile=certfile,
1888 ssl_version=ssl.PROTOCOL_TLSv1)
1889 s.connect((HOST, server.port))
1890 except ssl.SSLError as x:
1891 if support.verbose:
1892 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
1893 except OSError as x:
1894 if support.verbose:
1895 sys.stdout.write("\nOSError is %s\n" % x.args[1])
1896 except OSError as x:
1897 if x.errno != errno.ENOENT:
1898 raise
1899 if support.verbose:
1900 sys.stdout.write("\OSError is %s\n" % str(x))
Bill Janssen98d19da2007-09-10 21:51:02 +00001901 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00001902 raise AssertionError("Use of invalid cert should have failed!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001903
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001904 def server_params_test(client_context, server_context, indata=b"FOO\n",
1905 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001906 """
1907 Launch a server, connect a client to it and try various reads
1908 and writes.
1909 """
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001910 stats = {}
1911 server = ThreadedEchoServer(context=server_context,
Bill Janssen98d19da2007-09-10 21:51:02 +00001912 chatty=chatty,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001913 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001914 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001915 with closing(client_context.wrap_socket(socket.socket(),
1916 server_hostname=sni_name)) as s:
1917 s.connect((HOST, server.port))
1918 for arg in [indata, bytearray(indata), memoryview(indata)]:
1919 if connectionchatty:
1920 if support.verbose:
1921 sys.stdout.write(
1922 " client: sending %r...\n" % indata)
1923 s.write(arg)
1924 outdata = s.read()
1925 if connectionchatty:
1926 if support.verbose:
1927 sys.stdout.write(" client: read %r\n" % outdata)
1928 if outdata != indata.lower():
1929 raise AssertionError(
1930 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1931 % (outdata[:20], len(outdata),
1932 indata[:20].lower(), len(indata)))
1933 s.write(b"over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001934 if connectionchatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001935 if support.verbose:
1936 sys.stdout.write(" client: closing connection.\n")
1937 stats.update({
1938 'compression': s.compression(),
1939 'cipher': s.cipher(),
1940 'peercert': s.getpeercert(),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001941 'client_alpn_protocol': s.selected_alpn_protocol(),
Alex Gaynore98205d2014-09-04 13:33:22 -07001942 'client_npn_protocol': s.selected_npn_protocol(),
1943 'version': s.version(),
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001944 })
1945 s.close()
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05001946 stats['server_alpn_protocols'] = server.selected_alpn_protocols
1947 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001948 return stats
Bill Janssen98d19da2007-09-10 21:51:02 +00001949
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001950 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1951 certsreqs=None, server_options=0, client_options=0):
Alex Gaynore98205d2014-09-04 13:33:22 -07001952 """
1953 Try to SSL-connect using *client_protocol* to *server_protocol*.
1954 If *expect_success* is true, assert that the connection succeeds,
1955 if it's false, assert that the connection fails.
1956 Also, if *expect_success* is a string, assert that it is the protocol
1957 version actually used by the connection.
1958 """
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00001959 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +00001960 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +00001961 certtype = {
1962 ssl.CERT_NONE: "CERT_NONE",
1963 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1964 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1965 }[certsreqs]
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001966 if support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001967 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +00001968 sys.stdout.write(formatstr %
1969 (ssl.get_protocol_name(client_protocol),
1970 ssl.get_protocol_name(server_protocol),
1971 certtype))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001972 client_context = ssl.SSLContext(client_protocol)
1973 client_context.options |= client_options
1974 server_context = ssl.SSLContext(server_protocol)
1975 server_context.options |= server_options
1976
1977 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1978 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1979 # starting from OpenSSL 1.0.0 (see issue #8322).
1980 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1981 client_context.set_ciphers("ALL")
1982
1983 for ctx in (client_context, server_context):
1984 ctx.verify_mode = certsreqs
1985 ctx.load_cert_chain(CERTFILE)
1986 ctx.load_verify_locations(CERTFILE)
Bill Janssen98d19da2007-09-10 21:51:02 +00001987 try:
Alex Gaynore98205d2014-09-04 13:33:22 -07001988 stats = server_params_test(client_context, server_context,
1989 chatty=False, connectionchatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00001990 # Protocol mismatch can result in either an SSLError, or a
1991 # "Connection reset by peer" error.
1992 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001993 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +00001994 raise
Antoine Pitroudb187842010-04-27 10:32:58 +00001995 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001996 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +00001997 raise
Bill Janssen98d19da2007-09-10 21:51:02 +00001998 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001999 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00002000 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +00002001 "Client protocol %s succeeded with server protocol %s!"
2002 % (ssl.get_protocol_name(client_protocol),
2003 ssl.get_protocol_name(server_protocol)))
Alex Gaynore98205d2014-09-04 13:33:22 -07002004 elif (expect_success is not True
2005 and expect_success != stats['version']):
2006 raise AssertionError("version mismatch: expected %r, got %r"
2007 % (expect_success, stats['version']))
Bill Janssen98d19da2007-09-10 21:51:02 +00002008
2009
Bill Janssen934b16d2008-06-28 22:19:33 +00002010 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +00002011
Antoine Pitroud75efd92010-08-04 17:38:33 +00002012 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002013 def test_echo(self):
2014 """Basic test of an SSL client connecting to a server"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002015 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002016 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002017 for protocol in PROTOCOLS:
2018 context = ssl.SSLContext(protocol)
2019 context.load_cert_chain(CERTFILE)
2020 server_params_test(context, context,
2021 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002022
Antoine Pitrou3945c862010-04-28 21:11:01 +00002023 def test_getpeercert(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002024 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002025 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002026 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2027 context.verify_mode = ssl.CERT_REQUIRED
2028 context.load_verify_locations(CERTFILE)
2029 context.load_cert_chain(CERTFILE)
2030 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002031 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002032 s = context.wrap_socket(socket.socket(),
2033 do_handshake_on_connect=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002034 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002035 # getpeercert() raise ValueError while the handshake isn't
2036 # done.
2037 with self.assertRaises(ValueError):
2038 s.getpeercert()
2039 s.do_handshake()
Antoine Pitroudb187842010-04-27 10:32:58 +00002040 cert = s.getpeercert()
2041 self.assertTrue(cert, "Can't get peer certificate.")
2042 cipher = s.cipher()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002043 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002044 sys.stdout.write(pprint.pformat(cert) + '\n')
2045 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2046 if 'subject' not in cert:
2047 self.fail("No subject field in certificate: %s." %
2048 pprint.pformat(cert))
2049 if ((('organizationName', 'Python Software Foundation'),)
2050 not in cert['subject']):
2051 self.fail(
2052 "Missing or invalid 'organizationName' field in certificate subject; "
2053 "should be 'Python Software Foundation'.")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002054 self.assertIn('notBefore', cert)
2055 self.assertIn('notAfter', cert)
2056 before = ssl.cert_time_to_seconds(cert['notBefore'])
2057 after = ssl.cert_time_to_seconds(cert['notAfter'])
2058 self.assertLess(before, after)
Antoine Pitroudb187842010-04-27 10:32:58 +00002059 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002060
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002061 @unittest.skipUnless(have_verify_flags(),
2062 "verify_flags need OpenSSL > 0.9.8")
2063 def test_crl_check(self):
2064 if support.verbose:
2065 sys.stdout.write("\n")
2066
2067 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2068 server_context.load_cert_chain(SIGNED_CERTFILE)
2069
2070 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2071 context.verify_mode = ssl.CERT_REQUIRED
2072 context.load_verify_locations(SIGNING_CA)
Benjamin Petersond86699f2015-03-04 23:18:48 -05002073 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2074 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002075
2076 # VERIFY_DEFAULT should pass
2077 server = ThreadedEchoServer(context=server_context, chatty=True)
2078 with server:
2079 with closing(context.wrap_socket(socket.socket())) as s:
2080 s.connect((HOST, server.port))
2081 cert = s.getpeercert()
2082 self.assertTrue(cert, "Can't get peer certificate.")
2083
2084 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
2085 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
2086
2087 server = ThreadedEchoServer(context=server_context, chatty=True)
2088 with server:
2089 with closing(context.wrap_socket(socket.socket())) as s:
2090 with self.assertRaisesRegexp(ssl.SSLError,
2091 "certificate verify failed"):
2092 s.connect((HOST, server.port))
2093
2094 # now load a CRL file. The CRL file is signed by the CA.
2095 context.load_verify_locations(CRLFILE)
2096
2097 server = ThreadedEchoServer(context=server_context, chatty=True)
2098 with server:
2099 with closing(context.wrap_socket(socket.socket())) as s:
2100 s.connect((HOST, server.port))
2101 cert = s.getpeercert()
2102 self.assertTrue(cert, "Can't get peer certificate.")
2103
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002104 def test_check_hostname(self):
2105 if support.verbose:
2106 sys.stdout.write("\n")
2107
2108 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2109 server_context.load_cert_chain(SIGNED_CERTFILE)
2110
2111 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2112 context.verify_mode = ssl.CERT_REQUIRED
2113 context.check_hostname = True
2114 context.load_verify_locations(SIGNING_CA)
2115
2116 # correct hostname should verify
2117 server = ThreadedEchoServer(context=server_context, chatty=True)
2118 with server:
2119 with closing(context.wrap_socket(socket.socket(),
2120 server_hostname="localhost")) as s:
2121 s.connect((HOST, server.port))
2122 cert = s.getpeercert()
2123 self.assertTrue(cert, "Can't get peer certificate.")
2124
2125 # incorrect hostname should raise an exception
2126 server = ThreadedEchoServer(context=server_context, chatty=True)
2127 with server:
2128 with closing(context.wrap_socket(socket.socket(),
2129 server_hostname="invalid")) as s:
2130 with self.assertRaisesRegexp(ssl.CertificateError,
2131 "hostname 'invalid' doesn't match u?'localhost'"):
2132 s.connect((HOST, server.port))
2133
2134 # missing server_hostname arg should cause an exception, too
2135 server = ThreadedEchoServer(context=server_context, chatty=True)
2136 with server:
2137 with closing(socket.socket()) as s:
2138 with self.assertRaisesRegexp(ValueError,
2139 "check_hostname requires server_hostname"):
2140 context.wrap_socket(s)
2141
Antoine Pitrou3945c862010-04-28 21:11:01 +00002142 def test_empty_cert(self):
2143 """Connecting with an empty cert file"""
2144 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2145 "nullcert.pem"))
2146 def test_malformed_cert(self):
2147 """Connecting with a badly formatted certificate (syntax error)"""
2148 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2149 "badcert.pem"))
2150 def test_nonexisting_cert(self):
2151 """Connecting with a non-existing cert file"""
2152 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2153 "wrongcert.pem"))
2154 def test_malformed_key(self):
2155 """Connecting with a badly formatted key (syntax error)"""
2156 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2157 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +00002158
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002159 def test_rude_shutdown(self):
2160 """A brutal shutdown of an SSL server should raise an OSError
2161 in the client when attempting handshake.
2162 """
2163 listener_ready = threading.Event()
2164 listener_gone = threading.Event()
2165
2166 s = socket.socket()
2167 port = support.bind_port(s, HOST)
2168
2169 # `listener` runs in a thread. It sits in an accept() until
2170 # the main thread connects. Then it rudely closes the socket,
2171 # and sets Event `listener_gone` to let the main thread know
2172 # the socket is gone.
2173 def listener():
2174 s.listen(5)
2175 listener_ready.set()
2176 newsock, addr = s.accept()
2177 newsock.close()
2178 s.close()
2179 listener_gone.set()
2180
2181 def connector():
2182 listener_ready.wait()
2183 with closing(socket.socket()) as c:
2184 c.connect((HOST, port))
2185 listener_gone.wait()
2186 try:
2187 ssl_sock = ssl.wrap_socket(c)
Benjamin Petersone208b572014-08-20 14:49:08 -05002188 except socket.error:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002189 pass
2190 else:
2191 self.fail('connecting to closed SSL socket should have failed')
2192
2193 t = threading.Thread(target=listener)
2194 t.start()
2195 try:
2196 connector()
2197 finally:
2198 t.join()
2199
Antoine Pitroud75efd92010-08-04 17:38:33 +00002200 @skip_if_broken_ubuntu_ssl
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002201 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2202 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002203 def test_protocol_sslv2(self):
2204 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002205 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002206 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002207 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2208 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2209 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01002210 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002211 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2212 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002213 # SSLv23 client with specific SSL options
2214 if no_sslv2_implies_sslv3_hello():
2215 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2216 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2217 client_options=ssl.OP_NO_SSLv2)
2218 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2219 client_options=ssl.OP_NO_SSLv3)
2220 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2221 client_options=ssl.OP_NO_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00002222
Antoine Pitroud75efd92010-08-04 17:38:33 +00002223 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002224 def test_protocol_sslv23(self):
2225 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002226 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002227 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002228 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2229 try:
2230 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
2231 except socket.error as x:
2232 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2233 if support.verbose:
2234 sys.stdout.write(
2235 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2236 % str(x))
Benjamin Peterson60766c42014-12-05 21:59:35 -05002237 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002238 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002239 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Alex Gaynore98205d2014-09-04 13:33:22 -07002240 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Bill Janssen98d19da2007-09-10 21:51:02 +00002241
Benjamin Peterson60766c42014-12-05 21:59:35 -05002242 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002243 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002244 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Alex Gaynore98205d2014-09-04 13:33:22 -07002245 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00002246
Benjamin Peterson60766c42014-12-05 21:59:35 -05002247 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002248 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002249 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Alex Gaynore98205d2014-09-04 13:33:22 -07002250 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00002251
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002252 # Server with specific SSL options
Benjamin Peterson60766c42014-12-05 21:59:35 -05002253 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2254 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002255 server_options=ssl.OP_NO_SSLv3)
2256 # Will choose TLSv1
2257 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2258 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2259 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2260 server_options=ssl.OP_NO_TLSv1)
2261
2262
Antoine Pitroud75efd92010-08-04 17:38:33 +00002263 @skip_if_broken_ubuntu_ssl
Benjamin Peterson60766c42014-12-05 21:59:35 -05002264 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2265 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002266 def test_protocol_sslv3(self):
2267 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002268 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002269 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002270 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2271 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2272 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002273 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2274 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002275 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2276 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002277 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002278 if no_sslv2_implies_sslv3_hello():
2279 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Peterson10aaca92015-11-11 22:38:41 -08002280 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2281 False, client_options=ssl.OP_NO_SSLv2)
Bill Janssen98d19da2007-09-10 21:51:02 +00002282
Antoine Pitroud75efd92010-08-04 17:38:33 +00002283 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002284 def test_protocol_tlsv1(self):
2285 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002286 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002287 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002288 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2289 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2290 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002291 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2292 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002293 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2294 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002295 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2296 client_options=ssl.OP_NO_TLSv1)
2297
2298 @skip_if_broken_ubuntu_ssl
2299 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2300 "TLS version 1.1 not supported.")
2301 def test_protocol_tlsv1_1(self):
2302 """Connecting to a TLSv1.1 server with various client options.
2303 Testing against older TLS versions."""
2304 if support.verbose:
2305 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002306 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002307 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2308 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002309 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2310 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002311 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2312 client_options=ssl.OP_NO_TLSv1_1)
2313
Alex Gaynore98205d2014-09-04 13:33:22 -07002314 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002315 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2316 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2317
2318
2319 @skip_if_broken_ubuntu_ssl
2320 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2321 "TLS version 1.2 not supported.")
2322 def test_protocol_tlsv1_2(self):
2323 """Connecting to a TLSv1.2 server with various client options.
2324 Testing against older TLS versions."""
2325 if support.verbose:
2326 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002327 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002328 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2329 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2330 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2331 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Peterson60766c42014-12-05 21:59:35 -05002332 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2333 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002334 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2335 client_options=ssl.OP_NO_TLSv1_2)
2336
Alex Gaynore98205d2014-09-04 13:33:22 -07002337 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002338 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2339 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2340 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2341 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00002342
Antoine Pitrou3945c862010-04-28 21:11:01 +00002343 def test_starttls(self):
2344 """Switching from clear text to encrypted and back again."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002345 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 +00002346
Trent Nelsone41b0062008-04-08 23:47:30 +00002347 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00002348 ssl_version=ssl.PROTOCOL_TLSv1,
2349 starttls_server=True,
2350 chatty=True,
2351 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002352 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002353 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002354 s = socket.socket()
2355 s.setblocking(1)
2356 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002357 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002358 sys.stdout.write("\n")
2359 for indata in msgs:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002360 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002361 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002362 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002363 if wrapped:
2364 conn.write(indata)
2365 outdata = conn.read()
2366 else:
2367 s.send(indata)
2368 outdata = s.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002369 msg = outdata.strip().lower()
2370 if indata == b"STARTTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002371 # STARTTLS ok, switch to secure mode
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002372 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002373 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002374 " client: read %r from server, starting TLS...\n"
2375 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002376 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2377 wrapped = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002378 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002379 # ENDTLS ok, switch back to clear text
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002380 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002381 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002382 " client: read %r from server, ending TLS...\n"
2383 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002384 s = conn.unwrap()
2385 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00002386 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002387 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002388 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002389 " client: read %r from server\n" % msg)
2390 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002391 sys.stdout.write(" client: closing connection.\n")
2392 if wrapped:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002393 conn.write(b"over\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00002394 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002395 s.send(b"over\n")
2396 if wrapped:
2397 conn.close()
2398 else:
2399 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002400
Antoine Pitrou3945c862010-04-28 21:11:01 +00002401 def test_socketserver(self):
2402 """Using a SocketServer to create and manage SSL connections."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002403 server = make_https_server(self, certfile=CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00002404 # try to connect
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002405 if support.verbose:
2406 sys.stdout.write('\n')
2407 with open(CERTFILE, 'rb') as f:
2408 d1 = f.read()
2409 d2 = ''
2410 # now fetch the same data from the HTTPS server
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -06002411 url = 'https://localhost:%d/%s' % (
2412 server.port, os.path.split(CERTFILE)[1])
2413 context = ssl.create_default_context(cafile=CERTFILE)
Benjamin Petersonb0609ec2014-11-23 11:52:46 -06002414 f = urllib2.urlopen(url, context=context)
Bill Janssen296a59d2007-09-16 22:06:00 +00002415 try:
Bill Janssen296a59d2007-09-16 22:06:00 +00002416 dlen = f.info().getheader("content-length")
2417 if dlen and (int(dlen) > 0):
2418 d2 = f.read(int(dlen))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002419 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002420 sys.stdout.write(
2421 " client: read %d bytes from remote server '%s'\n"
2422 % (len(d2), server))
Bill Janssen296a59d2007-09-16 22:06:00 +00002423 finally:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002424 f.close()
2425 self.assertEqual(d1, d2)
Bill Janssen934b16d2008-06-28 22:19:33 +00002426
Antoine Pitrou3945c862010-04-28 21:11:01 +00002427 def test_asyncore_server(self):
2428 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00002429 indata = "TEST MESSAGE of mixed case\n"
2430
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002431 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00002432 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002433
2434 indata = b"FOO\n"
Bill Janssen934b16d2008-06-28 22:19:33 +00002435 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002436 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002437 s = ssl.wrap_socket(socket.socket())
2438 s.connect(('127.0.0.1', server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002439 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002440 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002441 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002442 s.write(indata)
2443 outdata = s.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002444 if support.verbose:
2445 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002446 if outdata != indata.lower():
2447 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002448 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2449 % (outdata[:20], len(outdata),
2450 indata[:20].lower(), len(indata)))
2451 s.write(b"over\n")
2452 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002453 sys.stdout.write(" client: closing connection.\n")
2454 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002455 if support.verbose:
2456 sys.stdout.write(" client: connection closed.\n")
Bill Janssen934b16d2008-06-28 22:19:33 +00002457
Antoine Pitrou3945c862010-04-28 21:11:01 +00002458 def test_recv_send(self):
2459 """Test recv(), send() and friends."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002460 if support.verbose:
Bill Janssen61c001a2008-09-08 16:37:24 +00002461 sys.stdout.write("\n")
2462
2463 server = ThreadedEchoServer(CERTFILE,
2464 certreqs=ssl.CERT_NONE,
2465 ssl_version=ssl.PROTOCOL_TLSv1,
2466 cacerts=CERTFILE,
2467 chatty=True,
2468 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002469 with server:
2470 s = ssl.wrap_socket(socket.socket(),
2471 server_side=False,
2472 certfile=CERTFILE,
2473 ca_certs=CERTFILE,
2474 cert_reqs=ssl.CERT_NONE,
2475 ssl_version=ssl.PROTOCOL_TLSv1)
2476 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00002477 # helper methods for standardising recv* method signatures
2478 def _recv_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002479 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002480 count = s.recv_into(b)
2481 return b[:count]
2482
2483 def _recvfrom_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002484 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002485 count, addr = s.recvfrom_into(b)
2486 return b[:count]
2487
2488 # (name, method, whether to expect success, *args)
2489 send_methods = [
2490 ('send', s.send, True, []),
2491 ('sendto', s.sendto, False, ["some.address"]),
2492 ('sendall', s.sendall, True, []),
2493 ]
2494 recv_methods = [
2495 ('recv', s.recv, True, []),
2496 ('recvfrom', s.recvfrom, False, ["some.address"]),
2497 ('recv_into', _recv_into, True, []),
2498 ('recvfrom_into', _recvfrom_into, False, []),
2499 ]
2500 data_prefix = u"PREFIX_"
2501
2502 for meth_name, send_meth, expect_success, args in send_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002503 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002504 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002505 send_meth(indata, *args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002506 outdata = s.read()
Bill Janssen61c001a2008-09-08 16:37:24 +00002507 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002508 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002509 "While sending with <<{name:s}>> bad data "
2510 "<<{outdata:r}>> ({nout:d}) received; "
2511 "expected <<{indata:r}>> ({nin:d})\n".format(
2512 name=meth_name, outdata=outdata[:20],
2513 nout=len(outdata),
2514 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002515 )
2516 )
2517 except ValueError as e:
2518 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002519 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002520 "Failed to send with method <<{name:s}>>; "
2521 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002522 )
2523 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002524 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002525 "Method <<{name:s}>> failed with unexpected "
2526 "exception message: {exp:s}\n".format(
2527 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002528 )
2529 )
2530
2531 for meth_name, recv_meth, expect_success, args in recv_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002532 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002533 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002534 s.send(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002535 outdata = recv_meth(*args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002536 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002537 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002538 "While receiving with <<{name:s}>> bad data "
2539 "<<{outdata:r}>> ({nout:d}) received; "
2540 "expected <<{indata:r}>> ({nin:d})\n".format(
2541 name=meth_name, outdata=outdata[:20],
2542 nout=len(outdata),
2543 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002544 )
2545 )
2546 except ValueError as e:
2547 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002548 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002549 "Failed to receive with method <<{name:s}>>; "
2550 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002551 )
2552 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002553 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002554 "Method <<{name:s}>> failed with unexpected "
2555 "exception message: {exp:s}\n".format(
2556 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002557 )
2558 )
2559 # consume data
2560 s.read()
2561
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002562 s.write(b"over\n")
Bill Janssen61c001a2008-09-08 16:37:24 +00002563 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00002564
Antoine Pitroufc69af12010-04-24 20:04:58 +00002565 def test_handshake_timeout(self):
2566 # Issue #5103: SSL handshake must respect the socket timeout
2567 server = socket.socket(socket.AF_INET)
2568 host = "127.0.0.1"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002569 port = support.bind_port(server)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002570 started = threading.Event()
2571 finish = False
2572
2573 def serve():
2574 server.listen(5)
2575 started.set()
2576 conns = []
2577 while not finish:
2578 r, w, e = select.select([server], [], [], 0.1)
2579 if server in r:
2580 # Let the socket hang around rather than having
2581 # it closed by garbage collection.
2582 conns.append(server.accept()[0])
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002583 for sock in conns:
2584 sock.close()
Antoine Pitroufc69af12010-04-24 20:04:58 +00002585
2586 t = threading.Thread(target=serve)
2587 t.start()
2588 started.wait()
2589
2590 try:
2591 try:
2592 c = socket.socket(socket.AF_INET)
2593 c.settimeout(0.2)
2594 c.connect((host, port))
2595 # Will attempt handshake and time out
2596 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2597 ssl.wrap_socket, c)
2598 finally:
2599 c.close()
2600 try:
2601 c = socket.socket(socket.AF_INET)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002602 c = ssl.wrap_socket(c)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002603 c.settimeout(0.2)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002604 # Will attempt handshake and time out
2605 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2606 c.connect, (host, port))
2607 finally:
2608 c.close()
2609 finally:
2610 finish = True
2611 t.join()
2612 server.close()
2613
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002614 def test_server_accept(self):
2615 # Issue #16357: accept() on a SSLSocket created through
2616 # SSLContext.wrap_socket().
2617 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2618 context.verify_mode = ssl.CERT_REQUIRED
2619 context.load_verify_locations(CERTFILE)
2620 context.load_cert_chain(CERTFILE)
2621 server = socket.socket(socket.AF_INET)
2622 host = "127.0.0.1"
2623 port = support.bind_port(server)
2624 server = context.wrap_socket(server, server_side=True)
2625
2626 evt = threading.Event()
2627 remote = [None]
2628 peer = [None]
2629 def serve():
2630 server.listen(5)
2631 # Block on the accept and wait on the connection to close.
2632 evt.set()
2633 remote[0], peer[0] = server.accept()
2634 remote[0].recv(1)
2635
2636 t = threading.Thread(target=serve)
2637 t.start()
2638 # Client wait until server setup and perform a connect.
2639 evt.wait()
2640 client = context.wrap_socket(socket.socket())
2641 client.connect((host, port))
2642 client_addr = client.getsockname()
2643 client.close()
2644 t.join()
2645 remote[0].close()
2646 server.close()
2647 # Sanity checks.
2648 self.assertIsInstance(remote[0], ssl.SSLSocket)
2649 self.assertEqual(peer[0], client_addr)
2650
2651 def test_getpeercert_enotconn(self):
2652 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2653 with closing(context.wrap_socket(socket.socket())) as sock:
2654 with self.assertRaises(socket.error) as cm:
2655 sock.getpeercert()
2656 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2657
2658 def test_do_handshake_enotconn(self):
2659 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2660 with closing(context.wrap_socket(socket.socket())) as sock:
2661 with self.assertRaises(socket.error) as cm:
2662 sock.do_handshake()
2663 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2664
Antoine Pitroud76088d2012-01-03 22:46:48 +01002665 def test_default_ciphers(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002666 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2667 try:
2668 # Force a set of weak ciphers on our client context
2669 context.set_ciphers("DES")
2670 except ssl.SSLError:
2671 self.skipTest("no DES cipher available")
Antoine Pitroud76088d2012-01-03 22:46:48 +01002672 with ThreadedEchoServer(CERTFILE,
2673 ssl_version=ssl.PROTOCOL_SSLv23,
2674 chatty=False) as server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002675 with closing(context.wrap_socket(socket.socket())) as s:
2676 with self.assertRaises(ssl.SSLError):
Antoine Pitroud76088d2012-01-03 22:46:48 +01002677 s.connect((HOST, server.port))
Antoine Pitroud76088d2012-01-03 22:46:48 +01002678 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2679
Alex Gaynore98205d2014-09-04 13:33:22 -07002680 def test_version_basic(self):
2681 """
2682 Basic tests for SSLSocket.version().
2683 More tests are done in the test_protocol_*() methods.
2684 """
2685 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2686 with ThreadedEchoServer(CERTFILE,
2687 ssl_version=ssl.PROTOCOL_TLSv1,
2688 chatty=False) as server:
2689 with closing(context.wrap_socket(socket.socket())) as s:
2690 self.assertIs(s.version(), None)
2691 s.connect((HOST, server.port))
2692 self.assertEqual(s.version(), "TLSv1")
2693 self.assertIs(s.version(), None)
2694
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002695 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2696 def test_default_ecdh_curve(self):
2697 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2698 # should be enabled by default on SSL contexts.
2699 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2700 context.load_cert_chain(CERTFILE)
2701 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2702 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2703 # our default cipher list should prefer ECDH-based ciphers
2704 # automatically.
2705 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2706 context.set_ciphers("ECCdraft:ECDH")
2707 with ThreadedEchoServer(context=context) as server:
2708 with closing(context.wrap_socket(socket.socket())) as s:
2709 s.connect((HOST, server.port))
2710 self.assertIn("ECDH", s.cipher()[0])
2711
2712 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2713 "'tls-unique' channel binding not available")
2714 def test_tls_unique_channel_binding(self):
2715 """Test tls-unique channel binding."""
2716 if support.verbose:
2717 sys.stdout.write("\n")
2718
2719 server = ThreadedEchoServer(CERTFILE,
2720 certreqs=ssl.CERT_NONE,
2721 ssl_version=ssl.PROTOCOL_TLSv1,
2722 cacerts=CERTFILE,
2723 chatty=True,
2724 connectionchatty=False)
2725 with server:
2726 s = ssl.wrap_socket(socket.socket(),
2727 server_side=False,
2728 certfile=CERTFILE,
2729 ca_certs=CERTFILE,
2730 cert_reqs=ssl.CERT_NONE,
2731 ssl_version=ssl.PROTOCOL_TLSv1)
2732 s.connect((HOST, server.port))
2733 # get the data
2734 cb_data = s.get_channel_binding("tls-unique")
2735 if support.verbose:
2736 sys.stdout.write(" got channel binding data: {0!r}\n"
2737 .format(cb_data))
2738
2739 # check if it is sane
2740 self.assertIsNotNone(cb_data)
2741 self.assertEqual(len(cb_data), 12) # True for TLSv1
2742
2743 # and compare with the peers version
2744 s.write(b"CB tls-unique\n")
2745 peer_data_repr = s.read().strip()
2746 self.assertEqual(peer_data_repr,
2747 repr(cb_data).encode("us-ascii"))
2748 s.close()
2749
2750 # now, again
2751 s = ssl.wrap_socket(socket.socket(),
2752 server_side=False,
2753 certfile=CERTFILE,
2754 ca_certs=CERTFILE,
2755 cert_reqs=ssl.CERT_NONE,
2756 ssl_version=ssl.PROTOCOL_TLSv1)
2757 s.connect((HOST, server.port))
2758 new_cb_data = s.get_channel_binding("tls-unique")
2759 if support.verbose:
2760 sys.stdout.write(" got another channel binding data: {0!r}\n"
2761 .format(new_cb_data))
2762 # is it really unique
2763 self.assertNotEqual(cb_data, new_cb_data)
2764 self.assertIsNotNone(cb_data)
2765 self.assertEqual(len(cb_data), 12) # True for TLSv1
2766 s.write(b"CB tls-unique\n")
2767 peer_data_repr = s.read().strip()
2768 self.assertEqual(peer_data_repr,
2769 repr(new_cb_data).encode("us-ascii"))
2770 s.close()
2771
2772 def test_compression(self):
2773 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2774 context.load_cert_chain(CERTFILE)
2775 stats = server_params_test(context, context,
2776 chatty=True, connectionchatty=True)
2777 if support.verbose:
2778 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2779 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2780
2781 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2782 "ssl.OP_NO_COMPRESSION needed for this test")
2783 def test_compression_disabled(self):
2784 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2785 context.load_cert_chain(CERTFILE)
2786 context.options |= ssl.OP_NO_COMPRESSION
2787 stats = server_params_test(context, context,
2788 chatty=True, connectionchatty=True)
2789 self.assertIs(stats['compression'], None)
2790
2791 def test_dh_params(self):
2792 # Check we can get a connection with ephemeral Diffie-Hellman
2793 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2794 context.load_cert_chain(CERTFILE)
2795 context.load_dh_params(DHFILE)
2796 context.set_ciphers("kEDH")
2797 stats = server_params_test(context, context,
2798 chatty=True, connectionchatty=True)
2799 cipher = stats["cipher"][0]
2800 parts = cipher.split("-")
2801 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2802 self.fail("Non-DH cipher: " + cipher[0])
2803
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002804 def test_selected_alpn_protocol(self):
2805 # selected_alpn_protocol() is None unless ALPN is used.
2806 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2807 context.load_cert_chain(CERTFILE)
2808 stats = server_params_test(context, context,
2809 chatty=True, connectionchatty=True)
2810 self.assertIs(stats['client_alpn_protocol'], None)
2811
2812 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
2813 def test_selected_alpn_protocol_if_server_uses_alpn(self):
2814 # selected_alpn_protocol() is None unless ALPN is used by the client.
2815 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2816 client_context.load_verify_locations(CERTFILE)
2817 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2818 server_context.load_cert_chain(CERTFILE)
2819 server_context.set_alpn_protocols(['foo', 'bar'])
2820 stats = server_params_test(client_context, server_context,
2821 chatty=True, connectionchatty=True)
2822 self.assertIs(stats['client_alpn_protocol'], None)
2823
2824 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
2825 def test_alpn_protocols(self):
2826 server_protocols = ['foo', 'bar', 'milkshake']
2827 protocol_tests = [
2828 (['foo', 'bar'], 'foo'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002829 (['bar', 'foo'], 'foo'),
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002830 (['milkshake'], 'milkshake'),
Benjamin Petersonaa707582015-01-23 17:30:26 -05002831 (['http/3.0', 'http/4.0'], None)
Benjamin Petersonb10bfbe2015-01-23 16:35:37 -05002832 ]
2833 for client_protocols, expected in protocol_tests:
2834 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2835 server_context.load_cert_chain(CERTFILE)
2836 server_context.set_alpn_protocols(server_protocols)
2837 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2838 client_context.load_cert_chain(CERTFILE)
2839 client_context.set_alpn_protocols(client_protocols)
2840 stats = server_params_test(client_context, server_context,
2841 chatty=True, connectionchatty=True)
2842
2843 msg = "failed trying %s (s) and %s (c).\n" \
2844 "was expecting %s, but got %%s from the %%s" \
2845 % (str(server_protocols), str(client_protocols),
2846 str(expected))
2847 client_result = stats['client_alpn_protocol']
2848 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2849 server_result = stats['server_alpn_protocols'][-1] \
2850 if len(stats['server_alpn_protocols']) else 'nothing'
2851 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2852
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002853 def test_selected_npn_protocol(self):
2854 # selected_npn_protocol() is None unless NPN is used
2855 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2856 context.load_cert_chain(CERTFILE)
2857 stats = server_params_test(context, context,
2858 chatty=True, connectionchatty=True)
2859 self.assertIs(stats['client_npn_protocol'], None)
2860
2861 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2862 def test_npn_protocols(self):
2863 server_protocols = ['http/1.1', 'spdy/2']
2864 protocol_tests = [
2865 (['http/1.1', 'spdy/2'], 'http/1.1'),
2866 (['spdy/2', 'http/1.1'], 'http/1.1'),
2867 (['spdy/2', 'test'], 'spdy/2'),
2868 (['abc', 'def'], 'abc')
2869 ]
2870 for client_protocols, expected in protocol_tests:
2871 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2872 server_context.load_cert_chain(CERTFILE)
2873 server_context.set_npn_protocols(server_protocols)
2874 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2875 client_context.load_cert_chain(CERTFILE)
2876 client_context.set_npn_protocols(client_protocols)
2877 stats = server_params_test(client_context, server_context,
2878 chatty=True, connectionchatty=True)
2879
2880 msg = "failed trying %s (s) and %s (c).\n" \
2881 "was expecting %s, but got %%s from the %%s" \
2882 % (str(server_protocols), str(client_protocols),
2883 str(expected))
2884 client_result = stats['client_npn_protocol']
2885 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2886 server_result = stats['server_npn_protocols'][-1] \
2887 if len(stats['server_npn_protocols']) else 'nothing'
2888 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2889
2890 def sni_contexts(self):
2891 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2892 server_context.load_cert_chain(SIGNED_CERTFILE)
2893 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2894 other_context.load_cert_chain(SIGNED_CERTFILE2)
2895 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2896 client_context.verify_mode = ssl.CERT_REQUIRED
2897 client_context.load_verify_locations(SIGNING_CA)
2898 return server_context, other_context, client_context
2899
2900 def check_common_name(self, stats, name):
2901 cert = stats['peercert']
2902 self.assertIn((('commonName', name),), cert['subject'])
2903
2904 @needs_sni
2905 def test_sni_callback(self):
2906 calls = []
2907 server_context, other_context, client_context = self.sni_contexts()
2908
2909 def servername_cb(ssl_sock, server_name, initial_context):
2910 calls.append((server_name, initial_context))
2911 if server_name is not None:
2912 ssl_sock.context = other_context
2913 server_context.set_servername_callback(servername_cb)
2914
2915 stats = server_params_test(client_context, server_context,
2916 chatty=True,
2917 sni_name='supermessage')
2918 # The hostname was fetched properly, and the certificate was
2919 # changed for the connection.
2920 self.assertEqual(calls, [("supermessage", server_context)])
2921 # CERTFILE4 was selected
2922 self.check_common_name(stats, 'fakehostname')
2923
2924 calls = []
2925 # The callback is called with server_name=None
2926 stats = server_params_test(client_context, server_context,
2927 chatty=True,
2928 sni_name=None)
2929 self.assertEqual(calls, [(None, server_context)])
2930 self.check_common_name(stats, 'localhost')
2931
2932 # Check disabling the callback
2933 calls = []
2934 server_context.set_servername_callback(None)
2935
2936 stats = server_params_test(client_context, server_context,
2937 chatty=True,
2938 sni_name='notfunny')
2939 # Certificate didn't change
2940 self.check_common_name(stats, 'localhost')
2941 self.assertEqual(calls, [])
2942
2943 @needs_sni
2944 def test_sni_callback_alert(self):
2945 # Returning a TLS alert is reflected to the connecting client
2946 server_context, other_context, client_context = self.sni_contexts()
2947
2948 def cb_returning_alert(ssl_sock, server_name, initial_context):
2949 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2950 server_context.set_servername_callback(cb_returning_alert)
2951
2952 with self.assertRaises(ssl.SSLError) as cm:
2953 stats = server_params_test(client_context, server_context,
2954 chatty=False,
2955 sni_name='supermessage')
2956 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2957
2958 @needs_sni
2959 def test_sni_callback_raising(self):
2960 # Raising fails the connection with a TLS handshake failure alert.
2961 server_context, other_context, client_context = self.sni_contexts()
2962
2963 def cb_raising(ssl_sock, server_name, initial_context):
Serhiy Storchaka5312a7f2015-01-31 11:27:06 +02002964 1.0/0.0
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002965 server_context.set_servername_callback(cb_raising)
2966
2967 with self.assertRaises(ssl.SSLError) as cm, \
2968 support.captured_stderr() as stderr:
2969 stats = server_params_test(client_context, server_context,
2970 chatty=False,
2971 sni_name='supermessage')
2972 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2973 self.assertIn("ZeroDivisionError", stderr.getvalue())
2974
2975 @needs_sni
2976 def test_sni_callback_wrong_return_type(self):
2977 # Returning the wrong return type terminates the TLS connection
2978 # with an internal error alert.
2979 server_context, other_context, client_context = self.sni_contexts()
2980
2981 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2982 return "foo"
2983 server_context.set_servername_callback(cb_wrong_return_type)
2984
2985 with self.assertRaises(ssl.SSLError) as cm, \
2986 support.captured_stderr() as stderr:
2987 stats = server_params_test(client_context, server_context,
2988 chatty=False,
2989 sni_name='supermessage')
2990 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2991 self.assertIn("TypeError", stderr.getvalue())
2992
2993 def test_read_write_after_close_raises_valuerror(self):
2994 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2995 context.verify_mode = ssl.CERT_REQUIRED
2996 context.load_verify_locations(CERTFILE)
2997 context.load_cert_chain(CERTFILE)
2998 server = ThreadedEchoServer(context=context, chatty=False)
2999
3000 with server:
3001 s = context.wrap_socket(socket.socket())
3002 s.connect((HOST, server.port))
3003 s.close()
3004
3005 self.assertRaises(ValueError, s.read, 1024)
3006 self.assertRaises(ValueError, s.write, b'hello')
3007
Bill Janssen61c001a2008-09-08 16:37:24 +00003008
Neal Norwitz9eb9b102007-08-27 01:15:33 +00003009def test_main(verbose=False):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003010 if support.verbose:
3011 plats = {
3012 'Linux': platform.linux_distribution,
3013 'Mac': platform.mac_ver,
3014 'Windows': platform.win32_ver,
3015 }
3016 for name, func in plats.items():
3017 plat = func()
3018 if plat and plat[0]:
3019 plat = '%s %r' % (name, plat)
3020 break
3021 else:
3022 plat = repr(platform.platform())
3023 print("test_ssl: testing with %r %r" %
3024 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3025 print(" under %s" % plat)
3026 print(" HAS_SNI = %r" % ssl.HAS_SNI)
3027 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3028 try:
3029 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3030 except AttributeError:
3031 pass
Bill Janssen296a59d2007-09-16 22:06:00 +00003032
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003033 for filename in [
Martin Panter71202bb2016-01-15 00:25:29 +00003034 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003035 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
3036 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
3037 BADCERT, BADKEY, EMPTYCERT]:
3038 if not os.path.exists(filename):
3039 raise support.TestFailed("Can't read certificate file %r" % filename)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003040
Benjamin Peterson2f334562014-10-01 23:53:01 -04003041 tests = [ContextTests, BasicTests, BasicSocketTests, SSLErrorTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003042
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003043 if support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00003044 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00003045
Bill Janssen98d19da2007-09-10 21:51:02 +00003046 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003047 thread_info = support.threading_setup()
3048 if thread_info:
Bill Janssen934b16d2008-06-28 22:19:33 +00003049 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003050
Antoine Pitrou3945c862010-04-28 21:11:01 +00003051 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003052 support.run_unittest(*tests)
Antoine Pitrou3945c862010-04-28 21:11:01 +00003053 finally:
3054 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05003055 support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00003056
3057if __name__ == "__main__":
3058 test_main()