blob: 1c4aa7ca1e0ade92baaf9a5fb688f86499ee67ef [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")
Antoine Pitrou152efa22010-05-16 18:19:27 +000058
Antoine Pitrou0e576f12011-12-22 10:03:38 +010059DHFILE = data_file("dh512.pem")
60BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000061
Thomas Woutersed03b412007-08-28 21:37:11 +000062def handle_error(prefix):
63 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000064 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000065 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000066
Antoine Pitroub5218772010-05-21 09:56:06 +000067def can_clear_options():
68 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020069 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000070
71def no_sslv2_implies_sslv3_hello():
72 # 0.9.7h or higher
73 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
74
Thomas Woutersed03b412007-08-28 21:37:11 +000075
Antoine Pitrou23df4832010-08-04 17:14:06 +000076# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
77def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020078 if hasattr(ssl, 'PROTOCOL_SSLv2'):
79 @functools.wraps(func)
80 def f(*args, **kwargs):
81 try:
82 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
83 except ssl.SSLError:
84 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
85 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
86 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
87 return func(*args, **kwargs)
88 return f
89 else:
90 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000091
92
Antoine Pitrou152efa22010-05-16 18:19:27 +000093class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020096 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 ssl.PROTOCOL_SSLv23
98 ssl.PROTOCOL_SSLv3
99 ssl.PROTOCOL_TLSv1
100 ssl.CERT_NONE
101 ssl.CERT_OPTIONAL
102 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100103 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100104 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100105 if ssl.HAS_ECDH:
106 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100107 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
108 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000109 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100110 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000111
Antoine Pitrou480a1242010-04-28 21:37:09 +0000112 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n RAND_status is %d (%s)\n"
116 % (v, (v and "sufficient randomness") or
117 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200118
119 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
120 self.assertEqual(len(data), 16)
121 self.assertEqual(is_cryptographic, v == 1)
122 if v:
123 data = ssl.RAND_bytes(16)
124 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200125 else:
126 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200127
Jesus Ceac8754a12012-09-11 02:00:58 +0200128 self.assertRaises(TypeError, ssl.RAND_egd, 1)
129 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000130 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000131
Antoine Pitrou480a1242010-04-28 21:37:09 +0000132 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000133 # note that this uses an 'unofficial' function in _ssl.c,
134 # provided solely for this test, to exercise the certificate
135 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000136 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000137 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200139 self.assertEqual(p['issuer'],
140 ((('countryName', 'XY'),),
141 (('localityName', 'Castle Anthrax'),),
142 (('organizationName', 'Python Software Foundation'),),
143 (('commonName', 'localhost'),))
144 )
145 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
146 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
147 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
148 self.assertEqual(p['subject'],
149 ((('countryName', 'XY'),),
150 (('localityName', 'Castle Anthrax'),),
151 (('organizationName', 'Python Software Foundation'),),
152 (('commonName', 'localhost'),))
153 )
154 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
155 # Issue #13034: the subjectAltName in some certificates
156 # (notably projects.developer.nokia.com:443) wasn't parsed
157 p = ssl._ssl._test_decode_cert(NOKIACERT)
158 if support.verbose:
159 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
160 self.assertEqual(p['subjectAltName'],
161 (('DNS', 'projects.developer.nokia.com'),
162 ('DNS', 'projects.forum.nokia.com'))
163 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000164
Antoine Pitrou480a1242010-04-28 21:37:09 +0000165 def test_DER_to_PEM(self):
166 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
167 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000168 d1 = ssl.PEM_cert_to_DER_cert(pem)
169 p2 = ssl.DER_cert_to_PEM_cert(d1)
170 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000171 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000172 if not p2.startswith(ssl.PEM_HEADER + '\n'):
173 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
174 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
175 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000176
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000177 def test_openssl_version(self):
178 n = ssl.OPENSSL_VERSION_NUMBER
179 t = ssl.OPENSSL_VERSION_INFO
180 s = ssl.OPENSSL_VERSION
181 self.assertIsInstance(n, int)
182 self.assertIsInstance(t, tuple)
183 self.assertIsInstance(s, str)
184 # Some sanity checks follow
185 # >= 0.9
186 self.assertGreaterEqual(n, 0x900000)
187 # < 2.0
188 self.assertLess(n, 0x20000000)
189 major, minor, fix, patch, status = t
190 self.assertGreaterEqual(major, 0)
191 self.assertLess(major, 2)
192 self.assertGreaterEqual(minor, 0)
193 self.assertLess(minor, 256)
194 self.assertGreaterEqual(fix, 0)
195 self.assertLess(fix, 256)
196 self.assertGreaterEqual(patch, 0)
197 self.assertLessEqual(patch, 26)
198 self.assertGreaterEqual(status, 0)
199 self.assertLessEqual(status, 15)
200 # Version string as returned by OpenSSL, the format might change
201 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
202 (s, t))
203
Antoine Pitrou9d543662010-04-23 23:10:32 +0000204 @support.cpython_only
205 def test_refcycle(self):
206 # Issue #7943: an SSL object doesn't create reference cycles with
207 # itself.
208 s = socket.socket(socket.AF_INET)
209 ss = ssl.wrap_socket(s)
210 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100211 with support.check_warnings(("", ResourceWarning)):
212 del ss
213 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000214
Antoine Pitroua468adc2010-09-14 14:43:44 +0000215 def test_wrapped_unconnected(self):
216 # Methods on an unconnected SSLSocket propagate the original
217 # socket.error raise by the underlying socket object.
218 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100219 with ssl.wrap_socket(s) as ss:
220 self.assertRaises(socket.error, ss.recv, 1)
221 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
222 self.assertRaises(socket.error, ss.recvfrom, 1)
223 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
224 self.assertRaises(socket.error, ss.send, b'x')
225 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000226
Antoine Pitrou40f08742010-04-24 22:04:40 +0000227 def test_timeout(self):
228 # Issue #8524: when creating an SSL socket, the timeout of the
229 # original socket should be retained.
230 for timeout in (None, 0.0, 5.0):
231 s = socket.socket(socket.AF_INET)
232 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100233 with ssl.wrap_socket(s) as ss:
234 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000235
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000236 def test_errors(self):
237 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000238 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000239 "certfile must be specified",
240 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000241 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000242 "certfile must be specified for server-side operations",
243 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000244 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000245 "certfile must be specified for server-side operations",
246 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100247 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
248 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
249 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000250 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000251 with socket.socket() as sock:
252 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000253 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000254 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000255 with socket.socket() as sock:
256 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000257 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000258 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000259 with socket.socket() as sock:
260 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000261 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000262
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000263 def test_match_hostname(self):
264 def ok(cert, hostname):
265 ssl.match_hostname(cert, hostname)
266 def fail(cert, hostname):
267 self.assertRaises(ssl.CertificateError,
268 ssl.match_hostname, cert, hostname)
269
270 cert = {'subject': ((('commonName', 'example.com'),),)}
271 ok(cert, 'example.com')
272 ok(cert, 'ExAmple.cOm')
273 fail(cert, 'www.example.com')
274 fail(cert, '.example.com')
275 fail(cert, 'example.org')
276 fail(cert, 'exampleXcom')
277
278 cert = {'subject': ((('commonName', '*.a.com'),),)}
279 ok(cert, 'foo.a.com')
280 fail(cert, 'bar.foo.a.com')
281 fail(cert, 'a.com')
282 fail(cert, 'Xa.com')
283 fail(cert, '.a.com')
284
285 cert = {'subject': ((('commonName', 'a.*.com'),),)}
286 ok(cert, 'a.foo.com')
287 fail(cert, 'a..com')
288 fail(cert, 'a.com')
289
290 cert = {'subject': ((('commonName', 'f*.com'),),)}
291 ok(cert, 'foo.com')
292 ok(cert, 'f.com')
293 fail(cert, 'bar.com')
294 fail(cert, 'foo.a.com')
295 fail(cert, 'bar.foo.com')
296
297 # Slightly fake real-world example
298 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
299 'subject': ((('commonName', 'linuxfrz.org'),),),
300 'subjectAltName': (('DNS', 'linuxfr.org'),
301 ('DNS', 'linuxfr.com'),
302 ('othername', '<unsupported>'))}
303 ok(cert, 'linuxfr.org')
304 ok(cert, 'linuxfr.com')
305 # Not a "DNS" entry
306 fail(cert, '<unsupported>')
307 # When there is a subjectAltName, commonName isn't used
308 fail(cert, 'linuxfrz.org')
309
310 # A pristine real-world example
311 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
312 'subject': ((('countryName', 'US'),),
313 (('stateOrProvinceName', 'California'),),
314 (('localityName', 'Mountain View'),),
315 (('organizationName', 'Google Inc'),),
316 (('commonName', 'mail.google.com'),))}
317 ok(cert, 'mail.google.com')
318 fail(cert, 'gmail.com')
319 # Only commonName is considered
320 fail(cert, 'California')
321
322 # Neither commonName nor subjectAltName
323 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
324 'subject': ((('countryName', 'US'),),
325 (('stateOrProvinceName', 'California'),),
326 (('localityName', 'Mountain View'),),
327 (('organizationName', 'Google Inc'),))}
328 fail(cert, 'mail.google.com')
329
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200330 # No DNS entry in subjectAltName but a commonName
331 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
332 'subject': ((('countryName', 'US'),),
333 (('stateOrProvinceName', 'California'),),
334 (('localityName', 'Mountain View'),),
335 (('commonName', 'mail.google.com'),)),
336 'subjectAltName': (('othername', 'blabla'), )}
337 ok(cert, 'mail.google.com')
338
339 # No DNS entry subjectAltName and no commonName
340 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
341 'subject': ((('countryName', 'US'),),
342 (('stateOrProvinceName', 'California'),),
343 (('localityName', 'Mountain View'),),
344 (('organizationName', 'Google Inc'),)),
345 'subjectAltName': (('othername', 'blabla'),)}
346 fail(cert, 'google.com')
347
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000348 # Empty cert / no cert
349 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
350 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
351
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200352 # Issue #17980: avoid denials of service by refusing more than one
353 # wildcard per fragment.
354 cert = {'subject': ((('commonName', 'a*b.com'),),)}
355 ok(cert, 'axxb.com')
356 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
357 ok(cert, 'axxb.com')
358 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
359 with self.assertRaises(ssl.CertificateError) as cm:
360 ssl.match_hostname(cert, 'axxbxxc.com')
361 self.assertIn("too many wildcards", str(cm.exception))
362
Antoine Pitroud5323212010-10-22 18:19:07 +0000363 def test_server_side(self):
364 # server_hostname doesn't work for server sockets
365 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000366 with socket.socket() as sock:
367 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
368 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000369
Antoine Pitroud6494802011-07-21 01:11:30 +0200370 def test_unknown_channel_binding(self):
371 # should raise ValueError for unknown type
372 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100373 with ssl.wrap_socket(s) as ss:
374 with self.assertRaises(ValueError):
375 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200376
377 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
378 "'tls-unique' channel binding not available")
379 def test_tls_unique_channel_binding(self):
380 # unconnected should return None for known type
381 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100382 with ssl.wrap_socket(s) as ss:
383 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200384 # the same for server-side
385 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100386 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
387 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200388
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600389 def test_dealloc_warn(self):
390 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
391 r = repr(ss)
392 with self.assertWarns(ResourceWarning) as cm:
393 ss = None
394 support.gc_collect()
395 self.assertIn(r, str(cm.warning.args[0]))
396
Antoine Pitrou152efa22010-05-16 18:19:27 +0000397class ContextTests(unittest.TestCase):
398
Antoine Pitrou23df4832010-08-04 17:14:06 +0000399 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000400 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200401 if hasattr(ssl, 'PROTOCOL_SSLv2'):
402 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000403 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
404 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
405 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
406 self.assertRaises(TypeError, ssl.SSLContext)
407 self.assertRaises(ValueError, ssl.SSLContext, -1)
408 self.assertRaises(ValueError, ssl.SSLContext, 42)
409
Antoine Pitrou23df4832010-08-04 17:14:06 +0000410 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000411 def test_protocol(self):
412 for proto in PROTOCOLS:
413 ctx = ssl.SSLContext(proto)
414 self.assertEqual(ctx.protocol, proto)
415
416 def test_ciphers(self):
417 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
418 ctx.set_ciphers("ALL")
419 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000420 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000421 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000422
Antoine Pitrou23df4832010-08-04 17:14:06 +0000423 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000424 def test_options(self):
425 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
426 # OP_ALL is the default value
427 self.assertEqual(ssl.OP_ALL, ctx.options)
428 ctx.options |= ssl.OP_NO_SSLv2
429 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
430 ctx.options)
431 ctx.options |= ssl.OP_NO_SSLv3
432 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
433 ctx.options)
434 if can_clear_options():
435 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
436 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
437 ctx.options)
438 ctx.options = 0
439 self.assertEqual(0, ctx.options)
440 else:
441 with self.assertRaises(ValueError):
442 ctx.options = 0
443
Antoine Pitrou152efa22010-05-16 18:19:27 +0000444 def test_verify(self):
445 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
446 # Default value
447 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
448 ctx.verify_mode = ssl.CERT_OPTIONAL
449 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
450 ctx.verify_mode = ssl.CERT_REQUIRED
451 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
452 ctx.verify_mode = ssl.CERT_NONE
453 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
454 with self.assertRaises(TypeError):
455 ctx.verify_mode = None
456 with self.assertRaises(ValueError):
457 ctx.verify_mode = 42
458
459 def test_load_cert_chain(self):
460 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
461 # Combined key and cert in a single file
462 ctx.load_cert_chain(CERTFILE)
463 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
464 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000465 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000467 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000468 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000469 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000470 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000471 ctx.load_cert_chain(EMPTYCERT)
472 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000473 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000474 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
475 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
476 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000477 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000478 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000479 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000480 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000481 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000482 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
483 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000484 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000485 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000486 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200487 # Password protected key and cert
488 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
489 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
490 ctx.load_cert_chain(CERTFILE_PROTECTED,
491 password=bytearray(KEY_PASSWORD.encode()))
492 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
493 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
494 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
495 bytearray(KEY_PASSWORD.encode()))
496 with self.assertRaisesRegex(TypeError, "should be a string"):
497 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
498 with self.assertRaises(ssl.SSLError):
499 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
500 with self.assertRaisesRegex(ValueError, "cannot be longer"):
501 # openssl has a fixed limit on the password buffer.
502 # PEM_BUFSIZE is generally set to 1kb.
503 # Return a string larger than this.
504 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
505 # Password callback
506 def getpass_unicode():
507 return KEY_PASSWORD
508 def getpass_bytes():
509 return KEY_PASSWORD.encode()
510 def getpass_bytearray():
511 return bytearray(KEY_PASSWORD.encode())
512 def getpass_badpass():
513 return "badpass"
514 def getpass_huge():
515 return b'a' * (1024 * 1024)
516 def getpass_bad_type():
517 return 9
518 def getpass_exception():
519 raise Exception('getpass error')
520 class GetPassCallable:
521 def __call__(self):
522 return KEY_PASSWORD
523 def getpass(self):
524 return KEY_PASSWORD
525 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
526 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
527 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
528 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
529 ctx.load_cert_chain(CERTFILE_PROTECTED,
530 password=GetPassCallable().getpass)
531 with self.assertRaises(ssl.SSLError):
532 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
533 with self.assertRaisesRegex(ValueError, "cannot be longer"):
534 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
535 with self.assertRaisesRegex(TypeError, "must return a string"):
536 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
537 with self.assertRaisesRegex(Exception, "getpass error"):
538 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
539 # Make sure the password function isn't called if it isn't needed
540 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000541
542 def test_load_verify_locations(self):
543 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
544 ctx.load_verify_locations(CERTFILE)
545 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
546 ctx.load_verify_locations(BYTES_CERTFILE)
547 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
548 self.assertRaises(TypeError, ctx.load_verify_locations)
549 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000550 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000551 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000552 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000553 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000554 ctx.load_verify_locations(BADCERT)
555 ctx.load_verify_locations(CERTFILE, CAPATH)
556 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
557
Victor Stinner80f75e62011-01-29 11:31:20 +0000558 # Issue #10989: crash if the second argument type is invalid
559 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
560
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100561 def test_load_dh_params(self):
562 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
563 ctx.load_dh_params(DHFILE)
564 if os.name != 'nt':
565 ctx.load_dh_params(BYTES_DHFILE)
566 self.assertRaises(TypeError, ctx.load_dh_params)
567 self.assertRaises(TypeError, ctx.load_dh_params, None)
568 with self.assertRaises(FileNotFoundError) as cm:
569 ctx.load_dh_params(WRONGCERT)
570 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200571 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100572 ctx.load_dh_params(CERTFILE)
573
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000574 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000575 def test_session_stats(self):
576 for proto in PROTOCOLS:
577 ctx = ssl.SSLContext(proto)
578 self.assertEqual(ctx.session_stats(), {
579 'number': 0,
580 'connect': 0,
581 'connect_good': 0,
582 'connect_renegotiate': 0,
583 'accept': 0,
584 'accept_good': 0,
585 'accept_renegotiate': 0,
586 'hits': 0,
587 'misses': 0,
588 'timeouts': 0,
589 'cache_full': 0,
590 })
591
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000592 def test_set_default_verify_paths(self):
593 # There's not much we can do to test that it acts as expected,
594 # so just check it doesn't crash or raise an exception.
595 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
596 ctx.set_default_verify_paths()
597
Antoine Pitrou501da612011-12-21 09:27:41 +0100598 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100599 def test_set_ecdh_curve(self):
600 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
601 ctx.set_ecdh_curve("prime256v1")
602 ctx.set_ecdh_curve(b"prime256v1")
603 self.assertRaises(TypeError, ctx.set_ecdh_curve)
604 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
605 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
606 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
607
Antoine Pitrou152efa22010-05-16 18:19:27 +0000608
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200609class SSLErrorTests(unittest.TestCase):
610
611 def test_str(self):
612 # The str() of a SSLError doesn't include the errno
613 e = ssl.SSLError(1, "foo")
614 self.assertEqual(str(e), "foo")
615 self.assertEqual(e.errno, 1)
616 # Same for a subclass
617 e = ssl.SSLZeroReturnError(1, "foo")
618 self.assertEqual(str(e), "foo")
619 self.assertEqual(e.errno, 1)
620
621 def test_lib_reason(self):
622 # Test the library and reason attributes
623 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
624 with self.assertRaises(ssl.SSLError) as cm:
625 ctx.load_dh_params(CERTFILE)
626 self.assertEqual(cm.exception.library, 'PEM')
627 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
628 s = str(cm.exception)
629 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
630
631 def test_subclass(self):
632 # Check that the appropriate SSLError subclass is raised
633 # (this only tests one of them)
634 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
635 with socket.socket() as s:
636 s.bind(("127.0.0.1", 0))
637 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100638 c = socket.socket()
639 c.connect(s.getsockname())
640 c.setblocking(False)
641 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200642 with self.assertRaises(ssl.SSLWantReadError) as cm:
643 c.do_handshake()
644 s = str(cm.exception)
645 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
646 # For compatibility
647 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
648
649
Bill Janssen6e027db2007-11-15 22:23:56 +0000650class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000651
Antoine Pitrou480a1242010-04-28 21:37:09 +0000652 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000653 with support.transient_internet("svn.python.org"):
654 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
655 cert_reqs=ssl.CERT_NONE)
656 try:
657 s.connect(("svn.python.org", 443))
658 self.assertEqual({}, s.getpeercert())
659 finally:
660 s.close()
661
662 # this should fail because we have no verification certs
663 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
664 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000665 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
666 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000667 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000668
Antoine Pitrou350c7222010-09-09 13:31:46 +0000669 # this should succeed because we specify the root cert
670 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
671 cert_reqs=ssl.CERT_REQUIRED,
672 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
673 try:
674 s.connect(("svn.python.org", 443))
675 self.assertTrue(s.getpeercert())
676 finally:
677 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000678
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000679 def test_connect_ex(self):
680 # Issue #11326: check connect_ex() implementation
681 with support.transient_internet("svn.python.org"):
682 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
683 cert_reqs=ssl.CERT_REQUIRED,
684 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
685 try:
686 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
687 self.assertTrue(s.getpeercert())
688 finally:
689 s.close()
690
691 def test_non_blocking_connect_ex(self):
692 # Issue #11326: non-blocking connect_ex() should allow handshake
693 # to proceed after the socket gets ready.
694 with support.transient_internet("svn.python.org"):
695 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
696 cert_reqs=ssl.CERT_REQUIRED,
697 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
698 do_handshake_on_connect=False)
699 try:
700 s.setblocking(False)
701 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000702 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
703 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000704 # Wait for connect to finish
705 select.select([], [s], [], 5.0)
706 # Non-blocking handshake
707 while True:
708 try:
709 s.do_handshake()
710 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200711 except ssl.SSLWantReadError:
712 select.select([s], [], [], 5.0)
713 except ssl.SSLWantWriteError:
714 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000715 # SSL established
716 self.assertTrue(s.getpeercert())
717 finally:
718 s.close()
719
Antoine Pitroub4410db2011-05-18 18:51:06 +0200720 def test_timeout_connect_ex(self):
721 # Issue #12065: on a timeout, connect_ex() should return the original
722 # errno (mimicking the behaviour of non-SSL sockets).
723 with support.transient_internet("svn.python.org"):
724 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
725 cert_reqs=ssl.CERT_REQUIRED,
726 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
727 do_handshake_on_connect=False)
728 try:
729 s.settimeout(0.0000001)
730 rc = s.connect_ex(('svn.python.org', 443))
731 if rc == 0:
732 self.skipTest("svn.python.org responded too quickly")
733 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
734 finally:
735 s.close()
736
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100737 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100738 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100739 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
740 cert_reqs=ssl.CERT_REQUIRED,
741 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
742 try:
743 self.assertEqual(errno.ECONNREFUSED,
744 s.connect_ex(("svn.python.org", 444)))
745 finally:
746 s.close()
747
Antoine Pitrou152efa22010-05-16 18:19:27 +0000748 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000749 with support.transient_internet("svn.python.org"):
750 # Same as test_connect, but with a separately created context
751 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
752 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
753 s.connect(("svn.python.org", 443))
754 try:
755 self.assertEqual({}, s.getpeercert())
756 finally:
757 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000758 # Same with a server hostname
759 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
760 server_hostname="svn.python.org")
761 if ssl.HAS_SNI:
762 s.connect(("svn.python.org", 443))
763 s.close()
764 else:
765 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000766 # This should fail because we have no verification certs
767 ctx.verify_mode = ssl.CERT_REQUIRED
768 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000769 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000770 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000771 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000772 # This should succeed because we specify the root cert
773 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
774 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
775 s.connect(("svn.python.org", 443))
776 try:
777 cert = s.getpeercert()
778 self.assertTrue(cert)
779 finally:
780 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000781
782 def test_connect_capath(self):
783 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000784 # NOTE: the subject hashing algorithm has been changed between
785 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
786 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000787 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000788 with support.transient_internet("svn.python.org"):
789 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
790 ctx.verify_mode = ssl.CERT_REQUIRED
791 ctx.load_verify_locations(capath=CAPATH)
792 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
793 s.connect(("svn.python.org", 443))
794 try:
795 cert = s.getpeercert()
796 self.assertTrue(cert)
797 finally:
798 s.close()
799 # Same with a bytes `capath` argument
800 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
801 ctx.verify_mode = ssl.CERT_REQUIRED
802 ctx.load_verify_locations(capath=BYTES_CAPATH)
803 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
804 s.connect(("svn.python.org", 443))
805 try:
806 cert = s.getpeercert()
807 self.assertTrue(cert)
808 finally:
809 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000810
Antoine Pitroue3220242010-04-24 11:13:53 +0000811 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
812 def test_makefile_close(self):
813 # Issue #5238: creating a file-like object with makefile() shouldn't
814 # delay closing the underlying "real socket" (here tested with its
815 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000816 with support.transient_internet("svn.python.org"):
817 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
818 ss.connect(("svn.python.org", 443))
819 fd = ss.fileno()
820 f = ss.makefile()
821 f.close()
822 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000823 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000824 # Closing the SSL socket should close the fd too
825 ss.close()
826 gc.collect()
827 with self.assertRaises(OSError) as e:
828 os.read(fd, 0)
829 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000830
Antoine Pitrou480a1242010-04-28 21:37:09 +0000831 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000832 with support.transient_internet("svn.python.org"):
833 s = socket.socket(socket.AF_INET)
834 s.connect(("svn.python.org", 443))
835 s.setblocking(False)
836 s = ssl.wrap_socket(s,
837 cert_reqs=ssl.CERT_NONE,
838 do_handshake_on_connect=False)
839 count = 0
840 while True:
841 try:
842 count += 1
843 s.do_handshake()
844 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200845 except ssl.SSLWantReadError:
846 select.select([s], [], [])
847 except ssl.SSLWantWriteError:
848 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000849 s.close()
850 if support.verbose:
851 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000852
Antoine Pitrou480a1242010-04-28 21:37:09 +0000853 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200854 def _test_get_server_certificate(host, port, cert=None):
855 with support.transient_internet(host):
856 pem = ssl.get_server_certificate((host, port))
857 if not pem:
858 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200859
Antoine Pitrou15399c32011-04-28 19:23:55 +0200860 try:
861 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
862 except ssl.SSLError as x:
863 #should fail
864 if support.verbose:
865 sys.stdout.write("%s\n" % x)
866 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200867 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
868
Antoine Pitrou15399c32011-04-28 19:23:55 +0200869 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
870 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200871 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000872 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200873 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000874
Antoine Pitrou15399c32011-04-28 19:23:55 +0200875 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
876 if support.IPV6_ENABLED:
877 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000878
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000879 def test_ciphers(self):
880 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000881 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100882 with ssl.wrap_socket(socket.socket(socket.AF_INET),
883 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
884 s.connect(remote)
885 with ssl.wrap_socket(socket.socket(socket.AF_INET),
886 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
887 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000888 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000889 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000890 with socket.socket(socket.AF_INET) as sock:
891 s = ssl.wrap_socket(sock,
892 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
893 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000894
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000895 def test_algorithms(self):
896 # Issue #8484: all algorithms should be available when verifying a
897 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000898 # SHA256 was added in OpenSSL 0.9.8
899 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
900 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200901 # sha256.tbs-internet.com needs SNI to use the correct certificate
902 if not ssl.HAS_SNI:
903 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000904 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
905 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000906 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000907 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200908 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
909 ctx.verify_mode = ssl.CERT_REQUIRED
910 ctx.load_verify_locations(sha256_cert)
911 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
912 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000913 try:
914 s.connect(remote)
915 if support.verbose:
916 sys.stdout.write("\nCipher with %r is %r\n" %
917 (remote, s.cipher()))
918 sys.stdout.write("Certificate is:\n%s\n" %
919 pprint.pformat(s.getpeercert()))
920 finally:
921 s.close()
922
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923
924try:
925 import threading
926except ImportError:
927 _have_threads = False
928else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000929 _have_threads = True
930
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000931 from test.ssl_servers import make_https_server
932
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 class ThreadedEchoServer(threading.Thread):
934
935 class ConnectionHandler(threading.Thread):
936
937 """A mildly complicated class, because we want it to work both
938 with and without the SSL wrapper around the socket connection, so
939 that we can test the STARTTLS functionality."""
940
Bill Janssen6e027db2007-11-15 22:23:56 +0000941 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000942 self.server = server
943 self.running = False
944 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000945 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000946 self.sock.setblocking(1)
947 self.sslconn = None
948 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000949 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000950
Antoine Pitrou480a1242010-04-28 21:37:09 +0000951 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000952 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000953 self.sslconn = self.server.context.wrap_socket(
954 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100955 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +0100956 except (ssl.SSLError, ConnectionResetError) as e:
957 # We treat ConnectionResetError as though it were an
958 # SSLError - OpenSSL on Ubuntu abruptly closes the
959 # connection when asked to use an unsupported protocol.
960 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000961 # XXX Various errors can have happened here, for example
962 # a mismatching protocol version, an invalid certificate,
963 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100964 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000965 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000966 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000967 self.running = False
968 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000969 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000971 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000972 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000973 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000974 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
976 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000977 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
979 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000980 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100982 sys.stdout.write(" server: selected protocol is now "
983 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 return True
985
986 def read(self):
987 if self.sslconn:
988 return self.sslconn.read()
989 else:
990 return self.sock.recv(1024)
991
992 def write(self, bytes):
993 if self.sslconn:
994 return self.sslconn.write(bytes)
995 else:
996 return self.sock.send(bytes)
997
998 def close(self):
999 if self.sslconn:
1000 self.sslconn.close()
1001 else:
1002 self.sock.close()
1003
Antoine Pitrou480a1242010-04-28 21:37:09 +00001004 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001005 self.running = True
1006 if not self.server.starttls_server:
1007 if not self.wrap_conn():
1008 return
1009 while self.running:
1010 try:
1011 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001012 stripped = msg.strip()
1013 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014 # eof, so quit this handler
1015 self.running = False
1016 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001017 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001018 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001019 sys.stdout.write(" server: client closed connection\n")
1020 self.close()
1021 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001022 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001023 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001024 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001025 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027 if not self.wrap_conn():
1028 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001029 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001030 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001031 if support.verbose and self.server.connectionchatty:
1032 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001033 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001034 self.sock = self.sslconn.unwrap()
1035 self.sslconn = None
1036 if support.verbose and self.server.connectionchatty:
1037 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001038 elif stripped == b'CB tls-unique':
1039 if support.verbose and self.server.connectionchatty:
1040 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1041 data = self.sslconn.get_channel_binding("tls-unique")
1042 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001043 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001044 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001045 self.server.connectionchatty):
1046 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001047 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1048 % (msg, ctype, msg.lower(), ctype))
1049 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001050 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001051 if self.server.chatty:
1052 handle_error("Test server failure:\n")
1053 self.close()
1054 self.running = False
1055 # normally, we'd just stop here, but for the test
1056 # harness, we want to stop the server
1057 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001058
Antoine Pitroub5218772010-05-21 09:56:06 +00001059 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001060 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001061 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001062 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001063 if context:
1064 self.context = context
1065 else:
1066 self.context = ssl.SSLContext(ssl_version
1067 if ssl_version is not None
1068 else ssl.PROTOCOL_TLSv1)
1069 self.context.verify_mode = (certreqs if certreqs is not None
1070 else ssl.CERT_NONE)
1071 if cacerts:
1072 self.context.load_verify_locations(cacerts)
1073 if certificate:
1074 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001075 if npn_protocols:
1076 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001077 if ciphers:
1078 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001079 self.chatty = chatty
1080 self.connectionchatty = connectionchatty
1081 self.starttls_server = starttls_server
1082 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001083 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001084 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001085 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001086 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001087 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001088 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001089 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001090
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001091 def __enter__(self):
1092 self.start(threading.Event())
1093 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001094 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001095
1096 def __exit__(self, *args):
1097 self.stop()
1098 self.join()
1099
Antoine Pitrou480a1242010-04-28 21:37:09 +00001100 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001101 self.flag = flag
1102 threading.Thread.start(self)
1103
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001105 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001106 self.sock.listen(5)
1107 self.active = True
1108 if self.flag:
1109 # signal an event
1110 self.flag.set()
1111 while self.active:
1112 try:
1113 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001114 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001115 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001116 + repr(connaddr) + '\n')
1117 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001118 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001119 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001120 except socket.timeout:
1121 pass
1122 except KeyboardInterrupt:
1123 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001124 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125
Antoine Pitrou480a1242010-04-28 21:37:09 +00001126 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001128
Bill Janssen54cc54c2007-12-14 22:08:56 +00001129 class AsyncoreEchoServer(threading.Thread):
1130
1131 # this one's based on asyncore.dispatcher
1132
1133 class EchoServer (asyncore.dispatcher):
1134
1135 class ConnectionHandler (asyncore.dispatcher_with_send):
1136
1137 def __init__(self, conn, certfile):
1138 self.socket = ssl.wrap_socket(conn, server_side=True,
1139 certfile=certfile,
1140 do_handshake_on_connect=False)
1141 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001142 self._ssl_accepting = True
1143 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001144
1145 def readable(self):
1146 if isinstance(self.socket, ssl.SSLSocket):
1147 while self.socket.pending() > 0:
1148 self.handle_read_event()
1149 return True
1150
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001151 def _do_ssl_handshake(self):
1152 try:
1153 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001154 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1155 return
1156 except ssl.SSLEOFError:
1157 return self.handle_close()
1158 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001159 raise
1160 except socket.error as err:
1161 if err.args[0] == errno.ECONNABORTED:
1162 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001163 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001164 self._ssl_accepting = False
1165
1166 def handle_read(self):
1167 if self._ssl_accepting:
1168 self._do_ssl_handshake()
1169 else:
1170 data = self.recv(1024)
1171 if support.verbose:
1172 sys.stdout.write(" server: read %s from client\n" % repr(data))
1173 if not data:
1174 self.close()
1175 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001176 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001177
1178 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001179 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001180 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001181 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1182
1183 def handle_error(self):
1184 raise
1185
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001186 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001187 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001188 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1189 self.port = support.bind_port(sock, '')
1190 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001191 self.listen(5)
1192
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001193 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001194 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001195 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1196 self.ConnectionHandler(sock_obj, self.certfile)
1197
1198 def handle_error(self):
1199 raise
1200
Trent Nelson78520002008-04-10 20:54:35 +00001201 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001202 self.flag = None
1203 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001204 self.server = self.EchoServer(certfile)
1205 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001206 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001207 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001208
1209 def __str__(self):
1210 return "<%s %s>" % (self.__class__.__name__, self.server)
1211
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001212 def __enter__(self):
1213 self.start(threading.Event())
1214 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001215 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001216
1217 def __exit__(self, *args):
1218 if support.verbose:
1219 sys.stdout.write(" cleanup: stopping server.\n")
1220 self.stop()
1221 if support.verbose:
1222 sys.stdout.write(" cleanup: joining server thread.\n")
1223 self.join()
1224 if support.verbose:
1225 sys.stdout.write(" cleanup: successfully joined.\n")
1226
Bill Janssen54cc54c2007-12-14 22:08:56 +00001227 def start (self, flag=None):
1228 self.flag = flag
1229 threading.Thread.start(self)
1230
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001232 self.active = True
1233 if self.flag:
1234 self.flag.set()
1235 while self.active:
1236 try:
1237 asyncore.loop(1)
1238 except:
1239 pass
1240
Antoine Pitrou480a1242010-04-28 21:37:09 +00001241 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001242 self.active = False
1243 self.server.close()
1244
Antoine Pitrou480a1242010-04-28 21:37:09 +00001245 def bad_cert_test(certfile):
1246 """
1247 Launch a server with CERT_REQUIRED, and check that trying to
1248 connect to it with the given client certificate fails.
1249 """
Trent Nelson78520002008-04-10 20:54:35 +00001250 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001251 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001252 cacerts=CERTFILE, chatty=False,
1253 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001254 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001255 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001256 with socket.socket() as sock:
1257 s = ssl.wrap_socket(sock,
1258 certfile=certfile,
1259 ssl_version=ssl.PROTOCOL_TLSv1)
1260 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001261 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001262 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001263 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001264 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001265 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001266 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001267 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001268 if x.errno != errno.ENOENT:
1269 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001270 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001271 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001272 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001273 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001274
Antoine Pitroub5218772010-05-21 09:56:06 +00001275 def server_params_test(client_context, server_context, indata=b"FOO\n",
1276 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001277 """
1278 Launch a server, connect a client to it and try various reads
1279 and writes.
1280 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001281 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001282 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001283 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001284 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001285 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001286 with client_context.wrap_socket(socket.socket()) as s:
1287 s.connect((HOST, server.port))
1288 for arg in [indata, bytearray(indata), memoryview(indata)]:
1289 if connectionchatty:
1290 if support.verbose:
1291 sys.stdout.write(
1292 " client: sending %r...\n" % indata)
1293 s.write(arg)
1294 outdata = s.read()
1295 if connectionchatty:
1296 if support.verbose:
1297 sys.stdout.write(" client: read %r\n" % outdata)
1298 if outdata != indata.lower():
1299 raise AssertionError(
1300 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1301 % (outdata[:20], len(outdata),
1302 indata[:20].lower(), len(indata)))
1303 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001304 if connectionchatty:
1305 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001306 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001307 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001308 'compression': s.compression(),
1309 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001310 'client_npn_protocol': s.selected_npn_protocol()
1311 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001312 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001313 stats['server_npn_protocols'] = server.selected_protocols
1314 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001315
Antoine Pitroub5218772010-05-21 09:56:06 +00001316 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1317 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001318 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001319 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001320 certtype = {
1321 ssl.CERT_NONE: "CERT_NONE",
1322 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1323 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1324 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001325 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001327 sys.stdout.write(formatstr %
1328 (ssl.get_protocol_name(client_protocol),
1329 ssl.get_protocol_name(server_protocol),
1330 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001331 client_context = ssl.SSLContext(client_protocol)
1332 client_context.options = ssl.OP_ALL | client_options
1333 server_context = ssl.SSLContext(server_protocol)
1334 server_context.options = ssl.OP_ALL | server_options
1335 for ctx in (client_context, server_context):
1336 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001337 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1338 # will send an SSLv3 hello (rather than SSLv2) starting from
1339 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001340 ctx.set_ciphers("ALL")
1341 ctx.load_cert_chain(CERTFILE)
1342 ctx.load_verify_locations(CERTFILE)
1343 try:
1344 server_params_test(client_context, server_context,
1345 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001346 # Protocol mismatch can result in either an SSLError, or a
1347 # "Connection reset by peer" error.
1348 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001349 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001350 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001351 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001353 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001354 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001355 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001356 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001357 "Client protocol %s succeeded with server protocol %s!"
1358 % (ssl.get_protocol_name(client_protocol),
1359 ssl.get_protocol_name(server_protocol)))
1360
1361
Bill Janssen6e027db2007-11-15 22:23:56 +00001362 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001363
Antoine Pitrou23df4832010-08-04 17:14:06 +00001364 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001365 def test_echo(self):
1366 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001367 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001368 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001369 for protocol in PROTOCOLS:
1370 context = ssl.SSLContext(protocol)
1371 context.load_cert_chain(CERTFILE)
1372 server_params_test(context, context,
1373 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001374
Antoine Pitrou480a1242010-04-28 21:37:09 +00001375 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001376 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001377 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001378 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1379 context.verify_mode = ssl.CERT_REQUIRED
1380 context.load_verify_locations(CERTFILE)
1381 context.load_cert_chain(CERTFILE)
1382 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001383 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001384 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001385 s.connect((HOST, server.port))
1386 cert = s.getpeercert()
1387 self.assertTrue(cert, "Can't get peer certificate.")
1388 cipher = s.cipher()
1389 if support.verbose:
1390 sys.stdout.write(pprint.pformat(cert) + '\n')
1391 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1392 if 'subject' not in cert:
1393 self.fail("No subject field in certificate: %s." %
1394 pprint.pformat(cert))
1395 if ((('organizationName', 'Python Software Foundation'),)
1396 not in cert['subject']):
1397 self.fail(
1398 "Missing or invalid 'organizationName' field in certificate subject; "
1399 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001400 self.assertIn('notBefore', cert)
1401 self.assertIn('notAfter', cert)
1402 before = ssl.cert_time_to_seconds(cert['notBefore'])
1403 after = ssl.cert_time_to_seconds(cert['notAfter'])
1404 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001405 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001406
Antoine Pitrou480a1242010-04-28 21:37:09 +00001407 def test_empty_cert(self):
1408 """Connecting with an empty cert file"""
1409 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1410 "nullcert.pem"))
1411 def test_malformed_cert(self):
1412 """Connecting with a badly formatted certificate (syntax error)"""
1413 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1414 "badcert.pem"))
1415 def test_nonexisting_cert(self):
1416 """Connecting with a non-existing cert file"""
1417 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1418 "wrongcert.pem"))
1419 def test_malformed_key(self):
1420 """Connecting with a badly formatted key (syntax error)"""
1421 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1422 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001423
Antoine Pitrou480a1242010-04-28 21:37:09 +00001424 def test_rude_shutdown(self):
1425 """A brutal shutdown of an SSL server should raise an IOError
1426 in the client when attempting handshake.
1427 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001428 listener_ready = threading.Event()
1429 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001430
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001431 s = socket.socket()
1432 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001433
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001434 # `listener` runs in a thread. It sits in an accept() until
1435 # the main thread connects. Then it rudely closes the socket,
1436 # and sets Event `listener_gone` to let the main thread know
1437 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001438 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001439 s.listen(5)
1440 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001441 newsock, addr = s.accept()
1442 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001443 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001444 listener_gone.set()
1445
1446 def connector():
1447 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001448 with socket.socket() as c:
1449 c.connect((HOST, port))
1450 listener_gone.wait()
1451 try:
1452 ssl_sock = ssl.wrap_socket(c)
1453 except IOError:
1454 pass
1455 else:
1456 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001457
1458 t = threading.Thread(target=listener)
1459 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001460 try:
1461 connector()
1462 finally:
1463 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001464
Antoine Pitrou23df4832010-08-04 17:14:06 +00001465 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001466 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1467 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001468 def test_protocol_sslv2(self):
1469 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001470 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001471 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001472 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1473 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1474 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1475 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1476 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1477 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001478 # SSLv23 client with specific SSL options
1479 if no_sslv2_implies_sslv3_hello():
1480 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1481 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1482 client_options=ssl.OP_NO_SSLv2)
1483 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1484 client_options=ssl.OP_NO_SSLv3)
1485 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1486 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001487
Antoine Pitrou23df4832010-08-04 17:14:06 +00001488 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001489 def test_protocol_sslv23(self):
1490 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001491 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001492 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001493 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1494 try:
1495 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1496 except (ssl.SSLError, socket.error) as x:
1497 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1498 if support.verbose:
1499 sys.stdout.write(
1500 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1501 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001502 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1503 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1504 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001505
Antoine Pitrou480a1242010-04-28 21:37:09 +00001506 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1507 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1508 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001509
Antoine Pitrou480a1242010-04-28 21:37:09 +00001510 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1511 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1512 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001513
Antoine Pitroub5218772010-05-21 09:56:06 +00001514 # Server with specific SSL options
1515 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1516 server_options=ssl.OP_NO_SSLv3)
1517 # Will choose TLSv1
1518 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1519 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1520 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1521 server_options=ssl.OP_NO_TLSv1)
1522
1523
Antoine Pitrou23df4832010-08-04 17:14:06 +00001524 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001525 def test_protocol_sslv3(self):
1526 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001527 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001528 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001529 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1530 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1531 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001532 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1533 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001534 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1535 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001536 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001537 if no_sslv2_implies_sslv3_hello():
1538 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1539 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1540 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001541
Antoine Pitrou23df4832010-08-04 17:14:06 +00001542 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001543 def test_protocol_tlsv1(self):
1544 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001545 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001546 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001547 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1548 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1549 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001550 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1551 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001552 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001553 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1554 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001555
Antoine Pitrou480a1242010-04-28 21:37:09 +00001556 def test_starttls(self):
1557 """Switching from clear text to encrypted and back again."""
1558 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 +00001559
Trent Nelson78520002008-04-10 20:54:35 +00001560 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001561 ssl_version=ssl.PROTOCOL_TLSv1,
1562 starttls_server=True,
1563 chatty=True,
1564 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001565 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001566 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001567 s = socket.socket()
1568 s.setblocking(1)
1569 s.connect((HOST, server.port))
1570 if support.verbose:
1571 sys.stdout.write("\n")
1572 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001573 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001574 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001575 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001576 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001577 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001578 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001579 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001580 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001581 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001582 msg = outdata.strip().lower()
1583 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1584 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001585 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001586 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001587 " client: read %r from server, starting TLS...\n"
1588 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001589 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1590 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001591 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1592 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001593 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001594 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001595 " client: read %r from server, ending TLS...\n"
1596 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001597 s = conn.unwrap()
1598 wrapped = False
1599 else:
1600 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001601 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001602 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001603 if support.verbose:
1604 sys.stdout.write(" client: closing connection.\n")
1605 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001606 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001607 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001608 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001609 if wrapped:
1610 conn.close()
1611 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001612 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001613
Antoine Pitrou480a1242010-04-28 21:37:09 +00001614 def test_socketserver(self):
1615 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001616 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001617 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001618 if support.verbose:
1619 sys.stdout.write('\n')
1620 with open(CERTFILE, 'rb') as f:
1621 d1 = f.read()
1622 d2 = ''
1623 # now fetch the same data from the HTTPS server
1624 url = 'https://%s:%d/%s' % (
1625 HOST, server.port, os.path.split(CERTFILE)[1])
1626 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001627 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001628 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001629 if dlen and (int(dlen) > 0):
1630 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001631 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001632 sys.stdout.write(
1633 " client: read %d bytes from remote server '%s'\n"
1634 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001635 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001636 f.close()
1637 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001638
Antoine Pitrou480a1242010-04-28 21:37:09 +00001639 def test_asyncore_server(self):
1640 """Check the example asyncore integration."""
1641 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001642
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001643 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001644 sys.stdout.write("\n")
1645
Antoine Pitrou480a1242010-04-28 21:37:09 +00001646 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001647 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001648 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001649 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001650 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001651 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001652 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001653 " client: sending %r...\n" % indata)
1654 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001655 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001656 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001657 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001658 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001659 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001660 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1661 % (outdata[:20], len(outdata),
1662 indata[:20].lower(), len(indata)))
1663 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001664 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001665 sys.stdout.write(" client: closing connection.\n")
1666 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001667 if support.verbose:
1668 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001669
Antoine Pitrou480a1242010-04-28 21:37:09 +00001670 def test_recv_send(self):
1671 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001672 if support.verbose:
1673 sys.stdout.write("\n")
1674
1675 server = ThreadedEchoServer(CERTFILE,
1676 certreqs=ssl.CERT_NONE,
1677 ssl_version=ssl.PROTOCOL_TLSv1,
1678 cacerts=CERTFILE,
1679 chatty=True,
1680 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001681 with server:
1682 s = ssl.wrap_socket(socket.socket(),
1683 server_side=False,
1684 certfile=CERTFILE,
1685 ca_certs=CERTFILE,
1686 cert_reqs=ssl.CERT_NONE,
1687 ssl_version=ssl.PROTOCOL_TLSv1)
1688 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001689 # helper methods for standardising recv* method signatures
1690 def _recv_into():
1691 b = bytearray(b"\0"*100)
1692 count = s.recv_into(b)
1693 return b[:count]
1694
1695 def _recvfrom_into():
1696 b = bytearray(b"\0"*100)
1697 count, addr = s.recvfrom_into(b)
1698 return b[:count]
1699
1700 # (name, method, whether to expect success, *args)
1701 send_methods = [
1702 ('send', s.send, True, []),
1703 ('sendto', s.sendto, False, ["some.address"]),
1704 ('sendall', s.sendall, True, []),
1705 ]
1706 recv_methods = [
1707 ('recv', s.recv, True, []),
1708 ('recvfrom', s.recvfrom, False, ["some.address"]),
1709 ('recv_into', _recv_into, True, []),
1710 ('recvfrom_into', _recvfrom_into, False, []),
1711 ]
1712 data_prefix = "PREFIX_"
1713
1714 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001715 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001716 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001717 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001718 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001719 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001720 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001721 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001722 "<<{outdata:r}>> ({nout:d}) received; "
1723 "expected <<{indata:r}>> ({nin:d})\n".format(
1724 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001725 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001726 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001727 )
1728 )
1729 except ValueError as e:
1730 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001731 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001732 "Failed to send with method <<{name:s}>>; "
1733 "expected to succeed.\n".format(name=meth_name)
1734 )
1735 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001736 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001737 "Method <<{name:s}>> failed with unexpected "
1738 "exception message: {exp:s}\n".format(
1739 name=meth_name, exp=e
1740 )
1741 )
1742
1743 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001744 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001745 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001746 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001747 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001748 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001749 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001750 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001751 "<<{outdata:r}>> ({nout:d}) received; "
1752 "expected <<{indata:r}>> ({nin:d})\n".format(
1753 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001754 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001755 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001756 )
1757 )
1758 except ValueError as e:
1759 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001760 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001761 "Failed to receive with method <<{name:s}>>; "
1762 "expected to succeed.\n".format(name=meth_name)
1763 )
1764 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001765 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001766 "Method <<{name:s}>> failed with unexpected "
1767 "exception message: {exp:s}\n".format(
1768 name=meth_name, exp=e
1769 )
1770 )
1771 # consume data
1772 s.read()
1773
Nick Coghlan513886a2011-08-28 00:00:27 +10001774 # Make sure sendmsg et al are disallowed to avoid
1775 # inadvertent disclosure of data and/or corruption
1776 # of the encrypted data stream
1777 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1778 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1779 self.assertRaises(NotImplementedError,
1780 s.recvmsg_into, bytearray(100))
1781
Antoine Pitrou480a1242010-04-28 21:37:09 +00001782 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001783 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001784
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001785 def test_handshake_timeout(self):
1786 # Issue #5103: SSL handshake must respect the socket timeout
1787 server = socket.socket(socket.AF_INET)
1788 host = "127.0.0.1"
1789 port = support.bind_port(server)
1790 started = threading.Event()
1791 finish = False
1792
1793 def serve():
1794 server.listen(5)
1795 started.set()
1796 conns = []
1797 while not finish:
1798 r, w, e = select.select([server], [], [], 0.1)
1799 if server in r:
1800 # Let the socket hang around rather than having
1801 # it closed by garbage collection.
1802 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001803 for sock in conns:
1804 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001805
1806 t = threading.Thread(target=serve)
1807 t.start()
1808 started.wait()
1809
1810 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001811 try:
1812 c = socket.socket(socket.AF_INET)
1813 c.settimeout(0.2)
1814 c.connect((host, port))
1815 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001816 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001817 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001818 finally:
1819 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001820 try:
1821 c = socket.socket(socket.AF_INET)
1822 c = ssl.wrap_socket(c)
1823 c.settimeout(0.2)
1824 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001825 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001826 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001827 finally:
1828 c.close()
1829 finally:
1830 finish = True
1831 t.join()
1832 server.close()
1833
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001834 def test_server_accept(self):
1835 # Issue #16357: accept() on a SSLSocket created through
1836 # SSLContext.wrap_socket().
1837 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1838 context.verify_mode = ssl.CERT_REQUIRED
1839 context.load_verify_locations(CERTFILE)
1840 context.load_cert_chain(CERTFILE)
1841 server = socket.socket(socket.AF_INET)
1842 host = "127.0.0.1"
1843 port = support.bind_port(server)
1844 server = context.wrap_socket(server, server_side=True)
1845
1846 evt = threading.Event()
1847 remote = None
1848 peer = None
1849 def serve():
1850 nonlocal remote, peer
1851 server.listen(5)
1852 # Block on the accept and wait on the connection to close.
1853 evt.set()
1854 remote, peer = server.accept()
1855 remote.recv(1)
1856
1857 t = threading.Thread(target=serve)
1858 t.start()
1859 # Client wait until server setup and perform a connect.
1860 evt.wait()
1861 client = context.wrap_socket(socket.socket())
1862 client.connect((host, port))
1863 client_addr = client.getsockname()
1864 client.close()
1865 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001866 remote.close()
1867 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001868 # Sanity checks.
1869 self.assertIsInstance(remote, ssl.SSLSocket)
1870 self.assertEqual(peer, client_addr)
1871
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001872 def test_default_ciphers(self):
1873 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1874 try:
1875 # Force a set of weak ciphers on our client context
1876 context.set_ciphers("DES")
1877 except ssl.SSLError:
1878 self.skipTest("no DES cipher available")
1879 with ThreadedEchoServer(CERTFILE,
1880 ssl_version=ssl.PROTOCOL_SSLv23,
1881 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001882 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001883 with self.assertRaises((OSError, ssl.SSLError)):
1884 s.connect((HOST, server.port))
1885 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1886
Antoine Pitroud6494802011-07-21 01:11:30 +02001887 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1888 "'tls-unique' channel binding not available")
1889 def test_tls_unique_channel_binding(self):
1890 """Test tls-unique channel binding."""
1891 if support.verbose:
1892 sys.stdout.write("\n")
1893
1894 server = ThreadedEchoServer(CERTFILE,
1895 certreqs=ssl.CERT_NONE,
1896 ssl_version=ssl.PROTOCOL_TLSv1,
1897 cacerts=CERTFILE,
1898 chatty=True,
1899 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001900 with server:
1901 s = ssl.wrap_socket(socket.socket(),
1902 server_side=False,
1903 certfile=CERTFILE,
1904 ca_certs=CERTFILE,
1905 cert_reqs=ssl.CERT_NONE,
1906 ssl_version=ssl.PROTOCOL_TLSv1)
1907 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001908 # get the data
1909 cb_data = s.get_channel_binding("tls-unique")
1910 if support.verbose:
1911 sys.stdout.write(" got channel binding data: {0!r}\n"
1912 .format(cb_data))
1913
1914 # check if it is sane
1915 self.assertIsNotNone(cb_data)
1916 self.assertEqual(len(cb_data), 12) # True for TLSv1
1917
1918 # and compare with the peers version
1919 s.write(b"CB tls-unique\n")
1920 peer_data_repr = s.read().strip()
1921 self.assertEqual(peer_data_repr,
1922 repr(cb_data).encode("us-ascii"))
1923 s.close()
1924
1925 # now, again
1926 s = ssl.wrap_socket(socket.socket(),
1927 server_side=False,
1928 certfile=CERTFILE,
1929 ca_certs=CERTFILE,
1930 cert_reqs=ssl.CERT_NONE,
1931 ssl_version=ssl.PROTOCOL_TLSv1)
1932 s.connect((HOST, server.port))
1933 new_cb_data = s.get_channel_binding("tls-unique")
1934 if support.verbose:
1935 sys.stdout.write(" got another channel binding data: {0!r}\n"
1936 .format(new_cb_data))
1937 # is it really unique
1938 self.assertNotEqual(cb_data, new_cb_data)
1939 self.assertIsNotNone(cb_data)
1940 self.assertEqual(len(cb_data), 12) # True for TLSv1
1941 s.write(b"CB tls-unique\n")
1942 peer_data_repr = s.read().strip()
1943 self.assertEqual(peer_data_repr,
1944 repr(new_cb_data).encode("us-ascii"))
1945 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001946
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001947 def test_compression(self):
1948 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1949 context.load_cert_chain(CERTFILE)
1950 stats = server_params_test(context, context,
1951 chatty=True, connectionchatty=True)
1952 if support.verbose:
1953 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1954 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1955
1956 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1957 "ssl.OP_NO_COMPRESSION needed for this test")
1958 def test_compression_disabled(self):
1959 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1960 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001961 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001962 stats = server_params_test(context, context,
1963 chatty=True, connectionchatty=True)
1964 self.assertIs(stats['compression'], None)
1965
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001966 def test_dh_params(self):
1967 # Check we can get a connection with ephemeral Diffie-Hellman
1968 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1969 context.load_cert_chain(CERTFILE)
1970 context.load_dh_params(DHFILE)
1971 context.set_ciphers("kEDH")
1972 stats = server_params_test(context, context,
1973 chatty=True, connectionchatty=True)
1974 cipher = stats["cipher"][0]
1975 parts = cipher.split("-")
1976 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1977 self.fail("Non-DH cipher: " + cipher[0])
1978
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001979 def test_selected_npn_protocol(self):
1980 # selected_npn_protocol() is None unless NPN is used
1981 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1982 context.load_cert_chain(CERTFILE)
1983 stats = server_params_test(context, context,
1984 chatty=True, connectionchatty=True)
1985 self.assertIs(stats['client_npn_protocol'], None)
1986
1987 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1988 def test_npn_protocols(self):
1989 server_protocols = ['http/1.1', 'spdy/2']
1990 protocol_tests = [
1991 (['http/1.1', 'spdy/2'], 'http/1.1'),
1992 (['spdy/2', 'http/1.1'], 'http/1.1'),
1993 (['spdy/2', 'test'], 'spdy/2'),
1994 (['abc', 'def'], 'abc')
1995 ]
1996 for client_protocols, expected in protocol_tests:
1997 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1998 server_context.load_cert_chain(CERTFILE)
1999 server_context.set_npn_protocols(server_protocols)
2000 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2001 client_context.load_cert_chain(CERTFILE)
2002 client_context.set_npn_protocols(client_protocols)
2003 stats = server_params_test(client_context, server_context,
2004 chatty=True, connectionchatty=True)
2005
2006 msg = "failed trying %s (s) and %s (c).\n" \
2007 "was expecting %s, but got %%s from the %%s" \
2008 % (str(server_protocols), str(client_protocols),
2009 str(expected))
2010 client_result = stats['client_npn_protocol']
2011 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2012 server_result = stats['server_npn_protocols'][-1] \
2013 if len(stats['server_npn_protocols']) else 'nothing'
2014 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2015
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002016
Thomas Woutersed03b412007-08-28 21:37:11 +00002017def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002018 if support.verbose:
2019 plats = {
2020 'Linux': platform.linux_distribution,
2021 'Mac': platform.mac_ver,
2022 'Windows': platform.win32_ver,
2023 }
2024 for name, func in plats.items():
2025 plat = func()
2026 if plat and plat[0]:
2027 plat = '%s %r' % (name, plat)
2028 break
2029 else:
2030 plat = repr(platform.platform())
2031 print("test_ssl: testing with %r %r" %
2032 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2033 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002034 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002035
Antoine Pitrou152efa22010-05-16 18:19:27 +00002036 for filename in [
2037 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2038 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2039 BADCERT, BADKEY, EMPTYCERT]:
2040 if not os.path.exists(filename):
2041 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002042
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002043 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002044
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002045 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002046 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002047
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002048 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002049 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002050 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002051 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002052
Antoine Pitrou480a1242010-04-28 21:37:09 +00002053 try:
2054 support.run_unittest(*tests)
2055 finally:
2056 if _have_threads:
2057 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002058
2059if __name__ == "__main__":
2060 test_main()