blob: 06d4598a87790bcad90b93ffa3977aec5ca5ad1c [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
Jesus Ceac8754a12012-09-11 02:00:58 +0200129 self.assertRaises(TypeError, ssl.RAND_egd, 1)
130 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000131 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000132
Christian Heimesf77b4b22013-08-21 13:26:05 +0200133 @unittest.skipUnless(os.name == 'posix', 'requires posix')
134 def test_random_fork(self):
135 status = ssl.RAND_status()
136 if not status:
137 self.fail("OpenSSL's PRNG has insufficient randomness")
138
139 rfd, wfd = os.pipe()
140 pid = os.fork()
141 if pid == 0:
142 try:
143 os.close(rfd)
144 child_random = ssl.RAND_pseudo_bytes(16)[0]
145 self.assertEqual(len(child_random), 16)
146 os.write(wfd, child_random)
147 os.close(wfd)
148 except BaseException:
149 os._exit(1)
150 else:
151 os._exit(0)
152 else:
153 os.close(wfd)
154 self.addCleanup(os.close, rfd)
155 _, status = os.waitpid(pid, 0)
156 self.assertEqual(status, 0)
157
158 child_random = os.read(rfd, 16)
159 self.assertEqual(len(child_random), 16)
160 parent_random = ssl.RAND_pseudo_bytes(16)[0]
161 self.assertEqual(len(parent_random), 16)
162
163 self.assertNotEqual(child_random, parent_random)
164
Antoine Pitrou480a1242010-04-28 21:37:09 +0000165 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000166 # note that this uses an 'unofficial' function in _ssl.c,
167 # provided solely for this test, to exercise the certificate
168 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000169 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000170 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000171 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200172 self.assertEqual(p['issuer'],
173 ((('countryName', 'XY'),),
174 (('localityName', 'Castle Anthrax'),),
175 (('organizationName', 'Python Software Foundation'),),
176 (('commonName', 'localhost'),))
177 )
178 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
179 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
180 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
181 self.assertEqual(p['subject'],
182 ((('countryName', 'XY'),),
183 (('localityName', 'Castle Anthrax'),),
184 (('organizationName', 'Python Software Foundation'),),
185 (('commonName', 'localhost'),))
186 )
187 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
188 # Issue #13034: the subjectAltName in some certificates
189 # (notably projects.developer.nokia.com:443) wasn't parsed
190 p = ssl._ssl._test_decode_cert(NOKIACERT)
191 if support.verbose:
192 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
193 self.assertEqual(p['subjectAltName'],
194 (('DNS', 'projects.developer.nokia.com'),
195 ('DNS', 'projects.forum.nokia.com'))
196 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000197
Christian Heimes824f7f32013-08-17 00:54:47 +0200198 def test_parse_cert_CVE_2013_4238(self):
199 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
200 if support.verbose:
201 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
202 subject = ((('countryName', 'US'),),
203 (('stateOrProvinceName', 'Oregon'),),
204 (('localityName', 'Beaverton'),),
205 (('organizationName', 'Python Software Foundation'),),
206 (('organizationalUnitName', 'Python Core Development'),),
207 (('commonName', 'null.python.org\x00example.org'),),
208 (('emailAddress', 'python-dev@python.org'),))
209 self.assertEqual(p['subject'], subject)
210 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200211 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
212 san = (('DNS', 'altnull.python.org\x00example.com'),
213 ('email', 'null@python.org\x00user@example.org'),
214 ('URI', 'http://null.python.org\x00http://example.org'),
215 ('IP Address', '192.0.2.1'),
216 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
217 else:
218 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
219 san = (('DNS', 'altnull.python.org\x00example.com'),
220 ('email', 'null@python.org\x00user@example.org'),
221 ('URI', 'http://null.python.org\x00http://example.org'),
222 ('IP Address', '192.0.2.1'),
223 ('IP Address', '<invalid>'))
224
225 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200226
Antoine Pitrou480a1242010-04-28 21:37:09 +0000227 def test_DER_to_PEM(self):
228 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
229 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000230 d1 = ssl.PEM_cert_to_DER_cert(pem)
231 p2 = ssl.DER_cert_to_PEM_cert(d1)
232 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000233 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000234 if not p2.startswith(ssl.PEM_HEADER + '\n'):
235 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
236 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
237 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000238
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000239 def test_openssl_version(self):
240 n = ssl.OPENSSL_VERSION_NUMBER
241 t = ssl.OPENSSL_VERSION_INFO
242 s = ssl.OPENSSL_VERSION
243 self.assertIsInstance(n, int)
244 self.assertIsInstance(t, tuple)
245 self.assertIsInstance(s, str)
246 # Some sanity checks follow
247 # >= 0.9
248 self.assertGreaterEqual(n, 0x900000)
249 # < 2.0
250 self.assertLess(n, 0x20000000)
251 major, minor, fix, patch, status = t
252 self.assertGreaterEqual(major, 0)
253 self.assertLess(major, 2)
254 self.assertGreaterEqual(minor, 0)
255 self.assertLess(minor, 256)
256 self.assertGreaterEqual(fix, 0)
257 self.assertLess(fix, 256)
258 self.assertGreaterEqual(patch, 0)
259 self.assertLessEqual(patch, 26)
260 self.assertGreaterEqual(status, 0)
261 self.assertLessEqual(status, 15)
262 # Version string as returned by OpenSSL, the format might change
263 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
264 (s, t))
265
Antoine Pitrou9d543662010-04-23 23:10:32 +0000266 @support.cpython_only
267 def test_refcycle(self):
268 # Issue #7943: an SSL object doesn't create reference cycles with
269 # itself.
270 s = socket.socket(socket.AF_INET)
271 ss = ssl.wrap_socket(s)
272 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100273 with support.check_warnings(("", ResourceWarning)):
274 del ss
275 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000276
Antoine Pitroua468adc2010-09-14 14:43:44 +0000277 def test_wrapped_unconnected(self):
278 # Methods on an unconnected SSLSocket propagate the original
279 # socket.error raise by the underlying socket object.
280 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100281 with ssl.wrap_socket(s) as ss:
282 self.assertRaises(socket.error, ss.recv, 1)
283 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
284 self.assertRaises(socket.error, ss.recvfrom, 1)
285 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
286 self.assertRaises(socket.error, ss.send, b'x')
287 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000288
Antoine Pitrou40f08742010-04-24 22:04:40 +0000289 def test_timeout(self):
290 # Issue #8524: when creating an SSL socket, the timeout of the
291 # original socket should be retained.
292 for timeout in (None, 0.0, 5.0):
293 s = socket.socket(socket.AF_INET)
294 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100295 with ssl.wrap_socket(s) as ss:
296 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000297
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000298 def test_errors(self):
299 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000300 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000301 "certfile must be specified",
302 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000303 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000304 "certfile must be specified for server-side operations",
305 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000306 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000307 "certfile must be specified for server-side operations",
308 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100309 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
310 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
311 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000312 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000313 with socket.socket() as sock:
314 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000315 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +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=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000319 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +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=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000323 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000324
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000325 def test_match_hostname(self):
326 def ok(cert, hostname):
327 ssl.match_hostname(cert, hostname)
328 def fail(cert, hostname):
329 self.assertRaises(ssl.CertificateError,
330 ssl.match_hostname, cert, hostname)
331
332 cert = {'subject': ((('commonName', 'example.com'),),)}
333 ok(cert, 'example.com')
334 ok(cert, 'ExAmple.cOm')
335 fail(cert, 'www.example.com')
336 fail(cert, '.example.com')
337 fail(cert, 'example.org')
338 fail(cert, 'exampleXcom')
339
340 cert = {'subject': ((('commonName', '*.a.com'),),)}
341 ok(cert, 'foo.a.com')
342 fail(cert, 'bar.foo.a.com')
343 fail(cert, 'a.com')
344 fail(cert, 'Xa.com')
345 fail(cert, '.a.com')
346
Georg Brandl72c98d32013-10-27 07:16:53 +0100347 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000348 cert = {'subject': ((('commonName', 'f*.com'),),)}
349 ok(cert, 'foo.com')
350 ok(cert, 'f.com')
351 fail(cert, 'bar.com')
352 fail(cert, 'foo.a.com')
353 fail(cert, 'bar.foo.com')
354
Christian Heimes824f7f32013-08-17 00:54:47 +0200355 # NULL bytes are bad, CVE-2013-4073
356 cert = {'subject': ((('commonName',
357 'null.python.org\x00example.org'),),)}
358 ok(cert, 'null.python.org\x00example.org') # or raise an error?
359 fail(cert, 'example.org')
360 fail(cert, 'null.python.org')
361
Georg Brandl72c98d32013-10-27 07:16:53 +0100362 # error cases with wildcards
363 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
364 fail(cert, 'bar.foo.a.com')
365 fail(cert, 'a.com')
366 fail(cert, 'Xa.com')
367 fail(cert, '.a.com')
368
369 cert = {'subject': ((('commonName', 'a.*.com'),),)}
370 fail(cert, 'a.foo.com')
371 fail(cert, 'a..com')
372 fail(cert, 'a.com')
373
374 # wildcard doesn't match IDNA prefix 'xn--'
375 idna = 'püthon.python.org'.encode("idna").decode("ascii")
376 cert = {'subject': ((('commonName', idna),),)}
377 ok(cert, idna)
378 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
379 fail(cert, idna)
380 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
381 fail(cert, idna)
382
383 # wildcard in first fragment and IDNA A-labels in sequent fragments
384 # are supported.
385 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
386 cert = {'subject': ((('commonName', idna),),)}
387 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
388 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
389 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
390 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
391
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000392 # Slightly fake real-world example
393 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
394 'subject': ((('commonName', 'linuxfrz.org'),),),
395 'subjectAltName': (('DNS', 'linuxfr.org'),
396 ('DNS', 'linuxfr.com'),
397 ('othername', '<unsupported>'))}
398 ok(cert, 'linuxfr.org')
399 ok(cert, 'linuxfr.com')
400 # Not a "DNS" entry
401 fail(cert, '<unsupported>')
402 # When there is a subjectAltName, commonName isn't used
403 fail(cert, 'linuxfrz.org')
404
405 # A pristine real-world example
406 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
407 'subject': ((('countryName', 'US'),),
408 (('stateOrProvinceName', 'California'),),
409 (('localityName', 'Mountain View'),),
410 (('organizationName', 'Google Inc'),),
411 (('commonName', 'mail.google.com'),))}
412 ok(cert, 'mail.google.com')
413 fail(cert, 'gmail.com')
414 # Only commonName is considered
415 fail(cert, 'California')
416
417 # Neither commonName nor subjectAltName
418 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
419 'subject': ((('countryName', 'US'),),
420 (('stateOrProvinceName', 'California'),),
421 (('localityName', 'Mountain View'),),
422 (('organizationName', 'Google Inc'),))}
423 fail(cert, 'mail.google.com')
424
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200425 # No DNS entry in subjectAltName but a commonName
426 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
427 'subject': ((('countryName', 'US'),),
428 (('stateOrProvinceName', 'California'),),
429 (('localityName', 'Mountain View'),),
430 (('commonName', 'mail.google.com'),)),
431 'subjectAltName': (('othername', 'blabla'), )}
432 ok(cert, 'mail.google.com')
433
434 # No DNS entry subjectAltName and no commonName
435 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
436 'subject': ((('countryName', 'US'),),
437 (('stateOrProvinceName', 'California'),),
438 (('localityName', 'Mountain View'),),
439 (('organizationName', 'Google Inc'),)),
440 'subjectAltName': (('othername', 'blabla'),)}
441 fail(cert, 'google.com')
442
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000443 # Empty cert / no cert
444 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
445 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
446
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200447 # Issue #17980: avoid denials of service by refusing more than one
448 # wildcard per fragment.
449 cert = {'subject': ((('commonName', 'a*b.com'),),)}
450 ok(cert, 'axxb.com')
451 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100452 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200453 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
454 with self.assertRaises(ssl.CertificateError) as cm:
455 ssl.match_hostname(cert, 'axxbxxc.com')
456 self.assertIn("too many wildcards", str(cm.exception))
457
Antoine Pitroud5323212010-10-22 18:19:07 +0000458 def test_server_side(self):
459 # server_hostname doesn't work for server sockets
460 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000461 with socket.socket() as sock:
462 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
463 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000464
Antoine Pitroud6494802011-07-21 01:11:30 +0200465 def test_unknown_channel_binding(self):
466 # should raise ValueError for unknown type
467 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100468 with ssl.wrap_socket(s) as ss:
469 with self.assertRaises(ValueError):
470 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200471
472 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
473 "'tls-unique' channel binding not available")
474 def test_tls_unique_channel_binding(self):
475 # unconnected should return None for known type
476 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100477 with ssl.wrap_socket(s) as ss:
478 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200479 # the same for server-side
480 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100481 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
482 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200483
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600484 def test_dealloc_warn(self):
485 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
486 r = repr(ss)
487 with self.assertWarns(ResourceWarning) as cm:
488 ss = None
489 support.gc_collect()
490 self.assertIn(r, str(cm.warning.args[0]))
491
Antoine Pitrou152efa22010-05-16 18:19:27 +0000492class ContextTests(unittest.TestCase):
493
Antoine Pitrou23df4832010-08-04 17:14:06 +0000494 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000495 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200496 if hasattr(ssl, 'PROTOCOL_SSLv2'):
497 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000498 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
499 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
500 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
501 self.assertRaises(TypeError, ssl.SSLContext)
502 self.assertRaises(ValueError, ssl.SSLContext, -1)
503 self.assertRaises(ValueError, ssl.SSLContext, 42)
504
Antoine Pitrou23df4832010-08-04 17:14:06 +0000505 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000506 def test_protocol(self):
507 for proto in PROTOCOLS:
508 ctx = ssl.SSLContext(proto)
509 self.assertEqual(ctx.protocol, proto)
510
511 def test_ciphers(self):
512 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
513 ctx.set_ciphers("ALL")
514 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000515 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000516 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000517
Antoine Pitrou23df4832010-08-04 17:14:06 +0000518 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000519 def test_options(self):
520 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
521 # OP_ALL is the default value
522 self.assertEqual(ssl.OP_ALL, ctx.options)
523 ctx.options |= ssl.OP_NO_SSLv2
524 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
525 ctx.options)
526 ctx.options |= ssl.OP_NO_SSLv3
527 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
528 ctx.options)
529 if can_clear_options():
530 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
531 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
532 ctx.options)
533 ctx.options = 0
534 self.assertEqual(0, ctx.options)
535 else:
536 with self.assertRaises(ValueError):
537 ctx.options = 0
538
Antoine Pitrou152efa22010-05-16 18:19:27 +0000539 def test_verify(self):
540 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
541 # Default value
542 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
543 ctx.verify_mode = ssl.CERT_OPTIONAL
544 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
545 ctx.verify_mode = ssl.CERT_REQUIRED
546 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
547 ctx.verify_mode = ssl.CERT_NONE
548 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
549 with self.assertRaises(TypeError):
550 ctx.verify_mode = None
551 with self.assertRaises(ValueError):
552 ctx.verify_mode = 42
553
554 def test_load_cert_chain(self):
555 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
556 # Combined key and cert in a single file
557 ctx.load_cert_chain(CERTFILE)
558 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
559 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000560 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000561 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000562 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000563 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000564 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000565 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000566 ctx.load_cert_chain(EMPTYCERT)
567 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000568 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000569 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
570 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
571 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000572 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000573 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000574 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000575 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000576 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000577 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
578 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000579 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000580 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000581 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200582 # Password protected key and cert
583 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
584 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
585 ctx.load_cert_chain(CERTFILE_PROTECTED,
586 password=bytearray(KEY_PASSWORD.encode()))
587 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
588 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
589 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
590 bytearray(KEY_PASSWORD.encode()))
591 with self.assertRaisesRegex(TypeError, "should be a string"):
592 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
593 with self.assertRaises(ssl.SSLError):
594 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
595 with self.assertRaisesRegex(ValueError, "cannot be longer"):
596 # openssl has a fixed limit on the password buffer.
597 # PEM_BUFSIZE is generally set to 1kb.
598 # Return a string larger than this.
599 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
600 # Password callback
601 def getpass_unicode():
602 return KEY_PASSWORD
603 def getpass_bytes():
604 return KEY_PASSWORD.encode()
605 def getpass_bytearray():
606 return bytearray(KEY_PASSWORD.encode())
607 def getpass_badpass():
608 return "badpass"
609 def getpass_huge():
610 return b'a' * (1024 * 1024)
611 def getpass_bad_type():
612 return 9
613 def getpass_exception():
614 raise Exception('getpass error')
615 class GetPassCallable:
616 def __call__(self):
617 return KEY_PASSWORD
618 def getpass(self):
619 return KEY_PASSWORD
620 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
621 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
622 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
623 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
624 ctx.load_cert_chain(CERTFILE_PROTECTED,
625 password=GetPassCallable().getpass)
626 with self.assertRaises(ssl.SSLError):
627 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
628 with self.assertRaisesRegex(ValueError, "cannot be longer"):
629 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
630 with self.assertRaisesRegex(TypeError, "must return a string"):
631 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
632 with self.assertRaisesRegex(Exception, "getpass error"):
633 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
634 # Make sure the password function isn't called if it isn't needed
635 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000636
637 def test_load_verify_locations(self):
638 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
639 ctx.load_verify_locations(CERTFILE)
640 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
641 ctx.load_verify_locations(BYTES_CERTFILE)
642 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
643 self.assertRaises(TypeError, ctx.load_verify_locations)
644 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000645 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000646 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000647 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000648 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000649 ctx.load_verify_locations(BADCERT)
650 ctx.load_verify_locations(CERTFILE, CAPATH)
651 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
652
Victor Stinner80f75e62011-01-29 11:31:20 +0000653 # Issue #10989: crash if the second argument type is invalid
654 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
655
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100656 def test_load_dh_params(self):
657 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
658 ctx.load_dh_params(DHFILE)
659 if os.name != 'nt':
660 ctx.load_dh_params(BYTES_DHFILE)
661 self.assertRaises(TypeError, ctx.load_dh_params)
662 self.assertRaises(TypeError, ctx.load_dh_params, None)
663 with self.assertRaises(FileNotFoundError) as cm:
664 ctx.load_dh_params(WRONGCERT)
665 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200666 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100667 ctx.load_dh_params(CERTFILE)
668
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000669 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000670 def test_session_stats(self):
671 for proto in PROTOCOLS:
672 ctx = ssl.SSLContext(proto)
673 self.assertEqual(ctx.session_stats(), {
674 'number': 0,
675 'connect': 0,
676 'connect_good': 0,
677 'connect_renegotiate': 0,
678 'accept': 0,
679 'accept_good': 0,
680 'accept_renegotiate': 0,
681 'hits': 0,
682 'misses': 0,
683 'timeouts': 0,
684 'cache_full': 0,
685 })
686
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000687 def test_set_default_verify_paths(self):
688 # There's not much we can do to test that it acts as expected,
689 # so just check it doesn't crash or raise an exception.
690 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
691 ctx.set_default_verify_paths()
692
Antoine Pitrou501da612011-12-21 09:27:41 +0100693 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100694 def test_set_ecdh_curve(self):
695 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
696 ctx.set_ecdh_curve("prime256v1")
697 ctx.set_ecdh_curve(b"prime256v1")
698 self.assertRaises(TypeError, ctx.set_ecdh_curve)
699 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
700 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
701 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
702
Antoine Pitrou152efa22010-05-16 18:19:27 +0000703
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200704class SSLErrorTests(unittest.TestCase):
705
706 def test_str(self):
707 # The str() of a SSLError doesn't include the errno
708 e = ssl.SSLError(1, "foo")
709 self.assertEqual(str(e), "foo")
710 self.assertEqual(e.errno, 1)
711 # Same for a subclass
712 e = ssl.SSLZeroReturnError(1, "foo")
713 self.assertEqual(str(e), "foo")
714 self.assertEqual(e.errno, 1)
715
716 def test_lib_reason(self):
717 # Test the library and reason attributes
718 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
719 with self.assertRaises(ssl.SSLError) as cm:
720 ctx.load_dh_params(CERTFILE)
721 self.assertEqual(cm.exception.library, 'PEM')
722 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
723 s = str(cm.exception)
724 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
725
726 def test_subclass(self):
727 # Check that the appropriate SSLError subclass is raised
728 # (this only tests one of them)
729 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
730 with socket.socket() as s:
731 s.bind(("127.0.0.1", 0))
732 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100733 c = socket.socket()
734 c.connect(s.getsockname())
735 c.setblocking(False)
736 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200737 with self.assertRaises(ssl.SSLWantReadError) as cm:
738 c.do_handshake()
739 s = str(cm.exception)
740 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
741 # For compatibility
742 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
743
744
Bill Janssen6e027db2007-11-15 22:23:56 +0000745class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000746
Antoine Pitrou480a1242010-04-28 21:37:09 +0000747 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000748 with support.transient_internet("svn.python.org"):
749 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
750 cert_reqs=ssl.CERT_NONE)
751 try:
752 s.connect(("svn.python.org", 443))
753 self.assertEqual({}, s.getpeercert())
754 finally:
755 s.close()
756
757 # this should fail because we have no verification certs
758 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
759 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000760 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
761 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000762 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763
Antoine Pitrou350c7222010-09-09 13:31:46 +0000764 # this should succeed because we specify the root cert
765 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
766 cert_reqs=ssl.CERT_REQUIRED,
767 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
768 try:
769 s.connect(("svn.python.org", 443))
770 self.assertTrue(s.getpeercert())
771 finally:
772 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000773
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000774 def test_connect_ex(self):
775 # Issue #11326: check connect_ex() implementation
776 with support.transient_internet("svn.python.org"):
777 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
778 cert_reqs=ssl.CERT_REQUIRED,
779 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
780 try:
781 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
782 self.assertTrue(s.getpeercert())
783 finally:
784 s.close()
785
786 def test_non_blocking_connect_ex(self):
787 # Issue #11326: non-blocking connect_ex() should allow handshake
788 # to proceed after the socket gets ready.
789 with support.transient_internet("svn.python.org"):
790 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
791 cert_reqs=ssl.CERT_REQUIRED,
792 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
793 do_handshake_on_connect=False)
794 try:
795 s.setblocking(False)
796 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000797 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
798 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000799 # Wait for connect to finish
800 select.select([], [s], [], 5.0)
801 # Non-blocking handshake
802 while True:
803 try:
804 s.do_handshake()
805 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200806 except ssl.SSLWantReadError:
807 select.select([s], [], [], 5.0)
808 except ssl.SSLWantWriteError:
809 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000810 # SSL established
811 self.assertTrue(s.getpeercert())
812 finally:
813 s.close()
814
Antoine Pitroub4410db2011-05-18 18:51:06 +0200815 def test_timeout_connect_ex(self):
816 # Issue #12065: on a timeout, connect_ex() should return the original
817 # errno (mimicking the behaviour of non-SSL sockets).
818 with support.transient_internet("svn.python.org"):
819 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
820 cert_reqs=ssl.CERT_REQUIRED,
821 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
822 do_handshake_on_connect=False)
823 try:
824 s.settimeout(0.0000001)
825 rc = s.connect_ex(('svn.python.org', 443))
826 if rc == 0:
827 self.skipTest("svn.python.org responded too quickly")
828 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
829 finally:
830 s.close()
831
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100832 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100833 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100834 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
835 cert_reqs=ssl.CERT_REQUIRED,
836 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
837 try:
838 self.assertEqual(errno.ECONNREFUSED,
839 s.connect_ex(("svn.python.org", 444)))
840 finally:
841 s.close()
842
Antoine Pitrou152efa22010-05-16 18:19:27 +0000843 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000844 with support.transient_internet("svn.python.org"):
845 # Same as test_connect, but with a separately created context
846 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
847 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
848 s.connect(("svn.python.org", 443))
849 try:
850 self.assertEqual({}, s.getpeercert())
851 finally:
852 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000853 # Same with a server hostname
854 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
855 server_hostname="svn.python.org")
856 if ssl.HAS_SNI:
857 s.connect(("svn.python.org", 443))
858 s.close()
859 else:
860 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000861 # This should fail because we have no verification certs
862 ctx.verify_mode = ssl.CERT_REQUIRED
863 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000864 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000865 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000866 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000867 # This should succeed because we specify the root cert
868 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
869 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
870 s.connect(("svn.python.org", 443))
871 try:
872 cert = s.getpeercert()
873 self.assertTrue(cert)
874 finally:
875 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000876
877 def test_connect_capath(self):
878 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000879 # NOTE: the subject hashing algorithm has been changed between
880 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
881 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000882 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000883 with support.transient_internet("svn.python.org"):
884 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
885 ctx.verify_mode = ssl.CERT_REQUIRED
886 ctx.load_verify_locations(capath=CAPATH)
887 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
888 s.connect(("svn.python.org", 443))
889 try:
890 cert = s.getpeercert()
891 self.assertTrue(cert)
892 finally:
893 s.close()
894 # Same with a bytes `capath` argument
895 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
896 ctx.verify_mode = ssl.CERT_REQUIRED
897 ctx.load_verify_locations(capath=BYTES_CAPATH)
898 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
899 s.connect(("svn.python.org", 443))
900 try:
901 cert = s.getpeercert()
902 self.assertTrue(cert)
903 finally:
904 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905
Antoine Pitroue3220242010-04-24 11:13:53 +0000906 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
907 def test_makefile_close(self):
908 # Issue #5238: creating a file-like object with makefile() shouldn't
909 # delay closing the underlying "real socket" (here tested with its
910 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000911 with support.transient_internet("svn.python.org"):
912 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
913 ss.connect(("svn.python.org", 443))
914 fd = ss.fileno()
915 f = ss.makefile()
916 f.close()
917 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000918 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000919 # Closing the SSL socket should close the fd too
920 ss.close()
921 gc.collect()
922 with self.assertRaises(OSError) as e:
923 os.read(fd, 0)
924 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000925
Antoine Pitrou480a1242010-04-28 21:37:09 +0000926 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000927 with support.transient_internet("svn.python.org"):
928 s = socket.socket(socket.AF_INET)
929 s.connect(("svn.python.org", 443))
930 s.setblocking(False)
931 s = ssl.wrap_socket(s,
932 cert_reqs=ssl.CERT_NONE,
933 do_handshake_on_connect=False)
934 count = 0
935 while True:
936 try:
937 count += 1
938 s.do_handshake()
939 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200940 except ssl.SSLWantReadError:
941 select.select([s], [], [])
942 except ssl.SSLWantWriteError:
943 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000944 s.close()
945 if support.verbose:
946 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947
Antoine Pitrou480a1242010-04-28 21:37:09 +0000948 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200949 def _test_get_server_certificate(host, port, cert=None):
950 with support.transient_internet(host):
951 pem = ssl.get_server_certificate((host, port))
952 if not pem:
953 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200954
Antoine Pitrou15399c32011-04-28 19:23:55 +0200955 try:
956 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
957 except ssl.SSLError as x:
958 #should fail
959 if support.verbose:
960 sys.stdout.write("%s\n" % x)
961 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200962 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
963
Antoine Pitrou15399c32011-04-28 19:23:55 +0200964 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
965 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200966 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000967 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200968 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000969
Antoine Pitrou15399c32011-04-28 19:23:55 +0200970 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
971 if support.IPV6_ENABLED:
972 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000973
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000974 def test_ciphers(self):
975 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000976 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100977 with ssl.wrap_socket(socket.socket(socket.AF_INET),
978 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
979 s.connect(remote)
980 with ssl.wrap_socket(socket.socket(socket.AF_INET),
981 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
982 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000983 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000984 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000985 with socket.socket(socket.AF_INET) as sock:
986 s = ssl.wrap_socket(sock,
987 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
988 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000989
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000990 def test_algorithms(self):
991 # Issue #8484: all algorithms should be available when verifying a
992 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000993 # SHA256 was added in OpenSSL 0.9.8
994 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
995 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200996 # sha256.tbs-internet.com needs SNI to use the correct certificate
997 if not ssl.HAS_SNI:
998 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000999 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1000 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001001 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001002 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001003 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1004 ctx.verify_mode = ssl.CERT_REQUIRED
1005 ctx.load_verify_locations(sha256_cert)
1006 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1007 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001008 try:
1009 s.connect(remote)
1010 if support.verbose:
1011 sys.stdout.write("\nCipher with %r is %r\n" %
1012 (remote, s.cipher()))
1013 sys.stdout.write("Certificate is:\n%s\n" %
1014 pprint.pformat(s.getpeercert()))
1015 finally:
1016 s.close()
1017
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001018
1019try:
1020 import threading
1021except ImportError:
1022 _have_threads = False
1023else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001024 _have_threads = True
1025
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001026 from test.ssl_servers import make_https_server
1027
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001028 class ThreadedEchoServer(threading.Thread):
1029
1030 class ConnectionHandler(threading.Thread):
1031
1032 """A mildly complicated class, because we want it to work both
1033 with and without the SSL wrapper around the socket connection, so
1034 that we can test the STARTTLS functionality."""
1035
Bill Janssen6e027db2007-11-15 22:23:56 +00001036 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001037 self.server = server
1038 self.running = False
1039 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001040 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001041 self.sock.setblocking(1)
1042 self.sslconn = None
1043 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001044 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001045
Antoine Pitrou480a1242010-04-28 21:37:09 +00001046 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001047 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001048 self.sslconn = self.server.context.wrap_socket(
1049 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001050 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001051 except (ssl.SSLError, ConnectionResetError) as e:
1052 # We treat ConnectionResetError as though it were an
1053 # SSLError - OpenSSL on Ubuntu abruptly closes the
1054 # connection when asked to use an unsupported protocol.
1055 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001056 # XXX Various errors can have happened here, for example
1057 # a mismatching protocol version, an invalid certificate,
1058 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001059 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001060 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001061 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001062 self.running = False
1063 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001064 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001065 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001067 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001068 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001069 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001070 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1071 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001072 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1074 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001075 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001076 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001077 sys.stdout.write(" server: selected protocol is now "
1078 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001079 return True
1080
1081 def read(self):
1082 if self.sslconn:
1083 return self.sslconn.read()
1084 else:
1085 return self.sock.recv(1024)
1086
1087 def write(self, bytes):
1088 if self.sslconn:
1089 return self.sslconn.write(bytes)
1090 else:
1091 return self.sock.send(bytes)
1092
1093 def close(self):
1094 if self.sslconn:
1095 self.sslconn.close()
1096 else:
1097 self.sock.close()
1098
Antoine Pitrou480a1242010-04-28 21:37:09 +00001099 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001100 self.running = True
1101 if not self.server.starttls_server:
1102 if not self.wrap_conn():
1103 return
1104 while self.running:
1105 try:
1106 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001107 stripped = msg.strip()
1108 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109 # eof, so quit this handler
1110 self.running = False
1111 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001112 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001113 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001114 sys.stdout.write(" server: client closed connection\n")
1115 self.close()
1116 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001117 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001118 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001119 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001120 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001121 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001122 if not self.wrap_conn():
1123 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001124 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001125 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001126 if support.verbose and self.server.connectionchatty:
1127 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001128 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001129 self.sock = self.sslconn.unwrap()
1130 self.sslconn = None
1131 if support.verbose and self.server.connectionchatty:
1132 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001133 elif stripped == b'CB tls-unique':
1134 if support.verbose and self.server.connectionchatty:
1135 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1136 data = self.sslconn.get_channel_binding("tls-unique")
1137 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001138 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001139 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140 self.server.connectionchatty):
1141 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001142 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1143 % (msg, ctype, msg.lower(), ctype))
1144 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001145 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001146 if self.server.chatty:
1147 handle_error("Test server failure:\n")
1148 self.close()
1149 self.running = False
1150 # normally, we'd just stop here, but for the test
1151 # harness, we want to stop the server
1152 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001153
Antoine Pitroub5218772010-05-21 09:56:06 +00001154 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001155 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001156 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001157 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001158 if context:
1159 self.context = context
1160 else:
1161 self.context = ssl.SSLContext(ssl_version
1162 if ssl_version is not None
1163 else ssl.PROTOCOL_TLSv1)
1164 self.context.verify_mode = (certreqs if certreqs is not None
1165 else ssl.CERT_NONE)
1166 if cacerts:
1167 self.context.load_verify_locations(cacerts)
1168 if certificate:
1169 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001170 if npn_protocols:
1171 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001172 if ciphers:
1173 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 self.chatty = chatty
1175 self.connectionchatty = connectionchatty
1176 self.starttls_server = starttls_server
1177 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001178 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001180 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001181 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001182 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001183 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001184 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001185
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001186 def __enter__(self):
1187 self.start(threading.Event())
1188 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001189 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001190
1191 def __exit__(self, *args):
1192 self.stop()
1193 self.join()
1194
Antoine Pitrou480a1242010-04-28 21:37:09 +00001195 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001196 self.flag = flag
1197 threading.Thread.start(self)
1198
Antoine Pitrou480a1242010-04-28 21:37:09 +00001199 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001200 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001201 self.sock.listen(5)
1202 self.active = True
1203 if self.flag:
1204 # signal an event
1205 self.flag.set()
1206 while self.active:
1207 try:
1208 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001209 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001210 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001211 + repr(connaddr) + '\n')
1212 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001213 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001214 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001215 except socket.timeout:
1216 pass
1217 except KeyboardInterrupt:
1218 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001219 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001220
Antoine Pitrou480a1242010-04-28 21:37:09 +00001221 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001222 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001223
Bill Janssen54cc54c2007-12-14 22:08:56 +00001224 class AsyncoreEchoServer(threading.Thread):
1225
1226 # this one's based on asyncore.dispatcher
1227
1228 class EchoServer (asyncore.dispatcher):
1229
1230 class ConnectionHandler (asyncore.dispatcher_with_send):
1231
1232 def __init__(self, conn, certfile):
1233 self.socket = ssl.wrap_socket(conn, server_side=True,
1234 certfile=certfile,
1235 do_handshake_on_connect=False)
1236 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001237 self._ssl_accepting = True
1238 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001239
1240 def readable(self):
1241 if isinstance(self.socket, ssl.SSLSocket):
1242 while self.socket.pending() > 0:
1243 self.handle_read_event()
1244 return True
1245
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001246 def _do_ssl_handshake(self):
1247 try:
1248 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001249 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1250 return
1251 except ssl.SSLEOFError:
1252 return self.handle_close()
1253 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001254 raise
1255 except socket.error as err:
1256 if err.args[0] == errno.ECONNABORTED:
1257 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001258 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001259 self._ssl_accepting = False
1260
1261 def handle_read(self):
1262 if self._ssl_accepting:
1263 self._do_ssl_handshake()
1264 else:
1265 data = self.recv(1024)
1266 if support.verbose:
1267 sys.stdout.write(" server: read %s from client\n" % repr(data))
1268 if not data:
1269 self.close()
1270 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001271 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001272
1273 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001274 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001275 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001276 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1277
1278 def handle_error(self):
1279 raise
1280
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001281 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001282 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001283 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1284 self.port = support.bind_port(sock, '')
1285 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001286 self.listen(5)
1287
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001288 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001289 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001290 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1291 self.ConnectionHandler(sock_obj, self.certfile)
1292
1293 def handle_error(self):
1294 raise
1295
Trent Nelson78520002008-04-10 20:54:35 +00001296 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001297 self.flag = None
1298 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001299 self.server = self.EchoServer(certfile)
1300 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001301 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001302 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001303
1304 def __str__(self):
1305 return "<%s %s>" % (self.__class__.__name__, self.server)
1306
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001307 def __enter__(self):
1308 self.start(threading.Event())
1309 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001310 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001311
1312 def __exit__(self, *args):
1313 if support.verbose:
1314 sys.stdout.write(" cleanup: stopping server.\n")
1315 self.stop()
1316 if support.verbose:
1317 sys.stdout.write(" cleanup: joining server thread.\n")
1318 self.join()
1319 if support.verbose:
1320 sys.stdout.write(" cleanup: successfully joined.\n")
1321
Bill Janssen54cc54c2007-12-14 22:08:56 +00001322 def start (self, flag=None):
1323 self.flag = flag
1324 threading.Thread.start(self)
1325
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001327 self.active = True
1328 if self.flag:
1329 self.flag.set()
1330 while self.active:
1331 try:
1332 asyncore.loop(1)
1333 except:
1334 pass
1335
Antoine Pitrou480a1242010-04-28 21:37:09 +00001336 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001337 self.active = False
1338 self.server.close()
1339
Antoine Pitrou480a1242010-04-28 21:37:09 +00001340 def bad_cert_test(certfile):
1341 """
1342 Launch a server with CERT_REQUIRED, and check that trying to
1343 connect to it with the given client certificate fails.
1344 """
Trent Nelson78520002008-04-10 20:54:35 +00001345 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001346 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001347 cacerts=CERTFILE, chatty=False,
1348 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001349 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001350 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001351 with socket.socket() as sock:
1352 s = ssl.wrap_socket(sock,
1353 certfile=certfile,
1354 ssl_version=ssl.PROTOCOL_TLSv1)
1355 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001356 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001357 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001358 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001359 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001360 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001361 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001362 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001363 if x.errno != errno.ENOENT:
1364 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001365 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001366 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001367 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001368 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001369
Antoine Pitroub5218772010-05-21 09:56:06 +00001370 def server_params_test(client_context, server_context, indata=b"FOO\n",
1371 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001372 """
1373 Launch a server, connect a client to it and try various reads
1374 and writes.
1375 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001376 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001377 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001378 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001379 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001380 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001381 with client_context.wrap_socket(socket.socket()) as s:
1382 s.connect((HOST, server.port))
1383 for arg in [indata, bytearray(indata), memoryview(indata)]:
1384 if connectionchatty:
1385 if support.verbose:
1386 sys.stdout.write(
1387 " client: sending %r...\n" % indata)
1388 s.write(arg)
1389 outdata = s.read()
1390 if connectionchatty:
1391 if support.verbose:
1392 sys.stdout.write(" client: read %r\n" % outdata)
1393 if outdata != indata.lower():
1394 raise AssertionError(
1395 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1396 % (outdata[:20], len(outdata),
1397 indata[:20].lower(), len(indata)))
1398 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001399 if connectionchatty:
1400 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001401 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001402 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001403 'compression': s.compression(),
1404 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001405 'client_npn_protocol': s.selected_npn_protocol()
1406 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001407 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001408 stats['server_npn_protocols'] = server.selected_protocols
1409 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001410
Antoine Pitroub5218772010-05-21 09:56:06 +00001411 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1412 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001413 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001414 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001415 certtype = {
1416 ssl.CERT_NONE: "CERT_NONE",
1417 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1418 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1419 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001420 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001421 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001422 sys.stdout.write(formatstr %
1423 (ssl.get_protocol_name(client_protocol),
1424 ssl.get_protocol_name(server_protocol),
1425 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001426 client_context = ssl.SSLContext(client_protocol)
1427 client_context.options = ssl.OP_ALL | client_options
1428 server_context = ssl.SSLContext(server_protocol)
1429 server_context.options = ssl.OP_ALL | server_options
1430 for ctx in (client_context, server_context):
1431 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001432 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1433 # will send an SSLv3 hello (rather than SSLv2) starting from
1434 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001435 ctx.set_ciphers("ALL")
1436 ctx.load_cert_chain(CERTFILE)
1437 ctx.load_verify_locations(CERTFILE)
1438 try:
1439 server_params_test(client_context, server_context,
1440 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001441 # Protocol mismatch can result in either an SSLError, or a
1442 # "Connection reset by peer" error.
1443 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001445 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001446 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001447 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001448 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001449 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001450 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001451 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001452 "Client protocol %s succeeded with server protocol %s!"
1453 % (ssl.get_protocol_name(client_protocol),
1454 ssl.get_protocol_name(server_protocol)))
1455
1456
Bill Janssen6e027db2007-11-15 22:23:56 +00001457 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001458
Antoine Pitrou23df4832010-08-04 17:14:06 +00001459 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001460 def test_echo(self):
1461 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001462 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001463 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001464 for protocol in PROTOCOLS:
1465 context = ssl.SSLContext(protocol)
1466 context.load_cert_chain(CERTFILE)
1467 server_params_test(context, context,
1468 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001469
Antoine Pitrou480a1242010-04-28 21:37:09 +00001470 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001471 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001472 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001473 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1474 context.verify_mode = ssl.CERT_REQUIRED
1475 context.load_verify_locations(CERTFILE)
1476 context.load_cert_chain(CERTFILE)
1477 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001478 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001479 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001480 s.connect((HOST, server.port))
1481 cert = s.getpeercert()
1482 self.assertTrue(cert, "Can't get peer certificate.")
1483 cipher = s.cipher()
1484 if support.verbose:
1485 sys.stdout.write(pprint.pformat(cert) + '\n')
1486 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1487 if 'subject' not in cert:
1488 self.fail("No subject field in certificate: %s." %
1489 pprint.pformat(cert))
1490 if ((('organizationName', 'Python Software Foundation'),)
1491 not in cert['subject']):
1492 self.fail(
1493 "Missing or invalid 'organizationName' field in certificate subject; "
1494 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001495 self.assertIn('notBefore', cert)
1496 self.assertIn('notAfter', cert)
1497 before = ssl.cert_time_to_seconds(cert['notBefore'])
1498 after = ssl.cert_time_to_seconds(cert['notAfter'])
1499 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001500 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001501
Antoine Pitrou480a1242010-04-28 21:37:09 +00001502 def test_empty_cert(self):
1503 """Connecting with an empty cert file"""
1504 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1505 "nullcert.pem"))
1506 def test_malformed_cert(self):
1507 """Connecting with a badly formatted certificate (syntax error)"""
1508 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1509 "badcert.pem"))
1510 def test_nonexisting_cert(self):
1511 """Connecting with a non-existing cert file"""
1512 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1513 "wrongcert.pem"))
1514 def test_malformed_key(self):
1515 """Connecting with a badly formatted key (syntax error)"""
1516 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1517 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001518
Antoine Pitrou480a1242010-04-28 21:37:09 +00001519 def test_rude_shutdown(self):
1520 """A brutal shutdown of an SSL server should raise an IOError
1521 in the client when attempting handshake.
1522 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001523 listener_ready = threading.Event()
1524 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001525
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001526 s = socket.socket()
1527 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001528
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001529 # `listener` runs in a thread. It sits in an accept() until
1530 # the main thread connects. Then it rudely closes the socket,
1531 # and sets Event `listener_gone` to let the main thread know
1532 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001533 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001534 s.listen(5)
1535 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001536 newsock, addr = s.accept()
1537 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001538 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001539 listener_gone.set()
1540
1541 def connector():
1542 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001543 with socket.socket() as c:
1544 c.connect((HOST, port))
1545 listener_gone.wait()
1546 try:
1547 ssl_sock = ssl.wrap_socket(c)
1548 except IOError:
1549 pass
1550 else:
1551 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001552
1553 t = threading.Thread(target=listener)
1554 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001555 try:
1556 connector()
1557 finally:
1558 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001559
Antoine Pitrou23df4832010-08-04 17:14:06 +00001560 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001561 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1562 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001563 def test_protocol_sslv2(self):
1564 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001565 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001566 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1568 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1569 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1570 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1571 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1572 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001573 # SSLv23 client with specific SSL options
1574 if no_sslv2_implies_sslv3_hello():
1575 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1576 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1577 client_options=ssl.OP_NO_SSLv2)
1578 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1579 client_options=ssl.OP_NO_SSLv3)
1580 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1581 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001582
Antoine Pitrou23df4832010-08-04 17:14:06 +00001583 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001584 def test_protocol_sslv23(self):
1585 """Connecting to an SSLv23 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")
Victor Stinner3de49192011-05-09 00:42:58 +02001588 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1589 try:
1590 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1591 except (ssl.SSLError, socket.error) as x:
1592 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1593 if support.verbose:
1594 sys.stdout.write(
1595 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1596 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001597 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1598 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1599 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001600
Antoine Pitrou480a1242010-04-28 21:37:09 +00001601 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1602 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1603 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001604
Antoine Pitrou480a1242010-04-28 21:37:09 +00001605 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1606 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1607 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001608
Antoine Pitroub5218772010-05-21 09:56:06 +00001609 # Server with specific SSL options
1610 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1611 server_options=ssl.OP_NO_SSLv3)
1612 # Will choose TLSv1
1613 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1614 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1615 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1616 server_options=ssl.OP_NO_TLSv1)
1617
1618
Antoine Pitrou23df4832010-08-04 17:14:06 +00001619 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001620 def test_protocol_sslv3(self):
1621 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001622 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001623 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001624 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1625 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1626 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001627 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1628 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001629 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1630 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001631 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001632 if no_sslv2_implies_sslv3_hello():
1633 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1634 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1635 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636
Antoine Pitrou23df4832010-08-04 17:14:06 +00001637 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 def test_protocol_tlsv1(self):
1639 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001640 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001641 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001642 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1643 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1644 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001645 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1646 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001647 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001648 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1649 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001650
Antoine Pitrou480a1242010-04-28 21:37:09 +00001651 def test_starttls(self):
1652 """Switching from clear text to encrypted and back again."""
1653 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 +00001654
Trent Nelson78520002008-04-10 20:54:35 +00001655 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001656 ssl_version=ssl.PROTOCOL_TLSv1,
1657 starttls_server=True,
1658 chatty=True,
1659 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001660 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001661 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001662 s = socket.socket()
1663 s.setblocking(1)
1664 s.connect((HOST, server.port))
1665 if support.verbose:
1666 sys.stdout.write("\n")
1667 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001668 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001669 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001670 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001671 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001672 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001673 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001674 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001675 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001676 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001677 msg = outdata.strip().lower()
1678 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1679 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001680 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001681 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001682 " client: read %r from server, starting TLS...\n"
1683 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001684 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1685 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001686 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1687 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001688 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001689 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001690 " client: read %r from server, ending TLS...\n"
1691 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001692 s = conn.unwrap()
1693 wrapped = False
1694 else:
1695 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001696 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001697 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001698 if support.verbose:
1699 sys.stdout.write(" client: closing connection.\n")
1700 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001701 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001702 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001703 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001704 if wrapped:
1705 conn.close()
1706 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001707 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001708
Antoine Pitrou480a1242010-04-28 21:37:09 +00001709 def test_socketserver(self):
1710 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001711 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001712 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001713 if support.verbose:
1714 sys.stdout.write('\n')
1715 with open(CERTFILE, 'rb') as f:
1716 d1 = f.read()
1717 d2 = ''
1718 # now fetch the same data from the HTTPS server
1719 url = 'https://%s:%d/%s' % (
1720 HOST, server.port, os.path.split(CERTFILE)[1])
1721 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001722 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001723 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001724 if dlen and (int(dlen) > 0):
1725 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001726 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001727 sys.stdout.write(
1728 " client: read %d bytes from remote server '%s'\n"
1729 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001730 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001731 f.close()
1732 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001733
Antoine Pitrou480a1242010-04-28 21:37:09 +00001734 def test_asyncore_server(self):
1735 """Check the example asyncore integration."""
1736 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001737
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001738 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001739 sys.stdout.write("\n")
1740
Antoine Pitrou480a1242010-04-28 21:37:09 +00001741 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001742 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001743 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001744 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001745 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001746 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001747 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001748 " client: sending %r...\n" % indata)
1749 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001750 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001751 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001752 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001753 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001754 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001755 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1756 % (outdata[:20], len(outdata),
1757 indata[:20].lower(), len(indata)))
1758 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001759 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001760 sys.stdout.write(" client: closing connection.\n")
1761 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001762 if support.verbose:
1763 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001764
Antoine Pitrou480a1242010-04-28 21:37:09 +00001765 def test_recv_send(self):
1766 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001767 if support.verbose:
1768 sys.stdout.write("\n")
1769
1770 server = ThreadedEchoServer(CERTFILE,
1771 certreqs=ssl.CERT_NONE,
1772 ssl_version=ssl.PROTOCOL_TLSv1,
1773 cacerts=CERTFILE,
1774 chatty=True,
1775 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001776 with server:
1777 s = ssl.wrap_socket(socket.socket(),
1778 server_side=False,
1779 certfile=CERTFILE,
1780 ca_certs=CERTFILE,
1781 cert_reqs=ssl.CERT_NONE,
1782 ssl_version=ssl.PROTOCOL_TLSv1)
1783 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001784 # helper methods for standardising recv* method signatures
1785 def _recv_into():
1786 b = bytearray(b"\0"*100)
1787 count = s.recv_into(b)
1788 return b[:count]
1789
1790 def _recvfrom_into():
1791 b = bytearray(b"\0"*100)
1792 count, addr = s.recvfrom_into(b)
1793 return b[:count]
1794
1795 # (name, method, whether to expect success, *args)
1796 send_methods = [
1797 ('send', s.send, True, []),
1798 ('sendto', s.sendto, False, ["some.address"]),
1799 ('sendall', s.sendall, True, []),
1800 ]
1801 recv_methods = [
1802 ('recv', s.recv, True, []),
1803 ('recvfrom', s.recvfrom, False, ["some.address"]),
1804 ('recv_into', _recv_into, True, []),
1805 ('recvfrom_into', _recvfrom_into, False, []),
1806 ]
1807 data_prefix = "PREFIX_"
1808
1809 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001810 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001811 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001812 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001813 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001814 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001815 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001816 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001817 "<<{outdata:r}>> ({nout:d}) received; "
1818 "expected <<{indata:r}>> ({nin:d})\n".format(
1819 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001820 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001821 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001822 )
1823 )
1824 except ValueError as e:
1825 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001826 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001827 "Failed to send with method <<{name:s}>>; "
1828 "expected to succeed.\n".format(name=meth_name)
1829 )
1830 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001831 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001832 "Method <<{name:s}>> failed with unexpected "
1833 "exception message: {exp:s}\n".format(
1834 name=meth_name, exp=e
1835 )
1836 )
1837
1838 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001839 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001840 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001841 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001842 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001843 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001844 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001845 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001846 "<<{outdata:r}>> ({nout:d}) received; "
1847 "expected <<{indata:r}>> ({nin:d})\n".format(
1848 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001849 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001850 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001851 )
1852 )
1853 except ValueError as e:
1854 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001855 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001856 "Failed to receive with method <<{name:s}>>; "
1857 "expected to succeed.\n".format(name=meth_name)
1858 )
1859 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001860 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001861 "Method <<{name:s}>> failed with unexpected "
1862 "exception message: {exp:s}\n".format(
1863 name=meth_name, exp=e
1864 )
1865 )
1866 # consume data
1867 s.read()
1868
Nick Coghlan513886a2011-08-28 00:00:27 +10001869 # Make sure sendmsg et al are disallowed to avoid
1870 # inadvertent disclosure of data and/or corruption
1871 # of the encrypted data stream
1872 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1873 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1874 self.assertRaises(NotImplementedError,
1875 s.recvmsg_into, bytearray(100))
1876
Antoine Pitrou480a1242010-04-28 21:37:09 +00001877 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001878 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001879
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001880 def test_handshake_timeout(self):
1881 # Issue #5103: SSL handshake must respect the socket timeout
1882 server = socket.socket(socket.AF_INET)
1883 host = "127.0.0.1"
1884 port = support.bind_port(server)
1885 started = threading.Event()
1886 finish = False
1887
1888 def serve():
1889 server.listen(5)
1890 started.set()
1891 conns = []
1892 while not finish:
1893 r, w, e = select.select([server], [], [], 0.1)
1894 if server in r:
1895 # Let the socket hang around rather than having
1896 # it closed by garbage collection.
1897 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001898 for sock in conns:
1899 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001900
1901 t = threading.Thread(target=serve)
1902 t.start()
1903 started.wait()
1904
1905 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001906 try:
1907 c = socket.socket(socket.AF_INET)
1908 c.settimeout(0.2)
1909 c.connect((host, port))
1910 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001911 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001912 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001913 finally:
1914 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001915 try:
1916 c = socket.socket(socket.AF_INET)
1917 c = ssl.wrap_socket(c)
1918 c.settimeout(0.2)
1919 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001920 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001921 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001922 finally:
1923 c.close()
1924 finally:
1925 finish = True
1926 t.join()
1927 server.close()
1928
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001929 def test_server_accept(self):
1930 # Issue #16357: accept() on a SSLSocket created through
1931 # SSLContext.wrap_socket().
1932 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1933 context.verify_mode = ssl.CERT_REQUIRED
1934 context.load_verify_locations(CERTFILE)
1935 context.load_cert_chain(CERTFILE)
1936 server = socket.socket(socket.AF_INET)
1937 host = "127.0.0.1"
1938 port = support.bind_port(server)
1939 server = context.wrap_socket(server, server_side=True)
1940
1941 evt = threading.Event()
1942 remote = None
1943 peer = None
1944 def serve():
1945 nonlocal remote, peer
1946 server.listen(5)
1947 # Block on the accept and wait on the connection to close.
1948 evt.set()
1949 remote, peer = server.accept()
1950 remote.recv(1)
1951
1952 t = threading.Thread(target=serve)
1953 t.start()
1954 # Client wait until server setup and perform a connect.
1955 evt.wait()
1956 client = context.wrap_socket(socket.socket())
1957 client.connect((host, port))
1958 client_addr = client.getsockname()
1959 client.close()
1960 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001961 remote.close()
1962 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001963 # Sanity checks.
1964 self.assertIsInstance(remote, ssl.SSLSocket)
1965 self.assertEqual(peer, client_addr)
1966
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001967 def test_default_ciphers(self):
1968 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1969 try:
1970 # Force a set of weak ciphers on our client context
1971 context.set_ciphers("DES")
1972 except ssl.SSLError:
1973 self.skipTest("no DES cipher available")
1974 with ThreadedEchoServer(CERTFILE,
1975 ssl_version=ssl.PROTOCOL_SSLv23,
1976 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001977 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001978 with self.assertRaises((OSError, ssl.SSLError)):
1979 s.connect((HOST, server.port))
1980 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1981
Antoine Pitroud6494802011-07-21 01:11:30 +02001982 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1983 "'tls-unique' channel binding not available")
1984 def test_tls_unique_channel_binding(self):
1985 """Test tls-unique channel binding."""
1986 if support.verbose:
1987 sys.stdout.write("\n")
1988
1989 server = ThreadedEchoServer(CERTFILE,
1990 certreqs=ssl.CERT_NONE,
1991 ssl_version=ssl.PROTOCOL_TLSv1,
1992 cacerts=CERTFILE,
1993 chatty=True,
1994 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001995 with server:
1996 s = ssl.wrap_socket(socket.socket(),
1997 server_side=False,
1998 certfile=CERTFILE,
1999 ca_certs=CERTFILE,
2000 cert_reqs=ssl.CERT_NONE,
2001 ssl_version=ssl.PROTOCOL_TLSv1)
2002 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002003 # get the data
2004 cb_data = s.get_channel_binding("tls-unique")
2005 if support.verbose:
2006 sys.stdout.write(" got channel binding data: {0!r}\n"
2007 .format(cb_data))
2008
2009 # check if it is sane
2010 self.assertIsNotNone(cb_data)
2011 self.assertEqual(len(cb_data), 12) # True for TLSv1
2012
2013 # and compare with the peers version
2014 s.write(b"CB tls-unique\n")
2015 peer_data_repr = s.read().strip()
2016 self.assertEqual(peer_data_repr,
2017 repr(cb_data).encode("us-ascii"))
2018 s.close()
2019
2020 # now, again
2021 s = ssl.wrap_socket(socket.socket(),
2022 server_side=False,
2023 certfile=CERTFILE,
2024 ca_certs=CERTFILE,
2025 cert_reqs=ssl.CERT_NONE,
2026 ssl_version=ssl.PROTOCOL_TLSv1)
2027 s.connect((HOST, server.port))
2028 new_cb_data = s.get_channel_binding("tls-unique")
2029 if support.verbose:
2030 sys.stdout.write(" got another channel binding data: {0!r}\n"
2031 .format(new_cb_data))
2032 # is it really unique
2033 self.assertNotEqual(cb_data, new_cb_data)
2034 self.assertIsNotNone(cb_data)
2035 self.assertEqual(len(cb_data), 12) # True for TLSv1
2036 s.write(b"CB tls-unique\n")
2037 peer_data_repr = s.read().strip()
2038 self.assertEqual(peer_data_repr,
2039 repr(new_cb_data).encode("us-ascii"))
2040 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002041
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002042 def test_compression(self):
2043 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2044 context.load_cert_chain(CERTFILE)
2045 stats = server_params_test(context, context,
2046 chatty=True, connectionchatty=True)
2047 if support.verbose:
2048 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2049 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2050
2051 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2052 "ssl.OP_NO_COMPRESSION needed for this test")
2053 def test_compression_disabled(self):
2054 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2055 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002056 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002057 stats = server_params_test(context, context,
2058 chatty=True, connectionchatty=True)
2059 self.assertIs(stats['compression'], None)
2060
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002061 def test_dh_params(self):
2062 # Check we can get a connection with ephemeral Diffie-Hellman
2063 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2064 context.load_cert_chain(CERTFILE)
2065 context.load_dh_params(DHFILE)
2066 context.set_ciphers("kEDH")
2067 stats = server_params_test(context, context,
2068 chatty=True, connectionchatty=True)
2069 cipher = stats["cipher"][0]
2070 parts = cipher.split("-")
2071 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2072 self.fail("Non-DH cipher: " + cipher[0])
2073
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002074 def test_selected_npn_protocol(self):
2075 # selected_npn_protocol() is None unless NPN is used
2076 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2077 context.load_cert_chain(CERTFILE)
2078 stats = server_params_test(context, context,
2079 chatty=True, connectionchatty=True)
2080 self.assertIs(stats['client_npn_protocol'], None)
2081
2082 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2083 def test_npn_protocols(self):
2084 server_protocols = ['http/1.1', 'spdy/2']
2085 protocol_tests = [
2086 (['http/1.1', 'spdy/2'], 'http/1.1'),
2087 (['spdy/2', 'http/1.1'], 'http/1.1'),
2088 (['spdy/2', 'test'], 'spdy/2'),
2089 (['abc', 'def'], 'abc')
2090 ]
2091 for client_protocols, expected in protocol_tests:
2092 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2093 server_context.load_cert_chain(CERTFILE)
2094 server_context.set_npn_protocols(server_protocols)
2095 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2096 client_context.load_cert_chain(CERTFILE)
2097 client_context.set_npn_protocols(client_protocols)
2098 stats = server_params_test(client_context, server_context,
2099 chatty=True, connectionchatty=True)
2100
2101 msg = "failed trying %s (s) and %s (c).\n" \
2102 "was expecting %s, but got %%s from the %%s" \
2103 % (str(server_protocols), str(client_protocols),
2104 str(expected))
2105 client_result = stats['client_npn_protocol']
2106 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2107 server_result = stats['server_npn_protocols'][-1] \
2108 if len(stats['server_npn_protocols']) else 'nothing'
2109 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2110
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002111
Thomas Woutersed03b412007-08-28 21:37:11 +00002112def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002113 if support.verbose:
2114 plats = {
2115 'Linux': platform.linux_distribution,
2116 'Mac': platform.mac_ver,
2117 'Windows': platform.win32_ver,
2118 }
2119 for name, func in plats.items():
2120 plat = func()
2121 if plat and plat[0]:
2122 plat = '%s %r' % (name, plat)
2123 break
2124 else:
2125 plat = repr(platform.platform())
2126 print("test_ssl: testing with %r %r" %
2127 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2128 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002129 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002130
Antoine Pitrou152efa22010-05-16 18:19:27 +00002131 for filename in [
2132 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2133 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2134 BADCERT, BADKEY, EMPTYCERT]:
2135 if not os.path.exists(filename):
2136 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002137
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002138 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002139
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002140 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002141 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002142
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002143 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002144 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002145 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002146 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002147
Antoine Pitrou480a1242010-04-28 21:37:09 +00002148 try:
2149 support.run_unittest(*tests)
2150 finally:
2151 if _have_threads:
2152 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002153
2154if __name__ == "__main__":
2155 test_main()