blob: b023fbc8a8b6280fb0311460dd4896801c5c7cbf [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
60SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
61
62EMPTYCERT = data_file("nullcert.pem")
63BADCERT = data_file("badcert.pem")
64WRONGCERT = data_file("XXXnonexisting.pem")
65BADKEY = data_file("badkey.pem")
66NOKIACERT = data_file("nokia.pem")
67NULLBYTECERT = data_file("nullbytecert.pem")
68
69DHFILE = data_file("dh512.pem")
70BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding())
71
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000072
Neal Norwitz3e533c22007-08-27 01:03:18 +000073def handle_error(prefix):
74 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersondaeb9252014-08-20 14:14:50 -050075 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +000076 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000077
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000078
79class BasicTests(unittest.TestCase):
80
Antoine Pitrou3945c862010-04-28 21:11:01 +000081 def test_sslwrap_simple(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000082 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000083 try:
84 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
85 except IOError, e:
86 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
87 pass
88 else:
89 raise
90 try:
91 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
92 except IOError, e:
93 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
94 pass
95 else:
96 raise
Benjamin Peterson2f334562014-10-01 23:53:01 -040097
98
Benjamin Petersondaeb9252014-08-20 14:14:50 -050099def can_clear_options():
100 # 0.9.8m or higher
101 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
102
103def no_sslv2_implies_sslv3_hello():
104 # 0.9.7h or higher
105 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
106
107def have_verify_flags():
108 # 0.9.8 or higher
109 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
110
111def utc_offset(): #NOTE: ignore issues like #1647654
112 # local time = utc time + utc offset
113 if time.daylight and time.localtime().tm_isdst > 0:
114 return -time.altzone # seconds
115 return -time.timezone
116
117def asn1time(cert_time):
118 # Some versions of OpenSSL ignore seconds, see #18207
119 # 0.9.8.i
120 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
121 fmt = "%b %d %H:%M:%S %Y GMT"
122 dt = datetime.datetime.strptime(cert_time, fmt)
123 dt = dt.replace(second=0)
124 cert_time = dt.strftime(fmt)
125 # %d adds leading zero but ASN1_TIME_print() uses leading space
126 if cert_time[4] == "0":
127 cert_time = cert_time[:4] + " " + cert_time[5:]
128
129 return cert_time
Neal Norwitz3e533c22007-08-27 01:03:18 +0000130
Antoine Pitroud75efd92010-08-04 17:38:33 +0000131# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
132def skip_if_broken_ubuntu_ssl(func):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200133 if hasattr(ssl, 'PROTOCOL_SSLv2'):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200134 @functools.wraps(func)
135 def f(*args, **kwargs):
136 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500137 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
138 except ssl.SSLError:
Victor Stinnerb1241f92011-05-10 01:52:03 +0200139 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500140 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
Victor Stinnerb1241f92011-05-10 01:52:03 +0200141 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
142 return func(*args, **kwargs)
143 return f
144 else:
145 return func
Antoine Pitroud75efd92010-08-04 17:38:33 +0000146
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500147needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
148
Antoine Pitroud75efd92010-08-04 17:38:33 +0000149
150class BasicSocketTests(unittest.TestCase):
151
Antoine Pitrou3945c862010-04-28 21:11:01 +0000152 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000153 ssl.CERT_NONE
154 ssl.CERT_OPTIONAL
155 ssl.CERT_REQUIRED
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500156 ssl.OP_CIPHER_SERVER_PREFERENCE
157 ssl.OP_SINGLE_DH_USE
158 if ssl.HAS_ECDH:
159 ssl.OP_SINGLE_ECDH_USE
160 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
161 ssl.OP_NO_COMPRESSION
162 self.assertIn(ssl.HAS_SNI, {True, False})
163 self.assertIn(ssl.HAS_ECDH, {True, False})
164
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000165
Antoine Pitrou3945c862010-04-28 21:11:01 +0000166 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000167 v = ssl.RAND_status()
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500168 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000169 sys.stdout.write("\n RAND_status is %d (%s)\n"
170 % (v, (v and "sufficient randomness") or
171 "insufficient randomness"))
Jesus Ceaa8a5b392012-09-11 01:55:04 +0200172 self.assertRaises(TypeError, ssl.RAND_egd, 1)
173 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000174 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000175
Antoine Pitrou3945c862010-04-28 21:11:01 +0000176 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000177 # note that this uses an 'unofficial' function in _ssl.c,
178 # provided solely for this test, to exercise the certificate
179 # parsing code
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500180 p = ssl._ssl._test_decode_cert(CERTFILE)
181 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000182 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500183 self.assertEqual(p['issuer'],
184 ((('countryName', 'XY'),),
185 (('localityName', 'Castle Anthrax'),),
186 (('organizationName', 'Python Software Foundation'),),
187 (('commonName', 'localhost'),))
188 )
189 # Note the next three asserts will fail if the keys are regenerated
190 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
191 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
192 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200193 self.assertEqual(p['subject'],
Antoine Pitrou60982912013-02-16 21:39:28 +0100194 ((('countryName', 'XY'),),
195 (('localityName', 'Castle Anthrax'),),
196 (('organizationName', 'Python Software Foundation'),),
197 (('commonName', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200198 )
Antoine Pitrou60982912013-02-16 21:39:28 +0100199 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200200 # Issue #13034: the subjectAltName in some certificates
201 # (notably projects.developer.nokia.com:443) wasn't parsed
202 p = ssl._ssl._test_decode_cert(NOKIACERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500203 if support.verbose:
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200204 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
205 self.assertEqual(p['subjectAltName'],
206 (('DNS', 'projects.developer.nokia.com'),
207 ('DNS', 'projects.forum.nokia.com'))
208 )
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500209 # extra OCSP and AIA fields
210 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
211 self.assertEqual(p['caIssuers'],
212 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
213 self.assertEqual(p['crlDistributionPoints'],
214 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000215
Christian Heimes88b174c2013-08-17 00:54:47 +0200216 def test_parse_cert_CVE_2013_4238(self):
217 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500218 if support.verbose:
Christian Heimes88b174c2013-08-17 00:54:47 +0200219 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
220 subject = ((('countryName', 'US'),),
221 (('stateOrProvinceName', 'Oregon'),),
222 (('localityName', 'Beaverton'),),
223 (('organizationName', 'Python Software Foundation'),),
224 (('organizationalUnitName', 'Python Core Development'),),
225 (('commonName', 'null.python.org\x00example.org'),),
226 (('emailAddress', 'python-dev@python.org'),))
227 self.assertEqual(p['subject'], subject)
228 self.assertEqual(p['issuer'], subject)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500229 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
Christian Heimesf869a942013-08-25 14:12:41 +0200230 san = (('DNS', 'altnull.python.org\x00example.com'),
231 ('email', 'null@python.org\x00user@example.org'),
232 ('URI', 'http://null.python.org\x00http://example.org'),
233 ('IP Address', '192.0.2.1'),
234 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
235 else:
236 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
237 san = (('DNS', 'altnull.python.org\x00example.com'),
238 ('email', 'null@python.org\x00user@example.org'),
239 ('URI', 'http://null.python.org\x00http://example.org'),
240 ('IP Address', '192.0.2.1'),
241 ('IP Address', '<invalid>'))
242
243 self.assertEqual(p['subjectAltName'], san)
Christian Heimes88b174c2013-08-17 00:54:47 +0200244
Antoine Pitrou3945c862010-04-28 21:11:01 +0000245 def test_DER_to_PEM(self):
246 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
247 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000248 d1 = ssl.PEM_cert_to_DER_cert(pem)
249 p2 = ssl.DER_cert_to_PEM_cert(d1)
250 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000251 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000252 if not p2.startswith(ssl.PEM_HEADER + '\n'):
253 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
254 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
255 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000256
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000257 def test_openssl_version(self):
258 n = ssl.OPENSSL_VERSION_NUMBER
259 t = ssl.OPENSSL_VERSION_INFO
260 s = ssl.OPENSSL_VERSION
261 self.assertIsInstance(n, (int, long))
262 self.assertIsInstance(t, tuple)
263 self.assertIsInstance(s, str)
264 # Some sanity checks follow
265 # >= 0.9
266 self.assertGreaterEqual(n, 0x900000)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400267 # < 3.0
268 self.assertLess(n, 0x30000000)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000269 major, minor, fix, patch, status = t
270 self.assertGreaterEqual(major, 0)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400271 self.assertLess(major, 3)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000272 self.assertGreaterEqual(minor, 0)
273 self.assertLess(minor, 256)
274 self.assertGreaterEqual(fix, 0)
275 self.assertLess(fix, 256)
276 self.assertGreaterEqual(patch, 0)
277 self.assertLessEqual(patch, 26)
278 self.assertGreaterEqual(status, 0)
279 self.assertLessEqual(status, 15)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400280 # Version string as returned by {Open,Libre}SSL, the format might change
281 if "LibreSSL" in s:
282 self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
283 (s, t))
284 else:
285 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
286 (s, t))
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000287
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500288 @support.cpython_only
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000289 def test_refcycle(self):
290 # Issue #7943: an SSL object doesn't create reference cycles with
291 # itself.
292 s = socket.socket(socket.AF_INET)
293 ss = ssl.wrap_socket(s)
294 wr = weakref.ref(ss)
295 del ss
296 self.assertEqual(wr(), None)
297
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000298 def test_wrapped_unconnected(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500299 # Methods on an unconnected SSLSocket propagate the original
300 # socket.error raise by the underlying socket object.
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000301 s = socket.socket(socket.AF_INET)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500302 with closing(ssl.wrap_socket(s)) as ss:
303 self.assertRaises(socket.error, ss.recv, 1)
304 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
305 self.assertRaises(socket.error, ss.recvfrom, 1)
306 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
307 self.assertRaises(socket.error, ss.send, b'x')
308 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
309
310 def test_timeout(self):
311 # Issue #8524: when creating an SSL socket, the timeout of the
312 # original socket should be retained.
313 for timeout in (None, 0.0, 5.0):
314 s = socket.socket(socket.AF_INET)
315 s.settimeout(timeout)
316 with closing(ssl.wrap_socket(s)) as ss:
317 self.assertEqual(timeout, ss.gettimeout())
318
319 def test_errors(self):
320 sock = socket.socket()
321 self.assertRaisesRegexp(ValueError,
322 "certfile must be specified",
323 ssl.wrap_socket, sock, keyfile=CERTFILE)
324 self.assertRaisesRegexp(ValueError,
325 "certfile must be specified for server-side operations",
326 ssl.wrap_socket, sock, server_side=True)
327 self.assertRaisesRegexp(ValueError,
328 "certfile must be specified for server-side operations",
329 ssl.wrap_socket, sock, server_side=True, certfile="")
330 with closing(ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)) as s:
331 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
332 s.connect, (HOST, 8080))
333 with self.assertRaises(IOError) as cm:
334 with closing(socket.socket()) as sock:
335 ssl.wrap_socket(sock, certfile=WRONGCERT)
336 self.assertEqual(cm.exception.errno, errno.ENOENT)
337 with self.assertRaises(IOError) as cm:
338 with closing(socket.socket()) as sock:
339 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
340 self.assertEqual(cm.exception.errno, errno.ENOENT)
341 with self.assertRaises(IOError) as cm:
342 with closing(socket.socket()) as sock:
343 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
344 self.assertEqual(cm.exception.errno, errno.ENOENT)
345
346 def test_match_hostname(self):
347 def ok(cert, hostname):
348 ssl.match_hostname(cert, hostname)
349 def fail(cert, hostname):
350 self.assertRaises(ssl.CertificateError,
351 ssl.match_hostname, cert, hostname)
352
353 cert = {'subject': ((('commonName', 'example.com'),),)}
354 ok(cert, 'example.com')
355 ok(cert, 'ExAmple.cOm')
356 fail(cert, 'www.example.com')
357 fail(cert, '.example.com')
358 fail(cert, 'example.org')
359 fail(cert, 'exampleXcom')
360
361 cert = {'subject': ((('commonName', '*.a.com'),),)}
362 ok(cert, 'foo.a.com')
363 fail(cert, 'bar.foo.a.com')
364 fail(cert, 'a.com')
365 fail(cert, 'Xa.com')
366 fail(cert, '.a.com')
367
368 # only match one left-most wildcard
369 cert = {'subject': ((('commonName', 'f*.com'),),)}
370 ok(cert, 'foo.com')
371 ok(cert, 'f.com')
372 fail(cert, 'bar.com')
373 fail(cert, 'foo.a.com')
374 fail(cert, 'bar.foo.com')
375
376 # NULL bytes are bad, CVE-2013-4073
377 cert = {'subject': ((('commonName',
378 'null.python.org\x00example.org'),),)}
379 ok(cert, 'null.python.org\x00example.org') # or raise an error?
380 fail(cert, 'example.org')
381 fail(cert, 'null.python.org')
382
383 # error cases with wildcards
384 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
385 fail(cert, 'bar.foo.a.com')
386 fail(cert, 'a.com')
387 fail(cert, 'Xa.com')
388 fail(cert, '.a.com')
389
390 cert = {'subject': ((('commonName', 'a.*.com'),),)}
391 fail(cert, 'a.foo.com')
392 fail(cert, 'a..com')
393 fail(cert, 'a.com')
394
395 # wildcard doesn't match IDNA prefix 'xn--'
396 idna = u'püthon.python.org'.encode("idna").decode("ascii")
397 cert = {'subject': ((('commonName', idna),),)}
398 ok(cert, idna)
399 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
400 fail(cert, idna)
401 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
402 fail(cert, idna)
403
404 # wildcard in first fragment and IDNA A-labels in sequent fragments
405 # are supported.
406 idna = u'www*.pythön.org'.encode("idna").decode("ascii")
407 cert = {'subject': ((('commonName', idna),),)}
408 ok(cert, u'www.pythön.org'.encode("idna").decode("ascii"))
409 ok(cert, u'www1.pythön.org'.encode("idna").decode("ascii"))
410 fail(cert, u'ftp.pythön.org'.encode("idna").decode("ascii"))
411 fail(cert, u'pythön.org'.encode("idna").decode("ascii"))
412
413 # Slightly fake real-world example
414 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
415 'subject': ((('commonName', 'linuxfrz.org'),),),
416 'subjectAltName': (('DNS', 'linuxfr.org'),
417 ('DNS', 'linuxfr.com'),
418 ('othername', '<unsupported>'))}
419 ok(cert, 'linuxfr.org')
420 ok(cert, 'linuxfr.com')
421 # Not a "DNS" entry
422 fail(cert, '<unsupported>')
423 # When there is a subjectAltName, commonName isn't used
424 fail(cert, 'linuxfrz.org')
425
426 # A pristine real-world example
427 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
428 'subject': ((('countryName', 'US'),),
429 (('stateOrProvinceName', 'California'),),
430 (('localityName', 'Mountain View'),),
431 (('organizationName', 'Google Inc'),),
432 (('commonName', 'mail.google.com'),))}
433 ok(cert, 'mail.google.com')
434 fail(cert, 'gmail.com')
435 # Only commonName is considered
436 fail(cert, 'California')
437
438 # Neither commonName nor subjectAltName
439 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
440 'subject': ((('countryName', 'US'),),
441 (('stateOrProvinceName', 'California'),),
442 (('localityName', 'Mountain View'),),
443 (('organizationName', 'Google Inc'),))}
444 fail(cert, 'mail.google.com')
445
446 # No DNS entry in subjectAltName but a commonName
447 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
448 'subject': ((('countryName', 'US'),),
449 (('stateOrProvinceName', 'California'),),
450 (('localityName', 'Mountain View'),),
451 (('commonName', 'mail.google.com'),)),
452 'subjectAltName': (('othername', 'blabla'), )}
453 ok(cert, 'mail.google.com')
454
455 # No DNS entry subjectAltName and no commonName
456 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
457 'subject': ((('countryName', 'US'),),
458 (('stateOrProvinceName', 'California'),),
459 (('localityName', 'Mountain View'),),
460 (('organizationName', 'Google Inc'),)),
461 'subjectAltName': (('othername', 'blabla'),)}
462 fail(cert, 'google.com')
463
464 # Empty cert / no cert
465 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
466 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
467
468 # Issue #17980: avoid denials of service by refusing more than one
469 # wildcard per fragment.
470 cert = {'subject': ((('commonName', 'a*b.com'),),)}
471 ok(cert, 'axxb.com')
472 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
473 fail(cert, 'axxb.com')
474 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
475 with self.assertRaises(ssl.CertificateError) as cm:
476 ssl.match_hostname(cert, 'axxbxxc.com')
477 self.assertIn("too many wildcards", str(cm.exception))
478
479 def test_server_side(self):
480 # server_hostname doesn't work for server sockets
481 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
482 with closing(socket.socket()) as sock:
483 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
484 server_hostname="some.hostname")
485
486 def test_unknown_channel_binding(self):
487 # should raise ValueError for unknown type
488 s = socket.socket(socket.AF_INET)
489 with closing(ssl.wrap_socket(s)) as ss:
490 with self.assertRaises(ValueError):
491 ss.get_channel_binding("unknown-type")
492
493 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
494 "'tls-unique' channel binding not available")
495 def test_tls_unique_channel_binding(self):
496 # unconnected should return None for known type
497 s = socket.socket(socket.AF_INET)
498 with closing(ssl.wrap_socket(s)) as ss:
499 self.assertIsNone(ss.get_channel_binding("tls-unique"))
500 # the same for server-side
501 s = socket.socket(socket.AF_INET)
502 with closing(ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)) as ss:
503 self.assertIsNone(ss.get_channel_binding("tls-unique"))
504
505 def test_get_default_verify_paths(self):
506 paths = ssl.get_default_verify_paths()
507 self.assertEqual(len(paths), 6)
508 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
509
510 with support.EnvironmentVarGuard() as env:
511 env["SSL_CERT_DIR"] = CAPATH
512 env["SSL_CERT_FILE"] = CERTFILE
513 paths = ssl.get_default_verify_paths()
514 self.assertEqual(paths.cafile, CERTFILE)
515 self.assertEqual(paths.capath, CAPATH)
516
517 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
518 def test_enum_certificates(self):
519 self.assertTrue(ssl.enum_certificates("CA"))
520 self.assertTrue(ssl.enum_certificates("ROOT"))
521
522 self.assertRaises(TypeError, ssl.enum_certificates)
523 self.assertRaises(WindowsError, ssl.enum_certificates, "")
524
525 trust_oids = set()
526 for storename in ("CA", "ROOT"):
527 store = ssl.enum_certificates(storename)
528 self.assertIsInstance(store, list)
529 for element in store:
530 self.assertIsInstance(element, tuple)
531 self.assertEqual(len(element), 3)
532 cert, enc, trust = element
533 self.assertIsInstance(cert, bytes)
534 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
535 self.assertIsInstance(trust, (set, bool))
536 if isinstance(trust, set):
537 trust_oids.update(trust)
538
539 serverAuth = "1.3.6.1.5.5.7.3.1"
540 self.assertIn(serverAuth, trust_oids)
541
542 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
543 def test_enum_crls(self):
544 self.assertTrue(ssl.enum_crls("CA"))
545 self.assertRaises(TypeError, ssl.enum_crls)
546 self.assertRaises(WindowsError, ssl.enum_crls, "")
547
548 crls = ssl.enum_crls("CA")
549 self.assertIsInstance(crls, list)
550 for element in crls:
551 self.assertIsInstance(element, tuple)
552 self.assertEqual(len(element), 2)
553 self.assertIsInstance(element[0], bytes)
554 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
555
556
557 def test_asn1object(self):
558 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
559 '1.3.6.1.5.5.7.3.1')
560
561 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
562 self.assertEqual(val, expected)
563 self.assertEqual(val.nid, 129)
564 self.assertEqual(val.shortname, 'serverAuth')
565 self.assertEqual(val.longname, 'TLS Web Server Authentication')
566 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
567 self.assertIsInstance(val, ssl._ASN1Object)
568 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
569
570 val = ssl._ASN1Object.fromnid(129)
571 self.assertEqual(val, expected)
572 self.assertIsInstance(val, ssl._ASN1Object)
573 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
574 with self.assertRaisesRegexp(ValueError, "unknown NID 100000"):
575 ssl._ASN1Object.fromnid(100000)
576 for i in range(1000):
577 try:
578 obj = ssl._ASN1Object.fromnid(i)
579 except ValueError:
580 pass
581 else:
582 self.assertIsInstance(obj.nid, int)
583 self.assertIsInstance(obj.shortname, str)
584 self.assertIsInstance(obj.longname, str)
585 self.assertIsInstance(obj.oid, (str, type(None)))
586
587 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
588 self.assertEqual(val, expected)
589 self.assertIsInstance(val, ssl._ASN1Object)
590 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
591 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
592 expected)
593 with self.assertRaisesRegexp(ValueError, "unknown object 'serverauth'"):
594 ssl._ASN1Object.fromname('serverauth')
595
596 def test_purpose_enum(self):
597 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
598 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
599 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
600 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
601 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
602 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
603 '1.3.6.1.5.5.7.3.1')
604
605 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
606 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
607 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
608 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
609 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
610 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
611 '1.3.6.1.5.5.7.3.2')
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000612
Antoine Pitrou63cc99d2013-12-28 17:26:33 +0100613 def test_unsupported_dtls(self):
614 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
615 self.addCleanup(s.close)
616 with self.assertRaises(NotImplementedError) as cx:
617 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
618 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500619 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
620 with self.assertRaises(NotImplementedError) as cx:
621 ctx.wrap_socket(s)
622 self.assertEqual(str(cx.exception), "only stream sockets are supported")
623
624 def cert_time_ok(self, timestring, timestamp):
625 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
626
627 def cert_time_fail(self, timestring):
628 with self.assertRaises(ValueError):
629 ssl.cert_time_to_seconds(timestring)
630
631 @unittest.skipUnless(utc_offset(),
632 'local time needs to be different from UTC')
633 def test_cert_time_to_seconds_timezone(self):
634 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
635 # results if local timezone is not UTC
636 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
637 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
638
639 def test_cert_time_to_seconds(self):
640 timestring = "Jan 5 09:34:43 2018 GMT"
641 ts = 1515144883.0
642 self.cert_time_ok(timestring, ts)
643 # accept keyword parameter, assert its name
644 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
645 # accept both %e and %d (space or zero generated by strftime)
646 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
647 # case-insensitive
648 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
649 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
650 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
651 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
652 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
653 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
654 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
655 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
656
657 newyear_ts = 1230768000.0
658 # leap seconds
659 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
660 # same timestamp
661 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
662
663 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
664 # allow 60th second (even if it is not a leap second)
665 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
666 # allow 2nd leap second for compatibility with time.strptime()
667 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
668 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
669
670 # no special treatement for the special value:
671 # 99991231235959Z (rfc 5280)
672 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
673
674 @support.run_with_locale('LC_ALL', '')
675 def test_cert_time_to_seconds_locale(self):
676 # `cert_time_to_seconds()` should be locale independent
677
678 def local_february_name():
679 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
680
681 if local_february_name().lower() == 'feb':
682 self.skipTest("locale-specific month name needs to be "
683 "different from C locale")
684
685 # locale-independent
686 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
687 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
688
689
690class ContextTests(unittest.TestCase):
691
692 @skip_if_broken_ubuntu_ssl
693 def test_constructor(self):
694 for protocol in PROTOCOLS:
695 ssl.SSLContext(protocol)
696 self.assertRaises(TypeError, ssl.SSLContext)
697 self.assertRaises(ValueError, ssl.SSLContext, -1)
698 self.assertRaises(ValueError, ssl.SSLContext, 42)
699
700 @skip_if_broken_ubuntu_ssl
701 def test_protocol(self):
702 for proto in PROTOCOLS:
703 ctx = ssl.SSLContext(proto)
704 self.assertEqual(ctx.protocol, proto)
705
706 def test_ciphers(self):
707 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
708 ctx.set_ciphers("ALL")
709 ctx.set_ciphers("DEFAULT")
710 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
711 ctx.set_ciphers("^$:,;?*'dorothyx")
712
713 @skip_if_broken_ubuntu_ssl
714 def test_options(self):
715 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
716 # OP_ALL | OP_NO_SSLv2 is the default value
717 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
718 ctx.options)
719 ctx.options |= ssl.OP_NO_SSLv3
720 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
721 ctx.options)
722 if can_clear_options():
723 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
724 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
725 ctx.options)
726 ctx.options = 0
727 self.assertEqual(0, ctx.options)
728 else:
729 with self.assertRaises(ValueError):
730 ctx.options = 0
731
732 def test_verify_mode(self):
733 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
734 # Default value
735 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
736 ctx.verify_mode = ssl.CERT_OPTIONAL
737 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
738 ctx.verify_mode = ssl.CERT_REQUIRED
739 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
740 ctx.verify_mode = ssl.CERT_NONE
741 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
742 with self.assertRaises(TypeError):
743 ctx.verify_mode = None
744 with self.assertRaises(ValueError):
745 ctx.verify_mode = 42
746
747 @unittest.skipUnless(have_verify_flags(),
748 "verify_flags need OpenSSL > 0.9.8")
749 def test_verify_flags(self):
750 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
751 # default value by OpenSSL
752 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
753 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
754 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
755 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
756 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
757 ctx.verify_flags = ssl.VERIFY_DEFAULT
758 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
759 # supports any value
760 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
761 self.assertEqual(ctx.verify_flags,
762 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
763 with self.assertRaises(TypeError):
764 ctx.verify_flags = None
765
766 def test_load_cert_chain(self):
767 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
768 # Combined key and cert in a single file
Benjamin Peterson04439fd2014-11-03 21:05:01 -0500769 ctx.load_cert_chain(CERTFILE, keyfile=None)
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500770 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
771 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
772 with self.assertRaises(IOError) as cm:
773 ctx.load_cert_chain(WRONGCERT)
774 self.assertEqual(cm.exception.errno, errno.ENOENT)
775 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
776 ctx.load_cert_chain(BADCERT)
777 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
778 ctx.load_cert_chain(EMPTYCERT)
779 # Separate key and cert
780 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
781 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
782 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
783 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
784 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
785 ctx.load_cert_chain(ONLYCERT)
786 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
787 ctx.load_cert_chain(ONLYKEY)
788 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
789 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
790 # Mismatching key and cert
791 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
792 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
793 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
794 # Password protected key and cert
795 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
796 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
797 ctx.load_cert_chain(CERTFILE_PROTECTED,
798 password=bytearray(KEY_PASSWORD.encode()))
799 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
800 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
801 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
802 bytearray(KEY_PASSWORD.encode()))
803 with self.assertRaisesRegexp(TypeError, "should be a string"):
804 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
805 with self.assertRaises(ssl.SSLError):
806 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
807 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
808 # openssl has a fixed limit on the password buffer.
809 # PEM_BUFSIZE is generally set to 1kb.
810 # Return a string larger than this.
811 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
812 # Password callback
813 def getpass_unicode():
814 return KEY_PASSWORD
815 def getpass_bytes():
816 return KEY_PASSWORD.encode()
817 def getpass_bytearray():
818 return bytearray(KEY_PASSWORD.encode())
819 def getpass_badpass():
820 return "badpass"
821 def getpass_huge():
822 return b'a' * (1024 * 1024)
823 def getpass_bad_type():
824 return 9
825 def getpass_exception():
826 raise Exception('getpass error')
827 class GetPassCallable:
828 def __call__(self):
829 return KEY_PASSWORD
830 def getpass(self):
831 return KEY_PASSWORD
832 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
833 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
834 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
835 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
836 ctx.load_cert_chain(CERTFILE_PROTECTED,
837 password=GetPassCallable().getpass)
838 with self.assertRaises(ssl.SSLError):
839 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
840 with self.assertRaisesRegexp(ValueError, "cannot be longer"):
841 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
842 with self.assertRaisesRegexp(TypeError, "must return a string"):
843 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
844 with self.assertRaisesRegexp(Exception, "getpass error"):
845 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
846 # Make sure the password function isn't called if it isn't needed
847 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
848
849 def test_load_verify_locations(self):
850 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
851 ctx.load_verify_locations(CERTFILE)
852 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
853 ctx.load_verify_locations(BYTES_CERTFILE)
854 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400855 ctx.load_verify_locations(cafile=BYTES_CERTFILE.decode('utf-8'))
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500856 self.assertRaises(TypeError, ctx.load_verify_locations)
857 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
858 with self.assertRaises(IOError) as cm:
859 ctx.load_verify_locations(WRONGCERT)
860 self.assertEqual(cm.exception.errno, errno.ENOENT)
Benjamin Peterson876473e2014-08-28 09:33:21 -0400861 with self.assertRaises(IOError):
862 ctx.load_verify_locations(u'')
Benjamin Petersondaeb9252014-08-20 14:14:50 -0500863 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
864 ctx.load_verify_locations(BADCERT)
865 ctx.load_verify_locations(CERTFILE, CAPATH)
866 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
867
868 # Issue #10989: crash if the second argument type is invalid
869 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
870
871 def test_load_verify_cadata(self):
872 # test cadata
873 with open(CAFILE_CACERT) as f:
874 cacert_pem = f.read().decode("ascii")
875 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
876 with open(CAFILE_NEURONIO) as f:
877 neuronio_pem = f.read().decode("ascii")
878 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
879
880 # test PEM
881 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
882 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
883 ctx.load_verify_locations(cadata=cacert_pem)
884 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
885 ctx.load_verify_locations(cadata=neuronio_pem)
886 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
887 # cert already in hash table
888 ctx.load_verify_locations(cadata=neuronio_pem)
889 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
890
891 # combined
892 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
893 combined = "\n".join((cacert_pem, neuronio_pem))
894 ctx.load_verify_locations(cadata=combined)
895 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
896
897 # with junk around the certs
898 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
899 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
900 neuronio_pem, "tail"]
901 ctx.load_verify_locations(cadata="\n".join(combined))
902 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
903
904 # test DER
905 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
906 ctx.load_verify_locations(cadata=cacert_der)
907 ctx.load_verify_locations(cadata=neuronio_der)
908 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
909 # cert already in hash table
910 ctx.load_verify_locations(cadata=cacert_der)
911 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
912
913 # combined
914 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
915 combined = b"".join((cacert_der, neuronio_der))
916 ctx.load_verify_locations(cadata=combined)
917 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
918
919 # error cases
920 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
921 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
922
923 with self.assertRaisesRegexp(ssl.SSLError, "no start line"):
924 ctx.load_verify_locations(cadata=u"broken")
925 with self.assertRaisesRegexp(ssl.SSLError, "not enough data"):
926 ctx.load_verify_locations(cadata=b"broken")
927
928
929 def test_load_dh_params(self):
930 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
931 ctx.load_dh_params(DHFILE)
932 if os.name != 'nt':
933 ctx.load_dh_params(BYTES_DHFILE)
934 self.assertRaises(TypeError, ctx.load_dh_params)
935 self.assertRaises(TypeError, ctx.load_dh_params, None)
936 with self.assertRaises(IOError) as cm:
937 ctx.load_dh_params(WRONGCERT)
938 self.assertEqual(cm.exception.errno, errno.ENOENT)
939 with self.assertRaises(ssl.SSLError) as cm:
940 ctx.load_dh_params(CERTFILE)
941
942 @skip_if_broken_ubuntu_ssl
943 def test_session_stats(self):
944 for proto in PROTOCOLS:
945 ctx = ssl.SSLContext(proto)
946 self.assertEqual(ctx.session_stats(), {
947 'number': 0,
948 'connect': 0,
949 'connect_good': 0,
950 'connect_renegotiate': 0,
951 'accept': 0,
952 'accept_good': 0,
953 'accept_renegotiate': 0,
954 'hits': 0,
955 'misses': 0,
956 'timeouts': 0,
957 'cache_full': 0,
958 })
959
960 def test_set_default_verify_paths(self):
961 # There's not much we can do to test that it acts as expected,
962 # so just check it doesn't crash or raise an exception.
963 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
964 ctx.set_default_verify_paths()
965
966 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
967 def test_set_ecdh_curve(self):
968 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
969 ctx.set_ecdh_curve("prime256v1")
970 ctx.set_ecdh_curve(b"prime256v1")
971 self.assertRaises(TypeError, ctx.set_ecdh_curve)
972 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
973 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
974 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
975
976 @needs_sni
977 def test_sni_callback(self):
978 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
979
980 # set_servername_callback expects a callable, or None
981 self.assertRaises(TypeError, ctx.set_servername_callback)
982 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
983 self.assertRaises(TypeError, ctx.set_servername_callback, "")
984 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
985
986 def dummycallback(sock, servername, ctx):
987 pass
988 ctx.set_servername_callback(None)
989 ctx.set_servername_callback(dummycallback)
990
991 @needs_sni
992 def test_sni_callback_refcycle(self):
993 # Reference cycles through the servername callback are detected
994 # and cleared.
995 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
996 def dummycallback(sock, servername, ctx, cycle=ctx):
997 pass
998 ctx.set_servername_callback(dummycallback)
999 wr = weakref.ref(ctx)
1000 del ctx, dummycallback
1001 gc.collect()
1002 self.assertIs(wr(), None)
1003
1004 def test_cert_store_stats(self):
1005 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1006 self.assertEqual(ctx.cert_store_stats(),
1007 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1008 ctx.load_cert_chain(CERTFILE)
1009 self.assertEqual(ctx.cert_store_stats(),
1010 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1011 ctx.load_verify_locations(CERTFILE)
1012 self.assertEqual(ctx.cert_store_stats(),
1013 {'x509_ca': 0, 'crl': 0, 'x509': 1})
1014 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1015 self.assertEqual(ctx.cert_store_stats(),
1016 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1017
1018 def test_get_ca_certs(self):
1019 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1020 self.assertEqual(ctx.get_ca_certs(), [])
1021 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1022 ctx.load_verify_locations(CERTFILE)
1023 self.assertEqual(ctx.get_ca_certs(), [])
1024 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
1025 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1026 self.assertEqual(ctx.get_ca_certs(),
1027 [{'issuer': ((('organizationName', 'Root CA'),),
1028 (('organizationalUnitName', 'http://www.cacert.org'),),
1029 (('commonName', 'CA Cert Signing Authority'),),
1030 (('emailAddress', 'support@cacert.org'),)),
1031 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1032 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1033 'serialNumber': '00',
1034 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
1035 'subject': ((('organizationName', 'Root CA'),),
1036 (('organizationalUnitName', 'http://www.cacert.org'),),
1037 (('commonName', 'CA Cert Signing Authority'),),
1038 (('emailAddress', 'support@cacert.org'),)),
1039 'version': 3}])
1040
1041 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
1042 pem = f.read()
1043 der = ssl.PEM_cert_to_DER_cert(pem)
1044 self.assertEqual(ctx.get_ca_certs(True), [der])
1045
1046 def test_load_default_certs(self):
1047 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1048 ctx.load_default_certs()
1049
1050 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1051 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1052 ctx.load_default_certs()
1053
1054 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1055 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1056
1057 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1058 self.assertRaises(TypeError, ctx.load_default_certs, None)
1059 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1060
Benjamin Petersona02ae252014-10-03 18:17:15 -04001061 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson0b30a2b2014-10-03 17:27:05 -04001062 def test_load_default_certs_env(self):
1063 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1064 with support.EnvironmentVarGuard() as env:
1065 env["SSL_CERT_DIR"] = CAPATH
1066 env["SSL_CERT_FILE"] = CERTFILE
1067 ctx.load_default_certs()
1068 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1069
Benjamin Petersona02ae252014-10-03 18:17:15 -04001070 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1071 def test_load_default_certs_env_windows(self):
1072 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1073 ctx.load_default_certs()
1074 stats = ctx.cert_store_stats()
1075
1076 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1077 with support.EnvironmentVarGuard() as env:
1078 env["SSL_CERT_DIR"] = CAPATH
1079 env["SSL_CERT_FILE"] = CERTFILE
1080 ctx.load_default_certs()
1081 stats["x509"] += 1
1082 self.assertEqual(ctx.cert_store_stats(), stats)
1083
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001084 def test_create_default_context(self):
1085 ctx = ssl.create_default_context()
1086 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1087 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1088 self.assertTrue(ctx.check_hostname)
1089 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1090 self.assertEqual(
1091 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1092 getattr(ssl, "OP_NO_COMPRESSION", 0),
1093 )
1094
1095 with open(SIGNING_CA) as f:
1096 cadata = f.read().decode("ascii")
1097 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1098 cadata=cadata)
1099 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1100 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1101 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1102 self.assertEqual(
1103 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1104 getattr(ssl, "OP_NO_COMPRESSION", 0),
1105 )
1106
1107 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
1108 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1109 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1110 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1111 self.assertEqual(
1112 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1113 getattr(ssl, "OP_NO_COMPRESSION", 0),
1114 )
1115 self.assertEqual(
1116 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1117 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1118 )
1119 self.assertEqual(
1120 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1121 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1122 )
1123
1124 def test__create_stdlib_context(self):
1125 ctx = ssl._create_stdlib_context()
1126 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1127 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1128 self.assertFalse(ctx.check_hostname)
1129 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1130
1131 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1132 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1133 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1134 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1135
1136 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
1137 cert_reqs=ssl.CERT_REQUIRED,
1138 check_hostname=True)
1139 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1140 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1141 self.assertTrue(ctx.check_hostname)
1142 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1143
1144 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1145 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1146 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1147 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1148
1149 def test_check_hostname(self):
1150 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1151 self.assertFalse(ctx.check_hostname)
1152
1153 # Requires CERT_REQUIRED or CERT_OPTIONAL
1154 with self.assertRaises(ValueError):
1155 ctx.check_hostname = True
1156 ctx.verify_mode = ssl.CERT_REQUIRED
1157 self.assertFalse(ctx.check_hostname)
1158 ctx.check_hostname = True
1159 self.assertTrue(ctx.check_hostname)
1160
1161 ctx.verify_mode = ssl.CERT_OPTIONAL
1162 ctx.check_hostname = True
1163 self.assertTrue(ctx.check_hostname)
1164
1165 # Cannot set CERT_NONE with check_hostname enabled
1166 with self.assertRaises(ValueError):
1167 ctx.verify_mode = ssl.CERT_NONE
1168 ctx.check_hostname = False
1169 self.assertFalse(ctx.check_hostname)
1170
1171
1172class SSLErrorTests(unittest.TestCase):
1173
1174 def test_str(self):
1175 # The str() of a SSLError doesn't include the errno
1176 e = ssl.SSLError(1, "foo")
1177 self.assertEqual(str(e), "foo")
1178 self.assertEqual(e.errno, 1)
1179 # Same for a subclass
1180 e = ssl.SSLZeroReturnError(1, "foo")
1181 self.assertEqual(str(e), "foo")
1182 self.assertEqual(e.errno, 1)
1183
1184 def test_lib_reason(self):
1185 # Test the library and reason attributes
1186 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1187 with self.assertRaises(ssl.SSLError) as cm:
1188 ctx.load_dh_params(CERTFILE)
1189 self.assertEqual(cm.exception.library, 'PEM')
1190 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1191 s = str(cm.exception)
1192 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1193
1194 def test_subclass(self):
1195 # Check that the appropriate SSLError subclass is raised
1196 # (this only tests one of them)
1197 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1198 with closing(socket.socket()) as s:
1199 s.bind(("127.0.0.1", 0))
1200 s.listen(5)
1201 c = socket.socket()
1202 c.connect(s.getsockname())
1203 c.setblocking(False)
1204 with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c:
1205 with self.assertRaises(ssl.SSLWantReadError) as cm:
1206 c.do_handshake()
1207 s = str(cm.exception)
1208 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1209 # For compatibility
1210 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
Antoine Pitrou63cc99d2013-12-28 17:26:33 +01001211
Antoine Pitrouf9de5342010-04-05 21:35:07 +00001212
Bill Janssen934b16d2008-06-28 22:19:33 +00001213class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +00001214
Antoine Pitrou3945c862010-04-28 21:11:01 +00001215 def test_connect(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001216 with support.transient_internet("svn.python.org"):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001217 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1218 cert_reqs=ssl.CERT_NONE)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001219 try:
1220 s.connect(("svn.python.org", 443))
1221 self.assertEqual({}, s.getpeercert())
1222 finally:
1223 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001224
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001225 # this should fail because we have no verification certs
1226 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1227 cert_reqs=ssl.CERT_REQUIRED)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001228 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
1229 s.connect, ("svn.python.org", 443))
1230 s.close()
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001231
1232 # this should succeed because we specify the root cert
1233 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1234 cert_reqs=ssl.CERT_REQUIRED,
1235 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1236 try:
1237 s.connect(("svn.python.org", 443))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001238 self.assertTrue(s.getpeercert())
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001239 finally:
1240 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +00001241
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001242 def test_connect_ex(self):
1243 # Issue #11326: check connect_ex() implementation
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001244 with support.transient_internet("svn.python.org"):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001245 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1246 cert_reqs=ssl.CERT_REQUIRED,
1247 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1248 try:
1249 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
1250 self.assertTrue(s.getpeercert())
1251 finally:
1252 s.close()
1253
1254 def test_non_blocking_connect_ex(self):
1255 # Issue #11326: non-blocking connect_ex() should allow handshake
1256 # to proceed after the socket gets ready.
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001257 with support.transient_internet("svn.python.org"):
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001258 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1259 cert_reqs=ssl.CERT_REQUIRED,
1260 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1261 do_handshake_on_connect=False)
1262 try:
1263 s.setblocking(False)
1264 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +00001265 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1266 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001267 # Wait for connect to finish
1268 select.select([], [s], [], 5.0)
1269 # Non-blocking handshake
1270 while True:
1271 try:
1272 s.do_handshake()
1273 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001274 except ssl.SSLWantReadError:
1275 select.select([s], [], [], 5.0)
1276 except ssl.SSLWantWriteError:
1277 select.select([], [s], [], 5.0)
Antoine Pitroud3f6ea12011-02-26 23:35:27 +00001278 # SSL established
1279 self.assertTrue(s.getpeercert())
1280 finally:
1281 s.close()
1282
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001283 def test_timeout_connect_ex(self):
1284 # Issue #12065: on a timeout, connect_ex() should return the original
1285 # errno (mimicking the behaviour of non-SSL sockets).
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001286 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001287 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1288 cert_reqs=ssl.CERT_REQUIRED,
1289 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1290 do_handshake_on_connect=False)
1291 try:
1292 s.settimeout(0.0000001)
1293 rc = s.connect_ex(('svn.python.org', 443))
1294 if rc == 0:
1295 self.skipTest("svn.python.org responded too quickly")
1296 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1297 finally:
1298 s.close()
1299
1300 def test_connect_ex_error(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001301 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001302 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1303 cert_reqs=ssl.CERT_REQUIRED,
1304 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1305 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001306 rc = s.connect_ex(("svn.python.org", 444))
1307 # Issue #19919: Windows machines or VMs hosted on Windows
1308 # machines sometimes return EWOULDBLOCK.
1309 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001310 finally:
1311 s.close()
1312
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001313 def test_connect_with_context(self):
1314 with support.transient_internet("svn.python.org"):
1315 # Same as test_connect, but with a separately created context
1316 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1317 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1318 s.connect(("svn.python.org", 443))
1319 try:
1320 self.assertEqual({}, s.getpeercert())
1321 finally:
1322 s.close()
1323 # Same with a server hostname
1324 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1325 server_hostname="svn.python.org")
Benjamin Peterson31aa69e2014-11-23 20:13:31 -06001326 s.connect(("svn.python.org", 443))
1327 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001328 # This should fail because we have no verification certs
1329 ctx.verify_mode = ssl.CERT_REQUIRED
1330 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1331 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
1332 s.connect, ("svn.python.org", 443))
1333 s.close()
1334 # This should succeed because we specify the root cert
1335 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1336 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1337 s.connect(("svn.python.org", 443))
1338 try:
1339 cert = s.getpeercert()
1340 self.assertTrue(cert)
1341 finally:
1342 s.close()
1343
1344 def test_connect_capath(self):
1345 # Verify server certificates using the `capath` argument
1346 # NOTE: the subject hashing algorithm has been changed between
1347 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1348 # contain both versions of each certificate (same content, different
1349 # filename) for this test to be portable across OpenSSL releases.
1350 with support.transient_internet("svn.python.org"):
1351 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1352 ctx.verify_mode = ssl.CERT_REQUIRED
1353 ctx.load_verify_locations(capath=CAPATH)
1354 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1355 s.connect(("svn.python.org", 443))
1356 try:
1357 cert = s.getpeercert()
1358 self.assertTrue(cert)
1359 finally:
1360 s.close()
1361 # Same with a bytes `capath` argument
1362 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1363 ctx.verify_mode = ssl.CERT_REQUIRED
1364 ctx.load_verify_locations(capath=BYTES_CAPATH)
1365 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1366 s.connect(("svn.python.org", 443))
1367 try:
1368 cert = s.getpeercert()
1369 self.assertTrue(cert)
1370 finally:
1371 s.close()
1372
1373 def test_connect_cadata(self):
1374 with open(CAFILE_CACERT) as f:
1375 pem = f.read().decode('ascii')
1376 der = ssl.PEM_cert_to_DER_cert(pem)
1377 with support.transient_internet("svn.python.org"):
1378 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1379 ctx.verify_mode = ssl.CERT_REQUIRED
1380 ctx.load_verify_locations(cadata=pem)
1381 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
1382 s.connect(("svn.python.org", 443))
1383 cert = s.getpeercert()
1384 self.assertTrue(cert)
1385
1386 # same with DER
1387 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1388 ctx.verify_mode = ssl.CERT_REQUIRED
1389 ctx.load_verify_locations(cadata=der)
1390 with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s:
1391 s.connect(("svn.python.org", 443))
1392 cert = s.getpeercert()
1393 self.assertTrue(cert)
1394
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001395 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1396 def test_makefile_close(self):
1397 # Issue #5238: creating a file-like object with makefile() shouldn't
1398 # delay closing the underlying "real socket" (here tested with its
1399 # file descriptor, hence skipping the test under Windows).
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001400 with support.transient_internet("svn.python.org"):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001401 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1402 ss.connect(("svn.python.org", 443))
1403 fd = ss.fileno()
1404 f = ss.makefile()
1405 f.close()
1406 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +00001407 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001408 # Closing the SSL socket should close the fd too
1409 ss.close()
1410 gc.collect()
1411 with self.assertRaises(OSError) as e:
1412 os.read(fd, 0)
1413 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +00001414
Antoine Pitrou3945c862010-04-28 21:11:01 +00001415 def test_non_blocking_handshake(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001416 with support.transient_internet("svn.python.org"):
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001417 s = socket.socket(socket.AF_INET)
1418 s.connect(("svn.python.org", 443))
1419 s.setblocking(False)
1420 s = ssl.wrap_socket(s,
1421 cert_reqs=ssl.CERT_NONE,
1422 do_handshake_on_connect=False)
1423 count = 0
1424 while True:
1425 try:
1426 count += 1
1427 s.do_handshake()
1428 break
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001429 except ssl.SSLWantReadError:
1430 select.select([s], [], [])
1431 except ssl.SSLWantWriteError:
1432 select.select([], [s], [])
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001433 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001434 if support.verbose:
Antoine Pitrou4e406d82010-09-09 13:35:44 +00001435 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +00001436
Antoine Pitrou3945c862010-04-28 21:11:01 +00001437 def test_get_server_certificate(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001438 def _test_get_server_certificate(host, port, cert=None):
1439 with support.transient_internet(host):
1440 pem = ssl.get_server_certificate((host, port))
1441 if not pem:
1442 self.fail("No server certificate on %s:%s!" % (host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001443
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001444 try:
1445 pem = ssl.get_server_certificate((host, port),
1446 ca_certs=CERTFILE)
1447 except ssl.SSLError as x:
1448 #should fail
1449 if support.verbose:
1450 sys.stdout.write("%s\n" % x)
1451 else:
1452 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
Bill Janssen296a59d2007-09-16 22:06:00 +00001453
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001454 pem = ssl.get_server_certificate((host, port),
1455 ca_certs=cert)
1456 if not pem:
1457 self.fail("No server certificate on %s:%s!" % (host, port))
1458 if support.verbose:
1459 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1460
1461 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1462 if support.IPV6_ENABLED:
1463 _test_get_server_certificate('ipv6.google.com', 443)
1464
1465 def test_ciphers(self):
1466 remote = ("svn.python.org", 443)
1467 with support.transient_internet(remote[0]):
1468 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1469 cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s:
1470 s.connect(remote)
1471 with closing(ssl.wrap_socket(socket.socket(socket.AF_INET),
1472 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s:
1473 s.connect(remote)
1474 # Error checking can happen at instantiation or when connecting
1475 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
1476 with closing(socket.socket(socket.AF_INET)) as sock:
1477 s = ssl.wrap_socket(sock,
1478 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1479 s.connect(remote)
Bill Janssen296a59d2007-09-16 22:06:00 +00001480
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001481 def test_algorithms(self):
1482 # Issue #8484: all algorithms should be available when verifying a
1483 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +00001484 # SHA256 was added in OpenSSL 0.9.8
1485 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1486 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001487 # sha256.tbs-internet.com needs SNI to use the correct certificate
1488 if not ssl.HAS_SNI:
1489 self.skipTest("SNI needed for this test")
1490 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
Antoine Pitroud43245a2011-01-08 10:32:51 +00001491 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001492 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001493 with support.transient_internet("sha256.tbs-internet.com"):
1494 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1495 ctx.verify_mode = ssl.CERT_REQUIRED
1496 ctx.load_verify_locations(sha256_cert)
1497 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1498 server_hostname="sha256.tbs-internet.com")
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001499 try:
1500 s.connect(remote)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001501 if support.verbose:
Antoine Pitrouc715a9e2010-04-21 19:28:03 +00001502 sys.stdout.write("\nCipher with %r is %r\n" %
1503 (remote, s.cipher()))
1504 sys.stdout.write("Certificate is:\n%s\n" %
1505 pprint.pformat(s.getpeercert()))
1506 finally:
1507 s.close()
1508
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001509 def test_get_ca_certs_capath(self):
1510 # capath certs are loaded on request
1511 with support.transient_internet("svn.python.org"):
1512 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1513 ctx.verify_mode = ssl.CERT_REQUIRED
1514 ctx.load_verify_locations(capath=CAPATH)
1515 self.assertEqual(ctx.get_ca_certs(), [])
1516 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1517 s.connect(("svn.python.org", 443))
1518 try:
1519 cert = s.getpeercert()
1520 self.assertTrue(cert)
1521 finally:
1522 s.close()
1523 self.assertEqual(len(ctx.get_ca_certs()), 1)
1524
1525 @needs_sni
1526 def test_context_setget(self):
1527 # Check that the context of a connected socket can be replaced.
1528 with support.transient_internet("svn.python.org"):
1529 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1530 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1531 s = socket.socket(socket.AF_INET)
1532 with closing(ctx1.wrap_socket(s)) as ss:
1533 ss.connect(("svn.python.org", 443))
1534 self.assertIs(ss.context, ctx1)
1535 self.assertIs(ss._sslobj.context, ctx1)
1536 ss.context = ctx2
1537 self.assertIs(ss.context, ctx2)
1538 self.assertIs(ss._sslobj.context, ctx2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001539
Bill Janssen98d19da2007-09-10 21:51:02 +00001540try:
1541 import threading
1542except ImportError:
1543 _have_threads = False
1544else:
Bill Janssen98d19da2007-09-10 21:51:02 +00001545 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001546
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001547 from test.ssl_servers import make_https_server
1548
Bill Janssen98d19da2007-09-10 21:51:02 +00001549 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001550
Bill Janssen98d19da2007-09-10 21:51:02 +00001551 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001552
Bill Janssen98d19da2007-09-10 21:51:02 +00001553 """A mildly complicated class, because we want it to work both
1554 with and without the SSL wrapper around the socket connection, so
1555 that we can test the STARTTLS functionality."""
1556
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001557 def __init__(self, server, connsock, addr):
Bill Janssen98d19da2007-09-10 21:51:02 +00001558 self.server = server
1559 self.running = False
1560 self.sock = connsock
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001561 self.addr = addr
Bill Janssen98d19da2007-09-10 21:51:02 +00001562 self.sock.setblocking(1)
1563 self.sslconn = None
1564 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001565 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001566
Antoine Pitrou3945c862010-04-28 21:11:01 +00001567 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001568 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001569 self.sslconn = self.server.context.wrap_socket(
1570 self.sock, server_side=True)
1571 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
1572 except socket.error as e:
1573 # We treat ConnectionResetError as though it were an
1574 # SSLError - OpenSSL on Ubuntu abruptly closes the
1575 # connection when asked to use an unsupported protocol.
1576 #
Antoine Pitroudb187842010-04-27 10:32:58 +00001577 # XXX Various errors can have happened here, for example
1578 # a mismatching protocol version, an invalid certificate,
1579 # or a low-level bug. This should be made more discriminating.
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001580 if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET:
1581 raise
Antoine Pitroud76088d2012-01-03 22:46:48 +01001582 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +00001583 if self.server.chatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001584 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00001585 self.running = False
1586 self.server.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001587 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001588 return False
Bill Janssen98d19da2007-09-10 21:51:02 +00001589 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001590 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
1591 cert = self.sslconn.getpeercert()
1592 if support.verbose and self.server.chatty:
1593 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1594 cert_binary = self.sslconn.getpeercert(True)
1595 if support.verbose and self.server.chatty:
1596 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1597 cipher = self.sslconn.cipher()
1598 if support.verbose and self.server.chatty:
1599 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
1600 sys.stdout.write(" server: selected protocol is now "
1601 + str(self.sslconn.selected_npn_protocol()) + "\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001602 return True
1603
1604 def read(self):
1605 if self.sslconn:
1606 return self.sslconn.read()
1607 else:
1608 return self.sock.recv(1024)
1609
1610 def write(self, bytes):
1611 if self.sslconn:
1612 return self.sslconn.write(bytes)
1613 else:
1614 return self.sock.send(bytes)
1615
1616 def close(self):
1617 if self.sslconn:
1618 self.sslconn.close()
1619 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001620 self.sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001621
Antoine Pitrou3945c862010-04-28 21:11:01 +00001622 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001623 self.running = True
1624 if not self.server.starttls_server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001625 if not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +00001626 return
1627 while self.running:
1628 try:
1629 msg = self.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001630 stripped = msg.strip()
1631 if not stripped:
Bill Janssen98d19da2007-09-10 21:51:02 +00001632 # eof, so quit this handler
1633 self.running = False
1634 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001635 elif stripped == b'over':
1636 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001637 sys.stdout.write(" server: client closed connection\n")
1638 self.close()
1639 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001640 elif (self.server.starttls_server and
1641 stripped == b'STARTTLS'):
1642 if support.verbose and self.server.connectionchatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001643 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001644 self.write(b"OK\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001645 if not self.wrap_conn():
1646 return
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001647 elif (self.server.starttls_server and self.sslconn
1648 and stripped == b'ENDTLS'):
1649 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001650 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001651 self.write(b"OK\n")
1652 self.sock = self.sslconn.unwrap()
Bill Janssen39295c22008-08-12 16:31:21 +00001653 self.sslconn = None
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001654 if support.verbose and self.server.connectionchatty:
Bill Janssen39295c22008-08-12 16:31:21 +00001655 sys.stdout.write(" server: connection is now unencrypted...\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001656 elif stripped == b'CB tls-unique':
1657 if support.verbose and self.server.connectionchatty:
1658 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1659 data = self.sslconn.get_channel_binding("tls-unique")
1660 self.write(repr(data).encode("us-ascii") + b"\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001661 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001662 if (support.verbose and
Bill Janssen98d19da2007-09-10 21:51:02 +00001663 self.server.connectionchatty):
1664 ctype = (self.sslconn and "encrypted") or "unencrypted"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001665 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1666 % (msg, ctype, msg.lower(), ctype))
Bill Janssen98d19da2007-09-10 21:51:02 +00001667 self.write(msg.lower())
1668 except ssl.SSLError:
1669 if self.server.chatty:
1670 handle_error("Test server failure:\n")
1671 self.close()
1672 self.running = False
1673 # normally, we'd just stop here, but for the test
1674 # harness, we want to stop the server
1675 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +00001676
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001677 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +00001678 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +00001679 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001680 npn_protocols=None, ciphers=None, context=None):
1681 if context:
1682 self.context = context
1683 else:
1684 self.context = ssl.SSLContext(ssl_version
1685 if ssl_version is not None
1686 else ssl.PROTOCOL_TLSv1)
1687 self.context.verify_mode = (certreqs if certreqs is not None
1688 else ssl.CERT_NONE)
1689 if cacerts:
1690 self.context.load_verify_locations(cacerts)
1691 if certificate:
1692 self.context.load_cert_chain(certificate)
1693 if npn_protocols:
1694 self.context.set_npn_protocols(npn_protocols)
1695 if ciphers:
1696 self.context.set_ciphers(ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +00001697 self.chatty = chatty
1698 self.connectionchatty = connectionchatty
1699 self.starttls_server = starttls_server
1700 self.sock = socket.socket()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001701 self.port = support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +00001702 self.flag = None
Bill Janssen98d19da2007-09-10 21:51:02 +00001703 self.active = False
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001704 self.selected_protocols = []
Antoine Pitroud76088d2012-01-03 22:46:48 +01001705 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001706 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001707 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +00001708
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001709 def __enter__(self):
1710 self.start(threading.Event())
1711 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001712 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001713
1714 def __exit__(self, *args):
1715 self.stop()
1716 self.join()
1717
Antoine Pitrou3945c862010-04-28 21:11:01 +00001718 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +00001719 self.flag = flag
1720 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001721
Antoine Pitrou3945c862010-04-28 21:11:01 +00001722 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +00001723 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +00001724 self.sock.listen(5)
1725 self.active = True
1726 if self.flag:
1727 # signal an event
1728 self.flag.set()
1729 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001730 try:
Bill Janssen98d19da2007-09-10 21:51:02 +00001731 newconn, connaddr = self.sock.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001732 if support.verbose and self.chatty:
Bill Janssen98d19da2007-09-10 21:51:02 +00001733 sys.stdout.write(' server: new connection from '
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001734 + repr(connaddr) + '\n')
1735 handler = self.ConnectionHandler(self, newconn, connaddr)
Bill Janssen98d19da2007-09-10 21:51:02 +00001736 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +01001737 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +00001738 except socket.timeout:
1739 pass
1740 except KeyboardInterrupt:
1741 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +00001742 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001743
Antoine Pitrou3945c862010-04-28 21:11:01 +00001744 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001745 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001746
Bill Janssen934b16d2008-06-28 22:19:33 +00001747 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +00001748
Antoine Pitrou3945c862010-04-28 21:11:01 +00001749 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +00001750
Antoine Pitrou3945c862010-04-28 21:11:01 +00001751 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +00001752
1753 def __init__(self, conn, certfile):
Bill Janssen934b16d2008-06-28 22:19:33 +00001754 self.socket = ssl.wrap_socket(conn, server_side=True,
1755 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +00001756 do_handshake_on_connect=False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001757 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroufc69af12010-04-24 20:04:58 +00001758 self._ssl_accepting = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001759 self._do_ssl_handshake()
Bill Janssen934b16d2008-06-28 22:19:33 +00001760
1761 def readable(self):
1762 if isinstance(self.socket, ssl.SSLSocket):
1763 while self.socket.pending() > 0:
1764 self.handle_read_event()
1765 return True
1766
Antoine Pitroufc69af12010-04-24 20:04:58 +00001767 def _do_ssl_handshake(self):
1768 try:
1769 self.socket.do_handshake()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001770 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1771 return
1772 except ssl.SSLEOFError:
1773 return self.handle_close()
1774 except ssl.SSLError:
Antoine Pitroufc69af12010-04-24 20:04:58 +00001775 raise
1776 except socket.error, err:
1777 if err.args[0] == errno.ECONNABORTED:
1778 return self.handle_close()
1779 else:
1780 self._ssl_accepting = False
1781
Bill Janssen934b16d2008-06-28 22:19:33 +00001782 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +00001783 if self._ssl_accepting:
1784 self._do_ssl_handshake()
1785 else:
1786 data = self.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001787 if support.verbose:
1788 sys.stdout.write(" server: read %s from client\n" % repr(data))
1789 if not data:
1790 self.close()
1791 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001792 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +00001793
1794 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +00001795 self.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001796 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001797 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1798
1799 def handle_error(self):
1800 raise
1801
1802 def __init__(self, certfile):
1803 self.certfile = certfile
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001804 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1805 self.port = support.bind_port(sock, '')
1806 asyncore.dispatcher.__init__(self, sock)
Bill Janssen934b16d2008-06-28 22:19:33 +00001807 self.listen(5)
1808
1809 def handle_accept(self):
1810 sock_obj, addr = self.accept()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001811 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00001812 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1813 self.ConnectionHandler(sock_obj, self.certfile)
1814
1815 def handle_error(self):
1816 raise
1817
1818 def __init__(self, certfile):
1819 self.flag = None
1820 self.active = False
1821 self.server = self.EchoServer(certfile)
1822 self.port = self.server.port
1823 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +00001824 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +00001825
1826 def __str__(self):
1827 return "<%s %s>" % (self.__class__.__name__, self.server)
1828
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001829 def __enter__(self):
1830 self.start(threading.Event())
1831 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +01001832 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001833
1834 def __exit__(self, *args):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001835 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001836 sys.stdout.write(" cleanup: stopping server.\n")
1837 self.stop()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001838 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001839 sys.stdout.write(" cleanup: joining server thread.\n")
1840 self.join()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001841 if support.verbose:
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001842 sys.stdout.write(" cleanup: successfully joined.\n")
1843
Antoine Pitrou3945c862010-04-28 21:11:01 +00001844 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +00001845 self.flag = flag
1846 threading.Thread.start(self)
1847
Antoine Pitrou3945c862010-04-28 21:11:01 +00001848 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001849 self.active = True
1850 if self.flag:
1851 self.flag.set()
1852 while self.active:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001853 try:
1854 asyncore.loop(1)
1855 except:
1856 pass
Bill Janssen934b16d2008-06-28 22:19:33 +00001857
Antoine Pitrou3945c862010-04-28 21:11:01 +00001858 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +00001859 self.active = False
1860 self.server.close()
1861
Antoine Pitrou3945c862010-04-28 21:11:01 +00001862 def bad_cert_test(certfile):
1863 """
1864 Launch a server with CERT_REQUIRED, and check that trying to
1865 connect to it with the given client certificate fails.
1866 """
Trent Nelsone41b0062008-04-08 23:47:30 +00001867 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001868 certreqs=ssl.CERT_REQUIRED,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001869 cacerts=CERTFILE, chatty=False,
1870 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001871 with server:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001872 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001873 with closing(socket.socket()) as sock:
1874 s = ssl.wrap_socket(sock,
1875 certfile=certfile,
1876 ssl_version=ssl.PROTOCOL_TLSv1)
1877 s.connect((HOST, server.port))
1878 except ssl.SSLError as x:
1879 if support.verbose:
1880 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
1881 except OSError as x:
1882 if support.verbose:
1883 sys.stdout.write("\nOSError is %s\n" % x.args[1])
1884 except OSError as x:
1885 if x.errno != errno.ENOENT:
1886 raise
1887 if support.verbose:
1888 sys.stdout.write("\OSError is %s\n" % str(x))
Bill Janssen98d19da2007-09-10 21:51:02 +00001889 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00001890 raise AssertionError("Use of invalid cert should have failed!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001891
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001892 def server_params_test(client_context, server_context, indata=b"FOO\n",
1893 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001894 """
1895 Launch a server, connect a client to it and try various reads
1896 and writes.
1897 """
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001898 stats = {}
1899 server = ThreadedEchoServer(context=server_context,
Bill Janssen98d19da2007-09-10 21:51:02 +00001900 chatty=chatty,
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001901 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001902 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001903 with closing(client_context.wrap_socket(socket.socket(),
1904 server_hostname=sni_name)) as s:
1905 s.connect((HOST, server.port))
1906 for arg in [indata, bytearray(indata), memoryview(indata)]:
1907 if connectionchatty:
1908 if support.verbose:
1909 sys.stdout.write(
1910 " client: sending %r...\n" % indata)
1911 s.write(arg)
1912 outdata = s.read()
1913 if connectionchatty:
1914 if support.verbose:
1915 sys.stdout.write(" client: read %r\n" % outdata)
1916 if outdata != indata.lower():
1917 raise AssertionError(
1918 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1919 % (outdata[:20], len(outdata),
1920 indata[:20].lower(), len(indata)))
1921 s.write(b"over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001922 if connectionchatty:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001923 if support.verbose:
1924 sys.stdout.write(" client: closing connection.\n")
1925 stats.update({
1926 'compression': s.compression(),
1927 'cipher': s.cipher(),
1928 'peercert': s.getpeercert(),
Alex Gaynore98205d2014-09-04 13:33:22 -07001929 'client_npn_protocol': s.selected_npn_protocol(),
1930 'version': s.version(),
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001931 })
1932 s.close()
1933 stats['server_npn_protocols'] = server.selected_protocols
1934 return stats
Bill Janssen98d19da2007-09-10 21:51:02 +00001935
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001936 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1937 certsreqs=None, server_options=0, client_options=0):
Alex Gaynore98205d2014-09-04 13:33:22 -07001938 """
1939 Try to SSL-connect using *client_protocol* to *server_protocol*.
1940 If *expect_success* is true, assert that the connection succeeds,
1941 if it's false, assert that the connection fails.
1942 Also, if *expect_success* is a string, assert that it is the protocol
1943 version actually used by the connection.
1944 """
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00001945 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +00001946 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +00001947 certtype = {
1948 ssl.CERT_NONE: "CERT_NONE",
1949 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1950 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1951 }[certsreqs]
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001952 if support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001953 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +00001954 sys.stdout.write(formatstr %
1955 (ssl.get_protocol_name(client_protocol),
1956 ssl.get_protocol_name(server_protocol),
1957 certtype))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05001958 client_context = ssl.SSLContext(client_protocol)
1959 client_context.options |= client_options
1960 server_context = ssl.SSLContext(server_protocol)
1961 server_context.options |= server_options
1962
1963 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1964 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1965 # starting from OpenSSL 1.0.0 (see issue #8322).
1966 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1967 client_context.set_ciphers("ALL")
1968
1969 for ctx in (client_context, server_context):
1970 ctx.verify_mode = certsreqs
1971 ctx.load_cert_chain(CERTFILE)
1972 ctx.load_verify_locations(CERTFILE)
Bill Janssen98d19da2007-09-10 21:51:02 +00001973 try:
Alex Gaynore98205d2014-09-04 13:33:22 -07001974 stats = server_params_test(client_context, server_context,
1975 chatty=False, connectionchatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00001976 # Protocol mismatch can result in either an SSLError, or a
1977 # "Connection reset by peer" error.
1978 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001979 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +00001980 raise
Antoine Pitroudb187842010-04-27 10:32:58 +00001981 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001982 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +00001983 raise
Bill Janssen98d19da2007-09-10 21:51:02 +00001984 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +00001985 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +00001986 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +00001987 "Client protocol %s succeeded with server protocol %s!"
1988 % (ssl.get_protocol_name(client_protocol),
1989 ssl.get_protocol_name(server_protocol)))
Alex Gaynore98205d2014-09-04 13:33:22 -07001990 elif (expect_success is not True
1991 and expect_success != stats['version']):
1992 raise AssertionError("version mismatch: expected %r, got %r"
1993 % (expect_success, stats['version']))
Bill Janssen98d19da2007-09-10 21:51:02 +00001994
1995
Bill Janssen934b16d2008-06-28 22:19:33 +00001996 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +00001997
Antoine Pitroud75efd92010-08-04 17:38:33 +00001998 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001999 def test_echo(self):
2000 """Basic test of an SSL client connecting to a server"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002001 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002002 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002003 for protocol in PROTOCOLS:
2004 context = ssl.SSLContext(protocol)
2005 context.load_cert_chain(CERTFILE)
2006 server_params_test(context, context,
2007 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002008
Antoine Pitrou3945c862010-04-28 21:11:01 +00002009 def test_getpeercert(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002010 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002011 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002012 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2013 context.verify_mode = ssl.CERT_REQUIRED
2014 context.load_verify_locations(CERTFILE)
2015 context.load_cert_chain(CERTFILE)
2016 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002017 with server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002018 s = context.wrap_socket(socket.socket(),
2019 do_handshake_on_connect=False)
Antoine Pitroudb187842010-04-27 10:32:58 +00002020 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002021 # getpeercert() raise ValueError while the handshake isn't
2022 # done.
2023 with self.assertRaises(ValueError):
2024 s.getpeercert()
2025 s.do_handshake()
Antoine Pitroudb187842010-04-27 10:32:58 +00002026 cert = s.getpeercert()
2027 self.assertTrue(cert, "Can't get peer certificate.")
2028 cipher = s.cipher()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002029 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002030 sys.stdout.write(pprint.pformat(cert) + '\n')
2031 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2032 if 'subject' not in cert:
2033 self.fail("No subject field in certificate: %s." %
2034 pprint.pformat(cert))
2035 if ((('organizationName', 'Python Software Foundation'),)
2036 not in cert['subject']):
2037 self.fail(
2038 "Missing or invalid 'organizationName' field in certificate subject; "
2039 "should be 'Python Software Foundation'.")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002040 self.assertIn('notBefore', cert)
2041 self.assertIn('notAfter', cert)
2042 before = ssl.cert_time_to_seconds(cert['notBefore'])
2043 after = ssl.cert_time_to_seconds(cert['notAfter'])
2044 self.assertLess(before, after)
Antoine Pitroudb187842010-04-27 10:32:58 +00002045 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002046
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002047 @unittest.skipUnless(have_verify_flags(),
2048 "verify_flags need OpenSSL > 0.9.8")
2049 def test_crl_check(self):
2050 if support.verbose:
2051 sys.stdout.write("\n")
2052
2053 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2054 server_context.load_cert_chain(SIGNED_CERTFILE)
2055
2056 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2057 context.verify_mode = ssl.CERT_REQUIRED
2058 context.load_verify_locations(SIGNING_CA)
2059 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT)
2060
2061 # VERIFY_DEFAULT should pass
2062 server = ThreadedEchoServer(context=server_context, chatty=True)
2063 with server:
2064 with closing(context.wrap_socket(socket.socket())) as s:
2065 s.connect((HOST, server.port))
2066 cert = s.getpeercert()
2067 self.assertTrue(cert, "Can't get peer certificate.")
2068
2069 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
2070 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
2071
2072 server = ThreadedEchoServer(context=server_context, chatty=True)
2073 with server:
2074 with closing(context.wrap_socket(socket.socket())) as s:
2075 with self.assertRaisesRegexp(ssl.SSLError,
2076 "certificate verify failed"):
2077 s.connect((HOST, server.port))
2078
2079 # now load a CRL file. The CRL file is signed by the CA.
2080 context.load_verify_locations(CRLFILE)
2081
2082 server = ThreadedEchoServer(context=server_context, chatty=True)
2083 with server:
2084 with closing(context.wrap_socket(socket.socket())) as s:
2085 s.connect((HOST, server.port))
2086 cert = s.getpeercert()
2087 self.assertTrue(cert, "Can't get peer certificate.")
2088
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002089 def test_check_hostname(self):
2090 if support.verbose:
2091 sys.stdout.write("\n")
2092
2093 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2094 server_context.load_cert_chain(SIGNED_CERTFILE)
2095
2096 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2097 context.verify_mode = ssl.CERT_REQUIRED
2098 context.check_hostname = True
2099 context.load_verify_locations(SIGNING_CA)
2100
2101 # correct hostname should verify
2102 server = ThreadedEchoServer(context=server_context, chatty=True)
2103 with server:
2104 with closing(context.wrap_socket(socket.socket(),
2105 server_hostname="localhost")) as s:
2106 s.connect((HOST, server.port))
2107 cert = s.getpeercert()
2108 self.assertTrue(cert, "Can't get peer certificate.")
2109
2110 # incorrect hostname should raise an exception
2111 server = ThreadedEchoServer(context=server_context, chatty=True)
2112 with server:
2113 with closing(context.wrap_socket(socket.socket(),
2114 server_hostname="invalid")) as s:
2115 with self.assertRaisesRegexp(ssl.CertificateError,
2116 "hostname 'invalid' doesn't match u?'localhost'"):
2117 s.connect((HOST, server.port))
2118
2119 # missing server_hostname arg should cause an exception, too
2120 server = ThreadedEchoServer(context=server_context, chatty=True)
2121 with server:
2122 with closing(socket.socket()) as s:
2123 with self.assertRaisesRegexp(ValueError,
2124 "check_hostname requires server_hostname"):
2125 context.wrap_socket(s)
2126
Antoine Pitrou3945c862010-04-28 21:11:01 +00002127 def test_empty_cert(self):
2128 """Connecting with an empty cert file"""
2129 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2130 "nullcert.pem"))
2131 def test_malformed_cert(self):
2132 """Connecting with a badly formatted certificate (syntax error)"""
2133 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2134 "badcert.pem"))
2135 def test_nonexisting_cert(self):
2136 """Connecting with a non-existing cert file"""
2137 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2138 "wrongcert.pem"))
2139 def test_malformed_key(self):
2140 """Connecting with a badly formatted key (syntax error)"""
2141 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2142 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +00002143
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002144 def test_rude_shutdown(self):
2145 """A brutal shutdown of an SSL server should raise an OSError
2146 in the client when attempting handshake.
2147 """
2148 listener_ready = threading.Event()
2149 listener_gone = threading.Event()
2150
2151 s = socket.socket()
2152 port = support.bind_port(s, HOST)
2153
2154 # `listener` runs in a thread. It sits in an accept() until
2155 # the main thread connects. Then it rudely closes the socket,
2156 # and sets Event `listener_gone` to let the main thread know
2157 # the socket is gone.
2158 def listener():
2159 s.listen(5)
2160 listener_ready.set()
2161 newsock, addr = s.accept()
2162 newsock.close()
2163 s.close()
2164 listener_gone.set()
2165
2166 def connector():
2167 listener_ready.wait()
2168 with closing(socket.socket()) as c:
2169 c.connect((HOST, port))
2170 listener_gone.wait()
2171 try:
2172 ssl_sock = ssl.wrap_socket(c)
Benjamin Petersone208b572014-08-20 14:49:08 -05002173 except socket.error:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002174 pass
2175 else:
2176 self.fail('connecting to closed SSL socket should have failed')
2177
2178 t = threading.Thread(target=listener)
2179 t.start()
2180 try:
2181 connector()
2182 finally:
2183 t.join()
2184
Antoine Pitroud75efd92010-08-04 17:38:33 +00002185 @skip_if_broken_ubuntu_ssl
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002186 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2187 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002188 def test_protocol_sslv2(self):
2189 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002190 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002191 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00002192 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2193 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2194 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01002195 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002196 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2197 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002198 # SSLv23 client with specific SSL options
2199 if no_sslv2_implies_sslv3_hello():
2200 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2201 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2202 client_options=ssl.OP_NO_SSLv2)
2203 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2204 client_options=ssl.OP_NO_SSLv3)
2205 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2206 client_options=ssl.OP_NO_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00002207
Antoine Pitroud75efd92010-08-04 17:38:33 +00002208 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002209 def test_protocol_sslv23(self):
2210 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002211 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002212 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002213 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2214 try:
2215 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
2216 except socket.error as x:
2217 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2218 if support.verbose:
2219 sys.stdout.write(
2220 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2221 % str(x))
Alex Gaynore98205d2014-09-04 13:33:22 -07002222 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3')
Antoine Pitrou3945c862010-04-28 21:11:01 +00002223 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Alex Gaynore98205d2014-09-04 13:33:22 -07002224 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Bill Janssen98d19da2007-09-10 21:51:02 +00002225
Alex Gaynore98205d2014-09-04 13:33:22 -07002226 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002227 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Alex Gaynore98205d2014-09-04 13:33:22 -07002228 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00002229
Alex Gaynore98205d2014-09-04 13:33:22 -07002230 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002231 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Alex Gaynore98205d2014-09-04 13:33:22 -07002232 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00002233
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002234 # Server with specific SSL options
2235 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
2236 server_options=ssl.OP_NO_SSLv3)
2237 # Will choose TLSv1
2238 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2239 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2240 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2241 server_options=ssl.OP_NO_TLSv1)
2242
2243
Antoine Pitroud75efd92010-08-04 17:38:33 +00002244 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002245 def test_protocol_sslv3(self):
2246 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002247 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002248 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002249 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2250 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2251 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002252 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2253 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002254 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2255 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002256 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002257 if no_sslv2_implies_sslv3_hello():
2258 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Alex Gaynore98205d2014-09-04 13:33:22 -07002259 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, 'SSLv3',
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002260 client_options=ssl.OP_NO_SSLv2)
Bill Janssen98d19da2007-09-10 21:51:02 +00002261
Antoine Pitroud75efd92010-08-04 17:38:33 +00002262 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00002263 def test_protocol_tlsv1(self):
2264 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002265 if support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +00002266 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002267 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2268 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2269 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02002270 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2271 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002272 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002273 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2274 client_options=ssl.OP_NO_TLSv1)
2275
2276 @skip_if_broken_ubuntu_ssl
2277 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2278 "TLS version 1.1 not supported.")
2279 def test_protocol_tlsv1_1(self):
2280 """Connecting to a TLSv1.1 server with various client options.
2281 Testing against older TLS versions."""
2282 if support.verbose:
2283 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002284 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002285 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2286 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
2287 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
2288 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2289 client_options=ssl.OP_NO_TLSv1_1)
2290
Alex Gaynore98205d2014-09-04 13:33:22 -07002291 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002292 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2293 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2294
2295
2296 @skip_if_broken_ubuntu_ssl
2297 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2298 "TLS version 1.2 not supported.")
2299 def test_protocol_tlsv1_2(self):
2300 """Connecting to a TLSv1.2 server with various client options.
2301 Testing against older TLS versions."""
2302 if support.verbose:
2303 sys.stdout.write("\n")
Alex Gaynore98205d2014-09-04 13:33:22 -07002304 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002305 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2306 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2307 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2308 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
2309 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
2310 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2311 client_options=ssl.OP_NO_TLSv1_2)
2312
Alex Gaynore98205d2014-09-04 13:33:22 -07002313 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002314 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2315 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2316 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2317 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00002318
Antoine Pitrou3945c862010-04-28 21:11:01 +00002319 def test_starttls(self):
2320 """Switching from clear text to encrypted and back again."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002321 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 +00002322
Trent Nelsone41b0062008-04-08 23:47:30 +00002323 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00002324 ssl_version=ssl.PROTOCOL_TLSv1,
2325 starttls_server=True,
2326 chatty=True,
2327 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00002328 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002329 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002330 s = socket.socket()
2331 s.setblocking(1)
2332 s.connect((HOST, server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002333 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002334 sys.stdout.write("\n")
2335 for indata in msgs:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002336 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002337 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002338 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002339 if wrapped:
2340 conn.write(indata)
2341 outdata = conn.read()
2342 else:
2343 s.send(indata)
2344 outdata = s.recv(1024)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002345 msg = outdata.strip().lower()
2346 if indata == b"STARTTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002347 # STARTTLS ok, switch to secure mode
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002348 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002349 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002350 " client: read %r from server, starting TLS...\n"
2351 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002352 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2353 wrapped = True
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002354 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
Antoine Pitrou3945c862010-04-28 21:11:01 +00002355 # ENDTLS ok, switch back to clear text
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002356 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002357 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002358 " client: read %r from server, ending TLS...\n"
2359 % msg)
Antoine Pitroudb187842010-04-27 10:32:58 +00002360 s = conn.unwrap()
2361 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00002362 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002363 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002364 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002365 " client: read %r from server\n" % msg)
2366 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002367 sys.stdout.write(" client: closing connection.\n")
2368 if wrapped:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002369 conn.write(b"over\n")
Antoine Pitroudb187842010-04-27 10:32:58 +00002370 else:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002371 s.send(b"over\n")
2372 if wrapped:
2373 conn.close()
2374 else:
2375 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00002376
Antoine Pitrou3945c862010-04-28 21:11:01 +00002377 def test_socketserver(self):
2378 """Using a SocketServer to create and manage SSL connections."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002379 server = make_https_server(self, certfile=CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00002380 # try to connect
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002381 if support.verbose:
2382 sys.stdout.write('\n')
2383 with open(CERTFILE, 'rb') as f:
2384 d1 = f.read()
2385 d2 = ''
2386 # now fetch the same data from the HTTPS server
Benjamin Petersonfcfb18e2014-11-23 11:42:45 -06002387 url = 'https://localhost:%d/%s' % (
2388 server.port, os.path.split(CERTFILE)[1])
2389 context = ssl.create_default_context(cafile=CERTFILE)
Benjamin Petersonb0609ec2014-11-23 11:52:46 -06002390 f = urllib2.urlopen(url, context=context)
Bill Janssen296a59d2007-09-16 22:06:00 +00002391 try:
Bill Janssen296a59d2007-09-16 22:06:00 +00002392 dlen = f.info().getheader("content-length")
2393 if dlen and (int(dlen) > 0):
2394 d2 = f.read(int(dlen))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002395 if support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00002396 sys.stdout.write(
2397 " client: read %d bytes from remote server '%s'\n"
2398 % (len(d2), server))
Bill Janssen296a59d2007-09-16 22:06:00 +00002399 finally:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002400 f.close()
2401 self.assertEqual(d1, d2)
Bill Janssen934b16d2008-06-28 22:19:33 +00002402
Antoine Pitrou3945c862010-04-28 21:11:01 +00002403 def test_asyncore_server(self):
2404 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00002405 indata = "TEST MESSAGE of mixed case\n"
2406
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002407 if support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +00002408 sys.stdout.write("\n")
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002409
2410 indata = b"FOO\n"
Bill Janssen934b16d2008-06-28 22:19:33 +00002411 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002412 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00002413 s = ssl.wrap_socket(socket.socket())
2414 s.connect(('127.0.0.1', server.port))
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002415 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002416 sys.stdout.write(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002417 " client: sending %r...\n" % indata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002418 s.write(indata)
2419 outdata = s.read()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002420 if support.verbose:
2421 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitroudb187842010-04-27 10:32:58 +00002422 if outdata != indata.lower():
2423 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002424 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2425 % (outdata[:20], len(outdata),
2426 indata[:20].lower(), len(indata)))
2427 s.write(b"over\n")
2428 if support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00002429 sys.stdout.write(" client: closing connection.\n")
2430 s.close()
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002431 if support.verbose:
2432 sys.stdout.write(" client: connection closed.\n")
Bill Janssen934b16d2008-06-28 22:19:33 +00002433
Antoine Pitrou3945c862010-04-28 21:11:01 +00002434 def test_recv_send(self):
2435 """Test recv(), send() and friends."""
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002436 if support.verbose:
Bill Janssen61c001a2008-09-08 16:37:24 +00002437 sys.stdout.write("\n")
2438
2439 server = ThreadedEchoServer(CERTFILE,
2440 certreqs=ssl.CERT_NONE,
2441 ssl_version=ssl.PROTOCOL_TLSv1,
2442 cacerts=CERTFILE,
2443 chatty=True,
2444 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01002445 with server:
2446 s = ssl.wrap_socket(socket.socket(),
2447 server_side=False,
2448 certfile=CERTFILE,
2449 ca_certs=CERTFILE,
2450 cert_reqs=ssl.CERT_NONE,
2451 ssl_version=ssl.PROTOCOL_TLSv1)
2452 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00002453 # helper methods for standardising recv* method signatures
2454 def _recv_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002455 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002456 count = s.recv_into(b)
2457 return b[:count]
2458
2459 def _recvfrom_into():
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002460 b = bytearray(b"\0"*100)
Bill Janssen61c001a2008-09-08 16:37:24 +00002461 count, addr = s.recvfrom_into(b)
2462 return b[:count]
2463
2464 # (name, method, whether to expect success, *args)
2465 send_methods = [
2466 ('send', s.send, True, []),
2467 ('sendto', s.sendto, False, ["some.address"]),
2468 ('sendall', s.sendall, True, []),
2469 ]
2470 recv_methods = [
2471 ('recv', s.recv, True, []),
2472 ('recvfrom', s.recvfrom, False, ["some.address"]),
2473 ('recv_into', _recv_into, True, []),
2474 ('recvfrom_into', _recvfrom_into, False, []),
2475 ]
2476 data_prefix = u"PREFIX_"
2477
2478 for meth_name, send_meth, expect_success, args in send_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002479 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002480 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002481 send_meth(indata, *args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002482 outdata = s.read()
Bill Janssen61c001a2008-09-08 16:37:24 +00002483 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002484 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002485 "While sending with <<{name:s}>> bad data "
2486 "<<{outdata:r}>> ({nout:d}) received; "
2487 "expected <<{indata:r}>> ({nin:d})\n".format(
2488 name=meth_name, outdata=outdata[:20],
2489 nout=len(outdata),
2490 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002491 )
2492 )
2493 except ValueError as e:
2494 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002495 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002496 "Failed to send with method <<{name:s}>>; "
2497 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002498 )
2499 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002500 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002501 "Method <<{name:s}>> failed with unexpected "
2502 "exception message: {exp:s}\n".format(
2503 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002504 )
2505 )
2506
2507 for meth_name, recv_meth, expect_success, args in recv_methods:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002508 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen61c001a2008-09-08 16:37:24 +00002509 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002510 s.send(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002511 outdata = recv_meth(*args)
Bill Janssen61c001a2008-09-08 16:37:24 +00002512 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002513 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002514 "While receiving with <<{name:s}>> bad data "
2515 "<<{outdata:r}>> ({nout:d}) received; "
2516 "expected <<{indata:r}>> ({nin:d})\n".format(
2517 name=meth_name, outdata=outdata[:20],
2518 nout=len(outdata),
2519 indata=indata[:20], nin=len(indata)
Bill Janssen61c001a2008-09-08 16:37:24 +00002520 )
2521 )
2522 except ValueError as e:
2523 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002524 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002525 "Failed to receive with method <<{name:s}>>; "
2526 "expected to succeed.\n".format(name=meth_name)
Bill Janssen61c001a2008-09-08 16:37:24 +00002527 )
2528 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00002529 self.fail(
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002530 "Method <<{name:s}>> failed with unexpected "
2531 "exception message: {exp:s}\n".format(
2532 name=meth_name, exp=e
Bill Janssen61c001a2008-09-08 16:37:24 +00002533 )
2534 )
2535 # consume data
2536 s.read()
2537
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002538 s.write(b"over\n")
Bill Janssen61c001a2008-09-08 16:37:24 +00002539 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00002540
Antoine Pitroufc69af12010-04-24 20:04:58 +00002541 def test_handshake_timeout(self):
2542 # Issue #5103: SSL handshake must respect the socket timeout
2543 server = socket.socket(socket.AF_INET)
2544 host = "127.0.0.1"
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002545 port = support.bind_port(server)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002546 started = threading.Event()
2547 finish = False
2548
2549 def serve():
2550 server.listen(5)
2551 started.set()
2552 conns = []
2553 while not finish:
2554 r, w, e = select.select([server], [], [], 0.1)
2555 if server in r:
2556 # Let the socket hang around rather than having
2557 # it closed by garbage collection.
2558 conns.append(server.accept()[0])
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002559 for sock in conns:
2560 sock.close()
Antoine Pitroufc69af12010-04-24 20:04:58 +00002561
2562 t = threading.Thread(target=serve)
2563 t.start()
2564 started.wait()
2565
2566 try:
2567 try:
2568 c = socket.socket(socket.AF_INET)
2569 c.settimeout(0.2)
2570 c.connect((host, port))
2571 # Will attempt handshake and time out
2572 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2573 ssl.wrap_socket, c)
2574 finally:
2575 c.close()
2576 try:
2577 c = socket.socket(socket.AF_INET)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002578 c = ssl.wrap_socket(c)
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002579 c.settimeout(0.2)
Antoine Pitroufc69af12010-04-24 20:04:58 +00002580 # Will attempt handshake and time out
2581 self.assertRaisesRegexp(ssl.SSLError, "timed out",
2582 c.connect, (host, port))
2583 finally:
2584 c.close()
2585 finally:
2586 finish = True
2587 t.join()
2588 server.close()
2589
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002590 def test_server_accept(self):
2591 # Issue #16357: accept() on a SSLSocket created through
2592 # SSLContext.wrap_socket().
2593 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2594 context.verify_mode = ssl.CERT_REQUIRED
2595 context.load_verify_locations(CERTFILE)
2596 context.load_cert_chain(CERTFILE)
2597 server = socket.socket(socket.AF_INET)
2598 host = "127.0.0.1"
2599 port = support.bind_port(server)
2600 server = context.wrap_socket(server, server_side=True)
2601
2602 evt = threading.Event()
2603 remote = [None]
2604 peer = [None]
2605 def serve():
2606 server.listen(5)
2607 # Block on the accept and wait on the connection to close.
2608 evt.set()
2609 remote[0], peer[0] = server.accept()
2610 remote[0].recv(1)
2611
2612 t = threading.Thread(target=serve)
2613 t.start()
2614 # Client wait until server setup and perform a connect.
2615 evt.wait()
2616 client = context.wrap_socket(socket.socket())
2617 client.connect((host, port))
2618 client_addr = client.getsockname()
2619 client.close()
2620 t.join()
2621 remote[0].close()
2622 server.close()
2623 # Sanity checks.
2624 self.assertIsInstance(remote[0], ssl.SSLSocket)
2625 self.assertEqual(peer[0], client_addr)
2626
2627 def test_getpeercert_enotconn(self):
2628 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2629 with closing(context.wrap_socket(socket.socket())) as sock:
2630 with self.assertRaises(socket.error) as cm:
2631 sock.getpeercert()
2632 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2633
2634 def test_do_handshake_enotconn(self):
2635 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2636 with closing(context.wrap_socket(socket.socket())) as sock:
2637 with self.assertRaises(socket.error) as cm:
2638 sock.do_handshake()
2639 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2640
Antoine Pitroud76088d2012-01-03 22:46:48 +01002641 def test_default_ciphers(self):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002642 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2643 try:
2644 # Force a set of weak ciphers on our client context
2645 context.set_ciphers("DES")
2646 except ssl.SSLError:
2647 self.skipTest("no DES cipher available")
Antoine Pitroud76088d2012-01-03 22:46:48 +01002648 with ThreadedEchoServer(CERTFILE,
2649 ssl_version=ssl.PROTOCOL_SSLv23,
2650 chatty=False) as server:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002651 with closing(context.wrap_socket(socket.socket())) as s:
2652 with self.assertRaises(ssl.SSLError):
Antoine Pitroud76088d2012-01-03 22:46:48 +01002653 s.connect((HOST, server.port))
Antoine Pitroud76088d2012-01-03 22:46:48 +01002654 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2655
Alex Gaynore98205d2014-09-04 13:33:22 -07002656 def test_version_basic(self):
2657 """
2658 Basic tests for SSLSocket.version().
2659 More tests are done in the test_protocol_*() methods.
2660 """
2661 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2662 with ThreadedEchoServer(CERTFILE,
2663 ssl_version=ssl.PROTOCOL_TLSv1,
2664 chatty=False) as server:
2665 with closing(context.wrap_socket(socket.socket())) as s:
2666 self.assertIs(s.version(), None)
2667 s.connect((HOST, server.port))
2668 self.assertEqual(s.version(), "TLSv1")
2669 self.assertIs(s.version(), None)
2670
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002671 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2672 def test_default_ecdh_curve(self):
2673 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2674 # should be enabled by default on SSL contexts.
2675 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2676 context.load_cert_chain(CERTFILE)
2677 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2678 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2679 # our default cipher list should prefer ECDH-based ciphers
2680 # automatically.
2681 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2682 context.set_ciphers("ECCdraft:ECDH")
2683 with ThreadedEchoServer(context=context) as server:
2684 with closing(context.wrap_socket(socket.socket())) as s:
2685 s.connect((HOST, server.port))
2686 self.assertIn("ECDH", s.cipher()[0])
2687
2688 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2689 "'tls-unique' channel binding not available")
2690 def test_tls_unique_channel_binding(self):
2691 """Test tls-unique channel binding."""
2692 if support.verbose:
2693 sys.stdout.write("\n")
2694
2695 server = ThreadedEchoServer(CERTFILE,
2696 certreqs=ssl.CERT_NONE,
2697 ssl_version=ssl.PROTOCOL_TLSv1,
2698 cacerts=CERTFILE,
2699 chatty=True,
2700 connectionchatty=False)
2701 with server:
2702 s = ssl.wrap_socket(socket.socket(),
2703 server_side=False,
2704 certfile=CERTFILE,
2705 ca_certs=CERTFILE,
2706 cert_reqs=ssl.CERT_NONE,
2707 ssl_version=ssl.PROTOCOL_TLSv1)
2708 s.connect((HOST, server.port))
2709 # get the data
2710 cb_data = s.get_channel_binding("tls-unique")
2711 if support.verbose:
2712 sys.stdout.write(" got channel binding data: {0!r}\n"
2713 .format(cb_data))
2714
2715 # check if it is sane
2716 self.assertIsNotNone(cb_data)
2717 self.assertEqual(len(cb_data), 12) # True for TLSv1
2718
2719 # and compare with the peers version
2720 s.write(b"CB tls-unique\n")
2721 peer_data_repr = s.read().strip()
2722 self.assertEqual(peer_data_repr,
2723 repr(cb_data).encode("us-ascii"))
2724 s.close()
2725
2726 # now, again
2727 s = ssl.wrap_socket(socket.socket(),
2728 server_side=False,
2729 certfile=CERTFILE,
2730 ca_certs=CERTFILE,
2731 cert_reqs=ssl.CERT_NONE,
2732 ssl_version=ssl.PROTOCOL_TLSv1)
2733 s.connect((HOST, server.port))
2734 new_cb_data = s.get_channel_binding("tls-unique")
2735 if support.verbose:
2736 sys.stdout.write(" got another channel binding data: {0!r}\n"
2737 .format(new_cb_data))
2738 # is it really unique
2739 self.assertNotEqual(cb_data, new_cb_data)
2740 self.assertIsNotNone(cb_data)
2741 self.assertEqual(len(cb_data), 12) # True for TLSv1
2742 s.write(b"CB tls-unique\n")
2743 peer_data_repr = s.read().strip()
2744 self.assertEqual(peer_data_repr,
2745 repr(new_cb_data).encode("us-ascii"))
2746 s.close()
2747
2748 def test_compression(self):
2749 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2750 context.load_cert_chain(CERTFILE)
2751 stats = server_params_test(context, context,
2752 chatty=True, connectionchatty=True)
2753 if support.verbose:
2754 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2755 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2756
2757 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2758 "ssl.OP_NO_COMPRESSION needed for this test")
2759 def test_compression_disabled(self):
2760 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2761 context.load_cert_chain(CERTFILE)
2762 context.options |= ssl.OP_NO_COMPRESSION
2763 stats = server_params_test(context, context,
2764 chatty=True, connectionchatty=True)
2765 self.assertIs(stats['compression'], None)
2766
2767 def test_dh_params(self):
2768 # Check we can get a connection with ephemeral Diffie-Hellman
2769 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2770 context.load_cert_chain(CERTFILE)
2771 context.load_dh_params(DHFILE)
2772 context.set_ciphers("kEDH")
2773 stats = server_params_test(context, context,
2774 chatty=True, connectionchatty=True)
2775 cipher = stats["cipher"][0]
2776 parts = cipher.split("-")
2777 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2778 self.fail("Non-DH cipher: " + cipher[0])
2779
2780 def test_selected_npn_protocol(self):
2781 # selected_npn_protocol() is None unless NPN is used
2782 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2783 context.load_cert_chain(CERTFILE)
2784 stats = server_params_test(context, context,
2785 chatty=True, connectionchatty=True)
2786 self.assertIs(stats['client_npn_protocol'], None)
2787
2788 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2789 def test_npn_protocols(self):
2790 server_protocols = ['http/1.1', 'spdy/2']
2791 protocol_tests = [
2792 (['http/1.1', 'spdy/2'], 'http/1.1'),
2793 (['spdy/2', 'http/1.1'], 'http/1.1'),
2794 (['spdy/2', 'test'], 'spdy/2'),
2795 (['abc', 'def'], 'abc')
2796 ]
2797 for client_protocols, expected in protocol_tests:
2798 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2799 server_context.load_cert_chain(CERTFILE)
2800 server_context.set_npn_protocols(server_protocols)
2801 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2802 client_context.load_cert_chain(CERTFILE)
2803 client_context.set_npn_protocols(client_protocols)
2804 stats = server_params_test(client_context, server_context,
2805 chatty=True, connectionchatty=True)
2806
2807 msg = "failed trying %s (s) and %s (c).\n" \
2808 "was expecting %s, but got %%s from the %%s" \
2809 % (str(server_protocols), str(client_protocols),
2810 str(expected))
2811 client_result = stats['client_npn_protocol']
2812 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2813 server_result = stats['server_npn_protocols'][-1] \
2814 if len(stats['server_npn_protocols']) else 'nothing'
2815 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2816
2817 def sni_contexts(self):
2818 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2819 server_context.load_cert_chain(SIGNED_CERTFILE)
2820 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2821 other_context.load_cert_chain(SIGNED_CERTFILE2)
2822 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2823 client_context.verify_mode = ssl.CERT_REQUIRED
2824 client_context.load_verify_locations(SIGNING_CA)
2825 return server_context, other_context, client_context
2826
2827 def check_common_name(self, stats, name):
2828 cert = stats['peercert']
2829 self.assertIn((('commonName', name),), cert['subject'])
2830
2831 @needs_sni
2832 def test_sni_callback(self):
2833 calls = []
2834 server_context, other_context, client_context = self.sni_contexts()
2835
2836 def servername_cb(ssl_sock, server_name, initial_context):
2837 calls.append((server_name, initial_context))
2838 if server_name is not None:
2839 ssl_sock.context = other_context
2840 server_context.set_servername_callback(servername_cb)
2841
2842 stats = server_params_test(client_context, server_context,
2843 chatty=True,
2844 sni_name='supermessage')
2845 # The hostname was fetched properly, and the certificate was
2846 # changed for the connection.
2847 self.assertEqual(calls, [("supermessage", server_context)])
2848 # CERTFILE4 was selected
2849 self.check_common_name(stats, 'fakehostname')
2850
2851 calls = []
2852 # The callback is called with server_name=None
2853 stats = server_params_test(client_context, server_context,
2854 chatty=True,
2855 sni_name=None)
2856 self.assertEqual(calls, [(None, server_context)])
2857 self.check_common_name(stats, 'localhost')
2858
2859 # Check disabling the callback
2860 calls = []
2861 server_context.set_servername_callback(None)
2862
2863 stats = server_params_test(client_context, server_context,
2864 chatty=True,
2865 sni_name='notfunny')
2866 # Certificate didn't change
2867 self.check_common_name(stats, 'localhost')
2868 self.assertEqual(calls, [])
2869
2870 @needs_sni
2871 def test_sni_callback_alert(self):
2872 # Returning a TLS alert is reflected to the connecting client
2873 server_context, other_context, client_context = self.sni_contexts()
2874
2875 def cb_returning_alert(ssl_sock, server_name, initial_context):
2876 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2877 server_context.set_servername_callback(cb_returning_alert)
2878
2879 with self.assertRaises(ssl.SSLError) as cm:
2880 stats = server_params_test(client_context, server_context,
2881 chatty=False,
2882 sni_name='supermessage')
2883 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2884
2885 @needs_sni
2886 def test_sni_callback_raising(self):
2887 # Raising fails the connection with a TLS handshake failure alert.
2888 server_context, other_context, client_context = self.sni_contexts()
2889
2890 def cb_raising(ssl_sock, server_name, initial_context):
2891 1/0
2892 server_context.set_servername_callback(cb_raising)
2893
2894 with self.assertRaises(ssl.SSLError) as cm, \
2895 support.captured_stderr() as stderr:
2896 stats = server_params_test(client_context, server_context,
2897 chatty=False,
2898 sni_name='supermessage')
2899 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2900 self.assertIn("ZeroDivisionError", stderr.getvalue())
2901
2902 @needs_sni
2903 def test_sni_callback_wrong_return_type(self):
2904 # Returning the wrong return type terminates the TLS connection
2905 # with an internal error alert.
2906 server_context, other_context, client_context = self.sni_contexts()
2907
2908 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2909 return "foo"
2910 server_context.set_servername_callback(cb_wrong_return_type)
2911
2912 with self.assertRaises(ssl.SSLError) as cm, \
2913 support.captured_stderr() as stderr:
2914 stats = server_params_test(client_context, server_context,
2915 chatty=False,
2916 sni_name='supermessage')
2917 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2918 self.assertIn("TypeError", stderr.getvalue())
2919
2920 def test_read_write_after_close_raises_valuerror(self):
2921 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2922 context.verify_mode = ssl.CERT_REQUIRED
2923 context.load_verify_locations(CERTFILE)
2924 context.load_cert_chain(CERTFILE)
2925 server = ThreadedEchoServer(context=context, chatty=False)
2926
2927 with server:
2928 s = context.wrap_socket(socket.socket())
2929 s.connect((HOST, server.port))
2930 s.close()
2931
2932 self.assertRaises(ValueError, s.read, 1024)
2933 self.assertRaises(ValueError, s.write, b'hello')
2934
Bill Janssen61c001a2008-09-08 16:37:24 +00002935
Neal Norwitz9eb9b102007-08-27 01:15:33 +00002936def test_main(verbose=False):
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002937 if support.verbose:
2938 plats = {
2939 'Linux': platform.linux_distribution,
2940 'Mac': platform.mac_ver,
2941 'Windows': platform.win32_ver,
2942 }
2943 for name, func in plats.items():
2944 plat = func()
2945 if plat and plat[0]:
2946 plat = '%s %r' % (name, plat)
2947 break
2948 else:
2949 plat = repr(platform.platform())
2950 print("test_ssl: testing with %r %r" %
2951 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2952 print(" under %s" % plat)
2953 print(" HAS_SNI = %r" % ssl.HAS_SNI)
2954 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2955 try:
2956 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2957 except AttributeError:
2958 pass
Bill Janssen296a59d2007-09-16 22:06:00 +00002959
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002960 for filename in [
2961 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2962 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2963 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
2964 BADCERT, BADKEY, EMPTYCERT]:
2965 if not os.path.exists(filename):
2966 raise support.TestFailed("Can't read certificate file %r" % filename)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00002967
Benjamin Peterson2f334562014-10-01 23:53:01 -04002968 tests = [ContextTests, BasicTests, BasicSocketTests, SSLErrorTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00002969
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002970 if support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00002971 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00002972
Bill Janssen98d19da2007-09-10 21:51:02 +00002973 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002974 thread_info = support.threading_setup()
2975 if thread_info:
Bill Janssen934b16d2008-06-28 22:19:33 +00002976 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00002977
Antoine Pitrou3945c862010-04-28 21:11:01 +00002978 try:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002979 support.run_unittest(*tests)
Antoine Pitrou3945c862010-04-28 21:11:01 +00002980 finally:
2981 if _have_threads:
Benjamin Petersondaeb9252014-08-20 14:14:50 -05002982 support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00002983
2984if __name__ == "__main__":
2985 test_main()