blob: e52a71c24102fe121914a817a995500312872efd [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):
Benjamin Petersond0fc83d2014-03-12 18:10:47 -0500967 pem = ssl.get_server_certificate((host, port),
968 ssl.PROTOCOL_SSLv23)
Antoine Pitrou15399c32011-04-28 19:23:55 +0200969 if not pem:
970 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200971
Antoine Pitrou15399c32011-04-28 19:23:55 +0200972 try:
Benjamin Petersond0fc83d2014-03-12 18:10:47 -0500973 pem = ssl.get_server_certificate((host, port),
974 ssl.PROTOCOL_SSLv23,
975 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +0200976 except ssl.SSLError as x:
977 #should fail
978 if support.verbose:
979 sys.stdout.write("%s\n" % x)
980 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200981 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
982
Benjamin Petersond0fc83d2014-03-12 18:10:47 -0500983 pem = ssl.get_server_certificate((host, port),
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500984 ssl.PROTOCOL_SSLv23,
Benjamin Petersond0fc83d2014-03-12 18:10:47 -0500985 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +0200986 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200987 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000988 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200989 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000990
Antoine Pitrou15399c32011-04-28 19:23:55 +0200991 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
992 if support.IPV6_ENABLED:
993 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000994
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000995 def test_ciphers(self):
996 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000997 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100998 with ssl.wrap_socket(socket.socket(socket.AF_INET),
999 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1000 s.connect(remote)
1001 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1002 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1003 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001004 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001005 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001006 with socket.socket(socket.AF_INET) as sock:
1007 s = ssl.wrap_socket(sock,
1008 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1009 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001010
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001011 def test_algorithms(self):
1012 # Issue #8484: all algorithms should be available when verifying a
1013 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001014 # SHA256 was added in OpenSSL 0.9.8
1015 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1016 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001017 # sha256.tbs-internet.com needs SNI to use the correct certificate
1018 if not ssl.HAS_SNI:
1019 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001020 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1021 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001022 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001023 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001024 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1025 ctx.verify_mode = ssl.CERT_REQUIRED
1026 ctx.load_verify_locations(sha256_cert)
1027 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1028 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001029 try:
1030 s.connect(remote)
1031 if support.verbose:
1032 sys.stdout.write("\nCipher with %r is %r\n" %
1033 (remote, s.cipher()))
1034 sys.stdout.write("Certificate is:\n%s\n" %
1035 pprint.pformat(s.getpeercert()))
1036 finally:
1037 s.close()
1038
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001039
1040try:
1041 import threading
1042except ImportError:
1043 _have_threads = False
1044else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001045 _have_threads = True
1046
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001047 from test.ssl_servers import make_https_server
1048
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001049 class ThreadedEchoServer(threading.Thread):
1050
1051 class ConnectionHandler(threading.Thread):
1052
1053 """A mildly complicated class, because we want it to work both
1054 with and without the SSL wrapper around the socket connection, so
1055 that we can test the STARTTLS functionality."""
1056
Bill Janssen6e027db2007-11-15 22:23:56 +00001057 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001058 self.server = server
1059 self.running = False
1060 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001061 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001062 self.sock.setblocking(1)
1063 self.sslconn = None
1064 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001065 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001068 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001069 self.sslconn = self.server.context.wrap_socket(
1070 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001071 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001072 except (ssl.SSLError, ConnectionResetError) as e:
1073 # We treat ConnectionResetError as though it were an
1074 # SSLError - OpenSSL on Ubuntu abruptly closes the
1075 # connection when asked to use an unsupported protocol.
1076 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001077 # XXX Various errors can have happened here, for example
1078 # a mismatching protocol version, an invalid certificate,
1079 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001080 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001081 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001082 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001083 self.running = False
1084 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001085 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001087 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001088 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001089 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001090 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001091 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1092 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001093 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001094 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1095 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001096 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001097 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001098 sys.stdout.write(" server: selected protocol is now "
1099 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001100 return True
1101
1102 def read(self):
1103 if self.sslconn:
1104 return self.sslconn.read()
1105 else:
1106 return self.sock.recv(1024)
1107
1108 def write(self, bytes):
1109 if self.sslconn:
1110 return self.sslconn.write(bytes)
1111 else:
1112 return self.sock.send(bytes)
1113
1114 def close(self):
1115 if self.sslconn:
1116 self.sslconn.close()
1117 else:
1118 self.sock.close()
1119
Antoine Pitrou480a1242010-04-28 21:37:09 +00001120 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001121 self.running = True
1122 if not self.server.starttls_server:
1123 if not self.wrap_conn():
1124 return
1125 while self.running:
1126 try:
1127 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001128 stripped = msg.strip()
1129 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001130 # eof, so quit this handler
1131 self.running = False
1132 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001133 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001134 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001135 sys.stdout.write(" server: client closed connection\n")
1136 self.close()
1137 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001138 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001139 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001140 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001141 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001142 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001143 if not self.wrap_conn():
1144 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001145 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001146 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001147 if support.verbose and self.server.connectionchatty:
1148 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001149 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001150 self.sock = self.sslconn.unwrap()
1151 self.sslconn = None
1152 if support.verbose and self.server.connectionchatty:
1153 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001154 elif stripped == b'CB tls-unique':
1155 if support.verbose and self.server.connectionchatty:
1156 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1157 data = self.sslconn.get_channel_binding("tls-unique")
1158 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001159 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001160 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001161 self.server.connectionchatty):
1162 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001163 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1164 % (msg, ctype, msg.lower(), ctype))
1165 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001166 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167 if self.server.chatty:
1168 handle_error("Test server failure:\n")
1169 self.close()
1170 self.running = False
1171 # normally, we'd just stop here, but for the test
1172 # harness, we want to stop the server
1173 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174
Antoine Pitroub5218772010-05-21 09:56:06 +00001175 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001176 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001177 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001178 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001179 if context:
1180 self.context = context
1181 else:
1182 self.context = ssl.SSLContext(ssl_version
1183 if ssl_version is not None
1184 else ssl.PROTOCOL_TLSv1)
1185 self.context.verify_mode = (certreqs if certreqs is not None
1186 else ssl.CERT_NONE)
1187 if cacerts:
1188 self.context.load_verify_locations(cacerts)
1189 if certificate:
1190 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001191 if npn_protocols:
1192 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001193 if ciphers:
1194 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001195 self.chatty = chatty
1196 self.connectionchatty = connectionchatty
1197 self.starttls_server = starttls_server
1198 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001199 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001200 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001201 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001202 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001203 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001204 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001205 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001206
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001207 def __enter__(self):
1208 self.start(threading.Event())
1209 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001210 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001211
1212 def __exit__(self, *args):
1213 self.stop()
1214 self.join()
1215
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001217 self.flag = flag
1218 threading.Thread.start(self)
1219
Antoine Pitrou480a1242010-04-28 21:37:09 +00001220 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001221 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001222 self.sock.listen(5)
1223 self.active = True
1224 if self.flag:
1225 # signal an event
1226 self.flag.set()
1227 while self.active:
1228 try:
1229 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001230 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001232 + repr(connaddr) + '\n')
1233 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001235 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001236 except socket.timeout:
1237 pass
1238 except KeyboardInterrupt:
1239 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001240 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001244
Bill Janssen54cc54c2007-12-14 22:08:56 +00001245 class AsyncoreEchoServer(threading.Thread):
1246
1247 # this one's based on asyncore.dispatcher
1248
1249 class EchoServer (asyncore.dispatcher):
1250
1251 class ConnectionHandler (asyncore.dispatcher_with_send):
1252
1253 def __init__(self, conn, certfile):
1254 self.socket = ssl.wrap_socket(conn, server_side=True,
1255 certfile=certfile,
1256 do_handshake_on_connect=False)
1257 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001258 self._ssl_accepting = True
1259 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001260
1261 def readable(self):
1262 if isinstance(self.socket, ssl.SSLSocket):
1263 while self.socket.pending() > 0:
1264 self.handle_read_event()
1265 return True
1266
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001267 def _do_ssl_handshake(self):
1268 try:
1269 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001270 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1271 return
1272 except ssl.SSLEOFError:
1273 return self.handle_close()
1274 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001275 raise
1276 except socket.error as err:
1277 if err.args[0] == errno.ECONNABORTED:
1278 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001279 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001280 self._ssl_accepting = False
1281
1282 def handle_read(self):
1283 if self._ssl_accepting:
1284 self._do_ssl_handshake()
1285 else:
1286 data = self.recv(1024)
1287 if support.verbose:
1288 sys.stdout.write(" server: read %s from client\n" % repr(data))
1289 if not data:
1290 self.close()
1291 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001292 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001293
1294 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001295 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001296 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001297 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1298
1299 def handle_error(self):
1300 raise
1301
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001302 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001303 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001304 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1305 self.port = support.bind_port(sock, '')
1306 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001307 self.listen(5)
1308
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001309 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001310 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001311 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1312 self.ConnectionHandler(sock_obj, self.certfile)
1313
1314 def handle_error(self):
1315 raise
1316
Trent Nelson78520002008-04-10 20:54:35 +00001317 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001318 self.flag = None
1319 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001320 self.server = self.EchoServer(certfile)
1321 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001322 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001323 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001324
1325 def __str__(self):
1326 return "<%s %s>" % (self.__class__.__name__, self.server)
1327
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001328 def __enter__(self):
1329 self.start(threading.Event())
1330 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001331 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001332
1333 def __exit__(self, *args):
1334 if support.verbose:
1335 sys.stdout.write(" cleanup: stopping server.\n")
1336 self.stop()
1337 if support.verbose:
1338 sys.stdout.write(" cleanup: joining server thread.\n")
1339 self.join()
1340 if support.verbose:
1341 sys.stdout.write(" cleanup: successfully joined.\n")
1342
Bill Janssen54cc54c2007-12-14 22:08:56 +00001343 def start (self, flag=None):
1344 self.flag = flag
1345 threading.Thread.start(self)
1346
Antoine Pitrou480a1242010-04-28 21:37:09 +00001347 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001348 self.active = True
1349 if self.flag:
1350 self.flag.set()
1351 while self.active:
1352 try:
1353 asyncore.loop(1)
1354 except:
1355 pass
1356
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001358 self.active = False
1359 self.server.close()
1360
Antoine Pitrou480a1242010-04-28 21:37:09 +00001361 def bad_cert_test(certfile):
1362 """
1363 Launch a server with CERT_REQUIRED, and check that trying to
1364 connect to it with the given client certificate fails.
1365 """
Trent Nelson78520002008-04-10 20:54:35 +00001366 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001367 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001368 cacerts=CERTFILE, chatty=False,
1369 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001370 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001371 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001372 with socket.socket() as sock:
1373 s = ssl.wrap_socket(sock,
1374 certfile=certfile,
1375 ssl_version=ssl.PROTOCOL_TLSv1)
1376 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001377 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001378 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001379 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001380 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001382 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001383 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001384 if x.errno != errno.ENOENT:
1385 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001386 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001387 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001388 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001389 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001390
Antoine Pitroub5218772010-05-21 09:56:06 +00001391 def server_params_test(client_context, server_context, indata=b"FOO\n",
1392 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001393 """
1394 Launch a server, connect a client to it and try various reads
1395 and writes.
1396 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001397 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001398 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001399 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001400 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001401 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001402 with client_context.wrap_socket(socket.socket()) as s:
1403 s.connect((HOST, server.port))
1404 for arg in [indata, bytearray(indata), memoryview(indata)]:
1405 if connectionchatty:
1406 if support.verbose:
1407 sys.stdout.write(
1408 " client: sending %r...\n" % indata)
1409 s.write(arg)
1410 outdata = s.read()
1411 if connectionchatty:
1412 if support.verbose:
1413 sys.stdout.write(" client: read %r\n" % outdata)
1414 if outdata != indata.lower():
1415 raise AssertionError(
1416 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1417 % (outdata[:20], len(outdata),
1418 indata[:20].lower(), len(indata)))
1419 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001420 if connectionchatty:
1421 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001422 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001423 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001424 'compression': s.compression(),
1425 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001426 'client_npn_protocol': s.selected_npn_protocol()
1427 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001428 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001429 stats['server_npn_protocols'] = server.selected_protocols
1430 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001431
Antoine Pitroub5218772010-05-21 09:56:06 +00001432 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1433 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001434 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001435 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001436 certtype = {
1437 ssl.CERT_NONE: "CERT_NONE",
1438 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1439 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1440 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001441 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001442 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001443 sys.stdout.write(formatstr %
1444 (ssl.get_protocol_name(client_protocol),
1445 ssl.get_protocol_name(server_protocol),
1446 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001447 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001448 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001449 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001450 server_context.options |= server_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001451 for ctx in (client_context, server_context):
1452 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001453 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1454 # will send an SSLv3 hello (rather than SSLv2) starting from
1455 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001456 ctx.set_ciphers("ALL")
1457 ctx.load_cert_chain(CERTFILE)
1458 ctx.load_verify_locations(CERTFILE)
1459 try:
1460 server_params_test(client_context, server_context,
1461 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001462 # Protocol mismatch can result in either an SSLError, or a
1463 # "Connection reset by peer" error.
1464 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001465 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001466 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001467 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001468 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001469 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001470 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001471 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001472 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001473 "Client protocol %s succeeded with server protocol %s!"
1474 % (ssl.get_protocol_name(client_protocol),
1475 ssl.get_protocol_name(server_protocol)))
1476
1477
Bill Janssen6e027db2007-11-15 22:23:56 +00001478 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001479
Antoine Pitrou23df4832010-08-04 17:14:06 +00001480 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001481 def test_echo(self):
1482 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001483 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001484 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001485 for protocol in PROTOCOLS:
1486 context = ssl.SSLContext(protocol)
1487 context.load_cert_chain(CERTFILE)
1488 server_params_test(context, context,
1489 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001490
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001492 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001493 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001494 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1495 context.verify_mode = ssl.CERT_REQUIRED
1496 context.load_verify_locations(CERTFILE)
1497 context.load_cert_chain(CERTFILE)
1498 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001499 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001500 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001501 s.connect((HOST, server.port))
1502 cert = s.getpeercert()
1503 self.assertTrue(cert, "Can't get peer certificate.")
1504 cipher = s.cipher()
1505 if support.verbose:
1506 sys.stdout.write(pprint.pformat(cert) + '\n')
1507 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1508 if 'subject' not in cert:
1509 self.fail("No subject field in certificate: %s." %
1510 pprint.pformat(cert))
1511 if ((('organizationName', 'Python Software Foundation'),)
1512 not in cert['subject']):
1513 self.fail(
1514 "Missing or invalid 'organizationName' field in certificate subject; "
1515 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001516 self.assertIn('notBefore', cert)
1517 self.assertIn('notAfter', cert)
1518 before = ssl.cert_time_to_seconds(cert['notBefore'])
1519 after = ssl.cert_time_to_seconds(cert['notAfter'])
1520 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001521 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001522
Antoine Pitrou480a1242010-04-28 21:37:09 +00001523 def test_empty_cert(self):
1524 """Connecting with an empty cert file"""
1525 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1526 "nullcert.pem"))
1527 def test_malformed_cert(self):
1528 """Connecting with a badly formatted certificate (syntax error)"""
1529 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1530 "badcert.pem"))
1531 def test_nonexisting_cert(self):
1532 """Connecting with a non-existing cert file"""
1533 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1534 "wrongcert.pem"))
1535 def test_malformed_key(self):
1536 """Connecting with a badly formatted key (syntax error)"""
1537 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1538 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001539
Antoine Pitrou480a1242010-04-28 21:37:09 +00001540 def test_rude_shutdown(self):
1541 """A brutal shutdown of an SSL server should raise an IOError
1542 in the client when attempting handshake.
1543 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001544 listener_ready = threading.Event()
1545 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001546
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001547 s = socket.socket()
1548 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001549
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001550 # `listener` runs in a thread. It sits in an accept() until
1551 # the main thread connects. Then it rudely closes the socket,
1552 # and sets Event `listener_gone` to let the main thread know
1553 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001554 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001555 s.listen(5)
1556 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001557 newsock, addr = s.accept()
1558 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001559 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001560 listener_gone.set()
1561
1562 def connector():
1563 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001564 with socket.socket() as c:
1565 c.connect((HOST, port))
1566 listener_gone.wait()
1567 try:
1568 ssl_sock = ssl.wrap_socket(c)
1569 except IOError:
1570 pass
1571 else:
1572 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001573
1574 t = threading.Thread(target=listener)
1575 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001576 try:
1577 connector()
1578 finally:
1579 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001580
Antoine Pitrou23df4832010-08-04 17:14:06 +00001581 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001582 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1583 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001584 def test_protocol_sslv2(self):
1585 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001586 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001587 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001588 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1589 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1590 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001591 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001592 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1593 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001594 # SSLv23 client with specific SSL options
1595 if no_sslv2_implies_sslv3_hello():
1596 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1597 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1598 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001599 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00001600 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01001601 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00001602 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001603
Antoine Pitrou23df4832010-08-04 17:14:06 +00001604 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001605 def test_protocol_sslv23(self):
1606 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001607 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001608 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001609 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1610 try:
1611 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1612 except (ssl.SSLError, socket.error) as x:
1613 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1614 if support.verbose:
1615 sys.stdout.write(
1616 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1617 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001618 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1619 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1620 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001621
Antoine Pitrou480a1242010-04-28 21:37:09 +00001622 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1623 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1624 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001625
Antoine Pitrou480a1242010-04-28 21:37:09 +00001626 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1627 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1628 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001629
Antoine Pitroub5218772010-05-21 09:56:06 +00001630 # Server with specific SSL options
1631 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1632 server_options=ssl.OP_NO_SSLv3)
1633 # Will choose TLSv1
1634 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1635 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1636 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1637 server_options=ssl.OP_NO_TLSv1)
1638
1639
Antoine Pitrou23df4832010-08-04 17:14:06 +00001640 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001641 def test_protocol_sslv3(self):
1642 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001643 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001644 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001645 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1646 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1647 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001648 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1649 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001650 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1651 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001652 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001653 if no_sslv2_implies_sslv3_hello():
1654 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1655 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1656 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001657
Antoine Pitrou23df4832010-08-04 17:14:06 +00001658 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001659 def test_protocol_tlsv1(self):
1660 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001661 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001662 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001663 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1664 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1665 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001666 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1667 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001668 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001669 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1670 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001671
Antoine Pitrou480a1242010-04-28 21:37:09 +00001672 def test_starttls(self):
1673 """Switching from clear text to encrypted and back again."""
1674 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 +00001675
Trent Nelson78520002008-04-10 20:54:35 +00001676 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001677 ssl_version=ssl.PROTOCOL_TLSv1,
1678 starttls_server=True,
1679 chatty=True,
1680 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001681 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001682 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001683 s = socket.socket()
1684 s.setblocking(1)
1685 s.connect((HOST, server.port))
1686 if support.verbose:
1687 sys.stdout.write("\n")
1688 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001689 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001690 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001691 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001692 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001693 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001694 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001695 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001696 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001697 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001698 msg = outdata.strip().lower()
1699 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1700 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001701 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001702 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001703 " client: read %r from server, starting TLS...\n"
1704 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001705 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1706 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001707 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1708 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001709 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001710 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001711 " client: read %r from server, ending TLS...\n"
1712 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001713 s = conn.unwrap()
1714 wrapped = False
1715 else:
1716 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001717 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001718 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001719 if support.verbose:
1720 sys.stdout.write(" client: closing connection.\n")
1721 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001722 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001723 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001724 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001725 if wrapped:
1726 conn.close()
1727 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001728 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001729
Antoine Pitrou480a1242010-04-28 21:37:09 +00001730 def test_socketserver(self):
1731 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001732 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001733 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001734 if support.verbose:
1735 sys.stdout.write('\n')
1736 with open(CERTFILE, 'rb') as f:
1737 d1 = f.read()
1738 d2 = ''
1739 # now fetch the same data from the HTTPS server
1740 url = 'https://%s:%d/%s' % (
1741 HOST, server.port, os.path.split(CERTFILE)[1])
1742 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001743 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001744 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001745 if dlen and (int(dlen) > 0):
1746 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001747 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001748 sys.stdout.write(
1749 " client: read %d bytes from remote server '%s'\n"
1750 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001751 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001752 f.close()
1753 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001754
Antoine Pitrou480a1242010-04-28 21:37:09 +00001755 def test_asyncore_server(self):
1756 """Check the example asyncore integration."""
1757 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001758
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001759 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001760 sys.stdout.write("\n")
1761
Antoine Pitrou480a1242010-04-28 21:37:09 +00001762 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001763 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001764 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001765 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001766 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001767 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001768 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001769 " client: sending %r...\n" % indata)
1770 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001771 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001772 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001773 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001774 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001775 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001776 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1777 % (outdata[:20], len(outdata),
1778 indata[:20].lower(), len(indata)))
1779 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001780 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001781 sys.stdout.write(" client: closing connection.\n")
1782 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001783 if support.verbose:
1784 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001785
Antoine Pitrou480a1242010-04-28 21:37:09 +00001786 def test_recv_send(self):
1787 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001788 if support.verbose:
1789 sys.stdout.write("\n")
1790
1791 server = ThreadedEchoServer(CERTFILE,
1792 certreqs=ssl.CERT_NONE,
1793 ssl_version=ssl.PROTOCOL_TLSv1,
1794 cacerts=CERTFILE,
1795 chatty=True,
1796 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001797 with server:
1798 s = ssl.wrap_socket(socket.socket(),
1799 server_side=False,
1800 certfile=CERTFILE,
1801 ca_certs=CERTFILE,
1802 cert_reqs=ssl.CERT_NONE,
1803 ssl_version=ssl.PROTOCOL_TLSv1)
1804 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001805 # helper methods for standardising recv* method signatures
1806 def _recv_into():
1807 b = bytearray(b"\0"*100)
1808 count = s.recv_into(b)
1809 return b[:count]
1810
1811 def _recvfrom_into():
1812 b = bytearray(b"\0"*100)
1813 count, addr = s.recvfrom_into(b)
1814 return b[:count]
1815
1816 # (name, method, whether to expect success, *args)
1817 send_methods = [
1818 ('send', s.send, True, []),
1819 ('sendto', s.sendto, False, ["some.address"]),
1820 ('sendall', s.sendall, True, []),
1821 ]
1822 recv_methods = [
1823 ('recv', s.recv, True, []),
1824 ('recvfrom', s.recvfrom, False, ["some.address"]),
1825 ('recv_into', _recv_into, True, []),
1826 ('recvfrom_into', _recvfrom_into, False, []),
1827 ]
1828 data_prefix = "PREFIX_"
1829
1830 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001831 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001832 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001833 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001834 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001835 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001836 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001837 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001838 "<<{outdata:r}>> ({nout:d}) received; "
1839 "expected <<{indata:r}>> ({nin:d})\n".format(
1840 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001841 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001842 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001843 )
1844 )
1845 except ValueError as e:
1846 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001847 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001848 "Failed to send with method <<{name:s}>>; "
1849 "expected to succeed.\n".format(name=meth_name)
1850 )
1851 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001852 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001853 "Method <<{name:s}>> failed with unexpected "
1854 "exception message: {exp:s}\n".format(
1855 name=meth_name, exp=e
1856 )
1857 )
1858
1859 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001860 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001861 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001862 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001863 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001864 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001865 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001866 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001867 "<<{outdata:r}>> ({nout:d}) received; "
1868 "expected <<{indata:r}>> ({nin:d})\n".format(
1869 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001870 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001871 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001872 )
1873 )
1874 except ValueError as e:
1875 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001876 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001877 "Failed to receive with method <<{name:s}>>; "
1878 "expected to succeed.\n".format(name=meth_name)
1879 )
1880 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001881 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001882 "Method <<{name:s}>> failed with unexpected "
1883 "exception message: {exp:s}\n".format(
1884 name=meth_name, exp=e
1885 )
1886 )
1887 # consume data
1888 s.read()
1889
Nick Coghlan513886a2011-08-28 00:00:27 +10001890 # Make sure sendmsg et al are disallowed to avoid
1891 # inadvertent disclosure of data and/or corruption
1892 # of the encrypted data stream
1893 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1894 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1895 self.assertRaises(NotImplementedError,
1896 s.recvmsg_into, bytearray(100))
1897
Antoine Pitrou480a1242010-04-28 21:37:09 +00001898 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001899 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001900
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001901 def test_handshake_timeout(self):
1902 # Issue #5103: SSL handshake must respect the socket timeout
1903 server = socket.socket(socket.AF_INET)
1904 host = "127.0.0.1"
1905 port = support.bind_port(server)
1906 started = threading.Event()
1907 finish = False
1908
1909 def serve():
1910 server.listen(5)
1911 started.set()
1912 conns = []
1913 while not finish:
1914 r, w, e = select.select([server], [], [], 0.1)
1915 if server in r:
1916 # Let the socket hang around rather than having
1917 # it closed by garbage collection.
1918 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001919 for sock in conns:
1920 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001921
1922 t = threading.Thread(target=serve)
1923 t.start()
1924 started.wait()
1925
1926 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001927 try:
1928 c = socket.socket(socket.AF_INET)
1929 c.settimeout(0.2)
1930 c.connect((host, port))
1931 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001932 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001933 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001934 finally:
1935 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001936 try:
1937 c = socket.socket(socket.AF_INET)
1938 c = ssl.wrap_socket(c)
1939 c.settimeout(0.2)
1940 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001941 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001942 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001943 finally:
1944 c.close()
1945 finally:
1946 finish = True
1947 t.join()
1948 server.close()
1949
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001950 def test_server_accept(self):
1951 # Issue #16357: accept() on a SSLSocket created through
1952 # SSLContext.wrap_socket().
1953 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1954 context.verify_mode = ssl.CERT_REQUIRED
1955 context.load_verify_locations(CERTFILE)
1956 context.load_cert_chain(CERTFILE)
1957 server = socket.socket(socket.AF_INET)
1958 host = "127.0.0.1"
1959 port = support.bind_port(server)
1960 server = context.wrap_socket(server, server_side=True)
1961
1962 evt = threading.Event()
1963 remote = None
1964 peer = None
1965 def serve():
1966 nonlocal remote, peer
1967 server.listen(5)
1968 # Block on the accept and wait on the connection to close.
1969 evt.set()
1970 remote, peer = server.accept()
1971 remote.recv(1)
1972
1973 t = threading.Thread(target=serve)
1974 t.start()
1975 # Client wait until server setup and perform a connect.
1976 evt.wait()
1977 client = context.wrap_socket(socket.socket())
1978 client.connect((host, port))
1979 client_addr = client.getsockname()
1980 client.close()
1981 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001982 remote.close()
1983 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001984 # Sanity checks.
1985 self.assertIsInstance(remote, ssl.SSLSocket)
1986 self.assertEqual(peer, client_addr)
1987
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001988 def test_default_ciphers(self):
1989 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1990 try:
1991 # Force a set of weak ciphers on our client context
1992 context.set_ciphers("DES")
1993 except ssl.SSLError:
1994 self.skipTest("no DES cipher available")
1995 with ThreadedEchoServer(CERTFILE,
1996 ssl_version=ssl.PROTOCOL_SSLv23,
1997 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001998 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001999 with self.assertRaises((OSError, ssl.SSLError)):
2000 s.connect((HOST, server.port))
2001 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2002
Antoine Pitroud6494802011-07-21 01:11:30 +02002003 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2004 "'tls-unique' channel binding not available")
2005 def test_tls_unique_channel_binding(self):
2006 """Test tls-unique channel binding."""
2007 if support.verbose:
2008 sys.stdout.write("\n")
2009
2010 server = ThreadedEchoServer(CERTFILE,
2011 certreqs=ssl.CERT_NONE,
2012 ssl_version=ssl.PROTOCOL_TLSv1,
2013 cacerts=CERTFILE,
2014 chatty=True,
2015 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002016 with server:
2017 s = ssl.wrap_socket(socket.socket(),
2018 server_side=False,
2019 certfile=CERTFILE,
2020 ca_certs=CERTFILE,
2021 cert_reqs=ssl.CERT_NONE,
2022 ssl_version=ssl.PROTOCOL_TLSv1)
2023 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002024 # get the data
2025 cb_data = s.get_channel_binding("tls-unique")
2026 if support.verbose:
2027 sys.stdout.write(" got channel binding data: {0!r}\n"
2028 .format(cb_data))
2029
2030 # check if it is sane
2031 self.assertIsNotNone(cb_data)
2032 self.assertEqual(len(cb_data), 12) # True for TLSv1
2033
2034 # and compare with the peers version
2035 s.write(b"CB tls-unique\n")
2036 peer_data_repr = s.read().strip()
2037 self.assertEqual(peer_data_repr,
2038 repr(cb_data).encode("us-ascii"))
2039 s.close()
2040
2041 # now, again
2042 s = ssl.wrap_socket(socket.socket(),
2043 server_side=False,
2044 certfile=CERTFILE,
2045 ca_certs=CERTFILE,
2046 cert_reqs=ssl.CERT_NONE,
2047 ssl_version=ssl.PROTOCOL_TLSv1)
2048 s.connect((HOST, server.port))
2049 new_cb_data = s.get_channel_binding("tls-unique")
2050 if support.verbose:
2051 sys.stdout.write(" got another channel binding data: {0!r}\n"
2052 .format(new_cb_data))
2053 # is it really unique
2054 self.assertNotEqual(cb_data, new_cb_data)
2055 self.assertIsNotNone(cb_data)
2056 self.assertEqual(len(cb_data), 12) # True for TLSv1
2057 s.write(b"CB tls-unique\n")
2058 peer_data_repr = s.read().strip()
2059 self.assertEqual(peer_data_repr,
2060 repr(new_cb_data).encode("us-ascii"))
2061 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002062
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002063 def test_compression(self):
2064 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2065 context.load_cert_chain(CERTFILE)
2066 stats = server_params_test(context, context,
2067 chatty=True, connectionchatty=True)
2068 if support.verbose:
2069 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2070 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2071
2072 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2073 "ssl.OP_NO_COMPRESSION needed for this test")
2074 def test_compression_disabled(self):
2075 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2076 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002077 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002078 stats = server_params_test(context, context,
2079 chatty=True, connectionchatty=True)
2080 self.assertIs(stats['compression'], None)
2081
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002082 def test_dh_params(self):
2083 # Check we can get a connection with ephemeral Diffie-Hellman
2084 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2085 context.load_cert_chain(CERTFILE)
2086 context.load_dh_params(DHFILE)
2087 context.set_ciphers("kEDH")
2088 stats = server_params_test(context, context,
2089 chatty=True, connectionchatty=True)
2090 cipher = stats["cipher"][0]
2091 parts = cipher.split("-")
2092 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2093 self.fail("Non-DH cipher: " + cipher[0])
2094
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002095 def test_selected_npn_protocol(self):
2096 # selected_npn_protocol() is None unless NPN is used
2097 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2098 context.load_cert_chain(CERTFILE)
2099 stats = server_params_test(context, context,
2100 chatty=True, connectionchatty=True)
2101 self.assertIs(stats['client_npn_protocol'], None)
2102
2103 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2104 def test_npn_protocols(self):
2105 server_protocols = ['http/1.1', 'spdy/2']
2106 protocol_tests = [
2107 (['http/1.1', 'spdy/2'], 'http/1.1'),
2108 (['spdy/2', 'http/1.1'], 'http/1.1'),
2109 (['spdy/2', 'test'], 'spdy/2'),
2110 (['abc', 'def'], 'abc')
2111 ]
2112 for client_protocols, expected in protocol_tests:
2113 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2114 server_context.load_cert_chain(CERTFILE)
2115 server_context.set_npn_protocols(server_protocols)
2116 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2117 client_context.load_cert_chain(CERTFILE)
2118 client_context.set_npn_protocols(client_protocols)
2119 stats = server_params_test(client_context, server_context,
2120 chatty=True, connectionchatty=True)
2121
2122 msg = "failed trying %s (s) and %s (c).\n" \
2123 "was expecting %s, but got %%s from the %%s" \
2124 % (str(server_protocols), str(client_protocols),
2125 str(expected))
2126 client_result = stats['client_npn_protocol']
2127 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2128 server_result = stats['server_npn_protocols'][-1] \
2129 if len(stats['server_npn_protocols']) else 'nothing'
2130 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2131
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002132
Thomas Woutersed03b412007-08-28 21:37:11 +00002133def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002134 if support.verbose:
2135 plats = {
2136 'Linux': platform.linux_distribution,
2137 'Mac': platform.mac_ver,
2138 'Windows': platform.win32_ver,
2139 }
2140 for name, func in plats.items():
2141 plat = func()
2142 if plat and plat[0]:
2143 plat = '%s %r' % (name, plat)
2144 break
2145 else:
2146 plat = repr(platform.platform())
2147 print("test_ssl: testing with %r %r" %
2148 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2149 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002150 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002151
Antoine Pitrou152efa22010-05-16 18:19:27 +00002152 for filename in [
2153 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2154 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2155 BADCERT, BADKEY, EMPTYCERT]:
2156 if not os.path.exists(filename):
2157 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002158
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002159 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002160
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002161 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002162 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002163
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002164 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002165 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002166 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002167 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002168
Antoine Pitrou480a1242010-04-28 21:37:09 +00002169 try:
2170 support.run_unittest(*tests)
2171 finally:
2172 if _have_threads:
2173 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002174
2175if __name__ == "__main__":
2176 test_main()