blob: 03d40b22551cec054d1706b861e67894f7299661 [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
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
23PROTOCOLS = [
Victor Stinner3de49192011-05-09 00:42:58 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner3de49192011-05-09 00:42:58 +020027if hasattr(ssl, 'PROTOCOL_SSLv2'):
28 PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
Thomas Woutersed03b412007-08-28 21:37:11 +000029
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
Martin Panter3d81d932016-01-14 09:36:00 +000032def data_file(*name):
33 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000034
Antoine Pitrou81564092010-10-08 23:06:24 +000035# The custom key and certificate files used in test_ssl are generated
36# using Lib/test/make_ssl_certs.py.
37# Other certificates are simply fetched from the Internet servers they
38# are meant to authenticate.
39
Antoine Pitrou152efa22010-05-16 18:19:27 +000040CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000041BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000042ONLYCERT = data_file("ssl_cert.pem")
43ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000044BYTES_ONLYCERT = os.fsencode(ONLYCERT)
45BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020046CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
47ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
48KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000049CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000050BYTES_CAPATH = os.fsencode(CAPATH)
Martin Panter3d81d932016-01-14 09:36:00 +000051CAFILE_CACERT = data_file("capath", "5ed36f99.0")
Antoine Pitrou152efa22010-05-16 18:19:27 +000052
Martin Panter3d81d932016-01-14 09:36:00 +000053REMOTE_HOST = "self-signed.pythontest.net"
54REMOTE_ROOT_CERT = data_file("selfsigned_pythontestdotnet.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000055
56EMPTYCERT = data_file("nullcert.pem")
57BADCERT = data_file("badcert.pem")
58WRONGCERT = data_file("XXXnonexisting.pem")
59BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020060NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020061NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000062
Antoine Pitrou0e576f12011-12-22 10:03:38 +010063DHFILE = data_file("dh512.pem")
64BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000065
Thomas Woutersed03b412007-08-28 21:37:11 +000066def handle_error(prefix):
67 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000068 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000069 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitroub5218772010-05-21 09:56:06 +000071def can_clear_options():
72 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020073 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000074
75def no_sslv2_implies_sslv3_hello():
76 # 0.9.7h or higher
77 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
78
Thomas Woutersed03b412007-08-28 21:37:11 +000079
Antoine Pitrou23df4832010-08-04 17:14:06 +000080# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
81def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020082 if hasattr(ssl, 'PROTOCOL_SSLv2'):
83 @functools.wraps(func)
84 def f(*args, **kwargs):
85 try:
86 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
87 except ssl.SSLError:
88 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
89 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
90 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
91 return func(*args, **kwargs)
92 return f
93 else:
94 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000095
96
Antoine Pitrou152efa22010-05-16 18:19:27 +000097class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000098
Antoine Pitrou480a1242010-04-28 21:37:09 +000099 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200100 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 ssl.PROTOCOL_SSLv23
102 ssl.PROTOCOL_SSLv3
103 ssl.PROTOCOL_TLSv1
104 ssl.CERT_NONE
105 ssl.CERT_OPTIONAL
106 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100107 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100108 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100109 if ssl.HAS_ECDH:
110 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100111 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
112 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000113 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100114 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000115
Antoine Pitrou480a1242010-04-28 21:37:09 +0000116 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000117 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000118 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000119 sys.stdout.write("\n RAND_status is %d (%s)\n"
120 % (v, (v and "sufficient randomness") or
121 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200122
123 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
124 self.assertEqual(len(data), 16)
125 self.assertEqual(is_cryptographic, v == 1)
126 if v:
127 data = ssl.RAND_bytes(16)
128 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200129 else:
130 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200131
Victor Stinner1e81a392013-12-19 16:47:04 +0100132 # negative num is invalid
133 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
134 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
135
Jesus Ceac8754a12012-09-11 02:00:58 +0200136 self.assertRaises(TypeError, ssl.RAND_egd, 1)
137 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000139
Christian Heimesf77b4b22013-08-21 13:26:05 +0200140 @unittest.skipUnless(os.name == 'posix', 'requires posix')
141 def test_random_fork(self):
142 status = ssl.RAND_status()
143 if not status:
144 self.fail("OpenSSL's PRNG has insufficient randomness")
145
146 rfd, wfd = os.pipe()
147 pid = os.fork()
148 if pid == 0:
149 try:
150 os.close(rfd)
151 child_random = ssl.RAND_pseudo_bytes(16)[0]
152 self.assertEqual(len(child_random), 16)
153 os.write(wfd, child_random)
154 os.close(wfd)
155 except BaseException:
156 os._exit(1)
157 else:
158 os._exit(0)
159 else:
160 os.close(wfd)
161 self.addCleanup(os.close, rfd)
162 _, status = os.waitpid(pid, 0)
163 self.assertEqual(status, 0)
164
165 child_random = os.read(rfd, 16)
166 self.assertEqual(len(child_random), 16)
167 parent_random = ssl.RAND_pseudo_bytes(16)[0]
168 self.assertEqual(len(parent_random), 16)
169
170 self.assertNotEqual(child_random, parent_random)
171
Antoine Pitrou480a1242010-04-28 21:37:09 +0000172 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000173 # note that this uses an 'unofficial' function in _ssl.c,
174 # provided solely for this test, to exercise the certificate
175 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000176 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000177 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000178 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200179 self.assertEqual(p['issuer'],
180 ((('countryName', 'XY'),),
181 (('localityName', 'Castle Anthrax'),),
182 (('organizationName', 'Python Software Foundation'),),
183 (('commonName', 'localhost'),))
184 )
185 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
186 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
187 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
188 self.assertEqual(p['subject'],
189 ((('countryName', 'XY'),),
190 (('localityName', 'Castle Anthrax'),),
191 (('organizationName', 'Python Software Foundation'),),
192 (('commonName', 'localhost'),))
193 )
194 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
195 # Issue #13034: the subjectAltName in some certificates
196 # (notably projects.developer.nokia.com:443) wasn't parsed
197 p = ssl._ssl._test_decode_cert(NOKIACERT)
198 if support.verbose:
199 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
200 self.assertEqual(p['subjectAltName'],
201 (('DNS', 'projects.developer.nokia.com'),
202 ('DNS', 'projects.forum.nokia.com'))
203 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000204
Christian Heimes824f7f32013-08-17 00:54:47 +0200205 def test_parse_cert_CVE_2013_4238(self):
206 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
207 if support.verbose:
208 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
209 subject = ((('countryName', 'US'),),
210 (('stateOrProvinceName', 'Oregon'),),
211 (('localityName', 'Beaverton'),),
212 (('organizationName', 'Python Software Foundation'),),
213 (('organizationalUnitName', 'Python Core Development'),),
214 (('commonName', 'null.python.org\x00example.org'),),
215 (('emailAddress', 'python-dev@python.org'),))
216 self.assertEqual(p['subject'], subject)
217 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200218 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
219 san = (('DNS', 'altnull.python.org\x00example.com'),
220 ('email', 'null@python.org\x00user@example.org'),
221 ('URI', 'http://null.python.org\x00http://example.org'),
222 ('IP Address', '192.0.2.1'),
223 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
224 else:
225 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
226 san = (('DNS', 'altnull.python.org\x00example.com'),
227 ('email', 'null@python.org\x00user@example.org'),
228 ('URI', 'http://null.python.org\x00http://example.org'),
229 ('IP Address', '192.0.2.1'),
230 ('IP Address', '<invalid>'))
231
232 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200233
Antoine Pitrou480a1242010-04-28 21:37:09 +0000234 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000235 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000236 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000237 d1 = ssl.PEM_cert_to_DER_cert(pem)
238 p2 = ssl.DER_cert_to_PEM_cert(d1)
239 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000240 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000241 if not p2.startswith(ssl.PEM_HEADER + '\n'):
242 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
243 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
244 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000245
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000246 def test_openssl_version(self):
247 n = ssl.OPENSSL_VERSION_NUMBER
248 t = ssl.OPENSSL_VERSION_INFO
249 s = ssl.OPENSSL_VERSION
250 self.assertIsInstance(n, int)
251 self.assertIsInstance(t, tuple)
252 self.assertIsInstance(s, str)
253 # Some sanity checks follow
254 # >= 0.9
255 self.assertGreaterEqual(n, 0x900000)
256 # < 2.0
257 self.assertLess(n, 0x20000000)
258 major, minor, fix, patch, status = t
259 self.assertGreaterEqual(major, 0)
260 self.assertLess(major, 2)
261 self.assertGreaterEqual(minor, 0)
262 self.assertLess(minor, 256)
263 self.assertGreaterEqual(fix, 0)
264 self.assertLess(fix, 256)
265 self.assertGreaterEqual(patch, 0)
266 self.assertLessEqual(patch, 26)
267 self.assertGreaterEqual(status, 0)
268 self.assertLessEqual(status, 15)
269 # Version string as returned by OpenSSL, the format might change
270 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
271 (s, t))
272
Antoine Pitrou9d543662010-04-23 23:10:32 +0000273 @support.cpython_only
274 def test_refcycle(self):
275 # Issue #7943: an SSL object doesn't create reference cycles with
276 # itself.
277 s = socket.socket(socket.AF_INET)
278 ss = ssl.wrap_socket(s)
279 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100280 with support.check_warnings(("", ResourceWarning)):
281 del ss
282 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000283
Antoine Pitroua468adc2010-09-14 14:43:44 +0000284 def test_wrapped_unconnected(self):
285 # Methods on an unconnected SSLSocket propagate the original
286 # socket.error raise by the underlying socket object.
287 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100288 with ssl.wrap_socket(s) as ss:
289 self.assertRaises(socket.error, ss.recv, 1)
290 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
291 self.assertRaises(socket.error, ss.recvfrom, 1)
292 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
293 self.assertRaises(socket.error, ss.send, b'x')
294 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000295
Antoine Pitrou40f08742010-04-24 22:04:40 +0000296 def test_timeout(self):
297 # Issue #8524: when creating an SSL socket, the timeout of the
298 # original socket should be retained.
299 for timeout in (None, 0.0, 5.0):
300 s = socket.socket(socket.AF_INET)
301 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100302 with ssl.wrap_socket(s) as ss:
303 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000304
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000305 def test_errors(self):
306 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000307 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000308 "certfile must be specified",
309 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000310 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000311 "certfile must be specified for server-side operations",
312 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000313 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000314 "certfile must be specified for server-side operations",
315 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100316 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
317 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
318 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000319 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000320 with socket.socket() as sock:
321 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000322 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000323 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000324 with socket.socket() as sock:
325 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000326 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000327 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000328 with socket.socket() as sock:
329 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000330 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000331
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000332 def test_match_hostname(self):
333 def ok(cert, hostname):
334 ssl.match_hostname(cert, hostname)
335 def fail(cert, hostname):
336 self.assertRaises(ssl.CertificateError,
337 ssl.match_hostname, cert, hostname)
338
339 cert = {'subject': ((('commonName', 'example.com'),),)}
340 ok(cert, 'example.com')
341 ok(cert, 'ExAmple.cOm')
342 fail(cert, 'www.example.com')
343 fail(cert, '.example.com')
344 fail(cert, 'example.org')
345 fail(cert, 'exampleXcom')
346
347 cert = {'subject': ((('commonName', '*.a.com'),),)}
348 ok(cert, 'foo.a.com')
349 fail(cert, 'bar.foo.a.com')
350 fail(cert, 'a.com')
351 fail(cert, 'Xa.com')
352 fail(cert, '.a.com')
353
Georg Brandl72c98d32013-10-27 07:16:53 +0100354 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000355 cert = {'subject': ((('commonName', 'f*.com'),),)}
356 ok(cert, 'foo.com')
357 ok(cert, 'f.com')
358 fail(cert, 'bar.com')
359 fail(cert, 'foo.a.com')
360 fail(cert, 'bar.foo.com')
361
Christian Heimes824f7f32013-08-17 00:54:47 +0200362 # NULL bytes are bad, CVE-2013-4073
363 cert = {'subject': ((('commonName',
364 'null.python.org\x00example.org'),),)}
365 ok(cert, 'null.python.org\x00example.org') # or raise an error?
366 fail(cert, 'example.org')
367 fail(cert, 'null.python.org')
368
Georg Brandl72c98d32013-10-27 07:16:53 +0100369 # error cases with wildcards
370 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
371 fail(cert, 'bar.foo.a.com')
372 fail(cert, 'a.com')
373 fail(cert, 'Xa.com')
374 fail(cert, '.a.com')
375
376 cert = {'subject': ((('commonName', 'a.*.com'),),)}
377 fail(cert, 'a.foo.com')
378 fail(cert, 'a..com')
379 fail(cert, 'a.com')
380
381 # wildcard doesn't match IDNA prefix 'xn--'
382 idna = 'püthon.python.org'.encode("idna").decode("ascii")
383 cert = {'subject': ((('commonName', idna),),)}
384 ok(cert, idna)
385 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
386 fail(cert, idna)
387 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
388 fail(cert, idna)
389
390 # wildcard in first fragment and IDNA A-labels in sequent fragments
391 # are supported.
392 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
393 cert = {'subject': ((('commonName', idna),),)}
394 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
395 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
396 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
397 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
398
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000399 # Slightly fake real-world example
400 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
401 'subject': ((('commonName', 'linuxfrz.org'),),),
402 'subjectAltName': (('DNS', 'linuxfr.org'),
403 ('DNS', 'linuxfr.com'),
404 ('othername', '<unsupported>'))}
405 ok(cert, 'linuxfr.org')
406 ok(cert, 'linuxfr.com')
407 # Not a "DNS" entry
408 fail(cert, '<unsupported>')
409 # When there is a subjectAltName, commonName isn't used
410 fail(cert, 'linuxfrz.org')
411
412 # A pristine real-world example
413 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
414 'subject': ((('countryName', 'US'),),
415 (('stateOrProvinceName', 'California'),),
416 (('localityName', 'Mountain View'),),
417 (('organizationName', 'Google Inc'),),
418 (('commonName', 'mail.google.com'),))}
419 ok(cert, 'mail.google.com')
420 fail(cert, 'gmail.com')
421 # Only commonName is considered
422 fail(cert, 'California')
423
424 # Neither commonName nor subjectAltName
425 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
426 'subject': ((('countryName', 'US'),),
427 (('stateOrProvinceName', 'California'),),
428 (('localityName', 'Mountain View'),),
429 (('organizationName', 'Google Inc'),))}
430 fail(cert, 'mail.google.com')
431
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200432 # No DNS entry in subjectAltName but a commonName
433 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
434 'subject': ((('countryName', 'US'),),
435 (('stateOrProvinceName', 'California'),),
436 (('localityName', 'Mountain View'),),
437 (('commonName', 'mail.google.com'),)),
438 'subjectAltName': (('othername', 'blabla'), )}
439 ok(cert, 'mail.google.com')
440
441 # No DNS entry subjectAltName and no commonName
442 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
443 'subject': ((('countryName', 'US'),),
444 (('stateOrProvinceName', 'California'),),
445 (('localityName', 'Mountain View'),),
446 (('organizationName', 'Google Inc'),)),
447 'subjectAltName': (('othername', 'blabla'),)}
448 fail(cert, 'google.com')
449
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000450 # Empty cert / no cert
451 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
452 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
453
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200454 # Issue #17980: avoid denials of service by refusing more than one
455 # wildcard per fragment.
456 cert = {'subject': ((('commonName', 'a*b.com'),),)}
457 ok(cert, 'axxb.com')
458 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100459 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200460 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
461 with self.assertRaises(ssl.CertificateError) as cm:
462 ssl.match_hostname(cert, 'axxbxxc.com')
463 self.assertIn("too many wildcards", str(cm.exception))
464
Antoine Pitroud5323212010-10-22 18:19:07 +0000465 def test_server_side(self):
466 # server_hostname doesn't work for server sockets
467 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000468 with socket.socket() as sock:
469 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
470 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000471
Antoine Pitroud6494802011-07-21 01:11:30 +0200472 def test_unknown_channel_binding(self):
473 # should raise ValueError for unknown type
474 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100475 with ssl.wrap_socket(s) as ss:
476 with self.assertRaises(ValueError):
477 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200478
479 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
480 "'tls-unique' channel binding not available")
481 def test_tls_unique_channel_binding(self):
482 # unconnected should return None for known type
483 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100484 with ssl.wrap_socket(s) as ss:
485 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200486 # the same for server-side
487 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100488 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
489 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200490
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600491 def test_dealloc_warn(self):
492 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
493 r = repr(ss)
494 with self.assertWarns(ResourceWarning) as cm:
495 ss = None
496 support.gc_collect()
497 self.assertIn(r, str(cm.warning.args[0]))
498
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100499 def test_unsupported_dtls(self):
500 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
501 self.addCleanup(s.close)
502 with self.assertRaises(NotImplementedError) as cx:
503 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
504 self.assertEqual(str(cx.exception), "only stream sockets are supported")
505 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
506 with self.assertRaises(NotImplementedError) as cx:
507 ctx.wrap_socket(s)
508 self.assertEqual(str(cx.exception), "only stream sockets are supported")
509
510
Antoine Pitrou152efa22010-05-16 18:19:27 +0000511class ContextTests(unittest.TestCase):
512
Antoine Pitrou23df4832010-08-04 17:14:06 +0000513 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000514 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200515 if hasattr(ssl, 'PROTOCOL_SSLv2'):
516 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000517 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
518 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
519 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
520 self.assertRaises(TypeError, ssl.SSLContext)
521 self.assertRaises(ValueError, ssl.SSLContext, -1)
522 self.assertRaises(ValueError, ssl.SSLContext, 42)
523
Antoine Pitrou23df4832010-08-04 17:14:06 +0000524 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000525 def test_protocol(self):
526 for proto in PROTOCOLS:
527 ctx = ssl.SSLContext(proto)
528 self.assertEqual(ctx.protocol, proto)
529
530 def test_ciphers(self):
531 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
532 ctx.set_ciphers("ALL")
533 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000534 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000535 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000536
Antoine Pitrou23df4832010-08-04 17:14:06 +0000537 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000538 def test_options(self):
539 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +0100540 # OP_ALL | OP_NO_SSLv2 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000541 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
542 ctx.options)
543 ctx.options |= ssl.OP_NO_SSLv3
544 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
545 ctx.options)
546 if can_clear_options():
547 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
548 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
549 ctx.options)
550 ctx.options = 0
551 self.assertEqual(0, ctx.options)
552 else:
553 with self.assertRaises(ValueError):
554 ctx.options = 0
555
Antoine Pitrou152efa22010-05-16 18:19:27 +0000556 def test_verify(self):
557 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
558 # Default value
559 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
560 ctx.verify_mode = ssl.CERT_OPTIONAL
561 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
562 ctx.verify_mode = ssl.CERT_REQUIRED
563 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
564 ctx.verify_mode = ssl.CERT_NONE
565 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
566 with self.assertRaises(TypeError):
567 ctx.verify_mode = None
568 with self.assertRaises(ValueError):
569 ctx.verify_mode = 42
570
571 def test_load_cert_chain(self):
572 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
573 # Combined key and cert in a single file
574 ctx.load_cert_chain(CERTFILE)
575 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
576 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000577 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000578 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000579 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000580 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000581 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000582 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000583 ctx.load_cert_chain(EMPTYCERT)
584 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000585 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000586 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
587 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
588 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000589 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000590 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000591 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000592 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000593 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000594 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
595 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000596 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000597 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +0000598 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200599 # Password protected key and cert
600 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
601 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
602 ctx.load_cert_chain(CERTFILE_PROTECTED,
603 password=bytearray(KEY_PASSWORD.encode()))
604 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
605 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
606 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
607 bytearray(KEY_PASSWORD.encode()))
608 with self.assertRaisesRegex(TypeError, "should be a string"):
609 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
610 with self.assertRaises(ssl.SSLError):
611 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
612 with self.assertRaisesRegex(ValueError, "cannot be longer"):
613 # openssl has a fixed limit on the password buffer.
614 # PEM_BUFSIZE is generally set to 1kb.
615 # Return a string larger than this.
616 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
617 # Password callback
618 def getpass_unicode():
619 return KEY_PASSWORD
620 def getpass_bytes():
621 return KEY_PASSWORD.encode()
622 def getpass_bytearray():
623 return bytearray(KEY_PASSWORD.encode())
624 def getpass_badpass():
625 return "badpass"
626 def getpass_huge():
627 return b'a' * (1024 * 1024)
628 def getpass_bad_type():
629 return 9
630 def getpass_exception():
631 raise Exception('getpass error')
632 class GetPassCallable:
633 def __call__(self):
634 return KEY_PASSWORD
635 def getpass(self):
636 return KEY_PASSWORD
637 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
638 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
639 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
640 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
641 ctx.load_cert_chain(CERTFILE_PROTECTED,
642 password=GetPassCallable().getpass)
643 with self.assertRaises(ssl.SSLError):
644 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
645 with self.assertRaisesRegex(ValueError, "cannot be longer"):
646 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
647 with self.assertRaisesRegex(TypeError, "must return a string"):
648 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
649 with self.assertRaisesRegex(Exception, "getpass error"):
650 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
651 # Make sure the password function isn't called if it isn't needed
652 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000653
654 def test_load_verify_locations(self):
655 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
656 ctx.load_verify_locations(CERTFILE)
657 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
658 ctx.load_verify_locations(BYTES_CERTFILE)
659 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
660 self.assertRaises(TypeError, ctx.load_verify_locations)
661 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000662 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000663 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000664 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000665 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000666 ctx.load_verify_locations(BADCERT)
667 ctx.load_verify_locations(CERTFILE, CAPATH)
668 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
669
Victor Stinner80f75e62011-01-29 11:31:20 +0000670 # Issue #10989: crash if the second argument type is invalid
671 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
672
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100673 def test_load_dh_params(self):
674 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
675 ctx.load_dh_params(DHFILE)
676 if os.name != 'nt':
677 ctx.load_dh_params(BYTES_DHFILE)
678 self.assertRaises(TypeError, ctx.load_dh_params)
679 self.assertRaises(TypeError, ctx.load_dh_params, None)
680 with self.assertRaises(FileNotFoundError) as cm:
681 ctx.load_dh_params(WRONGCERT)
682 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200683 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100684 ctx.load_dh_params(CERTFILE)
685
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000686 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000687 def test_session_stats(self):
688 for proto in PROTOCOLS:
689 ctx = ssl.SSLContext(proto)
690 self.assertEqual(ctx.session_stats(), {
691 'number': 0,
692 'connect': 0,
693 'connect_good': 0,
694 'connect_renegotiate': 0,
695 'accept': 0,
696 'accept_good': 0,
697 'accept_renegotiate': 0,
698 'hits': 0,
699 'misses': 0,
700 'timeouts': 0,
701 'cache_full': 0,
702 })
703
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000704 def test_set_default_verify_paths(self):
705 # There's not much we can do to test that it acts as expected,
706 # so just check it doesn't crash or raise an exception.
707 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
708 ctx.set_default_verify_paths()
709
Antoine Pitrou501da612011-12-21 09:27:41 +0100710 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100711 def test_set_ecdh_curve(self):
712 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
713 ctx.set_ecdh_curve("prime256v1")
714 ctx.set_ecdh_curve(b"prime256v1")
715 self.assertRaises(TypeError, ctx.set_ecdh_curve)
716 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
717 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
718 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
719
Antoine Pitrou152efa22010-05-16 18:19:27 +0000720
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200721class SSLErrorTests(unittest.TestCase):
722
723 def test_str(self):
724 # The str() of a SSLError doesn't include the errno
725 e = ssl.SSLError(1, "foo")
726 self.assertEqual(str(e), "foo")
727 self.assertEqual(e.errno, 1)
728 # Same for a subclass
729 e = ssl.SSLZeroReturnError(1, "foo")
730 self.assertEqual(str(e), "foo")
731 self.assertEqual(e.errno, 1)
732
733 def test_lib_reason(self):
734 # Test the library and reason attributes
735 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
736 with self.assertRaises(ssl.SSLError) as cm:
737 ctx.load_dh_params(CERTFILE)
738 self.assertEqual(cm.exception.library, 'PEM')
739 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
740 s = str(cm.exception)
741 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
742
743 def test_subclass(self):
744 # Check that the appropriate SSLError subclass is raised
745 # (this only tests one of them)
746 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
747 with socket.socket() as s:
748 s.bind(("127.0.0.1", 0))
749 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100750 c = socket.socket()
751 c.connect(s.getsockname())
752 c.setblocking(False)
753 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200754 with self.assertRaises(ssl.SSLWantReadError) as cm:
755 c.do_handshake()
756 s = str(cm.exception)
757 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
758 # For compatibility
759 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
760
761
Bill Janssen6e027db2007-11-15 22:23:56 +0000762class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763
Antoine Pitrou480a1242010-04-28 21:37:09 +0000764 def test_connect(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000765 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000766 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
767 cert_reqs=ssl.CERT_NONE)
768 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000769 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000770 self.assertEqual({}, s.getpeercert())
771 finally:
772 s.close()
773
774 # this should fail because we have no verification certs
775 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
776 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000777 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Martin Panter3d81d932016-01-14 09:36:00 +0000778 s.connect, (REMOTE_HOST, 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000779 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000780
Antoine Pitrou350c7222010-09-09 13:31:46 +0000781 # this should succeed because we specify the root cert
782 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
783 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000784 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000785 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000786 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000787 self.assertTrue(s.getpeercert())
788 finally:
789 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000790
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000791 def test_connect_ex(self):
792 # Issue #11326: check connect_ex() implementation
Martin Panter3d81d932016-01-14 09:36:00 +0000793 with support.transient_internet(REMOTE_HOST):
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000794 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
795 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000796 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000797 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000798 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000799 self.assertTrue(s.getpeercert())
800 finally:
801 s.close()
802
803 def test_non_blocking_connect_ex(self):
804 # Issue #11326: non-blocking connect_ex() should allow handshake
805 # to proceed after the socket gets ready.
Martin Panter3d81d932016-01-14 09:36:00 +0000806 with support.transient_internet(REMOTE_HOST):
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000807 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
808 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000809 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000810 do_handshake_on_connect=False)
811 try:
812 s.setblocking(False)
Martin Panter3d81d932016-01-14 09:36:00 +0000813 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000814 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
815 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000816 # Wait for connect to finish
817 select.select([], [s], [], 5.0)
818 # Non-blocking handshake
819 while True:
820 try:
821 s.do_handshake()
822 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200823 except ssl.SSLWantReadError:
824 select.select([s], [], [], 5.0)
825 except ssl.SSLWantWriteError:
826 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000827 # SSL established
828 self.assertTrue(s.getpeercert())
829 finally:
830 s.close()
831
Antoine Pitroub4410db2011-05-18 18:51:06 +0200832 def test_timeout_connect_ex(self):
833 # Issue #12065: on a timeout, connect_ex() should return the original
834 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter3d81d932016-01-14 09:36:00 +0000835 with support.transient_internet(REMOTE_HOST):
Antoine Pitroub4410db2011-05-18 18:51:06 +0200836 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
837 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000838 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroub4410db2011-05-18 18:51:06 +0200839 do_handshake_on_connect=False)
840 try:
841 s.settimeout(0.0000001)
Martin Panter3d81d932016-01-14 09:36:00 +0000842 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitroub4410db2011-05-18 18:51:06 +0200843 if rc == 0:
Martin Panter3d81d932016-01-14 09:36:00 +0000844 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitroub4410db2011-05-18 18:51:06 +0200845 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
846 finally:
847 s.close()
848
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100849 def test_connect_ex_error(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000850 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100851 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
852 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000853 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100854 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000855 rc = s.connect_ex((REMOTE_HOST, 444))
Christian Heimesde570742013-12-16 21:15:44 +0100856 # Issue #19919: Windows machines or VMs hosted on Windows
857 # machines sometimes return EWOULDBLOCK.
Martin Panter73f55072016-01-14 12:21:02 +0000858 errors = (
859 errno.ECONNREFUSED, errno.EHOSTUNREACH,
860 errno.EWOULDBLOCK,
861 )
862 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100863 finally:
864 s.close()
865
Antoine Pitrou152efa22010-05-16 18:19:27 +0000866 def test_connect_with_context(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000867 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000868 # Same as test_connect, but with a separately created context
869 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
870 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000871 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000872 try:
873 self.assertEqual({}, s.getpeercert())
874 finally:
875 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000876 # Same with a server hostname
877 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3d81d932016-01-14 09:36:00 +0000878 server_hostname=REMOTE_HOST)
Antoine Pitroud5323212010-10-22 18:19:07 +0000879 if ssl.HAS_SNI:
Martin Panter3d81d932016-01-14 09:36:00 +0000880 s.connect((REMOTE_HOST, 443))
Antoine Pitroud5323212010-10-22 18:19:07 +0000881 s.close()
882 else:
Martin Panter3d81d932016-01-14 09:36:00 +0000883 self.assertRaises(ValueError, s.connect, (REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000884 # This should fail because we have no verification certs
885 ctx.verify_mode = ssl.CERT_REQUIRED
886 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000887 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Martin Panter3d81d932016-01-14 09:36:00 +0000888 s.connect, (REMOTE_HOST, 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000889 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000890 # This should succeed because we specify the root cert
Martin Panter3d81d932016-01-14 09:36:00 +0000891 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000892 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000893 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000894 try:
895 cert = s.getpeercert()
896 self.assertTrue(cert)
897 finally:
898 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000899
900 def test_connect_capath(self):
901 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000902 # NOTE: the subject hashing algorithm has been changed between
903 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
904 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000905 # filename) for this test to be portable across OpenSSL releases.
Martin Panter3d81d932016-01-14 09:36:00 +0000906 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000907 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
908 ctx.verify_mode = ssl.CERT_REQUIRED
909 ctx.load_verify_locations(capath=CAPATH)
910 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000911 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000912 try:
913 cert = s.getpeercert()
914 self.assertTrue(cert)
915 finally:
916 s.close()
917 # Same with a bytes `capath` argument
918 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
919 ctx.verify_mode = ssl.CERT_REQUIRED
920 ctx.load_verify_locations(capath=BYTES_CAPATH)
921 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000922 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000923 try:
924 cert = s.getpeercert()
925 self.assertTrue(cert)
926 finally:
927 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000928
Antoine Pitroue3220242010-04-24 11:13:53 +0000929 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
930 def test_makefile_close(self):
931 # Issue #5238: creating a file-like object with makefile() shouldn't
932 # delay closing the underlying "real socket" (here tested with its
933 # file descriptor, hence skipping the test under Windows).
Martin Panter3d81d932016-01-14 09:36:00 +0000934 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000935 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000936 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000937 fd = ss.fileno()
938 f = ss.makefile()
939 f.close()
940 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000941 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000942 # Closing the SSL socket should close the fd too
943 ss.close()
944 gc.collect()
945 with self.assertRaises(OSError) as e:
946 os.read(fd, 0)
947 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000948
Antoine Pitrou480a1242010-04-28 21:37:09 +0000949 def test_non_blocking_handshake(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000950 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000951 s = socket.socket(socket.AF_INET)
Martin Panter3d81d932016-01-14 09:36:00 +0000952 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000953 s.setblocking(False)
954 s = ssl.wrap_socket(s,
955 cert_reqs=ssl.CERT_NONE,
956 do_handshake_on_connect=False)
957 count = 0
958 while True:
959 try:
960 count += 1
961 s.do_handshake()
962 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200963 except ssl.SSLWantReadError:
964 select.select([s], [], [])
965 except ssl.SSLWantWriteError:
966 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000967 s.close()
968 if support.verbose:
969 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970
Antoine Pitrou480a1242010-04-28 21:37:09 +0000971 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200972 def _test_get_server_certificate(host, port, cert=None):
973 with support.transient_internet(host):
Benjamin Petersond0fc83d2014-03-12 18:10:47 -0500974 pem = ssl.get_server_certificate((host, port),
975 ssl.PROTOCOL_SSLv23)
Antoine Pitrou15399c32011-04-28 19:23:55 +0200976 if not pem:
977 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200978
Antoine Pitrou15399c32011-04-28 19:23:55 +0200979 try:
Benjamin Petersond0fc83d2014-03-12 18:10:47 -0500980 pem = ssl.get_server_certificate((host, port),
981 ssl.PROTOCOL_SSLv23,
982 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +0200983 except ssl.SSLError as x:
984 #should fail
985 if support.verbose:
986 sys.stdout.write("%s\n" % x)
987 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200988 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
989
Benjamin Petersond0fc83d2014-03-12 18:10:47 -0500990 pem = ssl.get_server_certificate((host, port),
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500991 ssl.PROTOCOL_SSLv23,
Benjamin Petersond0fc83d2014-03-12 18:10:47 -0500992 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +0200993 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200994 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000995 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200996 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000997
Martin Panter73f55072016-01-14 12:21:02 +0000998 _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
Antoine Pitrou15399c32011-04-28 19:23:55 +0200999 if support.IPV6_ENABLED:
1000 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001001
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001002 def test_ciphers(self):
Martin Panter3d81d932016-01-14 09:36:00 +00001003 remote = (REMOTE_HOST, 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001004 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001005 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1006 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1007 s.connect(remote)
1008 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1009 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1010 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001011 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001012 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001013 with socket.socket(socket.AF_INET) as sock:
1014 s = ssl.wrap_socket(sock,
1015 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1016 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001017
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001018 def test_algorithms(self):
1019 # Issue #8484: all algorithms should be available when verifying a
1020 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001021 # SHA256 was added in OpenSSL 0.9.8
1022 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1023 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001024 # sha256.tbs-internet.com needs SNI to use the correct certificate
1025 if not ssl.HAS_SNI:
1026 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001027 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1028 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001029 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001030 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001031 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1032 ctx.verify_mode = ssl.CERT_REQUIRED
1033 ctx.load_verify_locations(sha256_cert)
1034 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1035 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001036 try:
1037 s.connect(remote)
1038 if support.verbose:
1039 sys.stdout.write("\nCipher with %r is %r\n" %
1040 (remote, s.cipher()))
1041 sys.stdout.write("Certificate is:\n%s\n" %
1042 pprint.pformat(s.getpeercert()))
1043 finally:
1044 s.close()
1045
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001046
1047try:
1048 import threading
1049except ImportError:
1050 _have_threads = False
1051else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001052 _have_threads = True
1053
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001054 from test.ssl_servers import make_https_server
1055
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001056 class ThreadedEchoServer(threading.Thread):
1057
1058 class ConnectionHandler(threading.Thread):
1059
1060 """A mildly complicated class, because we want it to work both
1061 with and without the SSL wrapper around the socket connection, so
1062 that we can test the STARTTLS functionality."""
1063
Bill Janssen6e027db2007-11-15 22:23:56 +00001064 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001065 self.server = server
1066 self.running = False
1067 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001068 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001069 self.sock.setblocking(1)
1070 self.sslconn = None
1071 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001072 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073
Antoine Pitrou480a1242010-04-28 21:37:09 +00001074 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001075 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001076 self.sslconn = self.server.context.wrap_socket(
1077 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001078 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001079 except (ssl.SSLError, ConnectionResetError) as e:
1080 # We treat ConnectionResetError as though it were an
1081 # SSLError - OpenSSL on Ubuntu abruptly closes the
1082 # connection when asked to use an unsupported protocol.
1083 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001084 # XXX Various errors can have happened here, for example
1085 # a mismatching protocol version, an invalid certificate,
1086 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001087 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001088 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001089 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001090 self.running = False
1091 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001092 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001094 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001095 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001096 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001097 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001098 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1099 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001100 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001101 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1102 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001103 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001104 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001105 sys.stdout.write(" server: selected protocol is now "
1106 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107 return True
1108
1109 def read(self):
1110 if self.sslconn:
1111 return self.sslconn.read()
1112 else:
1113 return self.sock.recv(1024)
1114
1115 def write(self, bytes):
1116 if self.sslconn:
1117 return self.sslconn.write(bytes)
1118 else:
1119 return self.sock.send(bytes)
1120
1121 def close(self):
1122 if self.sslconn:
1123 self.sslconn.close()
1124 else:
1125 self.sock.close()
1126
Antoine Pitrou480a1242010-04-28 21:37:09 +00001127 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001128 self.running = True
1129 if not self.server.starttls_server:
1130 if not self.wrap_conn():
1131 return
1132 while self.running:
1133 try:
1134 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001135 stripped = msg.strip()
1136 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001137 # eof, so quit this handler
1138 self.running = False
1139 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001140 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001141 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001142 sys.stdout.write(" server: client closed connection\n")
1143 self.close()
1144 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001145 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001146 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001147 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001149 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 if not self.wrap_conn():
1151 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001152 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001153 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001154 if support.verbose and self.server.connectionchatty:
1155 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001156 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001157 self.sock = self.sslconn.unwrap()
1158 self.sslconn = None
1159 if support.verbose and self.server.connectionchatty:
1160 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001161 elif stripped == b'CB tls-unique':
1162 if support.verbose and self.server.connectionchatty:
1163 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1164 data = self.sslconn.get_channel_binding("tls-unique")
1165 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001167 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001168 self.server.connectionchatty):
1169 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001170 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1171 % (msg, ctype, msg.lower(), ctype))
1172 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001173 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 if self.server.chatty:
1175 handle_error("Test server failure:\n")
1176 self.close()
1177 self.running = False
1178 # normally, we'd just stop here, but for the test
1179 # harness, we want to stop the server
1180 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001181
Antoine Pitroub5218772010-05-21 09:56:06 +00001182 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001183 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001184 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001185 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001186 if context:
1187 self.context = context
1188 else:
1189 self.context = ssl.SSLContext(ssl_version
1190 if ssl_version is not None
1191 else ssl.PROTOCOL_TLSv1)
1192 self.context.verify_mode = (certreqs if certreqs is not None
1193 else ssl.CERT_NONE)
1194 if cacerts:
1195 self.context.load_verify_locations(cacerts)
1196 if certificate:
1197 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001198 if npn_protocols:
1199 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001200 if ciphers:
1201 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001202 self.chatty = chatty
1203 self.connectionchatty = connectionchatty
1204 self.starttls_server = starttls_server
1205 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001206 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001207 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001208 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001209 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001210 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001212 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001213
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001214 def __enter__(self):
1215 self.start(threading.Event())
1216 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001217 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001218
1219 def __exit__(self, *args):
1220 self.stop()
1221 self.join()
1222
Antoine Pitrou480a1242010-04-28 21:37:09 +00001223 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001224 self.flag = flag
1225 threading.Thread.start(self)
1226
Antoine Pitrou480a1242010-04-28 21:37:09 +00001227 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001228 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001229 self.sock.listen(5)
1230 self.active = True
1231 if self.flag:
1232 # signal an event
1233 self.flag.set()
1234 while self.active:
1235 try:
1236 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001237 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001238 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001239 + repr(connaddr) + '\n')
1240 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001242 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 except socket.timeout:
1244 pass
1245 except KeyboardInterrupt:
1246 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001247 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001248
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001250 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001251
Bill Janssen54cc54c2007-12-14 22:08:56 +00001252 class AsyncoreEchoServer(threading.Thread):
1253
1254 # this one's based on asyncore.dispatcher
1255
1256 class EchoServer (asyncore.dispatcher):
1257
1258 class ConnectionHandler (asyncore.dispatcher_with_send):
1259
1260 def __init__(self, conn, certfile):
1261 self.socket = ssl.wrap_socket(conn, server_side=True,
1262 certfile=certfile,
1263 do_handshake_on_connect=False)
1264 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001265 self._ssl_accepting = True
1266 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001267
1268 def readable(self):
1269 if isinstance(self.socket, ssl.SSLSocket):
1270 while self.socket.pending() > 0:
1271 self.handle_read_event()
1272 return True
1273
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001274 def _do_ssl_handshake(self):
1275 try:
1276 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001277 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1278 return
1279 except ssl.SSLEOFError:
1280 return self.handle_close()
1281 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001282 raise
1283 except socket.error as err:
1284 if err.args[0] == errno.ECONNABORTED:
1285 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001286 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001287 self._ssl_accepting = False
1288
1289 def handle_read(self):
1290 if self._ssl_accepting:
1291 self._do_ssl_handshake()
1292 else:
1293 data = self.recv(1024)
1294 if support.verbose:
1295 sys.stdout.write(" server: read %s from client\n" % repr(data))
1296 if not data:
1297 self.close()
1298 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001299 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001300
1301 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001302 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001303 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001304 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1305
1306 def handle_error(self):
1307 raise
1308
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001309 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001310 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001311 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1312 self.port = support.bind_port(sock, '')
1313 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001314 self.listen(5)
1315
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001316 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001317 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001318 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1319 self.ConnectionHandler(sock_obj, self.certfile)
1320
1321 def handle_error(self):
1322 raise
1323
Trent Nelson78520002008-04-10 20:54:35 +00001324 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001325 self.flag = None
1326 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001327 self.server = self.EchoServer(certfile)
1328 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001329 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001330 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001331
1332 def __str__(self):
1333 return "<%s %s>" % (self.__class__.__name__, self.server)
1334
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001335 def __enter__(self):
1336 self.start(threading.Event())
1337 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001338 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001339
1340 def __exit__(self, *args):
1341 if support.verbose:
1342 sys.stdout.write(" cleanup: stopping server.\n")
1343 self.stop()
1344 if support.verbose:
1345 sys.stdout.write(" cleanup: joining server thread.\n")
1346 self.join()
1347 if support.verbose:
1348 sys.stdout.write(" cleanup: successfully joined.\n")
1349
Bill Janssen54cc54c2007-12-14 22:08:56 +00001350 def start (self, flag=None):
1351 self.flag = flag
1352 threading.Thread.start(self)
1353
Antoine Pitrou480a1242010-04-28 21:37:09 +00001354 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001355 self.active = True
1356 if self.flag:
1357 self.flag.set()
1358 while self.active:
1359 try:
1360 asyncore.loop(1)
1361 except:
1362 pass
1363
Antoine Pitrou480a1242010-04-28 21:37:09 +00001364 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001365 self.active = False
1366 self.server.close()
1367
Antoine Pitrou480a1242010-04-28 21:37:09 +00001368 def bad_cert_test(certfile):
1369 """
1370 Launch a server with CERT_REQUIRED, and check that trying to
1371 connect to it with the given client certificate fails.
1372 """
Trent Nelson78520002008-04-10 20:54:35 +00001373 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001374 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001375 cacerts=CERTFILE, chatty=False,
1376 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001377 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001378 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001379 with socket.socket() as sock:
1380 s = ssl.wrap_socket(sock,
1381 certfile=certfile,
1382 ssl_version=ssl.PROTOCOL_TLSv1)
1383 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001384 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001385 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001386 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001387 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001388 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001389 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001390 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001391 if x.errno != errno.ENOENT:
1392 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001393 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001394 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001396 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001397
Antoine Pitroub5218772010-05-21 09:56:06 +00001398 def server_params_test(client_context, server_context, indata=b"FOO\n",
1399 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 """
1401 Launch a server, connect a client to it and try various reads
1402 and writes.
1403 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001404 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001405 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001406 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001407 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001408 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001409 with client_context.wrap_socket(socket.socket()) as s:
1410 s.connect((HOST, server.port))
1411 for arg in [indata, bytearray(indata), memoryview(indata)]:
1412 if connectionchatty:
1413 if support.verbose:
1414 sys.stdout.write(
1415 " client: sending %r...\n" % indata)
1416 s.write(arg)
1417 outdata = s.read()
1418 if connectionchatty:
1419 if support.verbose:
1420 sys.stdout.write(" client: read %r\n" % outdata)
1421 if outdata != indata.lower():
1422 raise AssertionError(
1423 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1424 % (outdata[:20], len(outdata),
1425 indata[:20].lower(), len(indata)))
1426 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001427 if connectionchatty:
1428 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001429 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001430 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001431 'compression': s.compression(),
1432 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001433 'client_npn_protocol': s.selected_npn_protocol()
1434 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001435 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001436 stats['server_npn_protocols'] = server.selected_protocols
1437 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001438
Antoine Pitroub5218772010-05-21 09:56:06 +00001439 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1440 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001441 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001442 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001443 certtype = {
1444 ssl.CERT_NONE: "CERT_NONE",
1445 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1446 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1447 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001448 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001449 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001450 sys.stdout.write(formatstr %
1451 (ssl.get_protocol_name(client_protocol),
1452 ssl.get_protocol_name(server_protocol),
1453 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001454 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001455 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001456 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001457 server_context.options |= server_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001458 for ctx in (client_context, server_context):
1459 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001460 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1461 # will send an SSLv3 hello (rather than SSLv2) starting from
1462 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001463 ctx.set_ciphers("ALL")
1464 ctx.load_cert_chain(CERTFILE)
1465 ctx.load_verify_locations(CERTFILE)
1466 try:
1467 server_params_test(client_context, server_context,
1468 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001469 # Protocol mismatch can result in either an SSLError, or a
1470 # "Connection reset by peer" error.
1471 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001472 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001473 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001474 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001476 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001477 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001478 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001479 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001480 "Client protocol %s succeeded with server protocol %s!"
1481 % (ssl.get_protocol_name(client_protocol),
1482 ssl.get_protocol_name(server_protocol)))
1483
1484
Bill Janssen6e027db2007-11-15 22:23:56 +00001485 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001486
Antoine Pitrou23df4832010-08-04 17:14:06 +00001487 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001488 def test_echo(self):
1489 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001490 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001491 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001492 for protocol in PROTOCOLS:
1493 context = ssl.SSLContext(protocol)
1494 context.load_cert_chain(CERTFILE)
1495 server_params_test(context, context,
1496 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001497
Antoine Pitrou480a1242010-04-28 21:37:09 +00001498 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001499 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001500 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001501 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1502 context.verify_mode = ssl.CERT_REQUIRED
1503 context.load_verify_locations(CERTFILE)
1504 context.load_cert_chain(CERTFILE)
1505 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001506 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001507 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001508 s.connect((HOST, server.port))
1509 cert = s.getpeercert()
1510 self.assertTrue(cert, "Can't get peer certificate.")
1511 cipher = s.cipher()
1512 if support.verbose:
1513 sys.stdout.write(pprint.pformat(cert) + '\n')
1514 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1515 if 'subject' not in cert:
1516 self.fail("No subject field in certificate: %s." %
1517 pprint.pformat(cert))
1518 if ((('organizationName', 'Python Software Foundation'),)
1519 not in cert['subject']):
1520 self.fail(
1521 "Missing or invalid 'organizationName' field in certificate subject; "
1522 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001523 self.assertIn('notBefore', cert)
1524 self.assertIn('notAfter', cert)
1525 before = ssl.cert_time_to_seconds(cert['notBefore'])
1526 after = ssl.cert_time_to_seconds(cert['notAfter'])
1527 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001528 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001529
Antoine Pitrou480a1242010-04-28 21:37:09 +00001530 def test_empty_cert(self):
1531 """Connecting with an empty cert file"""
1532 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1533 "nullcert.pem"))
1534 def test_malformed_cert(self):
1535 """Connecting with a badly formatted certificate (syntax error)"""
1536 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1537 "badcert.pem"))
1538 def test_nonexisting_cert(self):
1539 """Connecting with a non-existing cert file"""
1540 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1541 "wrongcert.pem"))
1542 def test_malformed_key(self):
1543 """Connecting with a badly formatted key (syntax error)"""
1544 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1545 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001546
Antoine Pitrou480a1242010-04-28 21:37:09 +00001547 def test_rude_shutdown(self):
1548 """A brutal shutdown of an SSL server should raise an IOError
1549 in the client when attempting handshake.
1550 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001551 listener_ready = threading.Event()
1552 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001553
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001554 s = socket.socket()
1555 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001556
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001557 # `listener` runs in a thread. It sits in an accept() until
1558 # the main thread connects. Then it rudely closes the socket,
1559 # and sets Event `listener_gone` to let the main thread know
1560 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001561 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001562 s.listen(5)
1563 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001564 newsock, addr = s.accept()
1565 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001566 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001567 listener_gone.set()
1568
1569 def connector():
1570 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001571 with socket.socket() as c:
1572 c.connect((HOST, port))
1573 listener_gone.wait()
1574 try:
1575 ssl_sock = ssl.wrap_socket(c)
1576 except IOError:
1577 pass
1578 else:
1579 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001580
1581 t = threading.Thread(target=listener)
1582 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001583 try:
1584 connector()
1585 finally:
1586 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001587
Antoine Pitrou23df4832010-08-04 17:14:06 +00001588 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001589 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1590 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001591 def test_protocol_sslv2(self):
1592 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001593 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001594 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001595 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1596 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1597 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001598 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001599 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1600 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001601 # SSLv23 client with specific SSL options
1602 if no_sslv2_implies_sslv3_hello():
1603 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1604 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1605 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001606 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00001607 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001608 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00001609 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001610
Antoine Pitrou23df4832010-08-04 17:14:06 +00001611 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001612 def test_protocol_sslv23(self):
1613 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001614 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001615 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001616 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1617 try:
1618 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1619 except (ssl.SSLError, socket.error) as x:
1620 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1621 if support.verbose:
1622 sys.stdout.write(
1623 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1624 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001625 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1626 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1627 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001628
Antoine Pitrou480a1242010-04-28 21:37:09 +00001629 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1630 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1631 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001632
Antoine Pitrou480a1242010-04-28 21:37:09 +00001633 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1634 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1635 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636
Antoine Pitroub5218772010-05-21 09:56:06 +00001637 # Server with specific SSL options
1638 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1639 server_options=ssl.OP_NO_SSLv3)
1640 # Will choose TLSv1
1641 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1642 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1643 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1644 server_options=ssl.OP_NO_TLSv1)
1645
1646
Antoine Pitrou23df4832010-08-04 17:14:06 +00001647 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001648 def test_protocol_sslv3(self):
1649 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001650 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001651 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001652 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1653 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1654 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001655 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1656 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001657 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1658 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001659 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001660 if no_sslv2_implies_sslv3_hello():
1661 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1662 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1663 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001664
Antoine Pitrou23df4832010-08-04 17:14:06 +00001665 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001666 def test_protocol_tlsv1(self):
1667 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001668 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001669 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001670 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1671 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1672 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001673 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1674 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001675 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001676 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1677 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001678
Antoine Pitrou480a1242010-04-28 21:37:09 +00001679 def test_starttls(self):
1680 """Switching from clear text to encrypted and back again."""
1681 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 +00001682
Trent Nelson78520002008-04-10 20:54:35 +00001683 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001684 ssl_version=ssl.PROTOCOL_TLSv1,
1685 starttls_server=True,
1686 chatty=True,
1687 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001688 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001689 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001690 s = socket.socket()
1691 s.setblocking(1)
1692 s.connect((HOST, server.port))
1693 if support.verbose:
1694 sys.stdout.write("\n")
1695 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001696 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001697 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001698 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001699 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001700 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001701 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001702 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001703 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001704 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001705 msg = outdata.strip().lower()
1706 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1707 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001708 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001709 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001710 " client: read %r from server, starting TLS...\n"
1711 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001712 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1713 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001714 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1715 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001716 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001717 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001718 " client: read %r from server, ending TLS...\n"
1719 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001720 s = conn.unwrap()
1721 wrapped = False
1722 else:
1723 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001724 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001725 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001726 if support.verbose:
1727 sys.stdout.write(" client: closing connection.\n")
1728 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001729 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001730 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001731 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001732 if wrapped:
1733 conn.close()
1734 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001735 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001736
Antoine Pitrou480a1242010-04-28 21:37:09 +00001737 def test_socketserver(self):
1738 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001739 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001740 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001741 if support.verbose:
1742 sys.stdout.write('\n')
1743 with open(CERTFILE, 'rb') as f:
1744 d1 = f.read()
1745 d2 = ''
1746 # now fetch the same data from the HTTPS server
1747 url = 'https://%s:%d/%s' % (
1748 HOST, server.port, os.path.split(CERTFILE)[1])
1749 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001750 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001751 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001752 if dlen and (int(dlen) > 0):
1753 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001754 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001755 sys.stdout.write(
1756 " client: read %d bytes from remote server '%s'\n"
1757 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001758 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001759 f.close()
1760 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001761
Antoine Pitrou480a1242010-04-28 21:37:09 +00001762 def test_asyncore_server(self):
1763 """Check the example asyncore integration."""
1764 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001765
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001766 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001767 sys.stdout.write("\n")
1768
Antoine Pitrou480a1242010-04-28 21:37:09 +00001769 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001770 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001771 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001772 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001773 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001774 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001775 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001776 " client: sending %r...\n" % indata)
1777 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001778 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001779 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001780 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001781 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001782 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001783 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1784 % (outdata[:20], len(outdata),
1785 indata[:20].lower(), len(indata)))
1786 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001787 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001788 sys.stdout.write(" client: closing connection.\n")
1789 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001790 if support.verbose:
1791 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001792
Antoine Pitrou480a1242010-04-28 21:37:09 +00001793 def test_recv_send(self):
1794 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001795 if support.verbose:
1796 sys.stdout.write("\n")
1797
1798 server = ThreadedEchoServer(CERTFILE,
1799 certreqs=ssl.CERT_NONE,
1800 ssl_version=ssl.PROTOCOL_TLSv1,
1801 cacerts=CERTFILE,
1802 chatty=True,
1803 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001804 with server:
1805 s = ssl.wrap_socket(socket.socket(),
1806 server_side=False,
1807 certfile=CERTFILE,
1808 ca_certs=CERTFILE,
1809 cert_reqs=ssl.CERT_NONE,
1810 ssl_version=ssl.PROTOCOL_TLSv1)
1811 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001812 # helper methods for standardising recv* method signatures
1813 def _recv_into():
1814 b = bytearray(b"\0"*100)
1815 count = s.recv_into(b)
1816 return b[:count]
1817
1818 def _recvfrom_into():
1819 b = bytearray(b"\0"*100)
1820 count, addr = s.recvfrom_into(b)
1821 return b[:count]
1822
1823 # (name, method, whether to expect success, *args)
1824 send_methods = [
1825 ('send', s.send, True, []),
1826 ('sendto', s.sendto, False, ["some.address"]),
1827 ('sendall', s.sendall, True, []),
1828 ]
1829 recv_methods = [
1830 ('recv', s.recv, True, []),
1831 ('recvfrom', s.recvfrom, False, ["some.address"]),
1832 ('recv_into', _recv_into, True, []),
1833 ('recvfrom_into', _recvfrom_into, False, []),
1834 ]
1835 data_prefix = "PREFIX_"
1836
1837 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001838 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001839 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001840 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001841 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001842 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001843 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001844 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001845 "<<{outdata:r}>> ({nout:d}) received; "
1846 "expected <<{indata:r}>> ({nin:d})\n".format(
1847 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001848 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001849 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001850 )
1851 )
1852 except ValueError as e:
1853 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001854 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001855 "Failed to send with method <<{name:s}>>; "
1856 "expected to succeed.\n".format(name=meth_name)
1857 )
1858 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001859 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001860 "Method <<{name:s}>> failed with unexpected "
1861 "exception message: {exp:s}\n".format(
1862 name=meth_name, exp=e
1863 )
1864 )
1865
1866 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001867 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001868 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001869 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001870 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001871 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001872 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001873 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001874 "<<{outdata:r}>> ({nout:d}) received; "
1875 "expected <<{indata:r}>> ({nin:d})\n".format(
1876 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001877 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001878 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001879 )
1880 )
1881 except ValueError as e:
1882 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001883 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001884 "Failed to receive with method <<{name:s}>>; "
1885 "expected to succeed.\n".format(name=meth_name)
1886 )
1887 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001888 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001889 "Method <<{name:s}>> failed with unexpected "
1890 "exception message: {exp:s}\n".format(
1891 name=meth_name, exp=e
1892 )
1893 )
1894 # consume data
1895 s.read()
1896
Nick Coghlan513886a2011-08-28 00:00:27 +10001897 # Make sure sendmsg et al are disallowed to avoid
1898 # inadvertent disclosure of data and/or corruption
1899 # of the encrypted data stream
1900 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1901 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1902 self.assertRaises(NotImplementedError,
1903 s.recvmsg_into, bytearray(100))
1904
Antoine Pitrou480a1242010-04-28 21:37:09 +00001905 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001906 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001907
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001908 def test_handshake_timeout(self):
1909 # Issue #5103: SSL handshake must respect the socket timeout
1910 server = socket.socket(socket.AF_INET)
1911 host = "127.0.0.1"
1912 port = support.bind_port(server)
1913 started = threading.Event()
1914 finish = False
1915
1916 def serve():
1917 server.listen(5)
1918 started.set()
1919 conns = []
1920 while not finish:
1921 r, w, e = select.select([server], [], [], 0.1)
1922 if server in r:
1923 # Let the socket hang around rather than having
1924 # it closed by garbage collection.
1925 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001926 for sock in conns:
1927 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001928
1929 t = threading.Thread(target=serve)
1930 t.start()
1931 started.wait()
1932
1933 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001934 try:
1935 c = socket.socket(socket.AF_INET)
1936 c.settimeout(0.2)
1937 c.connect((host, port))
1938 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001939 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001940 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001941 finally:
1942 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001943 try:
1944 c = socket.socket(socket.AF_INET)
1945 c = ssl.wrap_socket(c)
1946 c.settimeout(0.2)
1947 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001948 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001949 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001950 finally:
1951 c.close()
1952 finally:
1953 finish = True
1954 t.join()
1955 server.close()
1956
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001957 def test_server_accept(self):
1958 # Issue #16357: accept() on a SSLSocket created through
1959 # SSLContext.wrap_socket().
1960 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1961 context.verify_mode = ssl.CERT_REQUIRED
1962 context.load_verify_locations(CERTFILE)
1963 context.load_cert_chain(CERTFILE)
1964 server = socket.socket(socket.AF_INET)
1965 host = "127.0.0.1"
1966 port = support.bind_port(server)
1967 server = context.wrap_socket(server, server_side=True)
1968
1969 evt = threading.Event()
1970 remote = None
1971 peer = None
1972 def serve():
1973 nonlocal remote, peer
1974 server.listen(5)
1975 # Block on the accept and wait on the connection to close.
1976 evt.set()
1977 remote, peer = server.accept()
1978 remote.recv(1)
1979
1980 t = threading.Thread(target=serve)
1981 t.start()
1982 # Client wait until server setup and perform a connect.
1983 evt.wait()
1984 client = context.wrap_socket(socket.socket())
1985 client.connect((host, port))
1986 client_addr = client.getsockname()
1987 client.close()
1988 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001989 remote.close()
1990 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001991 # Sanity checks.
1992 self.assertIsInstance(remote, ssl.SSLSocket)
1993 self.assertEqual(peer, client_addr)
1994
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001995 def test_default_ciphers(self):
1996 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1997 try:
1998 # Force a set of weak ciphers on our client context
1999 context.set_ciphers("DES")
2000 except ssl.SSLError:
2001 self.skipTest("no DES cipher available")
2002 with ThreadedEchoServer(CERTFILE,
2003 ssl_version=ssl.PROTOCOL_SSLv23,
2004 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002005 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002006 with self.assertRaises((OSError, ssl.SSLError)):
2007 s.connect((HOST, server.port))
2008 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2009
Antoine Pitroud6494802011-07-21 01:11:30 +02002010 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2011 "'tls-unique' channel binding not available")
2012 def test_tls_unique_channel_binding(self):
2013 """Test tls-unique channel binding."""
2014 if support.verbose:
2015 sys.stdout.write("\n")
2016
2017 server = ThreadedEchoServer(CERTFILE,
2018 certreqs=ssl.CERT_NONE,
2019 ssl_version=ssl.PROTOCOL_TLSv1,
2020 cacerts=CERTFILE,
2021 chatty=True,
2022 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002023 with server:
2024 s = ssl.wrap_socket(socket.socket(),
2025 server_side=False,
2026 certfile=CERTFILE,
2027 ca_certs=CERTFILE,
2028 cert_reqs=ssl.CERT_NONE,
2029 ssl_version=ssl.PROTOCOL_TLSv1)
2030 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002031 # get the data
2032 cb_data = s.get_channel_binding("tls-unique")
2033 if support.verbose:
2034 sys.stdout.write(" got channel binding data: {0!r}\n"
2035 .format(cb_data))
2036
2037 # check if it is sane
2038 self.assertIsNotNone(cb_data)
2039 self.assertEqual(len(cb_data), 12) # True for TLSv1
2040
2041 # and compare with the peers version
2042 s.write(b"CB tls-unique\n")
2043 peer_data_repr = s.read().strip()
2044 self.assertEqual(peer_data_repr,
2045 repr(cb_data).encode("us-ascii"))
2046 s.close()
2047
2048 # now, again
2049 s = ssl.wrap_socket(socket.socket(),
2050 server_side=False,
2051 certfile=CERTFILE,
2052 ca_certs=CERTFILE,
2053 cert_reqs=ssl.CERT_NONE,
2054 ssl_version=ssl.PROTOCOL_TLSv1)
2055 s.connect((HOST, server.port))
2056 new_cb_data = s.get_channel_binding("tls-unique")
2057 if support.verbose:
2058 sys.stdout.write(" got another channel binding data: {0!r}\n"
2059 .format(new_cb_data))
2060 # is it really unique
2061 self.assertNotEqual(cb_data, new_cb_data)
2062 self.assertIsNotNone(cb_data)
2063 self.assertEqual(len(cb_data), 12) # True for TLSv1
2064 s.write(b"CB tls-unique\n")
2065 peer_data_repr = s.read().strip()
2066 self.assertEqual(peer_data_repr,
2067 repr(new_cb_data).encode("us-ascii"))
2068 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002069
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002070 def test_compression(self):
2071 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2072 context.load_cert_chain(CERTFILE)
2073 stats = server_params_test(context, context,
2074 chatty=True, connectionchatty=True)
2075 if support.verbose:
2076 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2077 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2078
2079 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2080 "ssl.OP_NO_COMPRESSION needed for this test")
2081 def test_compression_disabled(self):
2082 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2083 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002084 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002085 stats = server_params_test(context, context,
2086 chatty=True, connectionchatty=True)
2087 self.assertIs(stats['compression'], None)
2088
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002089 def test_dh_params(self):
2090 # Check we can get a connection with ephemeral Diffie-Hellman
2091 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2092 context.load_cert_chain(CERTFILE)
2093 context.load_dh_params(DHFILE)
2094 context.set_ciphers("kEDH")
2095 stats = server_params_test(context, context,
2096 chatty=True, connectionchatty=True)
2097 cipher = stats["cipher"][0]
2098 parts = cipher.split("-")
2099 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2100 self.fail("Non-DH cipher: " + cipher[0])
2101
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002102 def test_selected_npn_protocol(self):
2103 # selected_npn_protocol() is None unless NPN is used
2104 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2105 context.load_cert_chain(CERTFILE)
2106 stats = server_params_test(context, context,
2107 chatty=True, connectionchatty=True)
2108 self.assertIs(stats['client_npn_protocol'], None)
2109
2110 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2111 def test_npn_protocols(self):
2112 server_protocols = ['http/1.1', 'spdy/2']
2113 protocol_tests = [
2114 (['http/1.1', 'spdy/2'], 'http/1.1'),
2115 (['spdy/2', 'http/1.1'], 'http/1.1'),
2116 (['spdy/2', 'test'], 'spdy/2'),
2117 (['abc', 'def'], 'abc')
2118 ]
2119 for client_protocols, expected in protocol_tests:
2120 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2121 server_context.load_cert_chain(CERTFILE)
2122 server_context.set_npn_protocols(server_protocols)
2123 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2124 client_context.load_cert_chain(CERTFILE)
2125 client_context.set_npn_protocols(client_protocols)
2126 stats = server_params_test(client_context, server_context,
2127 chatty=True, connectionchatty=True)
2128
2129 msg = "failed trying %s (s) and %s (c).\n" \
2130 "was expecting %s, but got %%s from the %%s" \
2131 % (str(server_protocols), str(client_protocols),
2132 str(expected))
2133 client_result = stats['client_npn_protocol']
2134 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2135 server_result = stats['server_npn_protocols'][-1] \
2136 if len(stats['server_npn_protocols']) else 'nothing'
2137 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2138
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002139
Thomas Woutersed03b412007-08-28 21:37:11 +00002140def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002141 if support.verbose:
2142 plats = {
2143 'Linux': platform.linux_distribution,
2144 'Mac': platform.mac_ver,
2145 'Windows': platform.win32_ver,
2146 }
2147 for name, func in plats.items():
2148 plat = func()
2149 if plat and plat[0]:
2150 plat = '%s %r' % (name, plat)
2151 break
2152 else:
2153 plat = repr(platform.platform())
2154 print("test_ssl: testing with %r %r" %
2155 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2156 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002157 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002158
Antoine Pitrou152efa22010-05-16 18:19:27 +00002159 for filename in [
Martin Panter3d81d932016-01-14 09:36:00 +00002160 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002161 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2162 BADCERT, BADKEY, EMPTYCERT]:
2163 if not os.path.exists(filename):
2164 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002165
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002166 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002167
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002168 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002169 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002170
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002171 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002172 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002173 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002174 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002175
Antoine Pitrou480a1242010-04-28 21:37:09 +00002176 try:
2177 support.run_unittest(*tests)
2178 finally:
2179 if _have_threads:
2180 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002181
2182if __name__ == "__main__":
2183 test_main()