blob: 815475ea4dd52ad0c29d3a7d6a6ffc550161863d [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 Pitroud5323212010-10-22 18:19:07 +0000352 def test_server_side(self):
353 # server_hostname doesn't work for server sockets
354 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000355 with socket.socket() as sock:
356 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
357 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000358
Antoine Pitroud6494802011-07-21 01:11:30 +0200359 def test_unknown_channel_binding(self):
360 # should raise ValueError for unknown type
361 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100362 with ssl.wrap_socket(s) as ss:
363 with self.assertRaises(ValueError):
364 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200365
366 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
367 "'tls-unique' channel binding not available")
368 def test_tls_unique_channel_binding(self):
369 # unconnected should return None for known type
370 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100371 with ssl.wrap_socket(s) as ss:
372 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200373 # the same for server-side
374 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100375 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
376 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200377
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600378 def test_dealloc_warn(self):
379 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
380 r = repr(ss)
381 with self.assertWarns(ResourceWarning) as cm:
382 ss = None
383 support.gc_collect()
384 self.assertIn(r, str(cm.warning.args[0]))
385
Antoine Pitrou152efa22010-05-16 18:19:27 +0000386class ContextTests(unittest.TestCase):
387
Antoine Pitrou23df4832010-08-04 17:14:06 +0000388 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000389 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200390 if hasattr(ssl, 'PROTOCOL_SSLv2'):
391 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000392 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
393 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
394 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
395 self.assertRaises(TypeError, ssl.SSLContext)
396 self.assertRaises(ValueError, ssl.SSLContext, -1)
397 self.assertRaises(ValueError, ssl.SSLContext, 42)
398
Antoine Pitrou23df4832010-08-04 17:14:06 +0000399 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000400 def test_protocol(self):
401 for proto in PROTOCOLS:
402 ctx = ssl.SSLContext(proto)
403 self.assertEqual(ctx.protocol, proto)
404
405 def test_ciphers(self):
406 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
407 ctx.set_ciphers("ALL")
408 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000409 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000410 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000411
Antoine Pitrou23df4832010-08-04 17:14:06 +0000412 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000413 def test_options(self):
414 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
415 # OP_ALL is the default value
416 self.assertEqual(ssl.OP_ALL, ctx.options)
417 ctx.options |= ssl.OP_NO_SSLv2
418 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
419 ctx.options)
420 ctx.options |= ssl.OP_NO_SSLv3
421 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
422 ctx.options)
423 if can_clear_options():
424 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
425 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
426 ctx.options)
427 ctx.options = 0
428 self.assertEqual(0, ctx.options)
429 else:
430 with self.assertRaises(ValueError):
431 ctx.options = 0
432
Antoine Pitrou152efa22010-05-16 18:19:27 +0000433 def test_verify(self):
434 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
435 # Default value
436 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
437 ctx.verify_mode = ssl.CERT_OPTIONAL
438 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
439 ctx.verify_mode = ssl.CERT_REQUIRED
440 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
441 ctx.verify_mode = ssl.CERT_NONE
442 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
443 with self.assertRaises(TypeError):
444 ctx.verify_mode = None
445 with self.assertRaises(ValueError):
446 ctx.verify_mode = 42
447
448 def test_load_cert_chain(self):
449 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
450 # Combined key and cert in a single file
451 ctx.load_cert_chain(CERTFILE)
452 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
453 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000454 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000455 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000456 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000457 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000458 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000459 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000460 ctx.load_cert_chain(EMPTYCERT)
461 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000462 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000463 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
464 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
465 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000466 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000467 ctx.load_cert_chain(ONLYCERT)
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(ONLYKEY)
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(certfile=ONLYKEY, keyfile=ONLYCERT)
472 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000473 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000474 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000475 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200476 # Password protected key and cert
477 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
478 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
479 ctx.load_cert_chain(CERTFILE_PROTECTED,
480 password=bytearray(KEY_PASSWORD.encode()))
481 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
482 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
483 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
484 bytearray(KEY_PASSWORD.encode()))
485 with self.assertRaisesRegex(TypeError, "should be a string"):
486 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
487 with self.assertRaises(ssl.SSLError):
488 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
489 with self.assertRaisesRegex(ValueError, "cannot be longer"):
490 # openssl has a fixed limit on the password buffer.
491 # PEM_BUFSIZE is generally set to 1kb.
492 # Return a string larger than this.
493 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
494 # Password callback
495 def getpass_unicode():
496 return KEY_PASSWORD
497 def getpass_bytes():
498 return KEY_PASSWORD.encode()
499 def getpass_bytearray():
500 return bytearray(KEY_PASSWORD.encode())
501 def getpass_badpass():
502 return "badpass"
503 def getpass_huge():
504 return b'a' * (1024 * 1024)
505 def getpass_bad_type():
506 return 9
507 def getpass_exception():
508 raise Exception('getpass error')
509 class GetPassCallable:
510 def __call__(self):
511 return KEY_PASSWORD
512 def getpass(self):
513 return KEY_PASSWORD
514 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
515 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
516 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
517 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
518 ctx.load_cert_chain(CERTFILE_PROTECTED,
519 password=GetPassCallable().getpass)
520 with self.assertRaises(ssl.SSLError):
521 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
522 with self.assertRaisesRegex(ValueError, "cannot be longer"):
523 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
524 with self.assertRaisesRegex(TypeError, "must return a string"):
525 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
526 with self.assertRaisesRegex(Exception, "getpass error"):
527 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
528 # Make sure the password function isn't called if it isn't needed
529 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000530
531 def test_load_verify_locations(self):
532 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
533 ctx.load_verify_locations(CERTFILE)
534 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
535 ctx.load_verify_locations(BYTES_CERTFILE)
536 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
537 self.assertRaises(TypeError, ctx.load_verify_locations)
538 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000539 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000540 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000541 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000542 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000543 ctx.load_verify_locations(BADCERT)
544 ctx.load_verify_locations(CERTFILE, CAPATH)
545 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
546
Victor Stinner80f75e62011-01-29 11:31:20 +0000547 # Issue #10989: crash if the second argument type is invalid
548 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
549
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100550 def test_load_dh_params(self):
551 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
552 ctx.load_dh_params(DHFILE)
553 if os.name != 'nt':
554 ctx.load_dh_params(BYTES_DHFILE)
555 self.assertRaises(TypeError, ctx.load_dh_params)
556 self.assertRaises(TypeError, ctx.load_dh_params, None)
557 with self.assertRaises(FileNotFoundError) as cm:
558 ctx.load_dh_params(WRONGCERT)
559 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200560 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100561 ctx.load_dh_params(CERTFILE)
562
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000563 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000564 def test_session_stats(self):
565 for proto in PROTOCOLS:
566 ctx = ssl.SSLContext(proto)
567 self.assertEqual(ctx.session_stats(), {
568 'number': 0,
569 'connect': 0,
570 'connect_good': 0,
571 'connect_renegotiate': 0,
572 'accept': 0,
573 'accept_good': 0,
574 'accept_renegotiate': 0,
575 'hits': 0,
576 'misses': 0,
577 'timeouts': 0,
578 'cache_full': 0,
579 })
580
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000581 def test_set_default_verify_paths(self):
582 # There's not much we can do to test that it acts as expected,
583 # so just check it doesn't crash or raise an exception.
584 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
585 ctx.set_default_verify_paths()
586
Antoine Pitrou501da612011-12-21 09:27:41 +0100587 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100588 def test_set_ecdh_curve(self):
589 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
590 ctx.set_ecdh_curve("prime256v1")
591 ctx.set_ecdh_curve(b"prime256v1")
592 self.assertRaises(TypeError, ctx.set_ecdh_curve)
593 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
594 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
595 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
596
Antoine Pitrou152efa22010-05-16 18:19:27 +0000597
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200598class SSLErrorTests(unittest.TestCase):
599
600 def test_str(self):
601 # The str() of a SSLError doesn't include the errno
602 e = ssl.SSLError(1, "foo")
603 self.assertEqual(str(e), "foo")
604 self.assertEqual(e.errno, 1)
605 # Same for a subclass
606 e = ssl.SSLZeroReturnError(1, "foo")
607 self.assertEqual(str(e), "foo")
608 self.assertEqual(e.errno, 1)
609
610 def test_lib_reason(self):
611 # Test the library and reason attributes
612 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
613 with self.assertRaises(ssl.SSLError) as cm:
614 ctx.load_dh_params(CERTFILE)
615 self.assertEqual(cm.exception.library, 'PEM')
616 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
617 s = str(cm.exception)
618 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
619
620 def test_subclass(self):
621 # Check that the appropriate SSLError subclass is raised
622 # (this only tests one of them)
623 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
624 with socket.socket() as s:
625 s.bind(("127.0.0.1", 0))
626 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100627 c = socket.socket()
628 c.connect(s.getsockname())
629 c.setblocking(False)
630 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200631 with self.assertRaises(ssl.SSLWantReadError) as cm:
632 c.do_handshake()
633 s = str(cm.exception)
634 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
635 # For compatibility
636 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
637
638
Bill Janssen6e027db2007-11-15 22:23:56 +0000639class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000640
Antoine Pitrou480a1242010-04-28 21:37:09 +0000641 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000642 with support.transient_internet("svn.python.org"):
643 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
644 cert_reqs=ssl.CERT_NONE)
645 try:
646 s.connect(("svn.python.org", 443))
647 self.assertEqual({}, s.getpeercert())
648 finally:
649 s.close()
650
651 # this should fail because we have no verification certs
652 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
653 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000654 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
655 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000656 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657
Antoine Pitrou350c7222010-09-09 13:31:46 +0000658 # this should succeed because we specify the root cert
659 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
660 cert_reqs=ssl.CERT_REQUIRED,
661 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
662 try:
663 s.connect(("svn.python.org", 443))
664 self.assertTrue(s.getpeercert())
665 finally:
666 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000667
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000668 def test_connect_ex(self):
669 # Issue #11326: check connect_ex() implementation
670 with support.transient_internet("svn.python.org"):
671 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
672 cert_reqs=ssl.CERT_REQUIRED,
673 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
674 try:
675 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
676 self.assertTrue(s.getpeercert())
677 finally:
678 s.close()
679
680 def test_non_blocking_connect_ex(self):
681 # Issue #11326: non-blocking connect_ex() should allow handshake
682 # to proceed after the socket gets ready.
683 with support.transient_internet("svn.python.org"):
684 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
685 cert_reqs=ssl.CERT_REQUIRED,
686 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
687 do_handshake_on_connect=False)
688 try:
689 s.setblocking(False)
690 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000691 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
692 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000693 # Wait for connect to finish
694 select.select([], [s], [], 5.0)
695 # Non-blocking handshake
696 while True:
697 try:
698 s.do_handshake()
699 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200700 except ssl.SSLWantReadError:
701 select.select([s], [], [], 5.0)
702 except ssl.SSLWantWriteError:
703 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000704 # SSL established
705 self.assertTrue(s.getpeercert())
706 finally:
707 s.close()
708
Antoine Pitroub4410db2011-05-18 18:51:06 +0200709 def test_timeout_connect_ex(self):
710 # Issue #12065: on a timeout, connect_ex() should return the original
711 # errno (mimicking the behaviour of non-SSL sockets).
712 with support.transient_internet("svn.python.org"):
713 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
714 cert_reqs=ssl.CERT_REQUIRED,
715 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
716 do_handshake_on_connect=False)
717 try:
718 s.settimeout(0.0000001)
719 rc = s.connect_ex(('svn.python.org', 443))
720 if rc == 0:
721 self.skipTest("svn.python.org responded too quickly")
722 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
723 finally:
724 s.close()
725
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100726 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100727 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100728 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
729 cert_reqs=ssl.CERT_REQUIRED,
730 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
731 try:
732 self.assertEqual(errno.ECONNREFUSED,
733 s.connect_ex(("svn.python.org", 444)))
734 finally:
735 s.close()
736
Antoine Pitrou152efa22010-05-16 18:19:27 +0000737 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000738 with support.transient_internet("svn.python.org"):
739 # Same as test_connect, but with a separately created context
740 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
741 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
742 s.connect(("svn.python.org", 443))
743 try:
744 self.assertEqual({}, s.getpeercert())
745 finally:
746 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000747 # Same with a server hostname
748 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
749 server_hostname="svn.python.org")
750 if ssl.HAS_SNI:
751 s.connect(("svn.python.org", 443))
752 s.close()
753 else:
754 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000755 # This should fail because we have no verification certs
756 ctx.verify_mode = ssl.CERT_REQUIRED
757 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000758 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000759 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000760 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000761 # This should succeed because we specify the root cert
762 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
763 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
764 s.connect(("svn.python.org", 443))
765 try:
766 cert = s.getpeercert()
767 self.assertTrue(cert)
768 finally:
769 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000770
771 def test_connect_capath(self):
772 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000773 # NOTE: the subject hashing algorithm has been changed between
774 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
775 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000776 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000777 with support.transient_internet("svn.python.org"):
778 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
779 ctx.verify_mode = ssl.CERT_REQUIRED
780 ctx.load_verify_locations(capath=CAPATH)
781 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
782 s.connect(("svn.python.org", 443))
783 try:
784 cert = s.getpeercert()
785 self.assertTrue(cert)
786 finally:
787 s.close()
788 # Same with a bytes `capath` argument
789 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
790 ctx.verify_mode = ssl.CERT_REQUIRED
791 ctx.load_verify_locations(capath=BYTES_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()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000799
Antoine Pitroue3220242010-04-24 11:13:53 +0000800 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
801 def test_makefile_close(self):
802 # Issue #5238: creating a file-like object with makefile() shouldn't
803 # delay closing the underlying "real socket" (here tested with its
804 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000805 with support.transient_internet("svn.python.org"):
806 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
807 ss.connect(("svn.python.org", 443))
808 fd = ss.fileno()
809 f = ss.makefile()
810 f.close()
811 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000812 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000813 # Closing the SSL socket should close the fd too
814 ss.close()
815 gc.collect()
816 with self.assertRaises(OSError) as e:
817 os.read(fd, 0)
818 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000819
Antoine Pitrou480a1242010-04-28 21:37:09 +0000820 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000821 with support.transient_internet("svn.python.org"):
822 s = socket.socket(socket.AF_INET)
823 s.connect(("svn.python.org", 443))
824 s.setblocking(False)
825 s = ssl.wrap_socket(s,
826 cert_reqs=ssl.CERT_NONE,
827 do_handshake_on_connect=False)
828 count = 0
829 while True:
830 try:
831 count += 1
832 s.do_handshake()
833 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200834 except ssl.SSLWantReadError:
835 select.select([s], [], [])
836 except ssl.SSLWantWriteError:
837 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000838 s.close()
839 if support.verbose:
840 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000841
Antoine Pitrou480a1242010-04-28 21:37:09 +0000842 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200843 def _test_get_server_certificate(host, port, cert=None):
844 with support.transient_internet(host):
845 pem = ssl.get_server_certificate((host, port))
846 if not pem:
847 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200848
Antoine Pitrou15399c32011-04-28 19:23:55 +0200849 try:
850 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
851 except ssl.SSLError as x:
852 #should fail
853 if support.verbose:
854 sys.stdout.write("%s\n" % x)
855 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200856 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
857
Antoine Pitrou15399c32011-04-28 19:23:55 +0200858 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
859 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200860 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000861 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200862 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000863
Antoine Pitrou15399c32011-04-28 19:23:55 +0200864 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
865 if support.IPV6_ENABLED:
866 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000867
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000868 def test_ciphers(self):
869 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000870 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100871 with ssl.wrap_socket(socket.socket(socket.AF_INET),
872 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
873 s.connect(remote)
874 with ssl.wrap_socket(socket.socket(socket.AF_INET),
875 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
876 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000877 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000878 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000879 with socket.socket(socket.AF_INET) as sock:
880 s = ssl.wrap_socket(sock,
881 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
882 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000883
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000884 def test_algorithms(self):
885 # Issue #8484: all algorithms should be available when verifying a
886 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000887 # SHA256 was added in OpenSSL 0.9.8
888 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
889 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200890 # sha256.tbs-internet.com needs SNI to use the correct certificate
891 if not ssl.HAS_SNI:
892 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000893 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
894 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000895 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000896 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200897 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
898 ctx.verify_mode = ssl.CERT_REQUIRED
899 ctx.load_verify_locations(sha256_cert)
900 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
901 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000902 try:
903 s.connect(remote)
904 if support.verbose:
905 sys.stdout.write("\nCipher with %r is %r\n" %
906 (remote, s.cipher()))
907 sys.stdout.write("Certificate is:\n%s\n" %
908 pprint.pformat(s.getpeercert()))
909 finally:
910 s.close()
911
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912
913try:
914 import threading
915except ImportError:
916 _have_threads = False
917else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918 _have_threads = True
919
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000920 from test.ssl_servers import make_https_server
921
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 class ThreadedEchoServer(threading.Thread):
923
924 class ConnectionHandler(threading.Thread):
925
926 """A mildly complicated class, because we want it to work both
927 with and without the SSL wrapper around the socket connection, so
928 that we can test the STARTTLS functionality."""
929
Bill Janssen6e027db2007-11-15 22:23:56 +0000930 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000931 self.server = server
932 self.running = False
933 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000934 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 self.sock.setblocking(1)
936 self.sslconn = None
937 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000938 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000939
Antoine Pitrou480a1242010-04-28 21:37:09 +0000940 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000942 self.sslconn = self.server.context.wrap_socket(
943 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100944 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +0100945 except (ssl.SSLError, ConnectionResetError) as e:
946 # We treat ConnectionResetError as though it were an
947 # SSLError - OpenSSL on Ubuntu abruptly closes the
948 # connection when asked to use an unsupported protocol.
949 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000950 # XXX Various errors can have happened here, for example
951 # a mismatching protocol version, an invalid certificate,
952 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100953 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000954 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000955 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000956 self.running = False
957 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000958 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000959 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000961 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000962 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000963 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000964 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
965 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000966 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000967 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
968 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000969 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100971 sys.stdout.write(" server: selected protocol is now "
972 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000973 return True
974
975 def read(self):
976 if self.sslconn:
977 return self.sslconn.read()
978 else:
979 return self.sock.recv(1024)
980
981 def write(self, bytes):
982 if self.sslconn:
983 return self.sslconn.write(bytes)
984 else:
985 return self.sock.send(bytes)
986
987 def close(self):
988 if self.sslconn:
989 self.sslconn.close()
990 else:
991 self.sock.close()
992
Antoine Pitrou480a1242010-04-28 21:37:09 +0000993 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000994 self.running = True
995 if not self.server.starttls_server:
996 if not self.wrap_conn():
997 return
998 while self.running:
999 try:
1000 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 stripped = msg.strip()
1002 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 # eof, so quit this handler
1004 self.running = False
1005 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001006 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001007 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001008 sys.stdout.write(" server: client closed connection\n")
1009 self.close()
1010 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001011 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001012 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001013 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001015 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001016 if not self.wrap_conn():
1017 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001018 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001019 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001020 if support.verbose and self.server.connectionchatty:
1021 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001022 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001023 self.sock = self.sslconn.unwrap()
1024 self.sslconn = None
1025 if support.verbose and self.server.connectionchatty:
1026 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001027 elif stripped == b'CB tls-unique':
1028 if support.verbose and self.server.connectionchatty:
1029 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1030 data = self.sslconn.get_channel_binding("tls-unique")
1031 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001032 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001033 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 self.server.connectionchatty):
1035 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001036 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1037 % (msg, ctype, msg.lower(), ctype))
1038 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001039 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001040 if self.server.chatty:
1041 handle_error("Test server failure:\n")
1042 self.close()
1043 self.running = False
1044 # normally, we'd just stop here, but for the test
1045 # harness, we want to stop the server
1046 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001047
Antoine Pitroub5218772010-05-21 09:56:06 +00001048 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001049 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001050 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001051 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001052 if context:
1053 self.context = context
1054 else:
1055 self.context = ssl.SSLContext(ssl_version
1056 if ssl_version is not None
1057 else ssl.PROTOCOL_TLSv1)
1058 self.context.verify_mode = (certreqs if certreqs is not None
1059 else ssl.CERT_NONE)
1060 if cacerts:
1061 self.context.load_verify_locations(cacerts)
1062 if certificate:
1063 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001064 if npn_protocols:
1065 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001066 if ciphers:
1067 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001068 self.chatty = chatty
1069 self.connectionchatty = connectionchatty
1070 self.starttls_server = starttls_server
1071 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001072 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001074 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001075 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001076 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001078 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001079
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001080 def __enter__(self):
1081 self.start(threading.Event())
1082 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001083 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001084
1085 def __exit__(self, *args):
1086 self.stop()
1087 self.join()
1088
Antoine Pitrou480a1242010-04-28 21:37:09 +00001089 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001090 self.flag = flag
1091 threading.Thread.start(self)
1092
Antoine Pitrou480a1242010-04-28 21:37:09 +00001093 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001094 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001095 self.sock.listen(5)
1096 self.active = True
1097 if self.flag:
1098 # signal an event
1099 self.flag.set()
1100 while self.active:
1101 try:
1102 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001103 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001104 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001105 + repr(connaddr) + '\n')
1106 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001108 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109 except socket.timeout:
1110 pass
1111 except KeyboardInterrupt:
1112 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001113 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001114
Antoine Pitrou480a1242010-04-28 21:37:09 +00001115 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001116 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001117
Bill Janssen54cc54c2007-12-14 22:08:56 +00001118 class AsyncoreEchoServer(threading.Thread):
1119
1120 # this one's based on asyncore.dispatcher
1121
1122 class EchoServer (asyncore.dispatcher):
1123
1124 class ConnectionHandler (asyncore.dispatcher_with_send):
1125
1126 def __init__(self, conn, certfile):
1127 self.socket = ssl.wrap_socket(conn, server_side=True,
1128 certfile=certfile,
1129 do_handshake_on_connect=False)
1130 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001131 self._ssl_accepting = True
1132 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001133
1134 def readable(self):
1135 if isinstance(self.socket, ssl.SSLSocket):
1136 while self.socket.pending() > 0:
1137 self.handle_read_event()
1138 return True
1139
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001140 def _do_ssl_handshake(self):
1141 try:
1142 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001143 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1144 return
1145 except ssl.SSLEOFError:
1146 return self.handle_close()
1147 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001148 raise
1149 except socket.error as err:
1150 if err.args[0] == errno.ECONNABORTED:
1151 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001152 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001153 self._ssl_accepting = False
1154
1155 def handle_read(self):
1156 if self._ssl_accepting:
1157 self._do_ssl_handshake()
1158 else:
1159 data = self.recv(1024)
1160 if support.verbose:
1161 sys.stdout.write(" server: read %s from client\n" % repr(data))
1162 if not data:
1163 self.close()
1164 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001165 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001166
1167 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001168 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001169 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001170 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1171
1172 def handle_error(self):
1173 raise
1174
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001175 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001176 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001177 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1178 self.port = support.bind_port(sock, '')
1179 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001180 self.listen(5)
1181
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001182 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001183 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001184 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1185 self.ConnectionHandler(sock_obj, self.certfile)
1186
1187 def handle_error(self):
1188 raise
1189
Trent Nelson78520002008-04-10 20:54:35 +00001190 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001191 self.flag = None
1192 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001193 self.server = self.EchoServer(certfile)
1194 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001195 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001196 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001197
1198 def __str__(self):
1199 return "<%s %s>" % (self.__class__.__name__, self.server)
1200
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001201 def __enter__(self):
1202 self.start(threading.Event())
1203 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001204 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001205
1206 def __exit__(self, *args):
1207 if support.verbose:
1208 sys.stdout.write(" cleanup: stopping server.\n")
1209 self.stop()
1210 if support.verbose:
1211 sys.stdout.write(" cleanup: joining server thread.\n")
1212 self.join()
1213 if support.verbose:
1214 sys.stdout.write(" cleanup: successfully joined.\n")
1215
Bill Janssen54cc54c2007-12-14 22:08:56 +00001216 def start (self, flag=None):
1217 self.flag = flag
1218 threading.Thread.start(self)
1219
Antoine Pitrou480a1242010-04-28 21:37:09 +00001220 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001221 self.active = True
1222 if self.flag:
1223 self.flag.set()
1224 while self.active:
1225 try:
1226 asyncore.loop(1)
1227 except:
1228 pass
1229
Antoine Pitrou480a1242010-04-28 21:37:09 +00001230 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001231 self.active = False
1232 self.server.close()
1233
Antoine Pitrou480a1242010-04-28 21:37:09 +00001234 def bad_cert_test(certfile):
1235 """
1236 Launch a server with CERT_REQUIRED, and check that trying to
1237 connect to it with the given client certificate fails.
1238 """
Trent Nelson78520002008-04-10 20:54:35 +00001239 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001240 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001241 cacerts=CERTFILE, chatty=False,
1242 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001243 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001244 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001245 with socket.socket() as sock:
1246 s = ssl.wrap_socket(sock,
1247 certfile=certfile,
1248 ssl_version=ssl.PROTOCOL_TLSv1)
1249 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001250 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001251 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001252 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001253 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001254 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001255 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001256 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001257 if x.errno != errno.ENOENT:
1258 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001259 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001260 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001261 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001262 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001263
Antoine Pitroub5218772010-05-21 09:56:06 +00001264 def server_params_test(client_context, server_context, indata=b"FOO\n",
1265 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001266 """
1267 Launch a server, connect a client to it and try various reads
1268 and writes.
1269 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001270 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001271 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001272 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001273 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001274 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001275 with client_context.wrap_socket(socket.socket()) as s:
1276 s.connect((HOST, server.port))
1277 for arg in [indata, bytearray(indata), memoryview(indata)]:
1278 if connectionchatty:
1279 if support.verbose:
1280 sys.stdout.write(
1281 " client: sending %r...\n" % indata)
1282 s.write(arg)
1283 outdata = s.read()
1284 if connectionchatty:
1285 if support.verbose:
1286 sys.stdout.write(" client: read %r\n" % outdata)
1287 if outdata != indata.lower():
1288 raise AssertionError(
1289 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1290 % (outdata[:20], len(outdata),
1291 indata[:20].lower(), len(indata)))
1292 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001293 if connectionchatty:
1294 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001295 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001296 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001297 'compression': s.compression(),
1298 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001299 'client_npn_protocol': s.selected_npn_protocol()
1300 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001301 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001302 stats['server_npn_protocols'] = server.selected_protocols
1303 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001304
Antoine Pitroub5218772010-05-21 09:56:06 +00001305 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1306 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001307 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001308 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001309 certtype = {
1310 ssl.CERT_NONE: "CERT_NONE",
1311 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1312 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1313 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001314 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001315 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001316 sys.stdout.write(formatstr %
1317 (ssl.get_protocol_name(client_protocol),
1318 ssl.get_protocol_name(server_protocol),
1319 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001320 client_context = ssl.SSLContext(client_protocol)
1321 client_context.options = ssl.OP_ALL | client_options
1322 server_context = ssl.SSLContext(server_protocol)
1323 server_context.options = ssl.OP_ALL | server_options
1324 for ctx in (client_context, server_context):
1325 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001326 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1327 # will send an SSLv3 hello (rather than SSLv2) starting from
1328 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001329 ctx.set_ciphers("ALL")
1330 ctx.load_cert_chain(CERTFILE)
1331 ctx.load_verify_locations(CERTFILE)
1332 try:
1333 server_params_test(client_context, server_context,
1334 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001335 # Protocol mismatch can result in either an SSLError, or a
1336 # "Connection reset by peer" error.
1337 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001338 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001339 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001340 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001342 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001343 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001344 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001345 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001346 "Client protocol %s succeeded with server protocol %s!"
1347 % (ssl.get_protocol_name(client_protocol),
1348 ssl.get_protocol_name(server_protocol)))
1349
1350
Bill Janssen6e027db2007-11-15 22:23:56 +00001351 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001352
Antoine Pitrou23df4832010-08-04 17:14:06 +00001353 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001354 def test_echo(self):
1355 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001356 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001357 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001358 for protocol in PROTOCOLS:
1359 context = ssl.SSLContext(protocol)
1360 context.load_cert_chain(CERTFILE)
1361 server_params_test(context, context,
1362 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001363
Antoine Pitrou480a1242010-04-28 21:37:09 +00001364 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001365 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001366 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001367 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1368 context.verify_mode = ssl.CERT_REQUIRED
1369 context.load_verify_locations(CERTFILE)
1370 context.load_cert_chain(CERTFILE)
1371 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001372 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001373 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001374 s.connect((HOST, server.port))
1375 cert = s.getpeercert()
1376 self.assertTrue(cert, "Can't get peer certificate.")
1377 cipher = s.cipher()
1378 if support.verbose:
1379 sys.stdout.write(pprint.pformat(cert) + '\n')
1380 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1381 if 'subject' not in cert:
1382 self.fail("No subject field in certificate: %s." %
1383 pprint.pformat(cert))
1384 if ((('organizationName', 'Python Software Foundation'),)
1385 not in cert['subject']):
1386 self.fail(
1387 "Missing or invalid 'organizationName' field in certificate subject; "
1388 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001389 self.assertIn('notBefore', cert)
1390 self.assertIn('notAfter', cert)
1391 before = ssl.cert_time_to_seconds(cert['notBefore'])
1392 after = ssl.cert_time_to_seconds(cert['notAfter'])
1393 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001394 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 def test_empty_cert(self):
1397 """Connecting with an empty cert file"""
1398 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1399 "nullcert.pem"))
1400 def test_malformed_cert(self):
1401 """Connecting with a badly formatted certificate (syntax error)"""
1402 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1403 "badcert.pem"))
1404 def test_nonexisting_cert(self):
1405 """Connecting with a non-existing cert file"""
1406 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1407 "wrongcert.pem"))
1408 def test_malformed_key(self):
1409 """Connecting with a badly formatted key (syntax error)"""
1410 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1411 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001412
Antoine Pitrou480a1242010-04-28 21:37:09 +00001413 def test_rude_shutdown(self):
1414 """A brutal shutdown of an SSL server should raise an IOError
1415 in the client when attempting handshake.
1416 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001417 listener_ready = threading.Event()
1418 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001419
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001420 s = socket.socket()
1421 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001422
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001423 # `listener` runs in a thread. It sits in an accept() until
1424 # the main thread connects. Then it rudely closes the socket,
1425 # and sets Event `listener_gone` to let the main thread know
1426 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001427 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001428 s.listen(5)
1429 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001430 newsock, addr = s.accept()
1431 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001432 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001433 listener_gone.set()
1434
1435 def connector():
1436 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001437 with socket.socket() as c:
1438 c.connect((HOST, port))
1439 listener_gone.wait()
1440 try:
1441 ssl_sock = ssl.wrap_socket(c)
1442 except IOError:
1443 pass
1444 else:
1445 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001446
1447 t = threading.Thread(target=listener)
1448 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001449 try:
1450 connector()
1451 finally:
1452 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001453
Antoine Pitrou23df4832010-08-04 17:14:06 +00001454 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001455 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1456 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001457 def test_protocol_sslv2(self):
1458 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001459 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001460 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001461 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1462 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1463 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1464 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1465 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1466 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001467 # SSLv23 client with specific SSL options
1468 if no_sslv2_implies_sslv3_hello():
1469 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1470 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1471 client_options=ssl.OP_NO_SSLv2)
1472 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1473 client_options=ssl.OP_NO_SSLv3)
1474 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1475 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001476
Antoine Pitrou23df4832010-08-04 17:14:06 +00001477 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001478 def test_protocol_sslv23(self):
1479 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001480 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001481 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001482 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1483 try:
1484 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1485 except (ssl.SSLError, socket.error) as x:
1486 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1487 if support.verbose:
1488 sys.stdout.write(
1489 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1490 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1492 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1493 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001494
Antoine Pitrou480a1242010-04-28 21:37:09 +00001495 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1496 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1497 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001498
Antoine Pitrou480a1242010-04-28 21:37:09 +00001499 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1500 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1501 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001502
Antoine Pitroub5218772010-05-21 09:56:06 +00001503 # Server with specific SSL options
1504 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1505 server_options=ssl.OP_NO_SSLv3)
1506 # Will choose TLSv1
1507 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1508 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1509 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1510 server_options=ssl.OP_NO_TLSv1)
1511
1512
Antoine Pitrou23df4832010-08-04 17:14:06 +00001513 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001514 def test_protocol_sslv3(self):
1515 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001516 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001517 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001518 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1519 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1520 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001521 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1522 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001523 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1524 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001525 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001526 if no_sslv2_implies_sslv3_hello():
1527 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1528 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1529 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530
Antoine Pitrou23df4832010-08-04 17:14:06 +00001531 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001532 def test_protocol_tlsv1(self):
1533 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001534 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001535 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001536 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1537 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1538 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001539 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1540 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001541 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001542 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1543 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001544
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 def test_starttls(self):
1546 """Switching from clear text to encrypted and back again."""
1547 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 +00001548
Trent Nelson78520002008-04-10 20:54:35 +00001549 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001550 ssl_version=ssl.PROTOCOL_TLSv1,
1551 starttls_server=True,
1552 chatty=True,
1553 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001554 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001555 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001556 s = socket.socket()
1557 s.setblocking(1)
1558 s.connect((HOST, server.port))
1559 if support.verbose:
1560 sys.stdout.write("\n")
1561 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001562 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001563 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001564 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001565 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001566 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001567 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001568 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001569 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001570 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 msg = outdata.strip().lower()
1572 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1573 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001574 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001575 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001576 " client: read %r from server, starting TLS...\n"
1577 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001578 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1579 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001580 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1581 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001582 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001583 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001584 " client: read %r from server, ending TLS...\n"
1585 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001586 s = conn.unwrap()
1587 wrapped = False
1588 else:
1589 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001590 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001591 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001592 if support.verbose:
1593 sys.stdout.write(" client: closing connection.\n")
1594 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001595 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001596 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001597 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001598 if wrapped:
1599 conn.close()
1600 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001601 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001602
Antoine Pitrou480a1242010-04-28 21:37:09 +00001603 def test_socketserver(self):
1604 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001605 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001606 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001607 if support.verbose:
1608 sys.stdout.write('\n')
1609 with open(CERTFILE, 'rb') as f:
1610 d1 = f.read()
1611 d2 = ''
1612 # now fetch the same data from the HTTPS server
1613 url = 'https://%s:%d/%s' % (
1614 HOST, server.port, os.path.split(CERTFILE)[1])
1615 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001616 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001617 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001618 if dlen and (int(dlen) > 0):
1619 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001620 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001621 sys.stdout.write(
1622 " client: read %d bytes from remote server '%s'\n"
1623 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001624 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001625 f.close()
1626 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001627
Antoine Pitrou480a1242010-04-28 21:37:09 +00001628 def test_asyncore_server(self):
1629 """Check the example asyncore integration."""
1630 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001631
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001632 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001633 sys.stdout.write("\n")
1634
Antoine Pitrou480a1242010-04-28 21:37:09 +00001635 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001636 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001637 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001638 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001639 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001640 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001641 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001642 " client: sending %r...\n" % indata)
1643 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001644 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001645 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001646 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001647 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001648 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001649 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1650 % (outdata[:20], len(outdata),
1651 indata[:20].lower(), len(indata)))
1652 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001653 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001654 sys.stdout.write(" client: closing connection.\n")
1655 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001656 if support.verbose:
1657 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001658
Antoine Pitrou480a1242010-04-28 21:37:09 +00001659 def test_recv_send(self):
1660 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001661 if support.verbose:
1662 sys.stdout.write("\n")
1663
1664 server = ThreadedEchoServer(CERTFILE,
1665 certreqs=ssl.CERT_NONE,
1666 ssl_version=ssl.PROTOCOL_TLSv1,
1667 cacerts=CERTFILE,
1668 chatty=True,
1669 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001670 with server:
1671 s = ssl.wrap_socket(socket.socket(),
1672 server_side=False,
1673 certfile=CERTFILE,
1674 ca_certs=CERTFILE,
1675 cert_reqs=ssl.CERT_NONE,
1676 ssl_version=ssl.PROTOCOL_TLSv1)
1677 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001678 # helper methods for standardising recv* method signatures
1679 def _recv_into():
1680 b = bytearray(b"\0"*100)
1681 count = s.recv_into(b)
1682 return b[:count]
1683
1684 def _recvfrom_into():
1685 b = bytearray(b"\0"*100)
1686 count, addr = s.recvfrom_into(b)
1687 return b[:count]
1688
1689 # (name, method, whether to expect success, *args)
1690 send_methods = [
1691 ('send', s.send, True, []),
1692 ('sendto', s.sendto, False, ["some.address"]),
1693 ('sendall', s.sendall, True, []),
1694 ]
1695 recv_methods = [
1696 ('recv', s.recv, True, []),
1697 ('recvfrom', s.recvfrom, False, ["some.address"]),
1698 ('recv_into', _recv_into, True, []),
1699 ('recvfrom_into', _recvfrom_into, False, []),
1700 ]
1701 data_prefix = "PREFIX_"
1702
1703 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001704 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001705 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001706 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001707 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001708 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001709 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001710 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001711 "<<{outdata:r}>> ({nout:d}) received; "
1712 "expected <<{indata:r}>> ({nin:d})\n".format(
1713 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001714 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001715 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001716 )
1717 )
1718 except ValueError as e:
1719 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001720 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001721 "Failed to send with method <<{name:s}>>; "
1722 "expected to succeed.\n".format(name=meth_name)
1723 )
1724 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001725 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001726 "Method <<{name:s}>> failed with unexpected "
1727 "exception message: {exp:s}\n".format(
1728 name=meth_name, exp=e
1729 )
1730 )
1731
1732 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001733 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001734 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001735 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001736 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001737 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001738 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001739 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001740 "<<{outdata:r}>> ({nout:d}) received; "
1741 "expected <<{indata:r}>> ({nin:d})\n".format(
1742 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001743 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001744 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001745 )
1746 )
1747 except ValueError as e:
1748 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001749 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001750 "Failed to receive with method <<{name:s}>>; "
1751 "expected to succeed.\n".format(name=meth_name)
1752 )
1753 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001754 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001755 "Method <<{name:s}>> failed with unexpected "
1756 "exception message: {exp:s}\n".format(
1757 name=meth_name, exp=e
1758 )
1759 )
1760 # consume data
1761 s.read()
1762
Nick Coghlan513886a2011-08-28 00:00:27 +10001763 # Make sure sendmsg et al are disallowed to avoid
1764 # inadvertent disclosure of data and/or corruption
1765 # of the encrypted data stream
1766 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1767 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1768 self.assertRaises(NotImplementedError,
1769 s.recvmsg_into, bytearray(100))
1770
Antoine Pitrou480a1242010-04-28 21:37:09 +00001771 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001772 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001773
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001774 def test_handshake_timeout(self):
1775 # Issue #5103: SSL handshake must respect the socket timeout
1776 server = socket.socket(socket.AF_INET)
1777 host = "127.0.0.1"
1778 port = support.bind_port(server)
1779 started = threading.Event()
1780 finish = False
1781
1782 def serve():
1783 server.listen(5)
1784 started.set()
1785 conns = []
1786 while not finish:
1787 r, w, e = select.select([server], [], [], 0.1)
1788 if server in r:
1789 # Let the socket hang around rather than having
1790 # it closed by garbage collection.
1791 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001792 for sock in conns:
1793 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001794
1795 t = threading.Thread(target=serve)
1796 t.start()
1797 started.wait()
1798
1799 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001800 try:
1801 c = socket.socket(socket.AF_INET)
1802 c.settimeout(0.2)
1803 c.connect((host, port))
1804 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001805 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001806 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001807 finally:
1808 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001809 try:
1810 c = socket.socket(socket.AF_INET)
1811 c = ssl.wrap_socket(c)
1812 c.settimeout(0.2)
1813 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001814 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001815 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001816 finally:
1817 c.close()
1818 finally:
1819 finish = True
1820 t.join()
1821 server.close()
1822
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001823 def test_server_accept(self):
1824 # Issue #16357: accept() on a SSLSocket created through
1825 # SSLContext.wrap_socket().
1826 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1827 context.verify_mode = ssl.CERT_REQUIRED
1828 context.load_verify_locations(CERTFILE)
1829 context.load_cert_chain(CERTFILE)
1830 server = socket.socket(socket.AF_INET)
1831 host = "127.0.0.1"
1832 port = support.bind_port(server)
1833 server = context.wrap_socket(server, server_side=True)
1834
1835 evt = threading.Event()
1836 remote = None
1837 peer = None
1838 def serve():
1839 nonlocal remote, peer
1840 server.listen(5)
1841 # Block on the accept and wait on the connection to close.
1842 evt.set()
1843 remote, peer = server.accept()
1844 remote.recv(1)
1845
1846 t = threading.Thread(target=serve)
1847 t.start()
1848 # Client wait until server setup and perform a connect.
1849 evt.wait()
1850 client = context.wrap_socket(socket.socket())
1851 client.connect((host, port))
1852 client_addr = client.getsockname()
1853 client.close()
1854 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001855 remote.close()
1856 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001857 # Sanity checks.
1858 self.assertIsInstance(remote, ssl.SSLSocket)
1859 self.assertEqual(peer, client_addr)
1860
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001861 def test_default_ciphers(self):
1862 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1863 try:
1864 # Force a set of weak ciphers on our client context
1865 context.set_ciphers("DES")
1866 except ssl.SSLError:
1867 self.skipTest("no DES cipher available")
1868 with ThreadedEchoServer(CERTFILE,
1869 ssl_version=ssl.PROTOCOL_SSLv23,
1870 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001871 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001872 with self.assertRaises((OSError, ssl.SSLError)):
1873 s.connect((HOST, server.port))
1874 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1875
Antoine Pitroud6494802011-07-21 01:11:30 +02001876 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1877 "'tls-unique' channel binding not available")
1878 def test_tls_unique_channel_binding(self):
1879 """Test tls-unique channel binding."""
1880 if support.verbose:
1881 sys.stdout.write("\n")
1882
1883 server = ThreadedEchoServer(CERTFILE,
1884 certreqs=ssl.CERT_NONE,
1885 ssl_version=ssl.PROTOCOL_TLSv1,
1886 cacerts=CERTFILE,
1887 chatty=True,
1888 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001889 with server:
1890 s = ssl.wrap_socket(socket.socket(),
1891 server_side=False,
1892 certfile=CERTFILE,
1893 ca_certs=CERTFILE,
1894 cert_reqs=ssl.CERT_NONE,
1895 ssl_version=ssl.PROTOCOL_TLSv1)
1896 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001897 # get the data
1898 cb_data = s.get_channel_binding("tls-unique")
1899 if support.verbose:
1900 sys.stdout.write(" got channel binding data: {0!r}\n"
1901 .format(cb_data))
1902
1903 # check if it is sane
1904 self.assertIsNotNone(cb_data)
1905 self.assertEqual(len(cb_data), 12) # True for TLSv1
1906
1907 # and compare with the peers version
1908 s.write(b"CB tls-unique\n")
1909 peer_data_repr = s.read().strip()
1910 self.assertEqual(peer_data_repr,
1911 repr(cb_data).encode("us-ascii"))
1912 s.close()
1913
1914 # now, again
1915 s = ssl.wrap_socket(socket.socket(),
1916 server_side=False,
1917 certfile=CERTFILE,
1918 ca_certs=CERTFILE,
1919 cert_reqs=ssl.CERT_NONE,
1920 ssl_version=ssl.PROTOCOL_TLSv1)
1921 s.connect((HOST, server.port))
1922 new_cb_data = s.get_channel_binding("tls-unique")
1923 if support.verbose:
1924 sys.stdout.write(" got another channel binding data: {0!r}\n"
1925 .format(new_cb_data))
1926 # is it really unique
1927 self.assertNotEqual(cb_data, new_cb_data)
1928 self.assertIsNotNone(cb_data)
1929 self.assertEqual(len(cb_data), 12) # True for TLSv1
1930 s.write(b"CB tls-unique\n")
1931 peer_data_repr = s.read().strip()
1932 self.assertEqual(peer_data_repr,
1933 repr(new_cb_data).encode("us-ascii"))
1934 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001935
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001936 def test_compression(self):
1937 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1938 context.load_cert_chain(CERTFILE)
1939 stats = server_params_test(context, context,
1940 chatty=True, connectionchatty=True)
1941 if support.verbose:
1942 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1943 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1944
1945 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1946 "ssl.OP_NO_COMPRESSION needed for this test")
1947 def test_compression_disabled(self):
1948 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1949 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001950 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001951 stats = server_params_test(context, context,
1952 chatty=True, connectionchatty=True)
1953 self.assertIs(stats['compression'], None)
1954
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001955 def test_dh_params(self):
1956 # Check we can get a connection with ephemeral Diffie-Hellman
1957 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1958 context.load_cert_chain(CERTFILE)
1959 context.load_dh_params(DHFILE)
1960 context.set_ciphers("kEDH")
1961 stats = server_params_test(context, context,
1962 chatty=True, connectionchatty=True)
1963 cipher = stats["cipher"][0]
1964 parts = cipher.split("-")
1965 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1966 self.fail("Non-DH cipher: " + cipher[0])
1967
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001968 def test_selected_npn_protocol(self):
1969 # selected_npn_protocol() is None unless NPN is used
1970 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1971 context.load_cert_chain(CERTFILE)
1972 stats = server_params_test(context, context,
1973 chatty=True, connectionchatty=True)
1974 self.assertIs(stats['client_npn_protocol'], None)
1975
1976 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1977 def test_npn_protocols(self):
1978 server_protocols = ['http/1.1', 'spdy/2']
1979 protocol_tests = [
1980 (['http/1.1', 'spdy/2'], 'http/1.1'),
1981 (['spdy/2', 'http/1.1'], 'http/1.1'),
1982 (['spdy/2', 'test'], 'spdy/2'),
1983 (['abc', 'def'], 'abc')
1984 ]
1985 for client_protocols, expected in protocol_tests:
1986 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1987 server_context.load_cert_chain(CERTFILE)
1988 server_context.set_npn_protocols(server_protocols)
1989 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1990 client_context.load_cert_chain(CERTFILE)
1991 client_context.set_npn_protocols(client_protocols)
1992 stats = server_params_test(client_context, server_context,
1993 chatty=True, connectionchatty=True)
1994
1995 msg = "failed trying %s (s) and %s (c).\n" \
1996 "was expecting %s, but got %%s from the %%s" \
1997 % (str(server_protocols), str(client_protocols),
1998 str(expected))
1999 client_result = stats['client_npn_protocol']
2000 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2001 server_result = stats['server_npn_protocols'][-1] \
2002 if len(stats['server_npn_protocols']) else 'nothing'
2003 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2004
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002005
Thomas Woutersed03b412007-08-28 21:37:11 +00002006def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002007 if support.verbose:
2008 plats = {
2009 'Linux': platform.linux_distribution,
2010 'Mac': platform.mac_ver,
2011 'Windows': platform.win32_ver,
2012 }
2013 for name, func in plats.items():
2014 plat = func()
2015 if plat and plat[0]:
2016 plat = '%s %r' % (name, plat)
2017 break
2018 else:
2019 plat = repr(platform.platform())
2020 print("test_ssl: testing with %r %r" %
2021 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2022 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002023 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002024
Antoine Pitrou152efa22010-05-16 18:19:27 +00002025 for filename in [
2026 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2027 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2028 BADCERT, BADKEY, EMPTYCERT]:
2029 if not os.path.exists(filename):
2030 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002031
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002032 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002033
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002034 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002035 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002036
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002037 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002038 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002039 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002040 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002041
Antoine Pitrou480a1242010-04-28 21:37:09 +00002042 try:
2043 support.run_unittest(*tests)
2044 finally:
2045 if _have_threads:
2046 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002047
2048if __name__ == "__main__":
2049 test_main()