blob: 9a48483067868726f511928a5dfa8b3bc563bc41 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Christian Heimes9424bb42013-06-17 15:32:57 +02009import datetime
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000010import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000011import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000012import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000013import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000014import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000015import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000016import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000017import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000018import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000019import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000020import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000021
Antoine Pitrou05d936d2010-10-13 11:38:36 +000022ssl = support.import_module("ssl")
23
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010024PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000025HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000026
Christian Heimesefff7062013-11-21 03:35:02 +010027def data_file(*name):
28 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000029
Antoine Pitrou81564092010-10-08 23:06:24 +000030# The custom key and certificate files used in test_ssl are generated
31# using Lib/test/make_ssl_certs.py.
32# Other certificates are simply fetched from the Internet servers they
33# are meant to authenticate.
34
Antoine Pitrou152efa22010-05-16 18:19:27 +000035CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000036BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000037ONLYCERT = data_file("ssl_cert.pem")
38ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000039BYTES_ONLYCERT = os.fsencode(ONLYCERT)
40BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020041CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
42ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
43KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000044CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000045BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010046CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
47CAFILE_CACERT = data_file("capath", "5ed36f99.0")
48
Antoine Pitrou152efa22010-05-16 18:19:27 +000049
Christian Heimes22587792013-11-21 23:56:13 +010050# empty CRL
51CRLFILE = data_file("revocation.crl")
52
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010053# Two keys and certs signed by the same CA (for SNI tests)
54SIGNED_CERTFILE = data_file("keycert3.pem")
55SIGNED_CERTFILE2 = data_file("keycert4.pem")
56SIGNING_CA = data_file("pycacert.pem")
57
Martin Panter3d81d932016-01-14 09:36:00 +000058REMOTE_HOST = "self-signed.pythontest.net"
59REMOTE_ROOT_CERT = data_file("selfsigned_pythontestdotnet.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000060
61EMPTYCERT = data_file("nullcert.pem")
62BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +000063NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000064BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020065NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020066NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000067
Benjamin Petersona7eaf562015-04-02 00:04:06 -040068DHFILE = data_file("dh1024.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +010069BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010071
Thomas Woutersed03b412007-08-28 21:37:11 +000072def handle_error(prefix):
73 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000074 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000075 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000076
Antoine Pitroub5218772010-05-21 09:56:06 +000077def can_clear_options():
78 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020079 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000080
81def no_sslv2_implies_sslv3_hello():
82 # 0.9.7h or higher
83 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
84
Christian Heimes2427b502013-11-23 11:24:32 +010085def have_verify_flags():
86 # 0.9.8 or higher
87 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
88
Antoine Pitrouc695c952014-04-28 20:57:36 +020089def utc_offset(): #NOTE: ignore issues like #1647654
90 # local time = utc time + utc offset
91 if time.daylight and time.localtime().tm_isdst > 0:
92 return -time.altzone # seconds
93 return -time.timezone
94
Christian Heimes9424bb42013-06-17 15:32:57 +020095def asn1time(cert_time):
96 # Some versions of OpenSSL ignore seconds, see #18207
97 # 0.9.8.i
98 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
99 fmt = "%b %d %H:%M:%S %Y GMT"
100 dt = datetime.datetime.strptime(cert_time, fmt)
101 dt = dt.replace(second=0)
102 cert_time = dt.strftime(fmt)
103 # %d adds leading zero but ASN1_TIME_print() uses leading space
104 if cert_time[4] == "0":
105 cert_time = cert_time[:4] + " " + cert_time[5:]
106
107 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000108
Antoine Pitrou23df4832010-08-04 17:14:06 +0000109# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
110def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +0200111 if hasattr(ssl, 'PROTOCOL_SSLv2'):
112 @functools.wraps(func)
113 def f(*args, **kwargs):
114 try:
115 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
116 except ssl.SSLError:
117 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
118 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
119 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
120 return func(*args, **kwargs)
121 return f
122 else:
123 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +0000124
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100125needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
126
Antoine Pitrou23df4832010-08-04 17:14:06 +0000127
Antoine Pitrou152efa22010-05-16 18:19:27 +0000128class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000129
Antoine Pitrou480a1242010-04-28 21:37:09 +0000130 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000131 ssl.CERT_NONE
132 ssl.CERT_OPTIONAL
133 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100134 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100135 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100136 if ssl.HAS_ECDH:
137 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100138 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
139 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000140 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100141 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000142
Antoine Pitrou172f0252014-04-18 20:33:08 +0200143 def test_str_for_enums(self):
144 # Make sure that the PROTOCOL_* constants have enum-like string
145 # reprs.
Victor Stinner648b8622014-12-12 12:23:59 +0100146 proto = ssl.PROTOCOL_SSLv23
147 self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_SSLv23')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200148 ctx = ssl.SSLContext(proto)
149 self.assertIs(ctx.protocol, proto)
150
Antoine Pitrou480a1242010-04-28 21:37:09 +0000151 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000152 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000153 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000154 sys.stdout.write("\n RAND_status is %d (%s)\n"
155 % (v, (v and "sufficient randomness") or
156 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200157
158 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
159 self.assertEqual(len(data), 16)
160 self.assertEqual(is_cryptographic, v == 1)
161 if v:
162 data = ssl.RAND_bytes(16)
163 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200164 else:
165 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200166
Victor Stinner1e81a392013-12-19 16:47:04 +0100167 # negative num is invalid
168 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
169 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
170
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100171 if hasattr(ssl, 'RAND_egd'):
172 self.assertRaises(TypeError, ssl.RAND_egd, 1)
173 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000174 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200175 ssl.RAND_add(b"this is a random bytes object", 75.0)
176 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000177
Christian Heimesf77b4b22013-08-21 13:26:05 +0200178 @unittest.skipUnless(os.name == 'posix', 'requires posix')
179 def test_random_fork(self):
180 status = ssl.RAND_status()
181 if not status:
182 self.fail("OpenSSL's PRNG has insufficient randomness")
183
184 rfd, wfd = os.pipe()
185 pid = os.fork()
186 if pid == 0:
187 try:
188 os.close(rfd)
189 child_random = ssl.RAND_pseudo_bytes(16)[0]
190 self.assertEqual(len(child_random), 16)
191 os.write(wfd, child_random)
192 os.close(wfd)
193 except BaseException:
194 os._exit(1)
195 else:
196 os._exit(0)
197 else:
198 os.close(wfd)
199 self.addCleanup(os.close, rfd)
200 _, status = os.waitpid(pid, 0)
201 self.assertEqual(status, 0)
202
203 child_random = os.read(rfd, 16)
204 self.assertEqual(len(child_random), 16)
205 parent_random = ssl.RAND_pseudo_bytes(16)[0]
206 self.assertEqual(len(parent_random), 16)
207
208 self.assertNotEqual(child_random, parent_random)
209
Antoine Pitrou480a1242010-04-28 21:37:09 +0000210 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000211 # note that this uses an 'unofficial' function in _ssl.c,
212 # provided solely for this test, to exercise the certificate
213 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000214 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000215 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000216 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200217 self.assertEqual(p['issuer'],
218 ((('countryName', 'XY'),),
219 (('localityName', 'Castle Anthrax'),),
220 (('organizationName', 'Python Software Foundation'),),
221 (('commonName', 'localhost'),))
222 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100223 # Note the next three asserts will fail if the keys are regenerated
Christian Heimes9424bb42013-06-17 15:32:57 +0200224 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
225 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200226 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
227 self.assertEqual(p['subject'],
228 ((('countryName', 'XY'),),
229 (('localityName', 'Castle Anthrax'),),
230 (('organizationName', 'Python Software Foundation'),),
231 (('commonName', 'localhost'),))
232 )
233 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
234 # Issue #13034: the subjectAltName in some certificates
235 # (notably projects.developer.nokia.com:443) wasn't parsed
236 p = ssl._ssl._test_decode_cert(NOKIACERT)
237 if support.verbose:
238 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
239 self.assertEqual(p['subjectAltName'],
240 (('DNS', 'projects.developer.nokia.com'),
241 ('DNS', 'projects.forum.nokia.com'))
242 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100243 # extra OCSP and AIA fields
244 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
245 self.assertEqual(p['caIssuers'],
246 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
247 self.assertEqual(p['crlDistributionPoints'],
248 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000249
Christian Heimes824f7f32013-08-17 00:54:47 +0200250 def test_parse_cert_CVE_2013_4238(self):
251 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
252 if support.verbose:
253 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
254 subject = ((('countryName', 'US'),),
255 (('stateOrProvinceName', 'Oregon'),),
256 (('localityName', 'Beaverton'),),
257 (('organizationName', 'Python Software Foundation'),),
258 (('organizationalUnitName', 'Python Core Development'),),
259 (('commonName', 'null.python.org\x00example.org'),),
260 (('emailAddress', 'python-dev@python.org'),))
261 self.assertEqual(p['subject'], subject)
262 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200263 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
264 san = (('DNS', 'altnull.python.org\x00example.com'),
265 ('email', 'null@python.org\x00user@example.org'),
266 ('URI', 'http://null.python.org\x00http://example.org'),
267 ('IP Address', '192.0.2.1'),
268 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
269 else:
270 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
271 san = (('DNS', 'altnull.python.org\x00example.com'),
272 ('email', 'null@python.org\x00user@example.org'),
273 ('URI', 'http://null.python.org\x00http://example.org'),
274 ('IP Address', '192.0.2.1'),
275 ('IP Address', '<invalid>'))
276
277 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200278
Antoine Pitrou480a1242010-04-28 21:37:09 +0000279 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000280 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000281 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000282 d1 = ssl.PEM_cert_to_DER_cert(pem)
283 p2 = ssl.DER_cert_to_PEM_cert(d1)
284 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000285 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000286 if not p2.startswith(ssl.PEM_HEADER + '\n'):
287 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
288 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
289 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000290
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000291 def test_openssl_version(self):
292 n = ssl.OPENSSL_VERSION_NUMBER
293 t = ssl.OPENSSL_VERSION_INFO
294 s = ssl.OPENSSL_VERSION
295 self.assertIsInstance(n, int)
296 self.assertIsInstance(t, tuple)
297 self.assertIsInstance(s, str)
298 # Some sanity checks follow
299 # >= 0.9
300 self.assertGreaterEqual(n, 0x900000)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400301 # < 3.0
302 self.assertLess(n, 0x30000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000303 major, minor, fix, patch, status = t
304 self.assertGreaterEqual(major, 0)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400305 self.assertLess(major, 3)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000306 self.assertGreaterEqual(minor, 0)
307 self.assertLess(minor, 256)
308 self.assertGreaterEqual(fix, 0)
309 self.assertLess(fix, 256)
310 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100311 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000312 self.assertGreaterEqual(status, 0)
313 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400314 # Version string as returned by {Open,Libre}SSL, the format might change
315 if "LibreSSL" in s:
316 self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
Victor Stinner789b8052015-01-06 11:51:06 +0100317 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400318 else:
319 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100320 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000321
Antoine Pitrou9d543662010-04-23 23:10:32 +0000322 @support.cpython_only
323 def test_refcycle(self):
324 # Issue #7943: an SSL object doesn't create reference cycles with
325 # itself.
326 s = socket.socket(socket.AF_INET)
327 ss = ssl.wrap_socket(s)
328 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100329 with support.check_warnings(("", ResourceWarning)):
330 del ss
331 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000332
Antoine Pitroua468adc2010-09-14 14:43:44 +0000333 def test_wrapped_unconnected(self):
334 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200335 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000336 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100337 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100338 self.assertRaises(OSError, ss.recv, 1)
339 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
340 self.assertRaises(OSError, ss.recvfrom, 1)
341 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
342 self.assertRaises(OSError, ss.send, b'x')
343 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000344
Antoine Pitrou40f08742010-04-24 22:04:40 +0000345 def test_timeout(self):
346 # Issue #8524: when creating an SSL socket, the timeout of the
347 # original socket should be retained.
348 for timeout in (None, 0.0, 5.0):
349 s = socket.socket(socket.AF_INET)
350 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100351 with ssl.wrap_socket(s) as ss:
352 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000353
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000354 def test_errors(self):
355 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000356 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000357 "certfile must be specified",
358 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000359 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000360 "certfile must be specified for server-side operations",
361 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000362 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000363 "certfile must be specified for server-side operations",
364 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100365 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
366 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
367 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200368 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000369 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000370 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000371 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200372 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000373 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000374 ssl.wrap_socket(sock,
375 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000376 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200377 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000378 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000379 ssl.wrap_socket(sock,
380 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000381 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000382
Martin Panter3464ea22016-02-01 21:58:11 +0000383 def bad_cert_test(self, certfile):
384 """Check that trying to use the given client certificate fails"""
385 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
386 certfile)
387 sock = socket.socket()
388 self.addCleanup(sock.close)
389 with self.assertRaises(ssl.SSLError):
390 ssl.wrap_socket(sock,
391 certfile=certfile,
392 ssl_version=ssl.PROTOCOL_TLSv1)
393
394 def test_empty_cert(self):
395 """Wrapping with an empty cert file"""
396 self.bad_cert_test("nullcert.pem")
397
398 def test_malformed_cert(self):
399 """Wrapping with a badly formatted certificate (syntax error)"""
400 self.bad_cert_test("badcert.pem")
401
402 def test_malformed_key(self):
403 """Wrapping with a badly formatted key (syntax error)"""
404 self.bad_cert_test("badkey.pem")
405
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000406 def test_match_hostname(self):
407 def ok(cert, hostname):
408 ssl.match_hostname(cert, hostname)
409 def fail(cert, hostname):
410 self.assertRaises(ssl.CertificateError,
411 ssl.match_hostname, cert, hostname)
412
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100413 # -- Hostname matching --
414
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000415 cert = {'subject': ((('commonName', 'example.com'),),)}
416 ok(cert, 'example.com')
417 ok(cert, 'ExAmple.cOm')
418 fail(cert, 'www.example.com')
419 fail(cert, '.example.com')
420 fail(cert, 'example.org')
421 fail(cert, 'exampleXcom')
422
423 cert = {'subject': ((('commonName', '*.a.com'),),)}
424 ok(cert, 'foo.a.com')
425 fail(cert, 'bar.foo.a.com')
426 fail(cert, 'a.com')
427 fail(cert, 'Xa.com')
428 fail(cert, '.a.com')
429
Georg Brandl72c98d32013-10-27 07:16:53 +0100430 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000431 cert = {'subject': ((('commonName', 'f*.com'),),)}
432 ok(cert, 'foo.com')
433 ok(cert, 'f.com')
434 fail(cert, 'bar.com')
435 fail(cert, 'foo.a.com')
436 fail(cert, 'bar.foo.com')
437
Christian Heimes824f7f32013-08-17 00:54:47 +0200438 # NULL bytes are bad, CVE-2013-4073
439 cert = {'subject': ((('commonName',
440 'null.python.org\x00example.org'),),)}
441 ok(cert, 'null.python.org\x00example.org') # or raise an error?
442 fail(cert, 'example.org')
443 fail(cert, 'null.python.org')
444
Georg Brandl72c98d32013-10-27 07:16:53 +0100445 # error cases with wildcards
446 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
447 fail(cert, 'bar.foo.a.com')
448 fail(cert, 'a.com')
449 fail(cert, 'Xa.com')
450 fail(cert, '.a.com')
451
452 cert = {'subject': ((('commonName', 'a.*.com'),),)}
453 fail(cert, 'a.foo.com')
454 fail(cert, 'a..com')
455 fail(cert, 'a.com')
456
457 # wildcard doesn't match IDNA prefix 'xn--'
458 idna = 'püthon.python.org'.encode("idna").decode("ascii")
459 cert = {'subject': ((('commonName', idna),),)}
460 ok(cert, idna)
461 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
462 fail(cert, idna)
463 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
464 fail(cert, idna)
465
466 # wildcard in first fragment and IDNA A-labels in sequent fragments
467 # are supported.
468 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
469 cert = {'subject': ((('commonName', idna),),)}
470 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
471 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
472 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
473 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
474
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000475 # Slightly fake real-world example
476 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
477 'subject': ((('commonName', 'linuxfrz.org'),),),
478 'subjectAltName': (('DNS', 'linuxfr.org'),
479 ('DNS', 'linuxfr.com'),
480 ('othername', '<unsupported>'))}
481 ok(cert, 'linuxfr.org')
482 ok(cert, 'linuxfr.com')
483 # Not a "DNS" entry
484 fail(cert, '<unsupported>')
485 # When there is a subjectAltName, commonName isn't used
486 fail(cert, 'linuxfrz.org')
487
488 # A pristine real-world example
489 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
490 'subject': ((('countryName', 'US'),),
491 (('stateOrProvinceName', 'California'),),
492 (('localityName', 'Mountain View'),),
493 (('organizationName', 'Google Inc'),),
494 (('commonName', 'mail.google.com'),))}
495 ok(cert, 'mail.google.com')
496 fail(cert, 'gmail.com')
497 # Only commonName is considered
498 fail(cert, 'California')
499
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100500 # -- IPv4 matching --
501 cert = {'subject': ((('commonName', 'example.com'),),),
502 'subjectAltName': (('DNS', 'example.com'),
503 ('IP Address', '10.11.12.13'),
504 ('IP Address', '14.15.16.17'))}
505 ok(cert, '10.11.12.13')
506 ok(cert, '14.15.16.17')
507 fail(cert, '14.15.16.18')
508 fail(cert, 'example.net')
509
510 # -- IPv6 matching --
511 cert = {'subject': ((('commonName', 'example.com'),),),
512 'subjectAltName': (('DNS', 'example.com'),
513 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
514 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
515 ok(cert, '2001::cafe')
516 ok(cert, '2003::baba')
517 fail(cert, '2003::bebe')
518 fail(cert, 'example.net')
519
520 # -- Miscellaneous --
521
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000522 # Neither commonName nor subjectAltName
523 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
524 'subject': ((('countryName', 'US'),),
525 (('stateOrProvinceName', 'California'),),
526 (('localityName', 'Mountain View'),),
527 (('organizationName', 'Google Inc'),))}
528 fail(cert, 'mail.google.com')
529
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200530 # No DNS entry in subjectAltName but a commonName
531 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
532 'subject': ((('countryName', 'US'),),
533 (('stateOrProvinceName', 'California'),),
534 (('localityName', 'Mountain View'),),
535 (('commonName', 'mail.google.com'),)),
536 'subjectAltName': (('othername', 'blabla'), )}
537 ok(cert, 'mail.google.com')
538
539 # No DNS entry subjectAltName and no commonName
540 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
541 'subject': ((('countryName', 'US'),),
542 (('stateOrProvinceName', 'California'),),
543 (('localityName', 'Mountain View'),),
544 (('organizationName', 'Google Inc'),)),
545 'subjectAltName': (('othername', 'blabla'),)}
546 fail(cert, 'google.com')
547
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000548 # Empty cert / no cert
549 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
550 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
551
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200552 # Issue #17980: avoid denials of service by refusing more than one
553 # wildcard per fragment.
554 cert = {'subject': ((('commonName', 'a*b.com'),),)}
555 ok(cert, 'axxb.com')
556 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100557 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200558 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
559 with self.assertRaises(ssl.CertificateError) as cm:
560 ssl.match_hostname(cert, 'axxbxxc.com')
561 self.assertIn("too many wildcards", str(cm.exception))
562
Antoine Pitroud5323212010-10-22 18:19:07 +0000563 def test_server_side(self):
564 # server_hostname doesn't work for server sockets
565 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000566 with socket.socket() as sock:
567 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
568 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000569
Antoine Pitroud6494802011-07-21 01:11:30 +0200570 def test_unknown_channel_binding(self):
571 # should raise ValueError for unknown type
572 s = socket.socket(socket.AF_INET)
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200573 s.bind(('127.0.0.1', 0))
574 s.listen()
575 c = socket.socket(socket.AF_INET)
576 c.connect(s.getsockname())
577 with ssl.wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100578 with self.assertRaises(ValueError):
579 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200580 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200581
582 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
583 "'tls-unique' channel binding not available")
584 def test_tls_unique_channel_binding(self):
585 # unconnected should return None for known type
586 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100587 with ssl.wrap_socket(s) as ss:
588 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200589 # the same for server-side
590 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100591 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
592 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200593
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600594 def test_dealloc_warn(self):
595 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
596 r = repr(ss)
597 with self.assertWarns(ResourceWarning) as cm:
598 ss = None
599 support.gc_collect()
600 self.assertIn(r, str(cm.warning.args[0]))
601
Christian Heimes6d7ad132013-06-09 18:02:55 +0200602 def test_get_default_verify_paths(self):
603 paths = ssl.get_default_verify_paths()
604 self.assertEqual(len(paths), 6)
605 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
606
607 with support.EnvironmentVarGuard() as env:
608 env["SSL_CERT_DIR"] = CAPATH
609 env["SSL_CERT_FILE"] = CERTFILE
610 paths = ssl.get_default_verify_paths()
611 self.assertEqual(paths.cafile, CERTFILE)
612 self.assertEqual(paths.capath, CAPATH)
613
Christian Heimes44109d72013-11-22 01:51:30 +0100614 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
615 def test_enum_certificates(self):
616 self.assertTrue(ssl.enum_certificates("CA"))
617 self.assertTrue(ssl.enum_certificates("ROOT"))
618
619 self.assertRaises(TypeError, ssl.enum_certificates)
620 self.assertRaises(WindowsError, ssl.enum_certificates, "")
621
Christian Heimesc2d65e12013-11-22 16:13:55 +0100622 trust_oids = set()
623 for storename in ("CA", "ROOT"):
624 store = ssl.enum_certificates(storename)
625 self.assertIsInstance(store, list)
626 for element in store:
627 self.assertIsInstance(element, tuple)
628 self.assertEqual(len(element), 3)
629 cert, enc, trust = element
630 self.assertIsInstance(cert, bytes)
631 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
632 self.assertIsInstance(trust, (set, bool))
633 if isinstance(trust, set):
634 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100635
636 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100637 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200638
Christian Heimes46bebee2013-06-09 19:03:31 +0200639 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100640 def test_enum_crls(self):
641 self.assertTrue(ssl.enum_crls("CA"))
642 self.assertRaises(TypeError, ssl.enum_crls)
643 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200644
Christian Heimes44109d72013-11-22 01:51:30 +0100645 crls = ssl.enum_crls("CA")
646 self.assertIsInstance(crls, list)
647 for element in crls:
648 self.assertIsInstance(element, tuple)
649 self.assertEqual(len(element), 2)
650 self.assertIsInstance(element[0], bytes)
651 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200652
Christian Heimes46bebee2013-06-09 19:03:31 +0200653
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100654 def test_asn1object(self):
655 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
656 '1.3.6.1.5.5.7.3.1')
657
658 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
659 self.assertEqual(val, expected)
660 self.assertEqual(val.nid, 129)
661 self.assertEqual(val.shortname, 'serverAuth')
662 self.assertEqual(val.longname, 'TLS Web Server Authentication')
663 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
664 self.assertIsInstance(val, ssl._ASN1Object)
665 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
666
667 val = ssl._ASN1Object.fromnid(129)
668 self.assertEqual(val, expected)
669 self.assertIsInstance(val, ssl._ASN1Object)
670 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100671 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
672 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100673 for i in range(1000):
674 try:
675 obj = ssl._ASN1Object.fromnid(i)
676 except ValueError:
677 pass
678 else:
679 self.assertIsInstance(obj.nid, int)
680 self.assertIsInstance(obj.shortname, str)
681 self.assertIsInstance(obj.longname, str)
682 self.assertIsInstance(obj.oid, (str, type(None)))
683
684 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
685 self.assertEqual(val, expected)
686 self.assertIsInstance(val, ssl._ASN1Object)
687 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
688 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
689 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100690 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
691 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100692
Christian Heimes72d28502013-11-23 13:56:58 +0100693 def test_purpose_enum(self):
694 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
695 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
696 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
697 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
698 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
699 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
700 '1.3.6.1.5.5.7.3.1')
701
702 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
703 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
704 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
705 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
706 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
707 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
708 '1.3.6.1.5.5.7.3.2')
709
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100710 def test_unsupported_dtls(self):
711 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
712 self.addCleanup(s.close)
713 with self.assertRaises(NotImplementedError) as cx:
714 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
715 self.assertEqual(str(cx.exception), "only stream sockets are supported")
716 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
717 with self.assertRaises(NotImplementedError) as cx:
718 ctx.wrap_socket(s)
719 self.assertEqual(str(cx.exception), "only stream sockets are supported")
720
Antoine Pitrouc695c952014-04-28 20:57:36 +0200721 def cert_time_ok(self, timestring, timestamp):
722 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
723
724 def cert_time_fail(self, timestring):
725 with self.assertRaises(ValueError):
726 ssl.cert_time_to_seconds(timestring)
727
728 @unittest.skipUnless(utc_offset(),
729 'local time needs to be different from UTC')
730 def test_cert_time_to_seconds_timezone(self):
731 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
732 # results if local timezone is not UTC
733 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
734 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
735
736 def test_cert_time_to_seconds(self):
737 timestring = "Jan 5 09:34:43 2018 GMT"
738 ts = 1515144883.0
739 self.cert_time_ok(timestring, ts)
740 # accept keyword parameter, assert its name
741 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
742 # accept both %e and %d (space or zero generated by strftime)
743 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
744 # case-insensitive
745 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
746 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
747 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
748 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
749 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
750 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
751 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
752 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
753
754 newyear_ts = 1230768000.0
755 # leap seconds
756 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
757 # same timestamp
758 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
759
760 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
761 # allow 60th second (even if it is not a leap second)
762 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
763 # allow 2nd leap second for compatibility with time.strptime()
764 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
765 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
766
767 # no special treatement for the special value:
768 # 99991231235959Z (rfc 5280)
769 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
770
771 @support.run_with_locale('LC_ALL', '')
772 def test_cert_time_to_seconds_locale(self):
773 # `cert_time_to_seconds()` should be locale independent
774
775 def local_february_name():
776 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
777
778 if local_february_name().lower() == 'feb':
779 self.skipTest("locale-specific month name needs to be "
780 "different from C locale")
781
782 # locale-independent
783 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
784 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
785
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100786
Antoine Pitrou152efa22010-05-16 18:19:27 +0000787class ContextTests(unittest.TestCase):
788
Antoine Pitrou23df4832010-08-04 17:14:06 +0000789 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000790 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100791 for protocol in PROTOCOLS:
792 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000793 self.assertRaises(TypeError, ssl.SSLContext)
794 self.assertRaises(ValueError, ssl.SSLContext, -1)
795 self.assertRaises(ValueError, ssl.SSLContext, 42)
796
Antoine Pitrou23df4832010-08-04 17:14:06 +0000797 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000798 def test_protocol(self):
799 for proto in PROTOCOLS:
800 ctx = ssl.SSLContext(proto)
801 self.assertEqual(ctx.protocol, proto)
802
803 def test_ciphers(self):
804 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
805 ctx.set_ciphers("ALL")
806 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000807 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000808 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000809
Antoine Pitrou23df4832010-08-04 17:14:06 +0000810 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000811 def test_options(self):
812 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -0800813 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000814 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
815 ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -0800816 ctx.options |= ssl.OP_NO_TLSv1
817 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1,
818 ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +0000819 if can_clear_options():
820 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
821 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
822 ctx.options)
823 ctx.options = 0
824 self.assertEqual(0, ctx.options)
825 else:
826 with self.assertRaises(ValueError):
827 ctx.options = 0
828
Christian Heimes22587792013-11-21 23:56:13 +0100829 def test_verify_mode(self):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000830 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
831 # Default value
832 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
833 ctx.verify_mode = ssl.CERT_OPTIONAL
834 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
835 ctx.verify_mode = ssl.CERT_REQUIRED
836 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
837 ctx.verify_mode = ssl.CERT_NONE
838 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
839 with self.assertRaises(TypeError):
840 ctx.verify_mode = None
841 with self.assertRaises(ValueError):
842 ctx.verify_mode = 42
843
Christian Heimes2427b502013-11-23 11:24:32 +0100844 @unittest.skipUnless(have_verify_flags(),
845 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +0100846 def test_verify_flags(self):
847 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -0500848 # default value
849 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
850 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +0100851 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
852 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
853 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
854 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
855 ctx.verify_flags = ssl.VERIFY_DEFAULT
856 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
857 # supports any value
858 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
859 self.assertEqual(ctx.verify_flags,
860 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
861 with self.assertRaises(TypeError):
862 ctx.verify_flags = None
863
Antoine Pitrou152efa22010-05-16 18:19:27 +0000864 def test_load_cert_chain(self):
865 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
866 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -0500867 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000868 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
869 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200870 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +0000871 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000872 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000873 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000874 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000875 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000876 ctx.load_cert_chain(EMPTYCERT)
877 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000878 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000879 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
880 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
881 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000882 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000883 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000884 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000885 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000886 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000887 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
888 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000889 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000890 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +0000891 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200892 # Password protected key and cert
893 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
894 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
895 ctx.load_cert_chain(CERTFILE_PROTECTED,
896 password=bytearray(KEY_PASSWORD.encode()))
897 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
898 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
899 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
900 bytearray(KEY_PASSWORD.encode()))
901 with self.assertRaisesRegex(TypeError, "should be a string"):
902 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
903 with self.assertRaises(ssl.SSLError):
904 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
905 with self.assertRaisesRegex(ValueError, "cannot be longer"):
906 # openssl has a fixed limit on the password buffer.
907 # PEM_BUFSIZE is generally set to 1kb.
908 # Return a string larger than this.
909 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
910 # Password callback
911 def getpass_unicode():
912 return KEY_PASSWORD
913 def getpass_bytes():
914 return KEY_PASSWORD.encode()
915 def getpass_bytearray():
916 return bytearray(KEY_PASSWORD.encode())
917 def getpass_badpass():
918 return "badpass"
919 def getpass_huge():
920 return b'a' * (1024 * 1024)
921 def getpass_bad_type():
922 return 9
923 def getpass_exception():
924 raise Exception('getpass error')
925 class GetPassCallable:
926 def __call__(self):
927 return KEY_PASSWORD
928 def getpass(self):
929 return KEY_PASSWORD
930 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
931 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
932 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
933 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
934 ctx.load_cert_chain(CERTFILE_PROTECTED,
935 password=GetPassCallable().getpass)
936 with self.assertRaises(ssl.SSLError):
937 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
938 with self.assertRaisesRegex(ValueError, "cannot be longer"):
939 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
940 with self.assertRaisesRegex(TypeError, "must return a string"):
941 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
942 with self.assertRaisesRegex(Exception, "getpass error"):
943 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
944 # Make sure the password function isn't called if it isn't needed
945 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000946
947 def test_load_verify_locations(self):
948 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
949 ctx.load_verify_locations(CERTFILE)
950 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
951 ctx.load_verify_locations(BYTES_CERTFILE)
952 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
953 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +0100954 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200955 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +0000956 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000957 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000958 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000959 ctx.load_verify_locations(BADCERT)
960 ctx.load_verify_locations(CERTFILE, CAPATH)
961 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
962
Victor Stinner80f75e62011-01-29 11:31:20 +0000963 # Issue #10989: crash if the second argument type is invalid
964 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
965
Christian Heimesefff7062013-11-21 03:35:02 +0100966 def test_load_verify_cadata(self):
967 # test cadata
968 with open(CAFILE_CACERT) as f:
969 cacert_pem = f.read()
970 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
971 with open(CAFILE_NEURONIO) as f:
972 neuronio_pem = f.read()
973 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
974
975 # test PEM
976 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
977 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
978 ctx.load_verify_locations(cadata=cacert_pem)
979 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
980 ctx.load_verify_locations(cadata=neuronio_pem)
981 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
982 # cert already in hash table
983 ctx.load_verify_locations(cadata=neuronio_pem)
984 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
985
986 # combined
987 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
988 combined = "\n".join((cacert_pem, neuronio_pem))
989 ctx.load_verify_locations(cadata=combined)
990 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
991
992 # with junk around the certs
993 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
994 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
995 neuronio_pem, "tail"]
996 ctx.load_verify_locations(cadata="\n".join(combined))
997 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
998
999 # test DER
1000 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1001 ctx.load_verify_locations(cadata=cacert_der)
1002 ctx.load_verify_locations(cadata=neuronio_der)
1003 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1004 # cert already in hash table
1005 ctx.load_verify_locations(cadata=cacert_der)
1006 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1007
1008 # combined
1009 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1010 combined = b"".join((cacert_der, neuronio_der))
1011 ctx.load_verify_locations(cadata=combined)
1012 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1013
1014 # error cases
1015 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1016 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1017
1018 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1019 ctx.load_verify_locations(cadata="broken")
1020 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1021 ctx.load_verify_locations(cadata=b"broken")
1022
1023
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001024 def test_load_dh_params(self):
1025 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1026 ctx.load_dh_params(DHFILE)
1027 if os.name != 'nt':
1028 ctx.load_dh_params(BYTES_DHFILE)
1029 self.assertRaises(TypeError, ctx.load_dh_params)
1030 self.assertRaises(TypeError, ctx.load_dh_params, None)
1031 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001032 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001033 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001034 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001035 ctx.load_dh_params(CERTFILE)
1036
Antoine Pitroueb585ad2010-10-22 18:24:20 +00001037 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +00001038 def test_session_stats(self):
1039 for proto in PROTOCOLS:
1040 ctx = ssl.SSLContext(proto)
1041 self.assertEqual(ctx.session_stats(), {
1042 'number': 0,
1043 'connect': 0,
1044 'connect_good': 0,
1045 'connect_renegotiate': 0,
1046 'accept': 0,
1047 'accept_good': 0,
1048 'accept_renegotiate': 0,
1049 'hits': 0,
1050 'misses': 0,
1051 'timeouts': 0,
1052 'cache_full': 0,
1053 })
1054
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001055 def test_set_default_verify_paths(self):
1056 # There's not much we can do to test that it acts as expected,
1057 # so just check it doesn't crash or raise an exception.
1058 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1059 ctx.set_default_verify_paths()
1060
Antoine Pitrou501da612011-12-21 09:27:41 +01001061 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001062 def test_set_ecdh_curve(self):
1063 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1064 ctx.set_ecdh_curve("prime256v1")
1065 ctx.set_ecdh_curve(b"prime256v1")
1066 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1067 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1068 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1069 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1070
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001071 @needs_sni
1072 def test_sni_callback(self):
1073 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1074
1075 # set_servername_callback expects a callable, or None
1076 self.assertRaises(TypeError, ctx.set_servername_callback)
1077 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1078 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1079 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1080
1081 def dummycallback(sock, servername, ctx):
1082 pass
1083 ctx.set_servername_callback(None)
1084 ctx.set_servername_callback(dummycallback)
1085
1086 @needs_sni
1087 def test_sni_callback_refcycle(self):
1088 # Reference cycles through the servername callback are detected
1089 # and cleared.
1090 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1091 def dummycallback(sock, servername, ctx, cycle=ctx):
1092 pass
1093 ctx.set_servername_callback(dummycallback)
1094 wr = weakref.ref(ctx)
1095 del ctx, dummycallback
1096 gc.collect()
1097 self.assertIs(wr(), None)
1098
Christian Heimes9a5395a2013-06-17 15:44:12 +02001099 def test_cert_store_stats(self):
1100 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1101 self.assertEqual(ctx.cert_store_stats(),
1102 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1103 ctx.load_cert_chain(CERTFILE)
1104 self.assertEqual(ctx.cert_store_stats(),
1105 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1106 ctx.load_verify_locations(CERTFILE)
1107 self.assertEqual(ctx.cert_store_stats(),
1108 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001109 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001110 self.assertEqual(ctx.cert_store_stats(),
1111 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1112
1113 def test_get_ca_certs(self):
1114 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1115 self.assertEqual(ctx.get_ca_certs(), [])
1116 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1117 ctx.load_verify_locations(CERTFILE)
1118 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001119 # but CAFILE_CACERT is a CA cert
1120 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001121 self.assertEqual(ctx.get_ca_certs(),
1122 [{'issuer': ((('organizationName', 'Root CA'),),
1123 (('organizationalUnitName', 'http://www.cacert.org'),),
1124 (('commonName', 'CA Cert Signing Authority'),),
1125 (('emailAddress', 'support@cacert.org'),)),
1126 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1127 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1128 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001129 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001130 'subject': ((('organizationName', 'Root CA'),),
1131 (('organizationalUnitName', 'http://www.cacert.org'),),
1132 (('commonName', 'CA Cert Signing Authority'),),
1133 (('emailAddress', 'support@cacert.org'),)),
1134 'version': 3}])
1135
Martin Panterb55f8b72016-01-14 12:53:56 +00001136 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001137 pem = f.read()
1138 der = ssl.PEM_cert_to_DER_cert(pem)
1139 self.assertEqual(ctx.get_ca_certs(True), [der])
1140
Christian Heimes72d28502013-11-23 13:56:58 +01001141 def test_load_default_certs(self):
1142 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1143 ctx.load_default_certs()
1144
1145 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1146 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1147 ctx.load_default_certs()
1148
1149 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1150 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1151
1152 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1153 self.assertRaises(TypeError, ctx.load_default_certs, None)
1154 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1155
Benjamin Peterson91244e02014-10-03 18:17:15 -04001156 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001157 def test_load_default_certs_env(self):
1158 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1159 with support.EnvironmentVarGuard() as env:
1160 env["SSL_CERT_DIR"] = CAPATH
1161 env["SSL_CERT_FILE"] = CERTFILE
1162 ctx.load_default_certs()
1163 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1164
Benjamin Peterson91244e02014-10-03 18:17:15 -04001165 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1166 def test_load_default_certs_env_windows(self):
1167 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1168 ctx.load_default_certs()
1169 stats = ctx.cert_store_stats()
1170
1171 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1172 with support.EnvironmentVarGuard() as env:
1173 env["SSL_CERT_DIR"] = CAPATH
1174 env["SSL_CERT_FILE"] = CERTFILE
1175 ctx.load_default_certs()
1176 stats["x509"] += 1
1177 self.assertEqual(ctx.cert_store_stats(), stats)
1178
Christian Heimes4c05b472013-11-23 15:58:30 +01001179 def test_create_default_context(self):
1180 ctx = ssl.create_default_context()
Donald Stufft6a2ba942014-03-23 19:05:28 -04001181 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001182 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001183 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001184 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001185 self.assertEqual(
1186 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1187 getattr(ssl, "OP_NO_COMPRESSION", 0),
1188 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001189
1190 with open(SIGNING_CA) as f:
1191 cadata = f.read()
1192 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1193 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001194 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001195 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1196 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001197 self.assertEqual(
1198 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1199 getattr(ssl, "OP_NO_COMPRESSION", 0),
1200 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001201
1202 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001203 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001204 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1205 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001206 self.assertEqual(
1207 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1208 getattr(ssl, "OP_NO_COMPRESSION", 0),
1209 )
1210 self.assertEqual(
1211 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1212 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1213 )
1214 self.assertEqual(
1215 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1216 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1217 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001218
Christian Heimes67986f92013-11-23 22:43:47 +01001219 def test__create_stdlib_context(self):
1220 ctx = ssl._create_stdlib_context()
1221 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1222 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001223 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001224 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1225
1226 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1227 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1228 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1229 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1230
1231 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001232 cert_reqs=ssl.CERT_REQUIRED,
1233 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001234 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1235 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001236 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001237 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1238
1239 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1240 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1241 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1242 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001243
Christian Heimes1aa9a752013-12-02 02:41:19 +01001244 def test_check_hostname(self):
1245 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1246 self.assertFalse(ctx.check_hostname)
1247
1248 # Requires CERT_REQUIRED or CERT_OPTIONAL
1249 with self.assertRaises(ValueError):
1250 ctx.check_hostname = True
1251 ctx.verify_mode = ssl.CERT_REQUIRED
1252 self.assertFalse(ctx.check_hostname)
1253 ctx.check_hostname = True
1254 self.assertTrue(ctx.check_hostname)
1255
1256 ctx.verify_mode = ssl.CERT_OPTIONAL
1257 ctx.check_hostname = True
1258 self.assertTrue(ctx.check_hostname)
1259
1260 # Cannot set CERT_NONE with check_hostname enabled
1261 with self.assertRaises(ValueError):
1262 ctx.verify_mode = ssl.CERT_NONE
1263 ctx.check_hostname = False
1264 self.assertFalse(ctx.check_hostname)
1265
Antoine Pitrou152efa22010-05-16 18:19:27 +00001266
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001267class SSLErrorTests(unittest.TestCase):
1268
1269 def test_str(self):
1270 # The str() of a SSLError doesn't include the errno
1271 e = ssl.SSLError(1, "foo")
1272 self.assertEqual(str(e), "foo")
1273 self.assertEqual(e.errno, 1)
1274 # Same for a subclass
1275 e = ssl.SSLZeroReturnError(1, "foo")
1276 self.assertEqual(str(e), "foo")
1277 self.assertEqual(e.errno, 1)
1278
1279 def test_lib_reason(self):
1280 # Test the library and reason attributes
1281 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1282 with self.assertRaises(ssl.SSLError) as cm:
1283 ctx.load_dh_params(CERTFILE)
1284 self.assertEqual(cm.exception.library, 'PEM')
1285 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1286 s = str(cm.exception)
1287 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1288
1289 def test_subclass(self):
1290 # Check that the appropriate SSLError subclass is raised
1291 # (this only tests one of them)
1292 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1293 with socket.socket() as s:
1294 s.bind(("127.0.0.1", 0))
Charles-François Natali6e204602014-07-23 19:28:13 +01001295 s.listen()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001296 c = socket.socket()
1297 c.connect(s.getsockname())
1298 c.setblocking(False)
1299 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001300 with self.assertRaises(ssl.SSLWantReadError) as cm:
1301 c.do_handshake()
1302 s = str(cm.exception)
1303 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1304 # For compatibility
1305 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1306
1307
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001308class MemoryBIOTests(unittest.TestCase):
1309
1310 def test_read_write(self):
1311 bio = ssl.MemoryBIO()
1312 bio.write(b'foo')
1313 self.assertEqual(bio.read(), b'foo')
1314 self.assertEqual(bio.read(), b'')
1315 bio.write(b'foo')
1316 bio.write(b'bar')
1317 self.assertEqual(bio.read(), b'foobar')
1318 self.assertEqual(bio.read(), b'')
1319 bio.write(b'baz')
1320 self.assertEqual(bio.read(2), b'ba')
1321 self.assertEqual(bio.read(1), b'z')
1322 self.assertEqual(bio.read(1), b'')
1323
1324 def test_eof(self):
1325 bio = ssl.MemoryBIO()
1326 self.assertFalse(bio.eof)
1327 self.assertEqual(bio.read(), b'')
1328 self.assertFalse(bio.eof)
1329 bio.write(b'foo')
1330 self.assertFalse(bio.eof)
1331 bio.write_eof()
1332 self.assertFalse(bio.eof)
1333 self.assertEqual(bio.read(2), b'fo')
1334 self.assertFalse(bio.eof)
1335 self.assertEqual(bio.read(1), b'o')
1336 self.assertTrue(bio.eof)
1337 self.assertEqual(bio.read(), b'')
1338 self.assertTrue(bio.eof)
1339
1340 def test_pending(self):
1341 bio = ssl.MemoryBIO()
1342 self.assertEqual(bio.pending, 0)
1343 bio.write(b'foo')
1344 self.assertEqual(bio.pending, 3)
1345 for i in range(3):
1346 bio.read(1)
1347 self.assertEqual(bio.pending, 3-i-1)
1348 for i in range(3):
1349 bio.write(b'x')
1350 self.assertEqual(bio.pending, i+1)
1351 bio.read()
1352 self.assertEqual(bio.pending, 0)
1353
1354 def test_buffer_types(self):
1355 bio = ssl.MemoryBIO()
1356 bio.write(b'foo')
1357 self.assertEqual(bio.read(), b'foo')
1358 bio.write(bytearray(b'bar'))
1359 self.assertEqual(bio.read(), b'bar')
1360 bio.write(memoryview(b'baz'))
1361 self.assertEqual(bio.read(), b'baz')
1362
1363 def test_error_types(self):
1364 bio = ssl.MemoryBIO()
1365 self.assertRaises(TypeError, bio.write, 'foo')
1366 self.assertRaises(TypeError, bio.write, None)
1367 self.assertRaises(TypeError, bio.write, True)
1368 self.assertRaises(TypeError, bio.write, 1)
1369
1370
Bill Janssen6e027db2007-11-15 22:23:56 +00001371class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001372
Antoine Pitrou480a1242010-04-28 21:37:09 +00001373 def test_connect(self):
Martin Panter3d81d932016-01-14 09:36:00 +00001374 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001375 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1376 cert_reqs=ssl.CERT_NONE)
1377 try:
Martin Panter3d81d932016-01-14 09:36:00 +00001378 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001379 self.assertEqual({}, s.getpeercert())
1380 finally:
1381 s.close()
1382
1383 # this should fail because we have no verification certs
1384 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1385 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001386 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Martin Panter3d81d932016-01-14 09:36:00 +00001387 s.connect, (REMOTE_HOST, 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001388 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001389
Antoine Pitrou350c7222010-09-09 13:31:46 +00001390 # this should succeed because we specify the root cert
1391 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1392 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +00001393 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001394 try:
Martin Panter3d81d932016-01-14 09:36:00 +00001395 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001396 self.assertTrue(s.getpeercert())
1397 finally:
1398 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001399
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001400 def test_connect_ex(self):
1401 # Issue #11326: check connect_ex() implementation
Martin Panter3d81d932016-01-14 09:36:00 +00001402 with support.transient_internet(REMOTE_HOST):
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001403 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1404 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +00001405 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001406 try:
Martin Panter3d81d932016-01-14 09:36:00 +00001407 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001408 self.assertTrue(s.getpeercert())
1409 finally:
1410 s.close()
1411
1412 def test_non_blocking_connect_ex(self):
1413 # Issue #11326: non-blocking connect_ex() should allow handshake
1414 # to proceed after the socket gets ready.
Martin Panter3d81d932016-01-14 09:36:00 +00001415 with support.transient_internet(REMOTE_HOST):
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001416 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1417 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +00001418 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001419 do_handshake_on_connect=False)
1420 try:
1421 s.setblocking(False)
Martin Panter3d81d932016-01-14 09:36:00 +00001422 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +00001423 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1424 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001425 # Wait for connect to finish
1426 select.select([], [s], [], 5.0)
1427 # Non-blocking handshake
1428 while True:
1429 try:
1430 s.do_handshake()
1431 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001432 except ssl.SSLWantReadError:
1433 select.select([s], [], [], 5.0)
1434 except ssl.SSLWantWriteError:
1435 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001436 # SSL established
1437 self.assertTrue(s.getpeercert())
1438 finally:
1439 s.close()
1440
Antoine Pitroub4410db2011-05-18 18:51:06 +02001441 def test_timeout_connect_ex(self):
1442 # Issue #12065: on a timeout, connect_ex() should return the original
1443 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter3d81d932016-01-14 09:36:00 +00001444 with support.transient_internet(REMOTE_HOST):
Antoine Pitroub4410db2011-05-18 18:51:06 +02001445 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1446 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +00001447 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroub4410db2011-05-18 18:51:06 +02001448 do_handshake_on_connect=False)
1449 try:
1450 s.settimeout(0.0000001)
Martin Panter3d81d932016-01-14 09:36:00 +00001451 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitroub4410db2011-05-18 18:51:06 +02001452 if rc == 0:
Martin Panter3d81d932016-01-14 09:36:00 +00001453 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitroub4410db2011-05-18 18:51:06 +02001454 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1455 finally:
1456 s.close()
1457
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001458 def test_connect_ex_error(self):
Martin Panter3d81d932016-01-14 09:36:00 +00001459 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001460 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1461 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +00001462 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001463 try:
Martin Panter3d81d932016-01-14 09:36:00 +00001464 rc = s.connect_ex((REMOTE_HOST, 444))
Christian Heimesde570742013-12-16 21:15:44 +01001465 # Issue #19919: Windows machines or VMs hosted on Windows
1466 # machines sometimes return EWOULDBLOCK.
Martin Panter73f55072016-01-14 12:21:02 +00001467 errors = (
Martin Panterfab75d92016-01-15 02:08:13 +00001468 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
Martin Panter73f55072016-01-14 12:21:02 +00001469 errno.EWOULDBLOCK,
1470 )
1471 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001472 finally:
1473 s.close()
1474
Antoine Pitrou152efa22010-05-16 18:19:27 +00001475 def test_connect_with_context(self):
Martin Panter3d81d932016-01-14 09:36:00 +00001476 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001477 # Same as test_connect, but with a separately created context
1478 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1479 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +00001480 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001481 try:
1482 self.assertEqual({}, s.getpeercert())
1483 finally:
1484 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +00001485 # Same with a server hostname
1486 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3d81d932016-01-14 09:36:00 +00001487 server_hostname=REMOTE_HOST)
Martin Panter514bb072016-01-14 12:46:49 +00001488 s.connect((REMOTE_HOST, 443))
Benjamin Peterson7243b572014-11-23 17:04:34 -06001489 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001490 # This should fail because we have no verification certs
1491 ctx.verify_mode = ssl.CERT_REQUIRED
1492 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +00001493 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Martin Panter3d81d932016-01-14 09:36:00 +00001494 s.connect, (REMOTE_HOST, 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001495 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001496 # This should succeed because we specify the root cert
Martin Panter3d81d932016-01-14 09:36:00 +00001497 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001498 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +00001499 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001500 try:
1501 cert = s.getpeercert()
1502 self.assertTrue(cert)
1503 finally:
1504 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001505
1506 def test_connect_capath(self):
1507 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001508 # NOTE: the subject hashing algorithm has been changed between
1509 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1510 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001511 # filename) for this test to be portable across OpenSSL releases.
Martin Panter3d81d932016-01-14 09:36:00 +00001512 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001513 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1514 ctx.verify_mode = ssl.CERT_REQUIRED
1515 ctx.load_verify_locations(capath=CAPATH)
1516 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +00001517 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001518 try:
1519 cert = s.getpeercert()
1520 self.assertTrue(cert)
1521 finally:
1522 s.close()
1523 # Same with a bytes `capath` argument
1524 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1525 ctx.verify_mode = ssl.CERT_REQUIRED
1526 ctx.load_verify_locations(capath=BYTES_CAPATH)
1527 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +00001528 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001529 try:
1530 cert = s.getpeercert()
1531 self.assertTrue(cert)
1532 finally:
1533 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001534
Christian Heimesefff7062013-11-21 03:35:02 +01001535 def test_connect_cadata(self):
Martin Panterb55f8b72016-01-14 12:53:56 +00001536 with open(REMOTE_ROOT_CERT) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01001537 pem = f.read()
1538 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panterb55f8b72016-01-14 12:53:56 +00001539 with support.transient_internet(REMOTE_HOST):
Christian Heimesefff7062013-11-21 03:35:02 +01001540 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1541 ctx.verify_mode = ssl.CERT_REQUIRED
1542 ctx.load_verify_locations(cadata=pem)
1543 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
Martin Panterb55f8b72016-01-14 12:53:56 +00001544 s.connect((REMOTE_HOST, 443))
Christian Heimesefff7062013-11-21 03:35:02 +01001545 cert = s.getpeercert()
1546 self.assertTrue(cert)
1547
1548 # same with DER
1549 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1550 ctx.verify_mode = ssl.CERT_REQUIRED
1551 ctx.load_verify_locations(cadata=der)
1552 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
Martin Panterb55f8b72016-01-14 12:53:56 +00001553 s.connect((REMOTE_HOST, 443))
Christian Heimesefff7062013-11-21 03:35:02 +01001554 cert = s.getpeercert()
1555 self.assertTrue(cert)
1556
Antoine Pitroue3220242010-04-24 11:13:53 +00001557 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1558 def test_makefile_close(self):
1559 # Issue #5238: creating a file-like object with makefile() shouldn't
1560 # delay closing the underlying "real socket" (here tested with its
1561 # file descriptor, hence skipping the test under Windows).
Martin Panter3d81d932016-01-14 09:36:00 +00001562 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001563 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +00001564 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001565 fd = ss.fileno()
1566 f = ss.makefile()
1567 f.close()
1568 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001569 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001570 # Closing the SSL socket should close the fd too
1571 ss.close()
1572 gc.collect()
1573 with self.assertRaises(OSError) as e:
1574 os.read(fd, 0)
1575 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001576
Antoine Pitrou480a1242010-04-28 21:37:09 +00001577 def test_non_blocking_handshake(self):
Martin Panter3d81d932016-01-14 09:36:00 +00001578 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001579 s = socket.socket(socket.AF_INET)
Martin Panter3d81d932016-01-14 09:36:00 +00001580 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001581 s.setblocking(False)
1582 s = ssl.wrap_socket(s,
1583 cert_reqs=ssl.CERT_NONE,
1584 do_handshake_on_connect=False)
1585 count = 0
1586 while True:
1587 try:
1588 count += 1
1589 s.do_handshake()
1590 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001591 except ssl.SSLWantReadError:
1592 select.select([s], [], [])
1593 except ssl.SSLWantWriteError:
1594 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001595 s.close()
1596 if support.verbose:
1597 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001598
Antoine Pitrou480a1242010-04-28 21:37:09 +00001599 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001600 def _test_get_server_certificate(host, port, cert=None):
1601 with support.transient_internet(host):
Antoine Pitrou94a5b662014-04-16 18:56:28 +02001602 pem = ssl.get_server_certificate((host, port))
Antoine Pitrou15399c32011-04-28 19:23:55 +02001603 if not pem:
1604 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001605
Antoine Pitrou15399c32011-04-28 19:23:55 +02001606 try:
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001607 pem = ssl.get_server_certificate((host, port),
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001608 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001609 except ssl.SSLError as x:
1610 #should fail
1611 if support.verbose:
1612 sys.stdout.write("%s\n" % x)
1613 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001614 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1615
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001616 pem = ssl.get_server_certificate((host, port),
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001617 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001618 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001619 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001620 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001621 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001622
Martin Panter73f55072016-01-14 12:21:02 +00001623 _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001624 if support.IPV6_ENABLED:
1625 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001626
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001627 def test_ciphers(self):
Martin Panter3d81d932016-01-14 09:36:00 +00001628 remote = (REMOTE_HOST, 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001629 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001630 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1631 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1632 s.connect(remote)
1633 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1634 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1635 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001636 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001637 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001638 with socket.socket(socket.AF_INET) as sock:
1639 s = ssl.wrap_socket(sock,
1640 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1641 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001642
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001643 def test_algorithms(self):
1644 # Issue #8484: all algorithms should be available when verifying a
1645 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001646 # SHA256 was added in OpenSSL 0.9.8
1647 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1648 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001649 # sha256.tbs-internet.com needs SNI to use the correct certificate
1650 if not ssl.HAS_SNI:
1651 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001652 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1653 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001654 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001655 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001656 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1657 ctx.verify_mode = ssl.CERT_REQUIRED
1658 ctx.load_verify_locations(sha256_cert)
1659 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1660 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001661 try:
1662 s.connect(remote)
1663 if support.verbose:
1664 sys.stdout.write("\nCipher with %r is %r\n" %
1665 (remote, s.cipher()))
1666 sys.stdout.write("Certificate is:\n%s\n" %
1667 pprint.pformat(s.getpeercert()))
1668 finally:
1669 s.close()
1670
Christian Heimes9a5395a2013-06-17 15:44:12 +02001671 def test_get_ca_certs_capath(self):
1672 # capath certs are loaded on request
Martin Panterb55f8b72016-01-14 12:53:56 +00001673 with support.transient_internet(REMOTE_HOST):
Christian Heimes9a5395a2013-06-17 15:44:12 +02001674 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1675 ctx.verify_mode = ssl.CERT_REQUIRED
1676 ctx.load_verify_locations(capath=CAPATH)
1677 self.assertEqual(ctx.get_ca_certs(), [])
1678 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panterb55f8b72016-01-14 12:53:56 +00001679 s.connect((REMOTE_HOST, 443))
Christian Heimes9a5395a2013-06-17 15:44:12 +02001680 try:
1681 cert = s.getpeercert()
1682 self.assertTrue(cert)
1683 finally:
1684 s.close()
1685 self.assertEqual(len(ctx.get_ca_certs()), 1)
1686
Christian Heimes575596e2013-12-15 21:49:17 +01001687 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001688 def test_context_setget(self):
1689 # Check that the context of a connected socket can be replaced.
Martin Panterb55f8b72016-01-14 12:53:56 +00001690 with support.transient_internet(REMOTE_HOST):
Christian Heimes8e7f3942013-12-05 07:41:08 +01001691 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1692 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1693 s = socket.socket(socket.AF_INET)
1694 with ctx1.wrap_socket(s) as ss:
Martin Panterb55f8b72016-01-14 12:53:56 +00001695 ss.connect((REMOTE_HOST, 443))
Christian Heimes8e7f3942013-12-05 07:41:08 +01001696 self.assertIs(ss.context, ctx1)
1697 self.assertIs(ss._sslobj.context, ctx1)
1698 ss.context = ctx2
1699 self.assertIs(ss.context, ctx2)
1700 self.assertIs(ss._sslobj.context, ctx2)
1701
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001702
1703class NetworkedBIOTests(unittest.TestCase):
1704
1705 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
1706 # A simple IO loop. Call func(*args) depending on the error we get
1707 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
1708 timeout = kwargs.get('timeout', 10)
1709 count = 0
1710 while True:
1711 errno = None
1712 count += 1
1713 try:
1714 ret = func(*args)
1715 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001716 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00001717 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001718 raise
1719 errno = e.errno
1720 # Get any data from the outgoing BIO irrespective of any error, and
1721 # send it to the socket.
1722 buf = outgoing.read()
1723 sock.sendall(buf)
1724 # If there's no error, we're done. For WANT_READ, we need to get
1725 # data from the socket and put it in the incoming BIO.
1726 if errno is None:
1727 break
1728 elif errno == ssl.SSL_ERROR_WANT_READ:
1729 buf = sock.recv(32768)
1730 if buf:
1731 incoming.write(buf)
1732 else:
1733 incoming.write_eof()
1734 if support.verbose:
1735 sys.stdout.write("Needed %d calls to complete %s().\n"
1736 % (count, func.__name__))
1737 return ret
1738
1739 def test_handshake(self):
Martin Panter40b97ec2016-01-14 13:05:46 +00001740 with support.transient_internet(REMOTE_HOST):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001741 sock = socket.socket(socket.AF_INET)
Martin Panter40b97ec2016-01-14 13:05:46 +00001742 sock.connect((REMOTE_HOST, 443))
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001743 incoming = ssl.MemoryBIO()
1744 outgoing = ssl.MemoryBIO()
1745 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1746 ctx.verify_mode = ssl.CERT_REQUIRED
Martin Panter40b97ec2016-01-14 13:05:46 +00001747 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Benjamin Petersonf9284ae2014-11-23 17:06:39 -06001748 ctx.check_hostname = True
Martin Panter40b97ec2016-01-14 13:05:46 +00001749 sslobj = ctx.wrap_bio(incoming, outgoing, False, REMOTE_HOST)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001750 self.assertIs(sslobj._sslobj.owner, sslobj)
1751 self.assertIsNone(sslobj.cipher())
Benjamin Peterson4cb17812015-01-07 11:14:26 -06001752 self.assertIsNone(sslobj.shared_ciphers())
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001753 self.assertRaises(ValueError, sslobj.getpeercert)
1754 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
1755 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
1756 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
1757 self.assertTrue(sslobj.cipher())
Benjamin Peterson4cb17812015-01-07 11:14:26 -06001758 self.assertIsNone(sslobj.shared_ciphers())
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001759 self.assertTrue(sslobj.getpeercert())
1760 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
1761 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
Martin Panter40b97ec2016-01-14 13:05:46 +00001762 try:
1763 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
1764 except ssl.SSLSyscallError:
1765 # self-signed.pythontest.net probably shuts down the TCP
1766 # connection without sending a secure shutdown message, and
1767 # this is reported as SSL_ERROR_SYSCALL
1768 pass
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001769 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
1770 sock.close()
1771
1772 def test_read_write_data(self):
Martin Panter40b97ec2016-01-14 13:05:46 +00001773 with support.transient_internet(REMOTE_HOST):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001774 sock = socket.socket(socket.AF_INET)
Martin Panter40b97ec2016-01-14 13:05:46 +00001775 sock.connect((REMOTE_HOST, 443))
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001776 incoming = ssl.MemoryBIO()
1777 outgoing = ssl.MemoryBIO()
1778 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1779 ctx.verify_mode = ssl.CERT_NONE
1780 sslobj = ctx.wrap_bio(incoming, outgoing, False)
1781 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
1782 req = b'GET / HTTP/1.0\r\n\r\n'
1783 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
1784 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
1785 self.assertEqual(buf[:5], b'HTTP/')
1786 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
1787 sock.close()
1788
1789
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001790try:
1791 import threading
1792except ImportError:
1793 _have_threads = False
1794else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001795 _have_threads = True
1796
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001797 from test.ssl_servers import make_https_server
1798
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001799 class ThreadedEchoServer(threading.Thread):
1800
1801 class ConnectionHandler(threading.Thread):
1802
1803 """A mildly complicated class, because we want it to work both
1804 with and without the SSL wrapper around the socket connection, so
1805 that we can test the STARTTLS functionality."""
1806
Bill Janssen6e027db2007-11-15 22:23:56 +00001807 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001808 self.server = server
1809 self.running = False
1810 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001811 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001812 self.sock.setblocking(1)
1813 self.sslconn = None
1814 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001815 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001816
Antoine Pitrou480a1242010-04-28 21:37:09 +00001817 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001818 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001819 self.sslconn = self.server.context.wrap_socket(
1820 self.sock, server_side=True)
Benjamin Petersoncca27322015-01-23 16:35:37 -05001821 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1822 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001823 except (ssl.SSLError, ConnectionResetError) as e:
1824 # We treat ConnectionResetError as though it were an
1825 # SSLError - OpenSSL on Ubuntu abruptly closes the
1826 # connection when asked to use an unsupported protocol.
1827 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001828 # XXX Various errors can have happened here, for example
1829 # a mismatching protocol version, an invalid certificate,
1830 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001831 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001832 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001833 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001834 self.running = False
1835 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001836 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001837 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001838 else:
Benjamin Peterson4cb17812015-01-07 11:14:26 -06001839 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
Antoine Pitroub5218772010-05-21 09:56:06 +00001840 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001841 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001842 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001843 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1844 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001845 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001846 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1847 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001848 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001849 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001850 sys.stdout.write(" server: selected protocol is now "
1851 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001852 return True
1853
1854 def read(self):
1855 if self.sslconn:
1856 return self.sslconn.read()
1857 else:
1858 return self.sock.recv(1024)
1859
1860 def write(self, bytes):
1861 if self.sslconn:
1862 return self.sslconn.write(bytes)
1863 else:
1864 return self.sock.send(bytes)
1865
1866 def close(self):
1867 if self.sslconn:
1868 self.sslconn.close()
1869 else:
1870 self.sock.close()
1871
Antoine Pitrou480a1242010-04-28 21:37:09 +00001872 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001873 self.running = True
1874 if not self.server.starttls_server:
1875 if not self.wrap_conn():
1876 return
1877 while self.running:
1878 try:
1879 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001880 stripped = msg.strip()
1881 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001882 # eof, so quit this handler
1883 self.running = False
1884 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001885 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001886 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001887 sys.stdout.write(" server: client closed connection\n")
1888 self.close()
1889 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001890 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001891 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001892 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001893 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001894 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001895 if not self.wrap_conn():
1896 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001897 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001898 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001899 if support.verbose and self.server.connectionchatty:
1900 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001901 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001902 self.sock = self.sslconn.unwrap()
1903 self.sslconn = None
1904 if support.verbose and self.server.connectionchatty:
1905 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001906 elif stripped == b'CB tls-unique':
1907 if support.verbose and self.server.connectionchatty:
1908 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1909 data = self.sslconn.get_channel_binding("tls-unique")
1910 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001911 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001912 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001913 self.server.connectionchatty):
1914 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001915 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1916 % (msg, ctype, msg.lower(), ctype))
1917 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001918 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001919 if self.server.chatty:
1920 handle_error("Test server failure:\n")
1921 self.close()
1922 self.running = False
1923 # normally, we'd just stop here, but for the test
1924 # harness, we want to stop the server
1925 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001926
Antoine Pitroub5218772010-05-21 09:56:06 +00001927 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001928 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001929 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersoncca27322015-01-23 16:35:37 -05001930 npn_protocols=None, alpn_protocols=None,
1931 ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001932 if context:
1933 self.context = context
1934 else:
1935 self.context = ssl.SSLContext(ssl_version
1936 if ssl_version is not None
1937 else ssl.PROTOCOL_TLSv1)
1938 self.context.verify_mode = (certreqs if certreqs is not None
1939 else ssl.CERT_NONE)
1940 if cacerts:
1941 self.context.load_verify_locations(cacerts)
1942 if certificate:
1943 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001944 if npn_protocols:
1945 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersoncca27322015-01-23 16:35:37 -05001946 if alpn_protocols:
1947 self.context.set_alpn_protocols(alpn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001948 if ciphers:
1949 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001950 self.chatty = chatty
1951 self.connectionchatty = connectionchatty
1952 self.starttls_server = starttls_server
1953 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001954 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001955 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001956 self.active = False
Benjamin Petersoncca27322015-01-23 16:35:37 -05001957 self.selected_npn_protocols = []
1958 self.selected_alpn_protocols = []
Benjamin Peterson4cb17812015-01-07 11:14:26 -06001959 self.shared_ciphers = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001960 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001961 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001962 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001963
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001964 def __enter__(self):
1965 self.start(threading.Event())
1966 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001967 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001968
1969 def __exit__(self, *args):
1970 self.stop()
1971 self.join()
1972
Antoine Pitrou480a1242010-04-28 21:37:09 +00001973 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001974 self.flag = flag
1975 threading.Thread.start(self)
1976
Antoine Pitrou480a1242010-04-28 21:37:09 +00001977 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001978 self.sock.settimeout(0.05)
Charles-François Natali6e204602014-07-23 19:28:13 +01001979 self.sock.listen()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001980 self.active = True
1981 if self.flag:
1982 # signal an event
1983 self.flag.set()
1984 while self.active:
1985 try:
1986 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001987 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001988 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001989 + repr(connaddr) + '\n')
1990 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001991 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001992 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001993 except socket.timeout:
1994 pass
1995 except KeyboardInterrupt:
1996 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001997 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001998
Antoine Pitrou480a1242010-04-28 21:37:09 +00001999 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002000 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002001
Bill Janssen54cc54c2007-12-14 22:08:56 +00002002 class AsyncoreEchoServer(threading.Thread):
2003
2004 # this one's based on asyncore.dispatcher
2005
2006 class EchoServer (asyncore.dispatcher):
2007
2008 class ConnectionHandler (asyncore.dispatcher_with_send):
2009
2010 def __init__(self, conn, certfile):
2011 self.socket = ssl.wrap_socket(conn, server_side=True,
2012 certfile=certfile,
2013 do_handshake_on_connect=False)
2014 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002015 self._ssl_accepting = True
2016 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002017
2018 def readable(self):
2019 if isinstance(self.socket, ssl.SSLSocket):
2020 while self.socket.pending() > 0:
2021 self.handle_read_event()
2022 return True
2023
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002024 def _do_ssl_handshake(self):
2025 try:
2026 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02002027 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2028 return
2029 except ssl.SSLEOFError:
2030 return self.handle_close()
2031 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002032 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02002033 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002034 if err.args[0] == errno.ECONNABORTED:
2035 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002036 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002037 self._ssl_accepting = False
2038
2039 def handle_read(self):
2040 if self._ssl_accepting:
2041 self._do_ssl_handshake()
2042 else:
2043 data = self.recv(1024)
2044 if support.verbose:
2045 sys.stdout.write(" server: read %s from client\n" % repr(data))
2046 if not data:
2047 self.close()
2048 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002049 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002050
2051 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00002052 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002053 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002054 sys.stdout.write(" server: closed connection %s\n" % self.socket)
2055
2056 def handle_error(self):
2057 raise
2058
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002059 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002060 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002061 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2062 self.port = support.bind_port(sock, '')
2063 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002064 self.listen(5)
2065
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00002066 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002067 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002068 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2069 self.ConnectionHandler(sock_obj, self.certfile)
2070
2071 def handle_error(self):
2072 raise
2073
Trent Nelson78520002008-04-10 20:54:35 +00002074 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002075 self.flag = None
2076 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002077 self.server = self.EchoServer(certfile)
2078 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00002079 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002080 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002081
2082 def __str__(self):
2083 return "<%s %s>" % (self.__class__.__name__, self.server)
2084
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002085 def __enter__(self):
2086 self.start(threading.Event())
2087 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002088 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002089
2090 def __exit__(self, *args):
2091 if support.verbose:
2092 sys.stdout.write(" cleanup: stopping server.\n")
2093 self.stop()
2094 if support.verbose:
2095 sys.stdout.write(" cleanup: joining server thread.\n")
2096 self.join()
2097 if support.verbose:
2098 sys.stdout.write(" cleanup: successfully joined.\n")
2099
Bill Janssen54cc54c2007-12-14 22:08:56 +00002100 def start (self, flag=None):
2101 self.flag = flag
2102 threading.Thread.start(self)
2103
Antoine Pitrou480a1242010-04-28 21:37:09 +00002104 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002105 self.active = True
2106 if self.flag:
2107 self.flag.set()
2108 while self.active:
2109 try:
2110 asyncore.loop(1)
2111 except:
2112 pass
2113
Antoine Pitrou480a1242010-04-28 21:37:09 +00002114 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002115 self.active = False
2116 self.server.close()
2117
Antoine Pitroub5218772010-05-21 09:56:06 +00002118 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002119 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00002120 """
2121 Launch a server, connect a client to it and try various reads
2122 and writes.
2123 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002124 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00002125 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002126 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00002127 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002128 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002129 with client_context.wrap_socket(socket.socket(),
2130 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01002131 s.connect((HOST, server.port))
2132 for arg in [indata, bytearray(indata), memoryview(indata)]:
2133 if connectionchatty:
2134 if support.verbose:
2135 sys.stdout.write(
2136 " client: sending %r...\n" % indata)
2137 s.write(arg)
2138 outdata = s.read()
2139 if connectionchatty:
2140 if support.verbose:
2141 sys.stdout.write(" client: read %r\n" % outdata)
2142 if outdata != indata.lower():
2143 raise AssertionError(
2144 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2145 % (outdata[:20], len(outdata),
2146 indata[:20].lower(), len(indata)))
2147 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00002148 if connectionchatty:
2149 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01002150 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002151 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01002152 'compression': s.compression(),
2153 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002154 'peercert': s.getpeercert(),
Benjamin Petersoncca27322015-01-23 16:35:37 -05002155 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitrou47e40422014-09-04 21:00:10 +02002156 'client_npn_protocol': s.selected_npn_protocol(),
2157 'version': s.version(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002158 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01002159 s.close()
Benjamin Petersoncca27322015-01-23 16:35:37 -05002160 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2161 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Peterson4cb17812015-01-07 11:14:26 -06002162 stats['server_shared_ciphers'] = server.shared_ciphers
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002163 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00002164
Antoine Pitroub5218772010-05-21 09:56:06 +00002165 def try_protocol_combo(server_protocol, client_protocol, expect_success,
2166 certsreqs=None, server_options=0, client_options=0):
Antoine Pitrou47e40422014-09-04 21:00:10 +02002167 """
2168 Try to SSL-connect using *client_protocol* to *server_protocol*.
2169 If *expect_success* is true, assert that the connection succeeds,
2170 if it's false, assert that the connection fails.
2171 Also, if *expect_success* is a string, assert that it is the protocol
2172 version actually used by the connection.
2173 """
Benjamin Peterson2a691a82008-03-31 01:51:45 +00002174 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002175 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00002176 certtype = {
2177 ssl.CERT_NONE: "CERT_NONE",
2178 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2179 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2180 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002181 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002182 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002183 sys.stdout.write(formatstr %
2184 (ssl.get_protocol_name(client_protocol),
2185 ssl.get_protocol_name(server_protocol),
2186 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00002187 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01002188 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00002189 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01002190 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002191
2192 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2193 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2194 # starting from OpenSSL 1.0.0 (see issue #8322).
2195 if client_context.protocol == ssl.PROTOCOL_SSLv23:
2196 client_context.set_ciphers("ALL")
2197
Antoine Pitroub5218772010-05-21 09:56:06 +00002198 for ctx in (client_context, server_context):
2199 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00002200 ctx.load_cert_chain(CERTFILE)
2201 ctx.load_verify_locations(CERTFILE)
2202 try:
Antoine Pitrou47e40422014-09-04 21:00:10 +02002203 stats = server_params_test(client_context, server_context,
2204 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002205 # Protocol mismatch can result in either an SSLError, or a
2206 # "Connection reset by peer" error.
2207 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002208 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002209 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02002210 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002211 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002212 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002213 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002214 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00002215 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002216 "Client protocol %s succeeded with server protocol %s!"
2217 % (ssl.get_protocol_name(client_protocol),
2218 ssl.get_protocol_name(server_protocol)))
Antoine Pitrou47e40422014-09-04 21:00:10 +02002219 elif (expect_success is not True
2220 and expect_success != stats['version']):
2221 raise AssertionError("version mismatch: expected %r, got %r"
2222 % (expect_success, stats['version']))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002223
2224
Bill Janssen6e027db2007-11-15 22:23:56 +00002225 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002226
Antoine Pitrou23df4832010-08-04 17:14:06 +00002227 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002228 def test_echo(self):
2229 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002230 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002231 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00002232 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01002233 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2234 context = ssl.SSLContext(protocol)
2235 context.load_cert_chain(CERTFILE)
2236 server_params_test(context, context,
2237 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002238
Antoine Pitrou480a1242010-04-28 21:37:09 +00002239 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002240 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002241 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00002242 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2243 context.verify_mode = ssl.CERT_REQUIRED
2244 context.load_verify_locations(CERTFILE)
2245 context.load_cert_chain(CERTFILE)
2246 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002247 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02002248 s = context.wrap_socket(socket.socket(),
2249 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002250 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02002251 # getpeercert() raise ValueError while the handshake isn't
2252 # done.
2253 with self.assertRaises(ValueError):
2254 s.getpeercert()
2255 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002256 cert = s.getpeercert()
2257 self.assertTrue(cert, "Can't get peer certificate.")
2258 cipher = s.cipher()
2259 if support.verbose:
2260 sys.stdout.write(pprint.pformat(cert) + '\n')
2261 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2262 if 'subject' not in cert:
2263 self.fail("No subject field in certificate: %s." %
2264 pprint.pformat(cert))
2265 if ((('organizationName', 'Python Software Foundation'),)
2266 not in cert['subject']):
2267 self.fail(
2268 "Missing or invalid 'organizationName' field in certificate subject; "
2269 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00002270 self.assertIn('notBefore', cert)
2271 self.assertIn('notAfter', cert)
2272 before = ssl.cert_time_to_seconds(cert['notBefore'])
2273 after = ssl.cert_time_to_seconds(cert['notAfter'])
2274 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002275 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002276
Christian Heimes2427b502013-11-23 11:24:32 +01002277 @unittest.skipUnless(have_verify_flags(),
2278 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01002279 def test_crl_check(self):
2280 if support.verbose:
2281 sys.stdout.write("\n")
2282
2283 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2284 server_context.load_cert_chain(SIGNED_CERTFILE)
2285
2286 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2287 context.verify_mode = ssl.CERT_REQUIRED
2288 context.load_verify_locations(SIGNING_CA)
Benjamin Petersonc3d9c5c2015-03-04 23:18:48 -05002289 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2290 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01002291
2292 # VERIFY_DEFAULT should pass
2293 server = ThreadedEchoServer(context=server_context, chatty=True)
2294 with server:
2295 with context.wrap_socket(socket.socket()) as s:
2296 s.connect((HOST, server.port))
2297 cert = s.getpeercert()
2298 self.assertTrue(cert, "Can't get peer certificate.")
2299
2300 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002301 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01002302
2303 server = ThreadedEchoServer(context=server_context, chatty=True)
2304 with server:
2305 with context.wrap_socket(socket.socket()) as s:
2306 with self.assertRaisesRegex(ssl.SSLError,
2307 "certificate verify failed"):
2308 s.connect((HOST, server.port))
2309
2310 # now load a CRL file. The CRL file is signed by the CA.
2311 context.load_verify_locations(CRLFILE)
2312
2313 server = ThreadedEchoServer(context=server_context, chatty=True)
2314 with server:
2315 with context.wrap_socket(socket.socket()) as s:
2316 s.connect((HOST, server.port))
2317 cert = s.getpeercert()
2318 self.assertTrue(cert, "Can't get peer certificate.")
2319
Christian Heimes1aa9a752013-12-02 02:41:19 +01002320 def test_check_hostname(self):
2321 if support.verbose:
2322 sys.stdout.write("\n")
2323
2324 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2325 server_context.load_cert_chain(SIGNED_CERTFILE)
2326
2327 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2328 context.verify_mode = ssl.CERT_REQUIRED
2329 context.check_hostname = True
2330 context.load_verify_locations(SIGNING_CA)
2331
2332 # correct hostname should verify
2333 server = ThreadedEchoServer(context=server_context, chatty=True)
2334 with server:
2335 with context.wrap_socket(socket.socket(),
2336 server_hostname="localhost") as s:
2337 s.connect((HOST, server.port))
2338 cert = s.getpeercert()
2339 self.assertTrue(cert, "Can't get peer certificate.")
2340
2341 # incorrect hostname should raise an exception
2342 server = ThreadedEchoServer(context=server_context, chatty=True)
2343 with server:
2344 with context.wrap_socket(socket.socket(),
2345 server_hostname="invalid") as s:
2346 with self.assertRaisesRegex(ssl.CertificateError,
2347 "hostname 'invalid' doesn't match 'localhost'"):
2348 s.connect((HOST, server.port))
2349
2350 # missing server_hostname arg should cause an exception, too
2351 server = ThreadedEchoServer(context=server_context, chatty=True)
2352 with server:
2353 with socket.socket() as s:
2354 with self.assertRaisesRegex(ValueError,
2355 "check_hostname requires server_hostname"):
2356 context.wrap_socket(s)
2357
Martin Panter407b62f2016-01-30 03:41:43 +00002358 def test_wrong_cert(self):
Martin Panter3464ea22016-02-01 21:58:11 +00002359 """Connecting when the server rejects the client's certificate
2360
2361 Launch a server with CERT_REQUIRED, and check that trying to
2362 connect to it with a wrong client certificate fails.
2363 """
2364 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
2365 "wrongcert.pem")
2366 server = ThreadedEchoServer(CERTFILE,
2367 certreqs=ssl.CERT_REQUIRED,
2368 cacerts=CERTFILE, chatty=False,
2369 connectionchatty=False)
2370 with server, \
2371 socket.socket() as sock, \
2372 ssl.wrap_socket(sock,
2373 certfile=certfile,
2374 ssl_version=ssl.PROTOCOL_TLSv1) as s:
2375 try:
2376 # Expect either an SSL error about the server rejecting
2377 # the connection, or a low-level connection reset (which
2378 # sometimes happens on Windows)
2379 s.connect((HOST, server.port))
2380 except ssl.SSLError as e:
2381 if support.verbose:
2382 sys.stdout.write("\nSSLError is %r\n" % e)
2383 except OSError as e:
2384 if e.errno != errno.ECONNRESET:
2385 raise
2386 if support.verbose:
2387 sys.stdout.write("\nsocket.error is %r\n" % e)
2388 else:
2389 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002390
Antoine Pitrou480a1242010-04-28 21:37:09 +00002391 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002392 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002393 in the client when attempting handshake.
2394 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002395 listener_ready = threading.Event()
2396 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002397
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002398 s = socket.socket()
2399 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002400
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002401 # `listener` runs in a thread. It sits in an accept() until
2402 # the main thread connects. Then it rudely closes the socket,
2403 # and sets Event `listener_gone` to let the main thread know
2404 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002405 def listener():
Charles-François Natali6e204602014-07-23 19:28:13 +01002406 s.listen()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002407 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002408 newsock, addr = s.accept()
2409 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002410 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002411 listener_gone.set()
2412
2413 def connector():
2414 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002415 with socket.socket() as c:
2416 c.connect((HOST, port))
2417 listener_gone.wait()
2418 try:
2419 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002420 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002421 pass
2422 else:
2423 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002424
2425 t = threading.Thread(target=listener)
2426 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002427 try:
2428 connector()
2429 finally:
2430 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002431
Antoine Pitrou23df4832010-08-04 17:14:06 +00002432 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002433 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2434 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002435 def test_protocol_sslv2(self):
2436 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002437 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002438 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002439 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2440 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2441 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002442 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Victor Stinner648b8622014-12-12 12:23:59 +01002443 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2444 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002445 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002446 # SSLv23 client with specific SSL options
2447 if no_sslv2_implies_sslv3_hello():
2448 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2449 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2450 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002451 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002452 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002453 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002454 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002455
Antoine Pitrou23df4832010-08-04 17:14:06 +00002456 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002457 def test_protocol_sslv23(self):
2458 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002459 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002460 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002461 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2462 try:
2463 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002464 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002465 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2466 if support.verbose:
2467 sys.stdout.write(
2468 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2469 % str(x))
Benjamin Petersone32467c2014-12-05 21:59:35 -05002470 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002471 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002472 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002473 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002474
Benjamin Petersone32467c2014-12-05 21:59:35 -05002475 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002476 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002477 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002478 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002479
Benjamin Petersone32467c2014-12-05 21:59:35 -05002480 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002481 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002482 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002483 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002484
Antoine Pitroub5218772010-05-21 09:56:06 +00002485 # Server with specific SSL options
Benjamin Petersone32467c2014-12-05 21:59:35 -05002486 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2487 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002488 server_options=ssl.OP_NO_SSLv3)
2489 # Will choose TLSv1
2490 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2491 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2492 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2493 server_options=ssl.OP_NO_TLSv1)
2494
2495
Antoine Pitrou23df4832010-08-04 17:14:06 +00002496 @skip_if_broken_ubuntu_ssl
Benjamin Petersone32467c2014-12-05 21:59:35 -05002497 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2498 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002499 def test_protocol_sslv3(self):
2500 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002501 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002502 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002503 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2504 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2505 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002506 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2507 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002508 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2509 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002510 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002511 if no_sslv2_implies_sslv3_hello():
2512 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002513 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2514 False, client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002515
Antoine Pitrou23df4832010-08-04 17:14:06 +00002516 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002517 def test_protocol_tlsv1(self):
2518 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002519 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002520 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002521 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2522 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2523 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002524 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2525 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002526 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2527 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002528 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2529 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002530
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002531 @skip_if_broken_ubuntu_ssl
2532 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2533 "TLS version 1.1 not supported.")
2534 def test_protocol_tlsv1_1(self):
2535 """Connecting to a TLSv1.1 server with various client options.
2536 Testing against older TLS versions."""
2537 if support.verbose:
2538 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002539 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002540 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2541 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002542 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2543 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002544 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2545 client_options=ssl.OP_NO_TLSv1_1)
2546
Antoine Pitrou47e40422014-09-04 21:00:10 +02002547 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002548 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2549 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2550
2551
2552 @skip_if_broken_ubuntu_ssl
2553 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2554 "TLS version 1.2 not supported.")
2555 def test_protocol_tlsv1_2(self):
2556 """Connecting to a TLSv1.2 server with various client options.
2557 Testing against older TLS versions."""
2558 if support.verbose:
2559 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002560 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002561 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2562 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2563 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2564 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002565 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2566 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002567 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2568 client_options=ssl.OP_NO_TLSv1_2)
2569
Antoine Pitrou47e40422014-09-04 21:00:10 +02002570 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002571 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2572 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2573 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2574 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2575
Antoine Pitrou480a1242010-04-28 21:37:09 +00002576 def test_starttls(self):
2577 """Switching from clear text to encrypted and back again."""
2578 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002579
Trent Nelson78520002008-04-10 20:54:35 +00002580 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002581 ssl_version=ssl.PROTOCOL_TLSv1,
2582 starttls_server=True,
2583 chatty=True,
2584 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002585 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002586 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002587 s = socket.socket()
2588 s.setblocking(1)
2589 s.connect((HOST, server.port))
2590 if support.verbose:
2591 sys.stdout.write("\n")
2592 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002593 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002594 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002595 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002596 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002597 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002598 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002599 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002600 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002601 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002602 msg = outdata.strip().lower()
2603 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2604 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002605 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002606 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002607 " client: read %r from server, starting TLS...\n"
2608 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002609 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2610 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002611 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2612 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002613 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002614 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002615 " client: read %r from server, ending TLS...\n"
2616 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002617 s = conn.unwrap()
2618 wrapped = False
2619 else:
2620 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002621 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002622 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002623 if support.verbose:
2624 sys.stdout.write(" client: closing connection.\n")
2625 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002626 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002627 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002628 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002629 if wrapped:
2630 conn.close()
2631 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002632 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002633
Antoine Pitrou480a1242010-04-28 21:37:09 +00002634 def test_socketserver(self):
2635 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002636 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002637 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002638 if support.verbose:
2639 sys.stdout.write('\n')
2640 with open(CERTFILE, 'rb') as f:
2641 d1 = f.read()
2642 d2 = ''
2643 # now fetch the same data from the HTTPS server
Benjamin Peterson4ffb0752014-11-03 14:29:33 -05002644 url = 'https://localhost:%d/%s' % (
2645 server.port, os.path.split(CERTFILE)[1])
2646 context = ssl.create_default_context(cafile=CERTFILE)
2647 f = urllib.request.urlopen(url, context=context)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002648 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002649 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002650 if dlen and (int(dlen) > 0):
2651 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002652 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002653 sys.stdout.write(
2654 " client: read %d bytes from remote server '%s'\n"
2655 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002656 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002657 f.close()
2658 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002659
Antoine Pitrou480a1242010-04-28 21:37:09 +00002660 def test_asyncore_server(self):
2661 """Check the example asyncore integration."""
2662 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002663
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002664 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002665 sys.stdout.write("\n")
2666
Antoine Pitrou480a1242010-04-28 21:37:09 +00002667 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002668 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002669 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002670 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002671 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002672 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002673 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002674 " client: sending %r...\n" % indata)
2675 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002676 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002677 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002678 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002679 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002680 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002681 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2682 % (outdata[:20], len(outdata),
2683 indata[:20].lower(), len(indata)))
2684 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002685 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002686 sys.stdout.write(" client: closing connection.\n")
2687 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002688 if support.verbose:
2689 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002690
Antoine Pitrou480a1242010-04-28 21:37:09 +00002691 def test_recv_send(self):
2692 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002693 if support.verbose:
2694 sys.stdout.write("\n")
2695
2696 server = ThreadedEchoServer(CERTFILE,
2697 certreqs=ssl.CERT_NONE,
2698 ssl_version=ssl.PROTOCOL_TLSv1,
2699 cacerts=CERTFILE,
2700 chatty=True,
2701 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002702 with server:
2703 s = ssl.wrap_socket(socket.socket(),
2704 server_side=False,
2705 certfile=CERTFILE,
2706 ca_certs=CERTFILE,
2707 cert_reqs=ssl.CERT_NONE,
2708 ssl_version=ssl.PROTOCOL_TLSv1)
2709 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002710 # helper methods for standardising recv* method signatures
2711 def _recv_into():
2712 b = bytearray(b"\0"*100)
2713 count = s.recv_into(b)
2714 return b[:count]
2715
2716 def _recvfrom_into():
2717 b = bytearray(b"\0"*100)
2718 count, addr = s.recvfrom_into(b)
2719 return b[:count]
2720
2721 # (name, method, whether to expect success, *args)
2722 send_methods = [
2723 ('send', s.send, True, []),
2724 ('sendto', s.sendto, False, ["some.address"]),
2725 ('sendall', s.sendall, True, []),
2726 ]
2727 recv_methods = [
2728 ('recv', s.recv, True, []),
2729 ('recvfrom', s.recvfrom, False, ["some.address"]),
2730 ('recv_into', _recv_into, True, []),
2731 ('recvfrom_into', _recvfrom_into, False, []),
2732 ]
2733 data_prefix = "PREFIX_"
2734
2735 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002736 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002737 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002738 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002739 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002740 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002741 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002742 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002743 "<<{outdata:r}>> ({nout:d}) received; "
2744 "expected <<{indata:r}>> ({nin:d})\n".format(
2745 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002746 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002747 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002748 )
2749 )
2750 except ValueError as e:
2751 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002752 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002753 "Failed to send with method <<{name:s}>>; "
2754 "expected to succeed.\n".format(name=meth_name)
2755 )
2756 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002757 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002758 "Method <<{name:s}>> failed with unexpected "
2759 "exception message: {exp:s}\n".format(
2760 name=meth_name, exp=e
2761 )
2762 )
2763
2764 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002765 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002766 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002767 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002768 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002769 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002770 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002771 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002772 "<<{outdata:r}>> ({nout:d}) received; "
2773 "expected <<{indata:r}>> ({nin:d})\n".format(
2774 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002775 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002776 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002777 )
2778 )
2779 except ValueError as e:
2780 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002781 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002782 "Failed to receive with method <<{name:s}>>; "
2783 "expected to succeed.\n".format(name=meth_name)
2784 )
2785 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002786 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002787 "Method <<{name:s}>> failed with unexpected "
2788 "exception message: {exp:s}\n".format(
2789 name=meth_name, exp=e
2790 )
2791 )
2792 # consume data
2793 s.read()
2794
Nick Coghlan513886a2011-08-28 00:00:27 +10002795 # Make sure sendmsg et al are disallowed to avoid
2796 # inadvertent disclosure of data and/or corruption
2797 # of the encrypted data stream
2798 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2799 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2800 self.assertRaises(NotImplementedError,
2801 s.recvmsg_into, bytearray(100))
2802
Antoine Pitrou480a1242010-04-28 21:37:09 +00002803 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002804 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002805
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002806 def test_nonblocking_send(self):
2807 server = ThreadedEchoServer(CERTFILE,
2808 certreqs=ssl.CERT_NONE,
2809 ssl_version=ssl.PROTOCOL_TLSv1,
2810 cacerts=CERTFILE,
2811 chatty=True,
2812 connectionchatty=False)
2813 with server:
2814 s = ssl.wrap_socket(socket.socket(),
2815 server_side=False,
2816 certfile=CERTFILE,
2817 ca_certs=CERTFILE,
2818 cert_reqs=ssl.CERT_NONE,
2819 ssl_version=ssl.PROTOCOL_TLSv1)
2820 s.connect((HOST, server.port))
2821 s.setblocking(False)
2822
2823 # If we keep sending data, at some point the buffers
2824 # will be full and the call will block
2825 buf = bytearray(8192)
2826 def fill_buffer():
2827 while True:
2828 s.send(buf)
2829 self.assertRaises((ssl.SSLWantWriteError,
2830 ssl.SSLWantReadError), fill_buffer)
2831
2832 # Now read all the output and discard it
2833 s.setblocking(True)
2834 s.close()
2835
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002836 def test_handshake_timeout(self):
2837 # Issue #5103: SSL handshake must respect the socket timeout
2838 server = socket.socket(socket.AF_INET)
2839 host = "127.0.0.1"
2840 port = support.bind_port(server)
2841 started = threading.Event()
2842 finish = False
2843
2844 def serve():
Charles-François Natali6e204602014-07-23 19:28:13 +01002845 server.listen()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002846 started.set()
2847 conns = []
2848 while not finish:
2849 r, w, e = select.select([server], [], [], 0.1)
2850 if server in r:
2851 # Let the socket hang around rather than having
2852 # it closed by garbage collection.
2853 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002854 for sock in conns:
2855 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002856
2857 t = threading.Thread(target=serve)
2858 t.start()
2859 started.wait()
2860
2861 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002862 try:
2863 c = socket.socket(socket.AF_INET)
2864 c.settimeout(0.2)
2865 c.connect((host, port))
2866 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002867 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002868 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002869 finally:
2870 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002871 try:
2872 c = socket.socket(socket.AF_INET)
2873 c = ssl.wrap_socket(c)
2874 c.settimeout(0.2)
2875 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002876 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002877 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002878 finally:
2879 c.close()
2880 finally:
2881 finish = True
2882 t.join()
2883 server.close()
2884
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002885 def test_server_accept(self):
2886 # Issue #16357: accept() on a SSLSocket created through
2887 # SSLContext.wrap_socket().
2888 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2889 context.verify_mode = ssl.CERT_REQUIRED
2890 context.load_verify_locations(CERTFILE)
2891 context.load_cert_chain(CERTFILE)
2892 server = socket.socket(socket.AF_INET)
2893 host = "127.0.0.1"
2894 port = support.bind_port(server)
2895 server = context.wrap_socket(server, server_side=True)
2896
2897 evt = threading.Event()
2898 remote = None
2899 peer = None
2900 def serve():
2901 nonlocal remote, peer
Charles-François Natali6e204602014-07-23 19:28:13 +01002902 server.listen()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002903 # Block on the accept and wait on the connection to close.
2904 evt.set()
2905 remote, peer = server.accept()
2906 remote.recv(1)
2907
2908 t = threading.Thread(target=serve)
2909 t.start()
2910 # Client wait until server setup and perform a connect.
2911 evt.wait()
2912 client = context.wrap_socket(socket.socket())
2913 client.connect((host, port))
2914 client_addr = client.getsockname()
2915 client.close()
2916 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002917 remote.close()
2918 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002919 # Sanity checks.
2920 self.assertIsInstance(remote, ssl.SSLSocket)
2921 self.assertEqual(peer, client_addr)
2922
Antoine Pitrou242db722013-05-01 20:52:07 +02002923 def test_getpeercert_enotconn(self):
2924 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2925 with context.wrap_socket(socket.socket()) as sock:
2926 with self.assertRaises(OSError) as cm:
2927 sock.getpeercert()
2928 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2929
2930 def test_do_handshake_enotconn(self):
2931 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2932 with context.wrap_socket(socket.socket()) as sock:
2933 with self.assertRaises(OSError) as cm:
2934 sock.do_handshake()
2935 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2936
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002937 def test_default_ciphers(self):
2938 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2939 try:
2940 # Force a set of weak ciphers on our client context
2941 context.set_ciphers("DES")
2942 except ssl.SSLError:
2943 self.skipTest("no DES cipher available")
2944 with ThreadedEchoServer(CERTFILE,
2945 ssl_version=ssl.PROTOCOL_SSLv23,
2946 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002947 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002948 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002949 s.connect((HOST, server.port))
2950 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2951
Antoine Pitrou47e40422014-09-04 21:00:10 +02002952 def test_version_basic(self):
2953 """
2954 Basic tests for SSLSocket.version().
2955 More tests are done in the test_protocol_*() methods.
2956 """
2957 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2958 with ThreadedEchoServer(CERTFILE,
2959 ssl_version=ssl.PROTOCOL_TLSv1,
2960 chatty=False) as server:
2961 with context.wrap_socket(socket.socket()) as s:
2962 self.assertIs(s.version(), None)
2963 s.connect((HOST, server.port))
2964 self.assertEqual(s.version(), "TLSv1")
2965 self.assertIs(s.version(), None)
2966
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002967 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2968 def test_default_ecdh_curve(self):
2969 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2970 # should be enabled by default on SSL contexts.
2971 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2972 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02002973 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2974 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2975 # our default cipher list should prefer ECDH-based ciphers
2976 # automatically.
2977 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2978 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002979 with ThreadedEchoServer(context=context) as server:
2980 with context.wrap_socket(socket.socket()) as s:
2981 s.connect((HOST, server.port))
2982 self.assertIn("ECDH", s.cipher()[0])
2983
Antoine Pitroud6494802011-07-21 01:11:30 +02002984 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2985 "'tls-unique' channel binding not available")
2986 def test_tls_unique_channel_binding(self):
2987 """Test tls-unique channel binding."""
2988 if support.verbose:
2989 sys.stdout.write("\n")
2990
2991 server = ThreadedEchoServer(CERTFILE,
2992 certreqs=ssl.CERT_NONE,
2993 ssl_version=ssl.PROTOCOL_TLSv1,
2994 cacerts=CERTFILE,
2995 chatty=True,
2996 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002997 with server:
2998 s = ssl.wrap_socket(socket.socket(),
2999 server_side=False,
3000 certfile=CERTFILE,
3001 ca_certs=CERTFILE,
3002 cert_reqs=ssl.CERT_NONE,
3003 ssl_version=ssl.PROTOCOL_TLSv1)
3004 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003005 # get the data
3006 cb_data = s.get_channel_binding("tls-unique")
3007 if support.verbose:
3008 sys.stdout.write(" got channel binding data: {0!r}\n"
3009 .format(cb_data))
3010
3011 # check if it is sane
3012 self.assertIsNotNone(cb_data)
3013 self.assertEqual(len(cb_data), 12) # True for TLSv1
3014
3015 # and compare with the peers version
3016 s.write(b"CB tls-unique\n")
3017 peer_data_repr = s.read().strip()
3018 self.assertEqual(peer_data_repr,
3019 repr(cb_data).encode("us-ascii"))
3020 s.close()
3021
3022 # now, again
3023 s = ssl.wrap_socket(socket.socket(),
3024 server_side=False,
3025 certfile=CERTFILE,
3026 ca_certs=CERTFILE,
3027 cert_reqs=ssl.CERT_NONE,
3028 ssl_version=ssl.PROTOCOL_TLSv1)
3029 s.connect((HOST, server.port))
3030 new_cb_data = s.get_channel_binding("tls-unique")
3031 if support.verbose:
3032 sys.stdout.write(" got another channel binding data: {0!r}\n"
3033 .format(new_cb_data))
3034 # is it really unique
3035 self.assertNotEqual(cb_data, new_cb_data)
3036 self.assertIsNotNone(cb_data)
3037 self.assertEqual(len(cb_data), 12) # True for TLSv1
3038 s.write(b"CB tls-unique\n")
3039 peer_data_repr = s.read().strip()
3040 self.assertEqual(peer_data_repr,
3041 repr(new_cb_data).encode("us-ascii"))
3042 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00003043
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003044 def test_compression(self):
3045 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3046 context.load_cert_chain(CERTFILE)
3047 stats = server_params_test(context, context,
3048 chatty=True, connectionchatty=True)
3049 if support.verbose:
3050 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3051 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3052
3053 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3054 "ssl.OP_NO_COMPRESSION needed for this test")
3055 def test_compression_disabled(self):
3056 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3057 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01003058 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003059 stats = server_params_test(context, context,
3060 chatty=True, connectionchatty=True)
3061 self.assertIs(stats['compression'], None)
3062
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003063 def test_dh_params(self):
3064 # Check we can get a connection with ephemeral Diffie-Hellman
3065 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3066 context.load_cert_chain(CERTFILE)
3067 context.load_dh_params(DHFILE)
3068 context.set_ciphers("kEDH")
3069 stats = server_params_test(context, context,
3070 chatty=True, connectionchatty=True)
3071 cipher = stats["cipher"][0]
3072 parts = cipher.split("-")
3073 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
3074 self.fail("Non-DH cipher: " + cipher[0])
3075
Benjamin Petersoncca27322015-01-23 16:35:37 -05003076 def test_selected_alpn_protocol(self):
3077 # selected_alpn_protocol() is None unless ALPN is used.
3078 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3079 context.load_cert_chain(CERTFILE)
3080 stats = server_params_test(context, context,
3081 chatty=True, connectionchatty=True)
3082 self.assertIs(stats['client_alpn_protocol'], None)
3083
3084 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
3085 def test_selected_alpn_protocol_if_server_uses_alpn(self):
3086 # selected_alpn_protocol() is None unless ALPN is used by the client.
3087 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3088 client_context.load_verify_locations(CERTFILE)
3089 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3090 server_context.load_cert_chain(CERTFILE)
3091 server_context.set_alpn_protocols(['foo', 'bar'])
3092 stats = server_params_test(client_context, server_context,
3093 chatty=True, connectionchatty=True)
3094 self.assertIs(stats['client_alpn_protocol'], None)
3095
3096 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
3097 def test_alpn_protocols(self):
3098 server_protocols = ['foo', 'bar', 'milkshake']
3099 protocol_tests = [
3100 (['foo', 'bar'], 'foo'),
Benjamin Peterson88615022015-01-23 17:30:26 -05003101 (['bar', 'foo'], 'foo'),
Benjamin Petersoncca27322015-01-23 16:35:37 -05003102 (['milkshake'], 'milkshake'),
Benjamin Peterson88615022015-01-23 17:30:26 -05003103 (['http/3.0', 'http/4.0'], None)
Benjamin Petersoncca27322015-01-23 16:35:37 -05003104 ]
3105 for client_protocols, expected in protocol_tests:
3106 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3107 server_context.load_cert_chain(CERTFILE)
3108 server_context.set_alpn_protocols(server_protocols)
3109 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3110 client_context.load_cert_chain(CERTFILE)
3111 client_context.set_alpn_protocols(client_protocols)
3112 stats = server_params_test(client_context, server_context,
3113 chatty=True, connectionchatty=True)
3114
3115 msg = "failed trying %s (s) and %s (c).\n" \
3116 "was expecting %s, but got %%s from the %%s" \
3117 % (str(server_protocols), str(client_protocols),
3118 str(expected))
3119 client_result = stats['client_alpn_protocol']
3120 self.assertEqual(client_result, expected, msg % (client_result, "client"))
3121 server_result = stats['server_alpn_protocols'][-1] \
3122 if len(stats['server_alpn_protocols']) else 'nothing'
3123 self.assertEqual(server_result, expected, msg % (server_result, "server"))
3124
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01003125 def test_selected_npn_protocol(self):
3126 # selected_npn_protocol() is None unless NPN is used
3127 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3128 context.load_cert_chain(CERTFILE)
3129 stats = server_params_test(context, context,
3130 chatty=True, connectionchatty=True)
3131 self.assertIs(stats['client_npn_protocol'], None)
3132
3133 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
3134 def test_npn_protocols(self):
3135 server_protocols = ['http/1.1', 'spdy/2']
3136 protocol_tests = [
3137 (['http/1.1', 'spdy/2'], 'http/1.1'),
3138 (['spdy/2', 'http/1.1'], 'http/1.1'),
3139 (['spdy/2', 'test'], 'spdy/2'),
3140 (['abc', 'def'], 'abc')
3141 ]
3142 for client_protocols, expected in protocol_tests:
3143 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3144 server_context.load_cert_chain(CERTFILE)
3145 server_context.set_npn_protocols(server_protocols)
3146 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3147 client_context.load_cert_chain(CERTFILE)
3148 client_context.set_npn_protocols(client_protocols)
3149 stats = server_params_test(client_context, server_context,
3150 chatty=True, connectionchatty=True)
3151
3152 msg = "failed trying %s (s) and %s (c).\n" \
3153 "was expecting %s, but got %%s from the %%s" \
3154 % (str(server_protocols), str(client_protocols),
3155 str(expected))
3156 client_result = stats['client_npn_protocol']
3157 self.assertEqual(client_result, expected, msg % (client_result, "client"))
3158 server_result = stats['server_npn_protocols'][-1] \
3159 if len(stats['server_npn_protocols']) else 'nothing'
3160 self.assertEqual(server_result, expected, msg % (server_result, "server"))
3161
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003162 def sni_contexts(self):
3163 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3164 server_context.load_cert_chain(SIGNED_CERTFILE)
3165 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3166 other_context.load_cert_chain(SIGNED_CERTFILE2)
3167 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3168 client_context.verify_mode = ssl.CERT_REQUIRED
3169 client_context.load_verify_locations(SIGNING_CA)
3170 return server_context, other_context, client_context
3171
3172 def check_common_name(self, stats, name):
3173 cert = stats['peercert']
3174 self.assertIn((('commonName', name),), cert['subject'])
3175
3176 @needs_sni
3177 def test_sni_callback(self):
3178 calls = []
3179 server_context, other_context, client_context = self.sni_contexts()
3180
3181 def servername_cb(ssl_sock, server_name, initial_context):
3182 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02003183 if server_name is not None:
3184 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003185 server_context.set_servername_callback(servername_cb)
3186
3187 stats = server_params_test(client_context, server_context,
3188 chatty=True,
3189 sni_name='supermessage')
3190 # The hostname was fetched properly, and the certificate was
3191 # changed for the connection.
3192 self.assertEqual(calls, [("supermessage", server_context)])
3193 # CERTFILE4 was selected
3194 self.check_common_name(stats, 'fakehostname')
3195
Antoine Pitrou50b24d02013-04-11 20:48:42 +02003196 calls = []
3197 # The callback is called with server_name=None
3198 stats = server_params_test(client_context, server_context,
3199 chatty=True,
3200 sni_name=None)
3201 self.assertEqual(calls, [(None, server_context)])
3202 self.check_common_name(stats, 'localhost')
3203
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003204 # Check disabling the callback
3205 calls = []
3206 server_context.set_servername_callback(None)
3207
3208 stats = server_params_test(client_context, server_context,
3209 chatty=True,
3210 sni_name='notfunny')
3211 # Certificate didn't change
3212 self.check_common_name(stats, 'localhost')
3213 self.assertEqual(calls, [])
3214
3215 @needs_sni
3216 def test_sni_callback_alert(self):
3217 # Returning a TLS alert is reflected to the connecting client
3218 server_context, other_context, client_context = self.sni_contexts()
3219
3220 def cb_returning_alert(ssl_sock, server_name, initial_context):
3221 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
3222 server_context.set_servername_callback(cb_returning_alert)
3223
3224 with self.assertRaises(ssl.SSLError) as cm:
3225 stats = server_params_test(client_context, server_context,
3226 chatty=False,
3227 sni_name='supermessage')
3228 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
3229
3230 @needs_sni
3231 def test_sni_callback_raising(self):
3232 # Raising fails the connection with a TLS handshake failure alert.
3233 server_context, other_context, client_context = self.sni_contexts()
3234
3235 def cb_raising(ssl_sock, server_name, initial_context):
3236 1/0
3237 server_context.set_servername_callback(cb_raising)
3238
3239 with self.assertRaises(ssl.SSLError) as cm, \
3240 support.captured_stderr() as stderr:
3241 stats = server_params_test(client_context, server_context,
3242 chatty=False,
3243 sni_name='supermessage')
3244 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
3245 self.assertIn("ZeroDivisionError", stderr.getvalue())
3246
3247 @needs_sni
3248 def test_sni_callback_wrong_return_type(self):
3249 # Returning the wrong return type terminates the TLS connection
3250 # with an internal error alert.
3251 server_context, other_context, client_context = self.sni_contexts()
3252
3253 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
3254 return "foo"
3255 server_context.set_servername_callback(cb_wrong_return_type)
3256
3257 with self.assertRaises(ssl.SSLError) as cm, \
3258 support.captured_stderr() as stderr:
3259 stats = server_params_test(client_context, server_context,
3260 chatty=False,
3261 sni_name='supermessage')
3262 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
3263 self.assertIn("TypeError", stderr.getvalue())
3264
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003265 def test_shared_ciphers(self):
Benjamin Petersonaacd5242015-01-07 11:42:38 -06003266 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson15042922015-01-07 22:12:43 -06003267 server_context.load_cert_chain(SIGNED_CERTFILE)
3268 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3269 client_context.verify_mode = ssl.CERT_REQUIRED
3270 client_context.load_verify_locations(SIGNING_CA)
Benjamin Peterson23ef9fa2015-01-07 21:21:34 -06003271 client_context.set_ciphers("RC4")
Benjamin Petersone6838e02015-01-07 20:52:40 -06003272 server_context.set_ciphers("AES:RC4")
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003273 stats = server_params_test(client_context, server_context)
3274 ciphers = stats['server_shared_ciphers'][0]
3275 self.assertGreater(len(ciphers), 0)
3276 for name, tls_version, bits in ciphers:
Benjamin Peterson23ef9fa2015-01-07 21:21:34 -06003277 self.assertIn("RC4", name.split("-"))
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003278
Antoine Pitrou60a26e02013-07-20 19:35:16 +02003279 def test_read_write_after_close_raises_valuerror(self):
3280 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3281 context.verify_mode = ssl.CERT_REQUIRED
3282 context.load_verify_locations(CERTFILE)
3283 context.load_cert_chain(CERTFILE)
3284 server = ThreadedEchoServer(context=context, chatty=False)
3285
3286 with server:
3287 s = context.wrap_socket(socket.socket())
3288 s.connect((HOST, server.port))
3289 s.close()
3290
3291 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02003292 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02003293
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02003294 def test_sendfile(self):
3295 TEST_DATA = b"x" * 512
3296 with open(support.TESTFN, 'wb') as f:
3297 f.write(TEST_DATA)
3298 self.addCleanup(support.unlink, support.TESTFN)
3299 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3300 context.verify_mode = ssl.CERT_REQUIRED
3301 context.load_verify_locations(CERTFILE)
3302 context.load_cert_chain(CERTFILE)
3303 server = ThreadedEchoServer(context=context, chatty=False)
3304 with server:
3305 with context.wrap_socket(socket.socket()) as s:
3306 s.connect((HOST, server.port))
3307 with open(support.TESTFN, 'rb') as file:
3308 s.sendfile(file)
3309 self.assertEqual(s.recv(1024), TEST_DATA)
3310
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003311
Thomas Woutersed03b412007-08-28 21:37:11 +00003312def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00003313 if support.verbose:
Berker Peksag9e7990a2015-05-16 23:21:26 +03003314 import warnings
Antoine Pitrou15cee622010-08-04 16:45:21 +00003315 plats = {
3316 'Linux': platform.linux_distribution,
3317 'Mac': platform.mac_ver,
3318 'Windows': platform.win32_ver,
3319 }
Berker Peksag9e7990a2015-05-16 23:21:26 +03003320 with warnings.catch_warnings():
3321 warnings.filterwarnings(
3322 'ignore',
3323 'dist\(\) and linux_distribution\(\) '
3324 'functions are deprecated .*',
3325 PendingDeprecationWarning,
3326 )
3327 for name, func in plats.items():
3328 plat = func()
3329 if plat and plat[0]:
3330 plat = '%s %r' % (name, plat)
3331 break
3332 else:
3333 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00003334 print("test_ssl: testing with %r %r" %
3335 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3336 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00003337 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01003338 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3339 try:
3340 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3341 except AttributeError:
3342 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00003343
Antoine Pitrou152efa22010-05-16 18:19:27 +00003344 for filename in [
Martin Panter3d81d932016-01-14 09:36:00 +00003345 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00003346 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003347 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00003348 BADCERT, BADKEY, EMPTYCERT]:
3349 if not os.path.exists(filename):
3350 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00003351
Antoine Pitroub1fdf472014-10-05 20:41:53 +02003352 tests = [ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00003353
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003354 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00003355 tests.append(NetworkedTests)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02003356 tests.append(NetworkedBIOTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00003357
Thomas Wouters1b7f8912007-09-19 03:06:30 +00003358 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003359 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01003360 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00003361 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00003362
Antoine Pitrou480a1242010-04-28 21:37:09 +00003363 try:
3364 support.run_unittest(*tests)
3365 finally:
3366 if _have_threads:
3367 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00003368
3369if __name__ == "__main__":
3370 test_main()