blob: 9fc6027afb44ccf955b1d668a6abf6842cd28b79 [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
32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Antoine Pitrou81564092010-10-08 23:06:24 +000034# The custom key and certificate files used in test_ssl are generated
35# using Lib/test/make_ssl_certs.py.
36# Other certificates are simply fetched from the Internet servers they
37# are meant to authenticate.
38
Antoine Pitrou152efa22010-05-16 18:19:27 +000039CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020045CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
46ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
47KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000048CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000049BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
52
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020057NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020058NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000059
Antoine Pitrou0e576f12011-12-22 10:03:38 +010060DHFILE = data_file("dh512.pem")
61BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000062
Thomas Woutersed03b412007-08-28 21:37:11 +000063def handle_error(prefix):
64 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000065 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000066 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000067
Antoine Pitroub5218772010-05-21 09:56:06 +000068def can_clear_options():
69 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020070 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000071
72def no_sslv2_implies_sslv3_hello():
73 # 0.9.7h or higher
74 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
75
Thomas Woutersed03b412007-08-28 21:37:11 +000076
Antoine Pitrou23df4832010-08-04 17:14:06 +000077# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
78def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020079 if hasattr(ssl, 'PROTOCOL_SSLv2'):
80 @functools.wraps(func)
81 def f(*args, **kwargs):
82 try:
83 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
84 except ssl.SSLError:
85 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
86 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
87 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
88 return func(*args, **kwargs)
89 return f
90 else:
91 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000092
93
Antoine Pitrou152efa22010-05-16 18:19:27 +000094class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000095
Antoine Pitrou480a1242010-04-28 21:37:09 +000096 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020097 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 ssl.PROTOCOL_SSLv23
99 ssl.PROTOCOL_SSLv3
100 ssl.PROTOCOL_TLSv1
101 ssl.CERT_NONE
102 ssl.CERT_OPTIONAL
103 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100104 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100105 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100106 if ssl.HAS_ECDH:
107 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100108 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
109 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000110 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100111 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000112
Antoine Pitrou480a1242010-04-28 21:37:09 +0000113 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000115 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000116 sys.stdout.write("\n RAND_status is %d (%s)\n"
117 % (v, (v and "sufficient randomness") or
118 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200119
120 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
121 self.assertEqual(len(data), 16)
122 self.assertEqual(is_cryptographic, v == 1)
123 if v:
124 data = ssl.RAND_bytes(16)
125 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200126 else:
127 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200128
Victor Stinner1e81a392013-12-19 16:47:04 +0100129 # negative num is invalid
130 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
131 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
132
Jesus Ceac8754a12012-09-11 02:00:58 +0200133 self.assertRaises(TypeError, ssl.RAND_egd, 1)
134 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000135 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000136
Christian Heimesf77b4b22013-08-21 13:26:05 +0200137 @unittest.skipUnless(os.name == 'posix', 'requires posix')
138 def test_random_fork(self):
139 status = ssl.RAND_status()
140 if not status:
141 self.fail("OpenSSL's PRNG has insufficient randomness")
142
143 rfd, wfd = os.pipe()
144 pid = os.fork()
145 if pid == 0:
146 try:
147 os.close(rfd)
148 child_random = ssl.RAND_pseudo_bytes(16)[0]
149 self.assertEqual(len(child_random), 16)
150 os.write(wfd, child_random)
151 os.close(wfd)
152 except BaseException:
153 os._exit(1)
154 else:
155 os._exit(0)
156 else:
157 os.close(wfd)
158 self.addCleanup(os.close, rfd)
159 _, status = os.waitpid(pid, 0)
160 self.assertEqual(status, 0)
161
162 child_random = os.read(rfd, 16)
163 self.assertEqual(len(child_random), 16)
164 parent_random = ssl.RAND_pseudo_bytes(16)[0]
165 self.assertEqual(len(parent_random), 16)
166
167 self.assertNotEqual(child_random, parent_random)
168
Antoine Pitrou480a1242010-04-28 21:37:09 +0000169 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000170 # note that this uses an 'unofficial' function in _ssl.c,
171 # provided solely for this test, to exercise the certificate
172 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000173 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000174 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000175 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200176 self.assertEqual(p['issuer'],
177 ((('countryName', 'XY'),),
178 (('localityName', 'Castle Anthrax'),),
179 (('organizationName', 'Python Software Foundation'),),
180 (('commonName', 'localhost'),))
181 )
182 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
183 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
184 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
185 self.assertEqual(p['subject'],
186 ((('countryName', 'XY'),),
187 (('localityName', 'Castle Anthrax'),),
188 (('organizationName', 'Python Software Foundation'),),
189 (('commonName', 'localhost'),))
190 )
191 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
192 # Issue #13034: the subjectAltName in some certificates
193 # (notably projects.developer.nokia.com:443) wasn't parsed
194 p = ssl._ssl._test_decode_cert(NOKIACERT)
195 if support.verbose:
196 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
197 self.assertEqual(p['subjectAltName'],
198 (('DNS', 'projects.developer.nokia.com'),
199 ('DNS', 'projects.forum.nokia.com'))
200 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000201
Christian Heimes824f7f32013-08-17 00:54:47 +0200202 def test_parse_cert_CVE_2013_4238(self):
203 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
204 if support.verbose:
205 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
206 subject = ((('countryName', 'US'),),
207 (('stateOrProvinceName', 'Oregon'),),
208 (('localityName', 'Beaverton'),),
209 (('organizationName', 'Python Software Foundation'),),
210 (('organizationalUnitName', 'Python Core Development'),),
211 (('commonName', 'null.python.org\x00example.org'),),
212 (('emailAddress', 'python-dev@python.org'),))
213 self.assertEqual(p['subject'], subject)
214 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200215 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
216 san = (('DNS', 'altnull.python.org\x00example.com'),
217 ('email', 'null@python.org\x00user@example.org'),
218 ('URI', 'http://null.python.org\x00http://example.org'),
219 ('IP Address', '192.0.2.1'),
220 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
221 else:
222 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
223 san = (('DNS', 'altnull.python.org\x00example.com'),
224 ('email', 'null@python.org\x00user@example.org'),
225 ('URI', 'http://null.python.org\x00http://example.org'),
226 ('IP Address', '192.0.2.1'),
227 ('IP Address', '<invalid>'))
228
229 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200230
Antoine Pitrou480a1242010-04-28 21:37:09 +0000231 def test_DER_to_PEM(self):
232 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
233 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000234 d1 = ssl.PEM_cert_to_DER_cert(pem)
235 p2 = ssl.DER_cert_to_PEM_cert(d1)
236 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000237 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000238 if not p2.startswith(ssl.PEM_HEADER + '\n'):
239 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
240 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
241 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000242
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000243 def test_openssl_version(self):
244 n = ssl.OPENSSL_VERSION_NUMBER
245 t = ssl.OPENSSL_VERSION_INFO
246 s = ssl.OPENSSL_VERSION
247 self.assertIsInstance(n, int)
248 self.assertIsInstance(t, tuple)
249 self.assertIsInstance(s, str)
250 # Some sanity checks follow
251 # >= 0.9
252 self.assertGreaterEqual(n, 0x900000)
253 # < 2.0
254 self.assertLess(n, 0x20000000)
255 major, minor, fix, patch, status = t
256 self.assertGreaterEqual(major, 0)
257 self.assertLess(major, 2)
258 self.assertGreaterEqual(minor, 0)
259 self.assertLess(minor, 256)
260 self.assertGreaterEqual(fix, 0)
261 self.assertLess(fix, 256)
262 self.assertGreaterEqual(patch, 0)
263 self.assertLessEqual(patch, 26)
264 self.assertGreaterEqual(status, 0)
265 self.assertLessEqual(status, 15)
266 # Version string as returned by OpenSSL, the format might change
267 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
268 (s, t))
269
Antoine Pitrou9d543662010-04-23 23:10:32 +0000270 @support.cpython_only
271 def test_refcycle(self):
272 # Issue #7943: an SSL object doesn't create reference cycles with
273 # itself.
274 s = socket.socket(socket.AF_INET)
275 ss = ssl.wrap_socket(s)
276 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100277 with support.check_warnings(("", ResourceWarning)):
278 del ss
279 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000280
Antoine Pitroua468adc2010-09-14 14:43:44 +0000281 def test_wrapped_unconnected(self):
282 # Methods on an unconnected SSLSocket propagate the original
283 # socket.error raise by the underlying socket object.
284 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100285 with ssl.wrap_socket(s) as ss:
286 self.assertRaises(socket.error, ss.recv, 1)
287 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
288 self.assertRaises(socket.error, ss.recvfrom, 1)
289 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
290 self.assertRaises(socket.error, ss.send, b'x')
291 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000292
Antoine Pitrou40f08742010-04-24 22:04:40 +0000293 def test_timeout(self):
294 # Issue #8524: when creating an SSL socket, the timeout of the
295 # original socket should be retained.
296 for timeout in (None, 0.0, 5.0):
297 s = socket.socket(socket.AF_INET)
298 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100299 with ssl.wrap_socket(s) as ss:
300 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000301
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000302 def test_errors(self):
303 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000304 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000305 "certfile must be specified",
306 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000307 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000308 "certfile must be specified for server-side operations",
309 ssl.wrap_socket, sock, server_side=True)
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, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100313 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
314 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
315 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000316 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000317 with socket.socket() as sock:
318 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000319 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000320 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000321 with socket.socket() as sock:
322 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000323 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000324 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000325 with socket.socket() as sock:
326 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000327 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000328
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000329 def test_match_hostname(self):
330 def ok(cert, hostname):
331 ssl.match_hostname(cert, hostname)
332 def fail(cert, hostname):
333 self.assertRaises(ssl.CertificateError,
334 ssl.match_hostname, cert, hostname)
335
336 cert = {'subject': ((('commonName', 'example.com'),),)}
337 ok(cert, 'example.com')
338 ok(cert, 'ExAmple.cOm')
339 fail(cert, 'www.example.com')
340 fail(cert, '.example.com')
341 fail(cert, 'example.org')
342 fail(cert, 'exampleXcom')
343
344 cert = {'subject': ((('commonName', '*.a.com'),),)}
345 ok(cert, 'foo.a.com')
346 fail(cert, 'bar.foo.a.com')
347 fail(cert, 'a.com')
348 fail(cert, 'Xa.com')
349 fail(cert, '.a.com')
350
Georg Brandl72c98d32013-10-27 07:16:53 +0100351 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000352 cert = {'subject': ((('commonName', 'f*.com'),),)}
353 ok(cert, 'foo.com')
354 ok(cert, 'f.com')
355 fail(cert, 'bar.com')
356 fail(cert, 'foo.a.com')
357 fail(cert, 'bar.foo.com')
358
Christian Heimes824f7f32013-08-17 00:54:47 +0200359 # NULL bytes are bad, CVE-2013-4073
360 cert = {'subject': ((('commonName',
361 'null.python.org\x00example.org'),),)}
362 ok(cert, 'null.python.org\x00example.org') # or raise an error?
363 fail(cert, 'example.org')
364 fail(cert, 'null.python.org')
365
Georg Brandl72c98d32013-10-27 07:16:53 +0100366 # error cases with wildcards
367 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
368 fail(cert, 'bar.foo.a.com')
369 fail(cert, 'a.com')
370 fail(cert, 'Xa.com')
371 fail(cert, '.a.com')
372
373 cert = {'subject': ((('commonName', 'a.*.com'),),)}
374 fail(cert, 'a.foo.com')
375 fail(cert, 'a..com')
376 fail(cert, 'a.com')
377
378 # wildcard doesn't match IDNA prefix 'xn--'
379 idna = 'püthon.python.org'.encode("idna").decode("ascii")
380 cert = {'subject': ((('commonName', idna),),)}
381 ok(cert, idna)
382 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
383 fail(cert, idna)
384 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
385 fail(cert, idna)
386
387 # wildcard in first fragment and IDNA A-labels in sequent fragments
388 # are supported.
389 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
390 cert = {'subject': ((('commonName', idna),),)}
391 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
392 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
393 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
394 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
395
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000396 # Slightly fake real-world example
397 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
398 'subject': ((('commonName', 'linuxfrz.org'),),),
399 'subjectAltName': (('DNS', 'linuxfr.org'),
400 ('DNS', 'linuxfr.com'),
401 ('othername', '<unsupported>'))}
402 ok(cert, 'linuxfr.org')
403 ok(cert, 'linuxfr.com')
404 # Not a "DNS" entry
405 fail(cert, '<unsupported>')
406 # When there is a subjectAltName, commonName isn't used
407 fail(cert, 'linuxfrz.org')
408
409 # A pristine real-world example
410 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
411 'subject': ((('countryName', 'US'),),
412 (('stateOrProvinceName', 'California'),),
413 (('localityName', 'Mountain View'),),
414 (('organizationName', 'Google Inc'),),
415 (('commonName', 'mail.google.com'),))}
416 ok(cert, 'mail.google.com')
417 fail(cert, 'gmail.com')
418 # Only commonName is considered
419 fail(cert, 'California')
420
421 # Neither commonName nor subjectAltName
422 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
423 'subject': ((('countryName', 'US'),),
424 (('stateOrProvinceName', 'California'),),
425 (('localityName', 'Mountain View'),),
426 (('organizationName', 'Google Inc'),))}
427 fail(cert, 'mail.google.com')
428
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200429 # No DNS entry in subjectAltName but a commonName
430 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
431 'subject': ((('countryName', 'US'),),
432 (('stateOrProvinceName', 'California'),),
433 (('localityName', 'Mountain View'),),
434 (('commonName', 'mail.google.com'),)),
435 'subjectAltName': (('othername', 'blabla'), )}
436 ok(cert, 'mail.google.com')
437
438 # No DNS entry subjectAltName and no commonName
439 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
440 'subject': ((('countryName', 'US'),),
441 (('stateOrProvinceName', 'California'),),
442 (('localityName', 'Mountain View'),),
443 (('organizationName', 'Google Inc'),)),
444 'subjectAltName': (('othername', 'blabla'),)}
445 fail(cert, 'google.com')
446
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000447 # Empty cert / no cert
448 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
449 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
450
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200451 # Issue #17980: avoid denials of service by refusing more than one
452 # wildcard per fragment.
453 cert = {'subject': ((('commonName', 'a*b.com'),),)}
454 ok(cert, 'axxb.com')
455 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100456 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200457 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
458 with self.assertRaises(ssl.CertificateError) as cm:
459 ssl.match_hostname(cert, 'axxbxxc.com')
460 self.assertIn("too many wildcards", str(cm.exception))
461
Antoine Pitroud5323212010-10-22 18:19:07 +0000462 def test_server_side(self):
463 # server_hostname doesn't work for server sockets
464 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000465 with socket.socket() as sock:
466 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
467 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000468
Antoine Pitroud6494802011-07-21 01:11:30 +0200469 def test_unknown_channel_binding(self):
470 # should raise ValueError for unknown type
471 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100472 with ssl.wrap_socket(s) as ss:
473 with self.assertRaises(ValueError):
474 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200475
476 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
477 "'tls-unique' channel binding not available")
478 def test_tls_unique_channel_binding(self):
479 # unconnected should return None for known type
480 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100481 with ssl.wrap_socket(s) as ss:
482 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200483 # the same for server-side
484 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100485 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
486 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200487
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600488 def test_dealloc_warn(self):
489 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
490 r = repr(ss)
491 with self.assertWarns(ResourceWarning) as cm:
492 ss = None
493 support.gc_collect()
494 self.assertIn(r, str(cm.warning.args[0]))
495
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100496 def test_unsupported_dtls(self):
497 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
498 self.addCleanup(s.close)
499 with self.assertRaises(NotImplementedError) as cx:
500 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
501 self.assertEqual(str(cx.exception), "only stream sockets are supported")
502 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
503 with self.assertRaises(NotImplementedError) as cx:
504 ctx.wrap_socket(s)
505 self.assertEqual(str(cx.exception), "only stream sockets are supported")
506
507
Antoine Pitrou152efa22010-05-16 18:19:27 +0000508class ContextTests(unittest.TestCase):
509
Antoine Pitrou23df4832010-08-04 17:14:06 +0000510 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000511 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200512 if hasattr(ssl, 'PROTOCOL_SSLv2'):
513 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000514 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
515 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
516 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
517 self.assertRaises(TypeError, ssl.SSLContext)
518 self.assertRaises(ValueError, ssl.SSLContext, -1)
519 self.assertRaises(ValueError, ssl.SSLContext, 42)
520
Antoine Pitrou23df4832010-08-04 17:14:06 +0000521 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000522 def test_protocol(self):
523 for proto in PROTOCOLS:
524 ctx = ssl.SSLContext(proto)
525 self.assertEqual(ctx.protocol, proto)
526
527 def test_ciphers(self):
528 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
529 ctx.set_ciphers("ALL")
530 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000531 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000532 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000533
Antoine Pitrou23df4832010-08-04 17:14:06 +0000534 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000535 def test_options(self):
536 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +0100537 # OP_ALL | OP_NO_SSLv2 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000538 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
539 ctx.options)
540 ctx.options |= ssl.OP_NO_SSLv3
541 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
542 ctx.options)
543 if can_clear_options():
544 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
545 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
546 ctx.options)
547 ctx.options = 0
548 self.assertEqual(0, ctx.options)
549 else:
550 with self.assertRaises(ValueError):
551 ctx.options = 0
552
Antoine Pitrou152efa22010-05-16 18:19:27 +0000553 def test_verify(self):
554 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
555 # Default value
556 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
557 ctx.verify_mode = ssl.CERT_OPTIONAL
558 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
559 ctx.verify_mode = ssl.CERT_REQUIRED
560 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
561 ctx.verify_mode = ssl.CERT_NONE
562 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
563 with self.assertRaises(TypeError):
564 ctx.verify_mode = None
565 with self.assertRaises(ValueError):
566 ctx.verify_mode = 42
567
568 def test_load_cert_chain(self):
569 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
570 # Combined key and cert in a single file
571 ctx.load_cert_chain(CERTFILE)
572 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
573 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000574 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000575 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000576 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000577 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000578 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000579 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000580 ctx.load_cert_chain(EMPTYCERT)
581 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000582 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000583 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
584 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
585 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000586 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000587 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000588 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000589 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000590 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000591 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
592 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000593 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000594 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000595 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200596 # Password protected key and cert
597 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
598 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
599 ctx.load_cert_chain(CERTFILE_PROTECTED,
600 password=bytearray(KEY_PASSWORD.encode()))
601 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
602 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
603 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
604 bytearray(KEY_PASSWORD.encode()))
605 with self.assertRaisesRegex(TypeError, "should be a string"):
606 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
607 with self.assertRaises(ssl.SSLError):
608 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
609 with self.assertRaisesRegex(ValueError, "cannot be longer"):
610 # openssl has a fixed limit on the password buffer.
611 # PEM_BUFSIZE is generally set to 1kb.
612 # Return a string larger than this.
613 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
614 # Password callback
615 def getpass_unicode():
616 return KEY_PASSWORD
617 def getpass_bytes():
618 return KEY_PASSWORD.encode()
619 def getpass_bytearray():
620 return bytearray(KEY_PASSWORD.encode())
621 def getpass_badpass():
622 return "badpass"
623 def getpass_huge():
624 return b'a' * (1024 * 1024)
625 def getpass_bad_type():
626 return 9
627 def getpass_exception():
628 raise Exception('getpass error')
629 class GetPassCallable:
630 def __call__(self):
631 return KEY_PASSWORD
632 def getpass(self):
633 return KEY_PASSWORD
634 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
635 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
636 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
637 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
638 ctx.load_cert_chain(CERTFILE_PROTECTED,
639 password=GetPassCallable().getpass)
640 with self.assertRaises(ssl.SSLError):
641 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
642 with self.assertRaisesRegex(ValueError, "cannot be longer"):
643 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
644 with self.assertRaisesRegex(TypeError, "must return a string"):
645 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
646 with self.assertRaisesRegex(Exception, "getpass error"):
647 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
648 # Make sure the password function isn't called if it isn't needed
649 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000650
651 def test_load_verify_locations(self):
652 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
653 ctx.load_verify_locations(CERTFILE)
654 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
655 ctx.load_verify_locations(BYTES_CERTFILE)
656 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
657 self.assertRaises(TypeError, ctx.load_verify_locations)
658 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000659 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000660 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000661 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000662 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000663 ctx.load_verify_locations(BADCERT)
664 ctx.load_verify_locations(CERTFILE, CAPATH)
665 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
666
Victor Stinner80f75e62011-01-29 11:31:20 +0000667 # Issue #10989: crash if the second argument type is invalid
668 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
669
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100670 def test_load_dh_params(self):
671 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
672 ctx.load_dh_params(DHFILE)
673 if os.name != 'nt':
674 ctx.load_dh_params(BYTES_DHFILE)
675 self.assertRaises(TypeError, ctx.load_dh_params)
676 self.assertRaises(TypeError, ctx.load_dh_params, None)
677 with self.assertRaises(FileNotFoundError) as cm:
678 ctx.load_dh_params(WRONGCERT)
679 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200680 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100681 ctx.load_dh_params(CERTFILE)
682
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000683 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000684 def test_session_stats(self):
685 for proto in PROTOCOLS:
686 ctx = ssl.SSLContext(proto)
687 self.assertEqual(ctx.session_stats(), {
688 'number': 0,
689 'connect': 0,
690 'connect_good': 0,
691 'connect_renegotiate': 0,
692 'accept': 0,
693 'accept_good': 0,
694 'accept_renegotiate': 0,
695 'hits': 0,
696 'misses': 0,
697 'timeouts': 0,
698 'cache_full': 0,
699 })
700
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000701 def test_set_default_verify_paths(self):
702 # There's not much we can do to test that it acts as expected,
703 # so just check it doesn't crash or raise an exception.
704 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
705 ctx.set_default_verify_paths()
706
Antoine Pitrou501da612011-12-21 09:27:41 +0100707 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100708 def test_set_ecdh_curve(self):
709 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
710 ctx.set_ecdh_curve("prime256v1")
711 ctx.set_ecdh_curve(b"prime256v1")
712 self.assertRaises(TypeError, ctx.set_ecdh_curve)
713 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
714 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
715 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
716
Antoine Pitrou152efa22010-05-16 18:19:27 +0000717
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200718class SSLErrorTests(unittest.TestCase):
719
720 def test_str(self):
721 # The str() of a SSLError doesn't include the errno
722 e = ssl.SSLError(1, "foo")
723 self.assertEqual(str(e), "foo")
724 self.assertEqual(e.errno, 1)
725 # Same for a subclass
726 e = ssl.SSLZeroReturnError(1, "foo")
727 self.assertEqual(str(e), "foo")
728 self.assertEqual(e.errno, 1)
729
730 def test_lib_reason(self):
731 # Test the library and reason attributes
732 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
733 with self.assertRaises(ssl.SSLError) as cm:
734 ctx.load_dh_params(CERTFILE)
735 self.assertEqual(cm.exception.library, 'PEM')
736 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
737 s = str(cm.exception)
738 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
739
740 def test_subclass(self):
741 # Check that the appropriate SSLError subclass is raised
742 # (this only tests one of them)
743 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
744 with socket.socket() as s:
745 s.bind(("127.0.0.1", 0))
746 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100747 c = socket.socket()
748 c.connect(s.getsockname())
749 c.setblocking(False)
750 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200751 with self.assertRaises(ssl.SSLWantReadError) as cm:
752 c.do_handshake()
753 s = str(cm.exception)
754 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
755 # For compatibility
756 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
757
758
Bill Janssen6e027db2007-11-15 22:23:56 +0000759class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000760
Antoine Pitrou480a1242010-04-28 21:37:09 +0000761 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000762 with support.transient_internet("svn.python.org"):
763 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
764 cert_reqs=ssl.CERT_NONE)
765 try:
766 s.connect(("svn.python.org", 443))
767 self.assertEqual({}, s.getpeercert())
768 finally:
769 s.close()
770
771 # this should fail because we have no verification certs
772 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
773 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000774 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
775 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000776 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000777
Antoine Pitrou350c7222010-09-09 13:31:46 +0000778 # this should succeed because we specify the root cert
779 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
780 cert_reqs=ssl.CERT_REQUIRED,
781 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
782 try:
783 s.connect(("svn.python.org", 443))
784 self.assertTrue(s.getpeercert())
785 finally:
786 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000787
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000788 def test_connect_ex(self):
789 # Issue #11326: check connect_ex() implementation
790 with support.transient_internet("svn.python.org"):
791 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
792 cert_reqs=ssl.CERT_REQUIRED,
793 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
794 try:
795 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
796 self.assertTrue(s.getpeercert())
797 finally:
798 s.close()
799
800 def test_non_blocking_connect_ex(self):
801 # Issue #11326: non-blocking connect_ex() should allow handshake
802 # to proceed after the socket gets ready.
803 with support.transient_internet("svn.python.org"):
804 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
805 cert_reqs=ssl.CERT_REQUIRED,
806 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
807 do_handshake_on_connect=False)
808 try:
809 s.setblocking(False)
810 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000811 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
812 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000813 # Wait for connect to finish
814 select.select([], [s], [], 5.0)
815 # Non-blocking handshake
816 while True:
817 try:
818 s.do_handshake()
819 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200820 except ssl.SSLWantReadError:
821 select.select([s], [], [], 5.0)
822 except ssl.SSLWantWriteError:
823 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000824 # SSL established
825 self.assertTrue(s.getpeercert())
826 finally:
827 s.close()
828
Antoine Pitroub4410db2011-05-18 18:51:06 +0200829 def test_timeout_connect_ex(self):
830 # Issue #12065: on a timeout, connect_ex() should return the original
831 # errno (mimicking the behaviour of non-SSL sockets).
832 with support.transient_internet("svn.python.org"):
833 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
834 cert_reqs=ssl.CERT_REQUIRED,
835 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
836 do_handshake_on_connect=False)
837 try:
838 s.settimeout(0.0000001)
839 rc = s.connect_ex(('svn.python.org', 443))
840 if rc == 0:
841 self.skipTest("svn.python.org responded too quickly")
842 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
843 finally:
844 s.close()
845
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100846 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100847 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100848 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
849 cert_reqs=ssl.CERT_REQUIRED,
850 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
851 try:
Christian Heimesde570742013-12-16 21:15:44 +0100852 rc = s.connect_ex(("svn.python.org", 444))
853 # Issue #19919: Windows machines or VMs hosted on Windows
854 # machines sometimes return EWOULDBLOCK.
855 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100856 finally:
857 s.close()
858
Antoine Pitrou152efa22010-05-16 18:19:27 +0000859 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000860 with support.transient_internet("svn.python.org"):
861 # Same as test_connect, but with a separately created context
862 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
863 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
864 s.connect(("svn.python.org", 443))
865 try:
866 self.assertEqual({}, s.getpeercert())
867 finally:
868 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000869 # Same with a server hostname
870 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
871 server_hostname="svn.python.org")
872 if ssl.HAS_SNI:
873 s.connect(("svn.python.org", 443))
874 s.close()
875 else:
876 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000877 # This should fail because we have no verification certs
878 ctx.verify_mode = ssl.CERT_REQUIRED
879 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000880 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000881 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000882 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000883 # This should succeed because we specify the root cert
884 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
885 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
886 s.connect(("svn.python.org", 443))
887 try:
888 cert = s.getpeercert()
889 self.assertTrue(cert)
890 finally:
891 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000892
893 def test_connect_capath(self):
894 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000895 # NOTE: the subject hashing algorithm has been changed between
896 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
897 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000898 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000899 with support.transient_internet("svn.python.org"):
900 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
901 ctx.verify_mode = ssl.CERT_REQUIRED
902 ctx.load_verify_locations(capath=CAPATH)
903 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
904 s.connect(("svn.python.org", 443))
905 try:
906 cert = s.getpeercert()
907 self.assertTrue(cert)
908 finally:
909 s.close()
910 # Same with a bytes `capath` argument
911 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
912 ctx.verify_mode = ssl.CERT_REQUIRED
913 ctx.load_verify_locations(capath=BYTES_CAPATH)
914 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
915 s.connect(("svn.python.org", 443))
916 try:
917 cert = s.getpeercert()
918 self.assertTrue(cert)
919 finally:
920 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921
Antoine Pitroue3220242010-04-24 11:13:53 +0000922 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
923 def test_makefile_close(self):
924 # Issue #5238: creating a file-like object with makefile() shouldn't
925 # delay closing the underlying "real socket" (here tested with its
926 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000927 with support.transient_internet("svn.python.org"):
928 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
929 ss.connect(("svn.python.org", 443))
930 fd = ss.fileno()
931 f = ss.makefile()
932 f.close()
933 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000934 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000935 # Closing the SSL socket should close the fd too
936 ss.close()
937 gc.collect()
938 with self.assertRaises(OSError) as e:
939 os.read(fd, 0)
940 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000941
Antoine Pitrou480a1242010-04-28 21:37:09 +0000942 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000943 with support.transient_internet("svn.python.org"):
944 s = socket.socket(socket.AF_INET)
945 s.connect(("svn.python.org", 443))
946 s.setblocking(False)
947 s = ssl.wrap_socket(s,
948 cert_reqs=ssl.CERT_NONE,
949 do_handshake_on_connect=False)
950 count = 0
951 while True:
952 try:
953 count += 1
954 s.do_handshake()
955 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200956 except ssl.SSLWantReadError:
957 select.select([s], [], [])
958 except ssl.SSLWantWriteError:
959 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000960 s.close()
961 if support.verbose:
962 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963
Antoine Pitrou480a1242010-04-28 21:37:09 +0000964 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200965 def _test_get_server_certificate(host, port, cert=None):
966 with support.transient_internet(host):
967 pem = ssl.get_server_certificate((host, port))
968 if not pem:
969 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200970
Antoine Pitrou15399c32011-04-28 19:23:55 +0200971 try:
972 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
973 except ssl.SSLError as x:
974 #should fail
975 if support.verbose:
976 sys.stdout.write("%s\n" % x)
977 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200978 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
979
Antoine Pitrou15399c32011-04-28 19:23:55 +0200980 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
981 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200982 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000983 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200984 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000985
Antoine Pitrou15399c32011-04-28 19:23:55 +0200986 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
987 if support.IPV6_ENABLED:
988 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000989
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000990 def test_ciphers(self):
991 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000992 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100993 with ssl.wrap_socket(socket.socket(socket.AF_INET),
994 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
995 s.connect(remote)
996 with ssl.wrap_socket(socket.socket(socket.AF_INET),
997 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
998 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000999 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001000 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001001 with socket.socket(socket.AF_INET) as sock:
1002 s = ssl.wrap_socket(sock,
1003 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1004 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001005
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001006 def test_algorithms(self):
1007 # Issue #8484: all algorithms should be available when verifying a
1008 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001009 # SHA256 was added in OpenSSL 0.9.8
1010 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1011 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001012 # sha256.tbs-internet.com needs SNI to use the correct certificate
1013 if not ssl.HAS_SNI:
1014 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001015 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1016 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001017 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001018 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001019 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1020 ctx.verify_mode = ssl.CERT_REQUIRED
1021 ctx.load_verify_locations(sha256_cert)
1022 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1023 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001024 try:
1025 s.connect(remote)
1026 if support.verbose:
1027 sys.stdout.write("\nCipher with %r is %r\n" %
1028 (remote, s.cipher()))
1029 sys.stdout.write("Certificate is:\n%s\n" %
1030 pprint.pformat(s.getpeercert()))
1031 finally:
1032 s.close()
1033
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034
1035try:
1036 import threading
1037except ImportError:
1038 _have_threads = False
1039else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001040 _have_threads = True
1041
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001042 from test.ssl_servers import make_https_server
1043
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001044 class ThreadedEchoServer(threading.Thread):
1045
1046 class ConnectionHandler(threading.Thread):
1047
1048 """A mildly complicated class, because we want it to work both
1049 with and without the SSL wrapper around the socket connection, so
1050 that we can test the STARTTLS functionality."""
1051
Bill Janssen6e027db2007-11-15 22:23:56 +00001052 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001053 self.server = server
1054 self.running = False
1055 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001056 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001057 self.sock.setblocking(1)
1058 self.sslconn = None
1059 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001060 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001061
Antoine Pitrou480a1242010-04-28 21:37:09 +00001062 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001063 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001064 self.sslconn = self.server.context.wrap_socket(
1065 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001066 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001067 except (ssl.SSLError, ConnectionResetError) as e:
1068 # We treat ConnectionResetError as though it were an
1069 # SSLError - OpenSSL on Ubuntu abruptly closes the
1070 # connection when asked to use an unsupported protocol.
1071 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001072 # XXX Various errors can have happened here, for example
1073 # a mismatching protocol version, an invalid certificate,
1074 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001075 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001076 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001077 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001078 self.running = False
1079 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001080 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001081 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001082 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001083 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001084 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001085 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1087 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001088 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001089 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1090 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001091 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001092 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001093 sys.stdout.write(" server: selected protocol is now "
1094 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001095 return True
1096
1097 def read(self):
1098 if self.sslconn:
1099 return self.sslconn.read()
1100 else:
1101 return self.sock.recv(1024)
1102
1103 def write(self, bytes):
1104 if self.sslconn:
1105 return self.sslconn.write(bytes)
1106 else:
1107 return self.sock.send(bytes)
1108
1109 def close(self):
1110 if self.sslconn:
1111 self.sslconn.close()
1112 else:
1113 self.sock.close()
1114
Antoine Pitrou480a1242010-04-28 21:37:09 +00001115 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001116 self.running = True
1117 if not self.server.starttls_server:
1118 if not self.wrap_conn():
1119 return
1120 while self.running:
1121 try:
1122 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001123 stripped = msg.strip()
1124 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125 # eof, so quit this handler
1126 self.running = False
1127 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001128 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001129 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001130 sys.stdout.write(" server: client closed connection\n")
1131 self.close()
1132 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001133 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001134 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001135 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001136 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001137 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001138 if not self.wrap_conn():
1139 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001140 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001141 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001142 if support.verbose and self.server.connectionchatty:
1143 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001144 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001145 self.sock = self.sslconn.unwrap()
1146 self.sslconn = None
1147 if support.verbose and self.server.connectionchatty:
1148 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001149 elif stripped == b'CB tls-unique':
1150 if support.verbose and self.server.connectionchatty:
1151 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1152 data = self.sslconn.get_channel_binding("tls-unique")
1153 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001154 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001155 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156 self.server.connectionchatty):
1157 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001158 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1159 % (msg, ctype, msg.lower(), ctype))
1160 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001161 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001162 if self.server.chatty:
1163 handle_error("Test server failure:\n")
1164 self.close()
1165 self.running = False
1166 # normally, we'd just stop here, but for the test
1167 # harness, we want to stop the server
1168 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001169
Antoine Pitroub5218772010-05-21 09:56:06 +00001170 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001171 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001172 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001173 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001174 if context:
1175 self.context = context
1176 else:
1177 self.context = ssl.SSLContext(ssl_version
1178 if ssl_version is not None
1179 else ssl.PROTOCOL_TLSv1)
1180 self.context.verify_mode = (certreqs if certreqs is not None
1181 else ssl.CERT_NONE)
1182 if cacerts:
1183 self.context.load_verify_locations(cacerts)
1184 if certificate:
1185 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001186 if npn_protocols:
1187 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001188 if ciphers:
1189 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001190 self.chatty = chatty
1191 self.connectionchatty = connectionchatty
1192 self.starttls_server = starttls_server
1193 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001194 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001195 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001196 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001197 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001198 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001199 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001200 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001201
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001202 def __enter__(self):
1203 self.start(threading.Event())
1204 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001205 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001206
1207 def __exit__(self, *args):
1208 self.stop()
1209 self.join()
1210
Antoine Pitrou480a1242010-04-28 21:37:09 +00001211 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001212 self.flag = flag
1213 threading.Thread.start(self)
1214
Antoine Pitrou480a1242010-04-28 21:37:09 +00001215 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001216 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001217 self.sock.listen(5)
1218 self.active = True
1219 if self.flag:
1220 # signal an event
1221 self.flag.set()
1222 while self.active:
1223 try:
1224 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001225 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001226 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001227 + repr(connaddr) + '\n')
1228 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001229 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001230 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 except socket.timeout:
1232 pass
1233 except KeyboardInterrupt:
1234 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001235 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001236
Antoine Pitrou480a1242010-04-28 21:37:09 +00001237 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001238 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001239
Bill Janssen54cc54c2007-12-14 22:08:56 +00001240 class AsyncoreEchoServer(threading.Thread):
1241
1242 # this one's based on asyncore.dispatcher
1243
1244 class EchoServer (asyncore.dispatcher):
1245
1246 class ConnectionHandler (asyncore.dispatcher_with_send):
1247
1248 def __init__(self, conn, certfile):
1249 self.socket = ssl.wrap_socket(conn, server_side=True,
1250 certfile=certfile,
1251 do_handshake_on_connect=False)
1252 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001253 self._ssl_accepting = True
1254 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001255
1256 def readable(self):
1257 if isinstance(self.socket, ssl.SSLSocket):
1258 while self.socket.pending() > 0:
1259 self.handle_read_event()
1260 return True
1261
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001262 def _do_ssl_handshake(self):
1263 try:
1264 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001265 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1266 return
1267 except ssl.SSLEOFError:
1268 return self.handle_close()
1269 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001270 raise
1271 except socket.error as err:
1272 if err.args[0] == errno.ECONNABORTED:
1273 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001274 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001275 self._ssl_accepting = False
1276
1277 def handle_read(self):
1278 if self._ssl_accepting:
1279 self._do_ssl_handshake()
1280 else:
1281 data = self.recv(1024)
1282 if support.verbose:
1283 sys.stdout.write(" server: read %s from client\n" % repr(data))
1284 if not data:
1285 self.close()
1286 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001287 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001288
1289 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001290 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001291 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001292 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1293
1294 def handle_error(self):
1295 raise
1296
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001297 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001298 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001299 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1300 self.port = support.bind_port(sock, '')
1301 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001302 self.listen(5)
1303
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001304 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001305 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001306 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1307 self.ConnectionHandler(sock_obj, self.certfile)
1308
1309 def handle_error(self):
1310 raise
1311
Trent Nelson78520002008-04-10 20:54:35 +00001312 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001313 self.flag = None
1314 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001315 self.server = self.EchoServer(certfile)
1316 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001317 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001318 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001319
1320 def __str__(self):
1321 return "<%s %s>" % (self.__class__.__name__, self.server)
1322
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001323 def __enter__(self):
1324 self.start(threading.Event())
1325 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001326 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001327
1328 def __exit__(self, *args):
1329 if support.verbose:
1330 sys.stdout.write(" cleanup: stopping server.\n")
1331 self.stop()
1332 if support.verbose:
1333 sys.stdout.write(" cleanup: joining server thread.\n")
1334 self.join()
1335 if support.verbose:
1336 sys.stdout.write(" cleanup: successfully joined.\n")
1337
Bill Janssen54cc54c2007-12-14 22:08:56 +00001338 def start (self, flag=None):
1339 self.flag = flag
1340 threading.Thread.start(self)
1341
Antoine Pitrou480a1242010-04-28 21:37:09 +00001342 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001343 self.active = True
1344 if self.flag:
1345 self.flag.set()
1346 while self.active:
1347 try:
1348 asyncore.loop(1)
1349 except:
1350 pass
1351
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001353 self.active = False
1354 self.server.close()
1355
Antoine Pitrou480a1242010-04-28 21:37:09 +00001356 def bad_cert_test(certfile):
1357 """
1358 Launch a server with CERT_REQUIRED, and check that trying to
1359 connect to it with the given client certificate fails.
1360 """
Trent Nelson78520002008-04-10 20:54:35 +00001361 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001362 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001363 cacerts=CERTFILE, chatty=False,
1364 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001365 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001366 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001367 with socket.socket() as sock:
1368 s = ssl.wrap_socket(sock,
1369 certfile=certfile,
1370 ssl_version=ssl.PROTOCOL_TLSv1)
1371 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001372 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001373 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001374 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001375 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001377 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001378 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001379 if x.errno != errno.ENOENT:
1380 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001381 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001382 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001383 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001384 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001385
Antoine Pitroub5218772010-05-21 09:56:06 +00001386 def server_params_test(client_context, server_context, indata=b"FOO\n",
1387 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001388 """
1389 Launch a server, connect a client to it and try various reads
1390 and writes.
1391 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001392 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001393 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001394 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001395 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001396 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001397 with client_context.wrap_socket(socket.socket()) as s:
1398 s.connect((HOST, server.port))
1399 for arg in [indata, bytearray(indata), memoryview(indata)]:
1400 if connectionchatty:
1401 if support.verbose:
1402 sys.stdout.write(
1403 " client: sending %r...\n" % indata)
1404 s.write(arg)
1405 outdata = s.read()
1406 if connectionchatty:
1407 if support.verbose:
1408 sys.stdout.write(" client: read %r\n" % outdata)
1409 if outdata != indata.lower():
1410 raise AssertionError(
1411 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1412 % (outdata[:20], len(outdata),
1413 indata[:20].lower(), len(indata)))
1414 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001415 if connectionchatty:
1416 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001417 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001418 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001419 'compression': s.compression(),
1420 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001421 'client_npn_protocol': s.selected_npn_protocol()
1422 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001423 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001424 stats['server_npn_protocols'] = server.selected_protocols
1425 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001426
Antoine Pitroub5218772010-05-21 09:56:06 +00001427 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1428 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001429 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001430 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001431 certtype = {
1432 ssl.CERT_NONE: "CERT_NONE",
1433 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1434 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1435 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001436 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001438 sys.stdout.write(formatstr %
1439 (ssl.get_protocol_name(client_protocol),
1440 ssl.get_protocol_name(server_protocol),
1441 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001442 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001443 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001444 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001445 server_context.options |= server_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001446 for ctx in (client_context, server_context):
1447 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001448 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1449 # will send an SSLv3 hello (rather than SSLv2) starting from
1450 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001451 ctx.set_ciphers("ALL")
1452 ctx.load_cert_chain(CERTFILE)
1453 ctx.load_verify_locations(CERTFILE)
1454 try:
1455 server_params_test(client_context, server_context,
1456 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001457 # Protocol mismatch can result in either an SSLError, or a
1458 # "Connection reset by peer" error.
1459 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001460 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001461 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001462 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001463 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001464 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001465 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001466 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001467 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001468 "Client protocol %s succeeded with server protocol %s!"
1469 % (ssl.get_protocol_name(client_protocol),
1470 ssl.get_protocol_name(server_protocol)))
1471
1472
Bill Janssen6e027db2007-11-15 22:23:56 +00001473 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001474
Antoine Pitrou23df4832010-08-04 17:14:06 +00001475 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001476 def test_echo(self):
1477 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001478 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001479 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001480 for protocol in PROTOCOLS:
1481 context = ssl.SSLContext(protocol)
1482 context.load_cert_chain(CERTFILE)
1483 server_params_test(context, context,
1484 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001485
Antoine Pitrou480a1242010-04-28 21:37:09 +00001486 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001487 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001488 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001489 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1490 context.verify_mode = ssl.CERT_REQUIRED
1491 context.load_verify_locations(CERTFILE)
1492 context.load_cert_chain(CERTFILE)
1493 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001494 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001495 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001496 s.connect((HOST, server.port))
1497 cert = s.getpeercert()
1498 self.assertTrue(cert, "Can't get peer certificate.")
1499 cipher = s.cipher()
1500 if support.verbose:
1501 sys.stdout.write(pprint.pformat(cert) + '\n')
1502 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1503 if 'subject' not in cert:
1504 self.fail("No subject field in certificate: %s." %
1505 pprint.pformat(cert))
1506 if ((('organizationName', 'Python Software Foundation'),)
1507 not in cert['subject']):
1508 self.fail(
1509 "Missing or invalid 'organizationName' field in certificate subject; "
1510 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001511 self.assertIn('notBefore', cert)
1512 self.assertIn('notAfter', cert)
1513 before = ssl.cert_time_to_seconds(cert['notBefore'])
1514 after = ssl.cert_time_to_seconds(cert['notAfter'])
1515 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001516 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001517
Antoine Pitrou480a1242010-04-28 21:37:09 +00001518 def test_empty_cert(self):
1519 """Connecting with an empty cert file"""
1520 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1521 "nullcert.pem"))
1522 def test_malformed_cert(self):
1523 """Connecting with a badly formatted certificate (syntax error)"""
1524 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1525 "badcert.pem"))
1526 def test_nonexisting_cert(self):
1527 """Connecting with a non-existing cert file"""
1528 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1529 "wrongcert.pem"))
1530 def test_malformed_key(self):
1531 """Connecting with a badly formatted key (syntax error)"""
1532 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1533 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001534
Antoine Pitrou480a1242010-04-28 21:37:09 +00001535 def test_rude_shutdown(self):
1536 """A brutal shutdown of an SSL server should raise an IOError
1537 in the client when attempting handshake.
1538 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001539 listener_ready = threading.Event()
1540 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001541
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001542 s = socket.socket()
1543 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001544
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001545 # `listener` runs in a thread. It sits in an accept() until
1546 # the main thread connects. Then it rudely closes the socket,
1547 # and sets Event `listener_gone` to let the main thread know
1548 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001549 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001550 s.listen(5)
1551 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001552 newsock, addr = s.accept()
1553 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001554 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001555 listener_gone.set()
1556
1557 def connector():
1558 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001559 with socket.socket() as c:
1560 c.connect((HOST, port))
1561 listener_gone.wait()
1562 try:
1563 ssl_sock = ssl.wrap_socket(c)
1564 except IOError:
1565 pass
1566 else:
1567 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001568
1569 t = threading.Thread(target=listener)
1570 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001571 try:
1572 connector()
1573 finally:
1574 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001575
Antoine Pitrou23df4832010-08-04 17:14:06 +00001576 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001577 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1578 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001579 def test_protocol_sslv2(self):
1580 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001581 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001582 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001583 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1584 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1585 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001586 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001587 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1588 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001589 # SSLv23 client with specific SSL options
1590 if no_sslv2_implies_sslv3_hello():
1591 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1592 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1593 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001594 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00001595 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001596 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00001597 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001598
Antoine Pitrou23df4832010-08-04 17:14:06 +00001599 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001600 def test_protocol_sslv23(self):
1601 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001602 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001603 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001604 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1605 try:
1606 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1607 except (ssl.SSLError, socket.error) as x:
1608 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1609 if support.verbose:
1610 sys.stdout.write(
1611 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1612 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001613 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1614 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1615 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001616
Antoine Pitrou480a1242010-04-28 21:37:09 +00001617 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1618 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1619 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001620
Antoine Pitrou480a1242010-04-28 21:37:09 +00001621 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1622 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1623 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001624
Antoine Pitroub5218772010-05-21 09:56:06 +00001625 # Server with specific SSL options
1626 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1627 server_options=ssl.OP_NO_SSLv3)
1628 # Will choose TLSv1
1629 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1630 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1631 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1632 server_options=ssl.OP_NO_TLSv1)
1633
1634
Antoine Pitrou23df4832010-08-04 17:14:06 +00001635 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001636 def test_protocol_sslv3(self):
1637 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001638 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001639 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001640 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1641 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1642 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001643 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1644 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001645 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1646 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001647 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001648 if no_sslv2_implies_sslv3_hello():
1649 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1650 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1651 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001652
Antoine Pitrou23df4832010-08-04 17:14:06 +00001653 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001654 def test_protocol_tlsv1(self):
1655 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001656 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001657 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001658 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1659 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1660 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001661 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1662 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001663 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001664 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1665 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001666
Antoine Pitrou480a1242010-04-28 21:37:09 +00001667 def test_starttls(self):
1668 """Switching from clear text to encrypted and back again."""
1669 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 +00001670
Trent Nelson78520002008-04-10 20:54:35 +00001671 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001672 ssl_version=ssl.PROTOCOL_TLSv1,
1673 starttls_server=True,
1674 chatty=True,
1675 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001676 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001677 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001678 s = socket.socket()
1679 s.setblocking(1)
1680 s.connect((HOST, server.port))
1681 if support.verbose:
1682 sys.stdout.write("\n")
1683 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001684 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001685 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001686 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001687 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001688 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001689 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001690 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001691 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001692 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001693 msg = outdata.strip().lower()
1694 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1695 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001696 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001697 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001698 " client: read %r from server, starting TLS...\n"
1699 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001700 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1701 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001702 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1703 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001704 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001705 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001706 " client: read %r from server, ending TLS...\n"
1707 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001708 s = conn.unwrap()
1709 wrapped = False
1710 else:
1711 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001712 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001713 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001714 if support.verbose:
1715 sys.stdout.write(" client: closing connection.\n")
1716 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001717 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001718 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001719 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001720 if wrapped:
1721 conn.close()
1722 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001723 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001724
Antoine Pitrou480a1242010-04-28 21:37:09 +00001725 def test_socketserver(self):
1726 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001727 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001728 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001729 if support.verbose:
1730 sys.stdout.write('\n')
1731 with open(CERTFILE, 'rb') as f:
1732 d1 = f.read()
1733 d2 = ''
1734 # now fetch the same data from the HTTPS server
1735 url = 'https://%s:%d/%s' % (
1736 HOST, server.port, os.path.split(CERTFILE)[1])
1737 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001738 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001739 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001740 if dlen and (int(dlen) > 0):
1741 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001742 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001743 sys.stdout.write(
1744 " client: read %d bytes from remote server '%s'\n"
1745 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001746 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001747 f.close()
1748 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001749
Antoine Pitrou480a1242010-04-28 21:37:09 +00001750 def test_asyncore_server(self):
1751 """Check the example asyncore integration."""
1752 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001753
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001754 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001755 sys.stdout.write("\n")
1756
Antoine Pitrou480a1242010-04-28 21:37:09 +00001757 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001758 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001759 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001760 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001761 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001762 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001763 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001764 " client: sending %r...\n" % indata)
1765 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001766 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001767 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001768 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001769 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001770 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001771 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1772 % (outdata[:20], len(outdata),
1773 indata[:20].lower(), len(indata)))
1774 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001775 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001776 sys.stdout.write(" client: closing connection.\n")
1777 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001778 if support.verbose:
1779 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001780
Antoine Pitrou480a1242010-04-28 21:37:09 +00001781 def test_recv_send(self):
1782 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001783 if support.verbose:
1784 sys.stdout.write("\n")
1785
1786 server = ThreadedEchoServer(CERTFILE,
1787 certreqs=ssl.CERT_NONE,
1788 ssl_version=ssl.PROTOCOL_TLSv1,
1789 cacerts=CERTFILE,
1790 chatty=True,
1791 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001792 with server:
1793 s = ssl.wrap_socket(socket.socket(),
1794 server_side=False,
1795 certfile=CERTFILE,
1796 ca_certs=CERTFILE,
1797 cert_reqs=ssl.CERT_NONE,
1798 ssl_version=ssl.PROTOCOL_TLSv1)
1799 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001800 # helper methods for standardising recv* method signatures
1801 def _recv_into():
1802 b = bytearray(b"\0"*100)
1803 count = s.recv_into(b)
1804 return b[:count]
1805
1806 def _recvfrom_into():
1807 b = bytearray(b"\0"*100)
1808 count, addr = s.recvfrom_into(b)
1809 return b[:count]
1810
1811 # (name, method, whether to expect success, *args)
1812 send_methods = [
1813 ('send', s.send, True, []),
1814 ('sendto', s.sendto, False, ["some.address"]),
1815 ('sendall', s.sendall, True, []),
1816 ]
1817 recv_methods = [
1818 ('recv', s.recv, True, []),
1819 ('recvfrom', s.recvfrom, False, ["some.address"]),
1820 ('recv_into', _recv_into, True, []),
1821 ('recvfrom_into', _recvfrom_into, False, []),
1822 ]
1823 data_prefix = "PREFIX_"
1824
1825 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001826 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001827 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001828 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001829 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001830 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001831 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001832 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001833 "<<{outdata:r}>> ({nout:d}) received; "
1834 "expected <<{indata:r}>> ({nin:d})\n".format(
1835 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001836 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001837 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001838 )
1839 )
1840 except ValueError as e:
1841 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001842 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001843 "Failed to send with method <<{name:s}>>; "
1844 "expected to succeed.\n".format(name=meth_name)
1845 )
1846 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001847 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001848 "Method <<{name:s}>> failed with unexpected "
1849 "exception message: {exp:s}\n".format(
1850 name=meth_name, exp=e
1851 )
1852 )
1853
1854 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001855 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001856 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001857 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001858 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001859 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001860 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001861 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001862 "<<{outdata:r}>> ({nout:d}) received; "
1863 "expected <<{indata:r}>> ({nin:d})\n".format(
1864 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001865 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001866 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001867 )
1868 )
1869 except ValueError as e:
1870 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001871 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001872 "Failed to receive with method <<{name:s}>>; "
1873 "expected to succeed.\n".format(name=meth_name)
1874 )
1875 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001876 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001877 "Method <<{name:s}>> failed with unexpected "
1878 "exception message: {exp:s}\n".format(
1879 name=meth_name, exp=e
1880 )
1881 )
1882 # consume data
1883 s.read()
1884
Nick Coghlan513886a2011-08-28 00:00:27 +10001885 # Make sure sendmsg et al are disallowed to avoid
1886 # inadvertent disclosure of data and/or corruption
1887 # of the encrypted data stream
1888 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1889 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1890 self.assertRaises(NotImplementedError,
1891 s.recvmsg_into, bytearray(100))
1892
Antoine Pitrou480a1242010-04-28 21:37:09 +00001893 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001894 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001895
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001896 def test_handshake_timeout(self):
1897 # Issue #5103: SSL handshake must respect the socket timeout
1898 server = socket.socket(socket.AF_INET)
1899 host = "127.0.0.1"
1900 port = support.bind_port(server)
1901 started = threading.Event()
1902 finish = False
1903
1904 def serve():
1905 server.listen(5)
1906 started.set()
1907 conns = []
1908 while not finish:
1909 r, w, e = select.select([server], [], [], 0.1)
1910 if server in r:
1911 # Let the socket hang around rather than having
1912 # it closed by garbage collection.
1913 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001914 for sock in conns:
1915 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001916
1917 t = threading.Thread(target=serve)
1918 t.start()
1919 started.wait()
1920
1921 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001922 try:
1923 c = socket.socket(socket.AF_INET)
1924 c.settimeout(0.2)
1925 c.connect((host, port))
1926 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001927 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001928 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001929 finally:
1930 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001931 try:
1932 c = socket.socket(socket.AF_INET)
1933 c = ssl.wrap_socket(c)
1934 c.settimeout(0.2)
1935 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001936 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001937 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001938 finally:
1939 c.close()
1940 finally:
1941 finish = True
1942 t.join()
1943 server.close()
1944
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001945 def test_server_accept(self):
1946 # Issue #16357: accept() on a SSLSocket created through
1947 # SSLContext.wrap_socket().
1948 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1949 context.verify_mode = ssl.CERT_REQUIRED
1950 context.load_verify_locations(CERTFILE)
1951 context.load_cert_chain(CERTFILE)
1952 server = socket.socket(socket.AF_INET)
1953 host = "127.0.0.1"
1954 port = support.bind_port(server)
1955 server = context.wrap_socket(server, server_side=True)
1956
1957 evt = threading.Event()
1958 remote = None
1959 peer = None
1960 def serve():
1961 nonlocal remote, peer
1962 server.listen(5)
1963 # Block on the accept and wait on the connection to close.
1964 evt.set()
1965 remote, peer = server.accept()
1966 remote.recv(1)
1967
1968 t = threading.Thread(target=serve)
1969 t.start()
1970 # Client wait until server setup and perform a connect.
1971 evt.wait()
1972 client = context.wrap_socket(socket.socket())
1973 client.connect((host, port))
1974 client_addr = client.getsockname()
1975 client.close()
1976 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001977 remote.close()
1978 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001979 # Sanity checks.
1980 self.assertIsInstance(remote, ssl.SSLSocket)
1981 self.assertEqual(peer, client_addr)
1982
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001983 def test_default_ciphers(self):
1984 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1985 try:
1986 # Force a set of weak ciphers on our client context
1987 context.set_ciphers("DES")
1988 except ssl.SSLError:
1989 self.skipTest("no DES cipher available")
1990 with ThreadedEchoServer(CERTFILE,
1991 ssl_version=ssl.PROTOCOL_SSLv23,
1992 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001993 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001994 with self.assertRaises((OSError, ssl.SSLError)):
1995 s.connect((HOST, server.port))
1996 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1997
Antoine Pitroud6494802011-07-21 01:11:30 +02001998 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1999 "'tls-unique' channel binding not available")
2000 def test_tls_unique_channel_binding(self):
2001 """Test tls-unique channel binding."""
2002 if support.verbose:
2003 sys.stdout.write("\n")
2004
2005 server = ThreadedEchoServer(CERTFILE,
2006 certreqs=ssl.CERT_NONE,
2007 ssl_version=ssl.PROTOCOL_TLSv1,
2008 cacerts=CERTFILE,
2009 chatty=True,
2010 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002011 with server:
2012 s = ssl.wrap_socket(socket.socket(),
2013 server_side=False,
2014 certfile=CERTFILE,
2015 ca_certs=CERTFILE,
2016 cert_reqs=ssl.CERT_NONE,
2017 ssl_version=ssl.PROTOCOL_TLSv1)
2018 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002019 # get the data
2020 cb_data = s.get_channel_binding("tls-unique")
2021 if support.verbose:
2022 sys.stdout.write(" got channel binding data: {0!r}\n"
2023 .format(cb_data))
2024
2025 # check if it is sane
2026 self.assertIsNotNone(cb_data)
2027 self.assertEqual(len(cb_data), 12) # True for TLSv1
2028
2029 # and compare with the peers version
2030 s.write(b"CB tls-unique\n")
2031 peer_data_repr = s.read().strip()
2032 self.assertEqual(peer_data_repr,
2033 repr(cb_data).encode("us-ascii"))
2034 s.close()
2035
2036 # now, again
2037 s = ssl.wrap_socket(socket.socket(),
2038 server_side=False,
2039 certfile=CERTFILE,
2040 ca_certs=CERTFILE,
2041 cert_reqs=ssl.CERT_NONE,
2042 ssl_version=ssl.PROTOCOL_TLSv1)
2043 s.connect((HOST, server.port))
2044 new_cb_data = s.get_channel_binding("tls-unique")
2045 if support.verbose:
2046 sys.stdout.write(" got another channel binding data: {0!r}\n"
2047 .format(new_cb_data))
2048 # is it really unique
2049 self.assertNotEqual(cb_data, new_cb_data)
2050 self.assertIsNotNone(cb_data)
2051 self.assertEqual(len(cb_data), 12) # True for TLSv1
2052 s.write(b"CB tls-unique\n")
2053 peer_data_repr = s.read().strip()
2054 self.assertEqual(peer_data_repr,
2055 repr(new_cb_data).encode("us-ascii"))
2056 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002057
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002058 def test_compression(self):
2059 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2060 context.load_cert_chain(CERTFILE)
2061 stats = server_params_test(context, context,
2062 chatty=True, connectionchatty=True)
2063 if support.verbose:
2064 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2065 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2066
2067 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2068 "ssl.OP_NO_COMPRESSION needed for this test")
2069 def test_compression_disabled(self):
2070 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2071 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002072 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002073 stats = server_params_test(context, context,
2074 chatty=True, connectionchatty=True)
2075 self.assertIs(stats['compression'], None)
2076
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002077 def test_dh_params(self):
2078 # Check we can get a connection with ephemeral Diffie-Hellman
2079 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2080 context.load_cert_chain(CERTFILE)
2081 context.load_dh_params(DHFILE)
2082 context.set_ciphers("kEDH")
2083 stats = server_params_test(context, context,
2084 chatty=True, connectionchatty=True)
2085 cipher = stats["cipher"][0]
2086 parts = cipher.split("-")
2087 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2088 self.fail("Non-DH cipher: " + cipher[0])
2089
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002090 def test_selected_npn_protocol(self):
2091 # selected_npn_protocol() is None unless NPN is used
2092 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2093 context.load_cert_chain(CERTFILE)
2094 stats = server_params_test(context, context,
2095 chatty=True, connectionchatty=True)
2096 self.assertIs(stats['client_npn_protocol'], None)
2097
2098 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2099 def test_npn_protocols(self):
2100 server_protocols = ['http/1.1', 'spdy/2']
2101 protocol_tests = [
2102 (['http/1.1', 'spdy/2'], 'http/1.1'),
2103 (['spdy/2', 'http/1.1'], 'http/1.1'),
2104 (['spdy/2', 'test'], 'spdy/2'),
2105 (['abc', 'def'], 'abc')
2106 ]
2107 for client_protocols, expected in protocol_tests:
2108 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2109 server_context.load_cert_chain(CERTFILE)
2110 server_context.set_npn_protocols(server_protocols)
2111 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2112 client_context.load_cert_chain(CERTFILE)
2113 client_context.set_npn_protocols(client_protocols)
2114 stats = server_params_test(client_context, server_context,
2115 chatty=True, connectionchatty=True)
2116
2117 msg = "failed trying %s (s) and %s (c).\n" \
2118 "was expecting %s, but got %%s from the %%s" \
2119 % (str(server_protocols), str(client_protocols),
2120 str(expected))
2121 client_result = stats['client_npn_protocol']
2122 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2123 server_result = stats['server_npn_protocols'][-1] \
2124 if len(stats['server_npn_protocols']) else 'nothing'
2125 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2126
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002127
Thomas Woutersed03b412007-08-28 21:37:11 +00002128def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002129 if support.verbose:
2130 plats = {
2131 'Linux': platform.linux_distribution,
2132 'Mac': platform.mac_ver,
2133 'Windows': platform.win32_ver,
2134 }
2135 for name, func in plats.items():
2136 plat = func()
2137 if plat and plat[0]:
2138 plat = '%s %r' % (name, plat)
2139 break
2140 else:
2141 plat = repr(platform.platform())
2142 print("test_ssl: testing with %r %r" %
2143 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2144 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002145 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002146
Antoine Pitrou152efa22010-05-16 18:19:27 +00002147 for filename in [
2148 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2149 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2150 BADCERT, BADKEY, EMPTYCERT]:
2151 if not os.path.exists(filename):
2152 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002153
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002154 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002155
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002156 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002157 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002158
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002159 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002160 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002161 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002162 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002163
Antoine Pitrou480a1242010-04-28 21:37:09 +00002164 try:
2165 support.run_unittest(*tests)
2166 finally:
2167 if _have_threads:
2168 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002169
2170if __name__ == "__main__":
2171 test_main()