blob: 0a6af5e0cb51ce33efe8a3090ba11cc92804ea34 [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)
211 del ss
212 self.assertEqual(wr(), None)
213
Antoine Pitroua468adc2010-09-14 14:43:44 +0000214 def test_wrapped_unconnected(self):
215 # Methods on an unconnected SSLSocket propagate the original
216 # socket.error raise by the underlying socket object.
217 s = socket.socket(socket.AF_INET)
218 ss = ssl.wrap_socket(s)
219 self.assertRaises(socket.error, ss.recv, 1)
220 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
221 self.assertRaises(socket.error, ss.recvfrom, 1)
222 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
223 self.assertRaises(socket.error, ss.send, b'x')
224 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
225
Antoine Pitrou40f08742010-04-24 22:04:40 +0000226 def test_timeout(self):
227 # Issue #8524: when creating an SSL socket, the timeout of the
228 # original socket should be retained.
229 for timeout in (None, 0.0, 5.0):
230 s = socket.socket(socket.AF_INET)
231 s.settimeout(timeout)
232 ss = ssl.wrap_socket(s)
233 self.assertEqual(timeout, ss.gettimeout())
234
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000235 def test_errors(self):
236 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000237 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000238 "certfile must be specified",
239 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000240 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000241 "certfile must be specified for server-side operations",
242 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000243 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000244 "certfile must be specified for server-side operations",
245 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000246 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000247 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000248 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000249 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000250 with socket.socket() as sock:
251 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000252 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000253 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000254 with socket.socket() as sock:
255 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000256 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000257 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000258 with socket.socket() as sock:
259 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000260 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000261
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000262 def test_match_hostname(self):
263 def ok(cert, hostname):
264 ssl.match_hostname(cert, hostname)
265 def fail(cert, hostname):
266 self.assertRaises(ssl.CertificateError,
267 ssl.match_hostname, cert, hostname)
268
269 cert = {'subject': ((('commonName', 'example.com'),),)}
270 ok(cert, 'example.com')
271 ok(cert, 'ExAmple.cOm')
272 fail(cert, 'www.example.com')
273 fail(cert, '.example.com')
274 fail(cert, 'example.org')
275 fail(cert, 'exampleXcom')
276
277 cert = {'subject': ((('commonName', '*.a.com'),),)}
278 ok(cert, 'foo.a.com')
279 fail(cert, 'bar.foo.a.com')
280 fail(cert, 'a.com')
281 fail(cert, 'Xa.com')
282 fail(cert, '.a.com')
283
284 cert = {'subject': ((('commonName', 'a.*.com'),),)}
285 ok(cert, 'a.foo.com')
286 fail(cert, 'a..com')
287 fail(cert, 'a.com')
288
289 cert = {'subject': ((('commonName', 'f*.com'),),)}
290 ok(cert, 'foo.com')
291 ok(cert, 'f.com')
292 fail(cert, 'bar.com')
293 fail(cert, 'foo.a.com')
294 fail(cert, 'bar.foo.com')
295
296 # Slightly fake real-world example
297 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
298 'subject': ((('commonName', 'linuxfrz.org'),),),
299 'subjectAltName': (('DNS', 'linuxfr.org'),
300 ('DNS', 'linuxfr.com'),
301 ('othername', '<unsupported>'))}
302 ok(cert, 'linuxfr.org')
303 ok(cert, 'linuxfr.com')
304 # Not a "DNS" entry
305 fail(cert, '<unsupported>')
306 # When there is a subjectAltName, commonName isn't used
307 fail(cert, 'linuxfrz.org')
308
309 # A pristine real-world example
310 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
311 'subject': ((('countryName', 'US'),),
312 (('stateOrProvinceName', 'California'),),
313 (('localityName', 'Mountain View'),),
314 (('organizationName', 'Google Inc'),),
315 (('commonName', 'mail.google.com'),))}
316 ok(cert, 'mail.google.com')
317 fail(cert, 'gmail.com')
318 # Only commonName is considered
319 fail(cert, 'California')
320
321 # Neither commonName nor subjectAltName
322 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
323 'subject': ((('countryName', 'US'),),
324 (('stateOrProvinceName', 'California'),),
325 (('localityName', 'Mountain View'),),
326 (('organizationName', 'Google Inc'),))}
327 fail(cert, 'mail.google.com')
328
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200329 # No DNS entry in subjectAltName but a commonName
330 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
331 'subject': ((('countryName', 'US'),),
332 (('stateOrProvinceName', 'California'),),
333 (('localityName', 'Mountain View'),),
334 (('commonName', 'mail.google.com'),)),
335 'subjectAltName': (('othername', 'blabla'), )}
336 ok(cert, 'mail.google.com')
337
338 # No DNS entry subjectAltName and no commonName
339 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
340 'subject': ((('countryName', 'US'),),
341 (('stateOrProvinceName', 'California'),),
342 (('localityName', 'Mountain View'),),
343 (('organizationName', 'Google Inc'),)),
344 'subjectAltName': (('othername', 'blabla'),)}
345 fail(cert, 'google.com')
346
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000347 # Empty cert / no cert
348 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
349 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
350
Antoine Pitroud5323212010-10-22 18:19:07 +0000351 def test_server_side(self):
352 # server_hostname doesn't work for server sockets
353 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000354 with socket.socket() as sock:
355 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
356 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000357
Antoine Pitroud6494802011-07-21 01:11:30 +0200358 def test_unknown_channel_binding(self):
359 # should raise ValueError for unknown type
360 s = socket.socket(socket.AF_INET)
361 ss = ssl.wrap_socket(s)
362 with self.assertRaises(ValueError):
363 ss.get_channel_binding("unknown-type")
364
365 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
366 "'tls-unique' channel binding not available")
367 def test_tls_unique_channel_binding(self):
368 # unconnected should return None for known type
369 s = socket.socket(socket.AF_INET)
370 ss = ssl.wrap_socket(s)
371 self.assertIsNone(ss.get_channel_binding("tls-unique"))
372 # the same for server-side
373 s = socket.socket(socket.AF_INET)
374 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
375 self.assertIsNone(ss.get_channel_binding("tls-unique"))
376
Antoine Pitrou152efa22010-05-16 18:19:27 +0000377class ContextTests(unittest.TestCase):
378
Antoine Pitrou23df4832010-08-04 17:14:06 +0000379 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000380 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200381 if hasattr(ssl, 'PROTOCOL_SSLv2'):
382 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000383 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
384 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
385 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
386 self.assertRaises(TypeError, ssl.SSLContext)
387 self.assertRaises(ValueError, ssl.SSLContext, -1)
388 self.assertRaises(ValueError, ssl.SSLContext, 42)
389
Antoine Pitrou23df4832010-08-04 17:14:06 +0000390 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000391 def test_protocol(self):
392 for proto in PROTOCOLS:
393 ctx = ssl.SSLContext(proto)
394 self.assertEqual(ctx.protocol, proto)
395
396 def test_ciphers(self):
397 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
398 ctx.set_ciphers("ALL")
399 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000400 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000401 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000402
Antoine Pitrou23df4832010-08-04 17:14:06 +0000403 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000404 def test_options(self):
405 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
406 # OP_ALL is the default value
407 self.assertEqual(ssl.OP_ALL, ctx.options)
408 ctx.options |= ssl.OP_NO_SSLv2
409 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
410 ctx.options)
411 ctx.options |= ssl.OP_NO_SSLv3
412 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
413 ctx.options)
414 if can_clear_options():
415 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
416 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
417 ctx.options)
418 ctx.options = 0
419 self.assertEqual(0, ctx.options)
420 else:
421 with self.assertRaises(ValueError):
422 ctx.options = 0
423
Antoine Pitrou152efa22010-05-16 18:19:27 +0000424 def test_verify(self):
425 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
426 # Default value
427 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
428 ctx.verify_mode = ssl.CERT_OPTIONAL
429 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
430 ctx.verify_mode = ssl.CERT_REQUIRED
431 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
432 ctx.verify_mode = ssl.CERT_NONE
433 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
434 with self.assertRaises(TypeError):
435 ctx.verify_mode = None
436 with self.assertRaises(ValueError):
437 ctx.verify_mode = 42
438
439 def test_load_cert_chain(self):
440 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
441 # Combined key and cert in a single file
442 ctx.load_cert_chain(CERTFILE)
443 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
444 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000445 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000446 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000447 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000448 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000449 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000450 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000451 ctx.load_cert_chain(EMPTYCERT)
452 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000453 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000454 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
455 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
456 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
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(ONLYCERT)
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(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000461 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000462 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
463 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000464 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000465 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000466 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200467 # Password protected key and cert
468 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
469 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
470 ctx.load_cert_chain(CERTFILE_PROTECTED,
471 password=bytearray(KEY_PASSWORD.encode()))
472 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
473 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
474 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
475 bytearray(KEY_PASSWORD.encode()))
476 with self.assertRaisesRegex(TypeError, "should be a string"):
477 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
478 with self.assertRaises(ssl.SSLError):
479 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
480 with self.assertRaisesRegex(ValueError, "cannot be longer"):
481 # openssl has a fixed limit on the password buffer.
482 # PEM_BUFSIZE is generally set to 1kb.
483 # Return a string larger than this.
484 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
485 # Password callback
486 def getpass_unicode():
487 return KEY_PASSWORD
488 def getpass_bytes():
489 return KEY_PASSWORD.encode()
490 def getpass_bytearray():
491 return bytearray(KEY_PASSWORD.encode())
492 def getpass_badpass():
493 return "badpass"
494 def getpass_huge():
495 return b'a' * (1024 * 1024)
496 def getpass_bad_type():
497 return 9
498 def getpass_exception():
499 raise Exception('getpass error')
500 class GetPassCallable:
501 def __call__(self):
502 return KEY_PASSWORD
503 def getpass(self):
504 return KEY_PASSWORD
505 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
506 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
507 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
508 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
509 ctx.load_cert_chain(CERTFILE_PROTECTED,
510 password=GetPassCallable().getpass)
511 with self.assertRaises(ssl.SSLError):
512 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
513 with self.assertRaisesRegex(ValueError, "cannot be longer"):
514 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
515 with self.assertRaisesRegex(TypeError, "must return a string"):
516 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
517 with self.assertRaisesRegex(Exception, "getpass error"):
518 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
519 # Make sure the password function isn't called if it isn't needed
520 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000521
522 def test_load_verify_locations(self):
523 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
524 ctx.load_verify_locations(CERTFILE)
525 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
526 ctx.load_verify_locations(BYTES_CERTFILE)
527 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
528 self.assertRaises(TypeError, ctx.load_verify_locations)
529 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000530 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000531 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000532 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000533 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000534 ctx.load_verify_locations(BADCERT)
535 ctx.load_verify_locations(CERTFILE, CAPATH)
536 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
537
Victor Stinner80f75e62011-01-29 11:31:20 +0000538 # Issue #10989: crash if the second argument type is invalid
539 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
540
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100541 def test_load_dh_params(self):
542 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
543 ctx.load_dh_params(DHFILE)
544 if os.name != 'nt':
545 ctx.load_dh_params(BYTES_DHFILE)
546 self.assertRaises(TypeError, ctx.load_dh_params)
547 self.assertRaises(TypeError, ctx.load_dh_params, None)
548 with self.assertRaises(FileNotFoundError) as cm:
549 ctx.load_dh_params(WRONGCERT)
550 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200551 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100552 ctx.load_dh_params(CERTFILE)
553
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000554 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000555 def test_session_stats(self):
556 for proto in PROTOCOLS:
557 ctx = ssl.SSLContext(proto)
558 self.assertEqual(ctx.session_stats(), {
559 'number': 0,
560 'connect': 0,
561 'connect_good': 0,
562 'connect_renegotiate': 0,
563 'accept': 0,
564 'accept_good': 0,
565 'accept_renegotiate': 0,
566 'hits': 0,
567 'misses': 0,
568 'timeouts': 0,
569 'cache_full': 0,
570 })
571
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000572 def test_set_default_verify_paths(self):
573 # There's not much we can do to test that it acts as expected,
574 # so just check it doesn't crash or raise an exception.
575 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
576 ctx.set_default_verify_paths()
577
Antoine Pitrou501da612011-12-21 09:27:41 +0100578 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100579 def test_set_ecdh_curve(self):
580 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
581 ctx.set_ecdh_curve("prime256v1")
582 ctx.set_ecdh_curve(b"prime256v1")
583 self.assertRaises(TypeError, ctx.set_ecdh_curve)
584 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
585 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
586 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
587
Antoine Pitrou152efa22010-05-16 18:19:27 +0000588
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200589class SSLErrorTests(unittest.TestCase):
590
591 def test_str(self):
592 # The str() of a SSLError doesn't include the errno
593 e = ssl.SSLError(1, "foo")
594 self.assertEqual(str(e), "foo")
595 self.assertEqual(e.errno, 1)
596 # Same for a subclass
597 e = ssl.SSLZeroReturnError(1, "foo")
598 self.assertEqual(str(e), "foo")
599 self.assertEqual(e.errno, 1)
600
601 def test_lib_reason(self):
602 # Test the library and reason attributes
603 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
604 with self.assertRaises(ssl.SSLError) as cm:
605 ctx.load_dh_params(CERTFILE)
606 self.assertEqual(cm.exception.library, 'PEM')
607 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
608 s = str(cm.exception)
609 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
610
611 def test_subclass(self):
612 # Check that the appropriate SSLError subclass is raised
613 # (this only tests one of them)
614 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
615 with socket.socket() as s:
616 s.bind(("127.0.0.1", 0))
617 s.listen(5)
618 with socket.socket() as c:
619 c.connect(s.getsockname())
620 c.setblocking(False)
621 c = ctx.wrap_socket(c, False, do_handshake_on_connect=False)
622 with self.assertRaises(ssl.SSLWantReadError) as cm:
623 c.do_handshake()
624 s = str(cm.exception)
625 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
626 # For compatibility
627 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
628
629
Bill Janssen6e027db2007-11-15 22:23:56 +0000630class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000631
Antoine Pitrou480a1242010-04-28 21:37:09 +0000632 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000633 with support.transient_internet("svn.python.org"):
634 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
635 cert_reqs=ssl.CERT_NONE)
636 try:
637 s.connect(("svn.python.org", 443))
638 self.assertEqual({}, s.getpeercert())
639 finally:
640 s.close()
641
642 # this should fail because we have no verification certs
643 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
644 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000645 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
646 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000647 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000648
Antoine Pitrou350c7222010-09-09 13:31:46 +0000649 # this should succeed because we specify the root cert
650 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
651 cert_reqs=ssl.CERT_REQUIRED,
652 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
653 try:
654 s.connect(("svn.python.org", 443))
655 self.assertTrue(s.getpeercert())
656 finally:
657 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000658
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000659 def test_connect_ex(self):
660 # Issue #11326: check connect_ex() implementation
661 with support.transient_internet("svn.python.org"):
662 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
663 cert_reqs=ssl.CERT_REQUIRED,
664 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
665 try:
666 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
667 self.assertTrue(s.getpeercert())
668 finally:
669 s.close()
670
671 def test_non_blocking_connect_ex(self):
672 # Issue #11326: non-blocking connect_ex() should allow handshake
673 # to proceed after the socket gets ready.
674 with support.transient_internet("svn.python.org"):
675 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
676 cert_reqs=ssl.CERT_REQUIRED,
677 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
678 do_handshake_on_connect=False)
679 try:
680 s.setblocking(False)
681 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000682 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
683 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000684 # Wait for connect to finish
685 select.select([], [s], [], 5.0)
686 # Non-blocking handshake
687 while True:
688 try:
689 s.do_handshake()
690 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200691 except ssl.SSLWantReadError:
692 select.select([s], [], [], 5.0)
693 except ssl.SSLWantWriteError:
694 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000695 # SSL established
696 self.assertTrue(s.getpeercert())
697 finally:
698 s.close()
699
Antoine Pitroub4410db2011-05-18 18:51:06 +0200700 def test_timeout_connect_ex(self):
701 # Issue #12065: on a timeout, connect_ex() should return the original
702 # errno (mimicking the behaviour of non-SSL sockets).
703 with support.transient_internet("svn.python.org"):
704 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
705 cert_reqs=ssl.CERT_REQUIRED,
706 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
707 do_handshake_on_connect=False)
708 try:
709 s.settimeout(0.0000001)
710 rc = s.connect_ex(('svn.python.org', 443))
711 if rc == 0:
712 self.skipTest("svn.python.org responded too quickly")
713 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
714 finally:
715 s.close()
716
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100717 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100718 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100719 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
720 cert_reqs=ssl.CERT_REQUIRED,
721 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
722 try:
723 self.assertEqual(errno.ECONNREFUSED,
724 s.connect_ex(("svn.python.org", 444)))
725 finally:
726 s.close()
727
Antoine Pitrou152efa22010-05-16 18:19:27 +0000728 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000729 with support.transient_internet("svn.python.org"):
730 # Same as test_connect, but with a separately created context
731 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
732 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
733 s.connect(("svn.python.org", 443))
734 try:
735 self.assertEqual({}, s.getpeercert())
736 finally:
737 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000738 # Same with a server hostname
739 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
740 server_hostname="svn.python.org")
741 if ssl.HAS_SNI:
742 s.connect(("svn.python.org", 443))
743 s.close()
744 else:
745 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000746 # This should fail because we have no verification certs
747 ctx.verify_mode = ssl.CERT_REQUIRED
748 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000749 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000750 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000751 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000752 # This should succeed because we specify the root cert
753 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
754 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
755 s.connect(("svn.python.org", 443))
756 try:
757 cert = s.getpeercert()
758 self.assertTrue(cert)
759 finally:
760 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000761
762 def test_connect_capath(self):
763 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000764 # NOTE: the subject hashing algorithm has been changed between
765 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
766 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000767 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000768 with support.transient_internet("svn.python.org"):
769 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
770 ctx.verify_mode = ssl.CERT_REQUIRED
771 ctx.load_verify_locations(capath=CAPATH)
772 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
773 s.connect(("svn.python.org", 443))
774 try:
775 cert = s.getpeercert()
776 self.assertTrue(cert)
777 finally:
778 s.close()
779 # Same with a bytes `capath` argument
780 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
781 ctx.verify_mode = ssl.CERT_REQUIRED
782 ctx.load_verify_locations(capath=BYTES_CAPATH)
783 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
784 s.connect(("svn.python.org", 443))
785 try:
786 cert = s.getpeercert()
787 self.assertTrue(cert)
788 finally:
789 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000790
Antoine Pitroue3220242010-04-24 11:13:53 +0000791 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
792 def test_makefile_close(self):
793 # Issue #5238: creating a file-like object with makefile() shouldn't
794 # delay closing the underlying "real socket" (here tested with its
795 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000796 with support.transient_internet("svn.python.org"):
797 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
798 ss.connect(("svn.python.org", 443))
799 fd = ss.fileno()
800 f = ss.makefile()
801 f.close()
802 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000803 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000804 # Closing the SSL socket should close the fd too
805 ss.close()
806 gc.collect()
807 with self.assertRaises(OSError) as e:
808 os.read(fd, 0)
809 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000810
Antoine Pitrou480a1242010-04-28 21:37:09 +0000811 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000812 with support.transient_internet("svn.python.org"):
813 s = socket.socket(socket.AF_INET)
814 s.connect(("svn.python.org", 443))
815 s.setblocking(False)
816 s = ssl.wrap_socket(s,
817 cert_reqs=ssl.CERT_NONE,
818 do_handshake_on_connect=False)
819 count = 0
820 while True:
821 try:
822 count += 1
823 s.do_handshake()
824 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200825 except ssl.SSLWantReadError:
826 select.select([s], [], [])
827 except ssl.SSLWantWriteError:
828 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000829 s.close()
830 if support.verbose:
831 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000832
Antoine Pitrou480a1242010-04-28 21:37:09 +0000833 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200834 def _test_get_server_certificate(host, port, cert=None):
835 with support.transient_internet(host):
836 pem = ssl.get_server_certificate((host, port))
837 if not pem:
838 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200839
Antoine Pitrou15399c32011-04-28 19:23:55 +0200840 try:
841 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
842 except ssl.SSLError as x:
843 #should fail
844 if support.verbose:
845 sys.stdout.write("%s\n" % x)
846 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200847 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
848
Antoine Pitrou15399c32011-04-28 19:23:55 +0200849 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
850 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200851 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000852 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200853 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000854
Antoine Pitrou15399c32011-04-28 19:23:55 +0200855 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
856 if support.IPV6_ENABLED:
857 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000858
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000859 def test_ciphers(self):
860 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000861 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000862 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000863 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000864 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000865 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
866 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
867 s.connect(remote)
868 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000869 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000870 with socket.socket(socket.AF_INET) as sock:
871 s = ssl.wrap_socket(sock,
872 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
873 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000874
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000875 def test_algorithms(self):
876 # Issue #8484: all algorithms should be available when verifying a
877 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000878 # SHA256 was added in OpenSSL 0.9.8
879 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
880 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200881 # sha256.tbs-internet.com needs SNI to use the correct certificate
882 if not ssl.HAS_SNI:
883 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000884 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
885 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000886 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000887 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200888 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
889 ctx.verify_mode = ssl.CERT_REQUIRED
890 ctx.load_verify_locations(sha256_cert)
891 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
892 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000893 try:
894 s.connect(remote)
895 if support.verbose:
896 sys.stdout.write("\nCipher with %r is %r\n" %
897 (remote, s.cipher()))
898 sys.stdout.write("Certificate is:\n%s\n" %
899 pprint.pformat(s.getpeercert()))
900 finally:
901 s.close()
902
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903
904try:
905 import threading
906except ImportError:
907 _have_threads = False
908else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 _have_threads = True
910
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000911 from test.ssl_servers import make_https_server
912
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000913 class ThreadedEchoServer(threading.Thread):
914
915 class ConnectionHandler(threading.Thread):
916
917 """A mildly complicated class, because we want it to work both
918 with and without the SSL wrapper around the socket connection, so
919 that we can test the STARTTLS functionality."""
920
Bill Janssen6e027db2007-11-15 22:23:56 +0000921 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 self.server = server
923 self.running = False
924 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000925 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000926 self.sock.setblocking(1)
927 self.sslconn = None
928 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000929 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930
Antoine Pitrou480a1242010-04-28 21:37:09 +0000931 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000932 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000933 self.sslconn = self.server.context.wrap_socket(
934 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100935 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100936 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000937 # XXX Various errors can have happened here, for example
938 # a mismatching protocol version, an invalid certificate,
939 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100940 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000942 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000943 self.running = False
944 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000945 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000946 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000948 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000950 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
952 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000953 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000954 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
955 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000956 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000957 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100958 sys.stdout.write(" server: selected protocol is now "
959 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960 return True
961
962 def read(self):
963 if self.sslconn:
964 return self.sslconn.read()
965 else:
966 return self.sock.recv(1024)
967
968 def write(self, bytes):
969 if self.sslconn:
970 return self.sslconn.write(bytes)
971 else:
972 return self.sock.send(bytes)
973
974 def close(self):
975 if self.sslconn:
976 self.sslconn.close()
977 else:
978 self.sock.close()
979
Antoine Pitrou480a1242010-04-28 21:37:09 +0000980 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 self.running = True
982 if not self.server.starttls_server:
983 if not self.wrap_conn():
984 return
985 while self.running:
986 try:
987 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000988 stripped = msg.strip()
989 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 # eof, so quit this handler
991 self.running = False
992 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000993 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000994 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995 sys.stdout.write(" server: client closed connection\n")
996 self.close()
997 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000998 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000999 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001000 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001002 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 if not self.wrap_conn():
1004 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001005 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001006 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001007 if support.verbose and self.server.connectionchatty:
1008 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001009 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001010 self.sock = self.sslconn.unwrap()
1011 self.sslconn = None
1012 if support.verbose and self.server.connectionchatty:
1013 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001014 elif stripped == b'CB tls-unique':
1015 if support.verbose and self.server.connectionchatty:
1016 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1017 data = self.sslconn.get_channel_binding("tls-unique")
1018 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001019 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001020 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001021 self.server.connectionchatty):
1022 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001023 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1024 % (msg, ctype, msg.lower(), ctype))
1025 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001026 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027 if self.server.chatty:
1028 handle_error("Test server failure:\n")
1029 self.close()
1030 self.running = False
1031 # normally, we'd just stop here, but for the test
1032 # harness, we want to stop the server
1033 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034
Antoine Pitroub5218772010-05-21 09:56:06 +00001035 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001036 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001037 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001038 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001039 if context:
1040 self.context = context
1041 else:
1042 self.context = ssl.SSLContext(ssl_version
1043 if ssl_version is not None
1044 else ssl.PROTOCOL_TLSv1)
1045 self.context.verify_mode = (certreqs if certreqs is not None
1046 else ssl.CERT_NONE)
1047 if cacerts:
1048 self.context.load_verify_locations(cacerts)
1049 if certificate:
1050 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001051 if npn_protocols:
1052 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001053 if ciphers:
1054 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001055 self.chatty = chatty
1056 self.connectionchatty = connectionchatty
1057 self.starttls_server = starttls_server
1058 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001059 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001060 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001061 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001062 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001063 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001064 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001065 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001067 def __enter__(self):
1068 self.start(threading.Event())
1069 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001070 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001071
1072 def __exit__(self, *args):
1073 self.stop()
1074 self.join()
1075
Antoine Pitrou480a1242010-04-28 21:37:09 +00001076 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077 self.flag = flag
1078 threading.Thread.start(self)
1079
Antoine Pitrou480a1242010-04-28 21:37:09 +00001080 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001081 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001082 self.sock.listen(5)
1083 self.active = True
1084 if self.flag:
1085 # signal an event
1086 self.flag.set()
1087 while self.active:
1088 try:
1089 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001090 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001091 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001092 + repr(connaddr) + '\n')
1093 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001094 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001095 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001096 except socket.timeout:
1097 pass
1098 except KeyboardInterrupt:
1099 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001100 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001101
Antoine Pitrou480a1242010-04-28 21:37:09 +00001102 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001103 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001104
Bill Janssen54cc54c2007-12-14 22:08:56 +00001105 class AsyncoreEchoServer(threading.Thread):
1106
1107 # this one's based on asyncore.dispatcher
1108
1109 class EchoServer (asyncore.dispatcher):
1110
1111 class ConnectionHandler (asyncore.dispatcher_with_send):
1112
1113 def __init__(self, conn, certfile):
1114 self.socket = ssl.wrap_socket(conn, server_side=True,
1115 certfile=certfile,
1116 do_handshake_on_connect=False)
1117 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001118 self._ssl_accepting = True
1119 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001120
1121 def readable(self):
1122 if isinstance(self.socket, ssl.SSLSocket):
1123 while self.socket.pending() > 0:
1124 self.handle_read_event()
1125 return True
1126
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001127 def _do_ssl_handshake(self):
1128 try:
1129 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001130 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1131 return
1132 except ssl.SSLEOFError:
1133 return self.handle_close()
1134 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001135 raise
1136 except socket.error as err:
1137 if err.args[0] == errno.ECONNABORTED:
1138 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001139 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001140 self._ssl_accepting = False
1141
1142 def handle_read(self):
1143 if self._ssl_accepting:
1144 self._do_ssl_handshake()
1145 else:
1146 data = self.recv(1024)
1147 if support.verbose:
1148 sys.stdout.write(" server: read %s from client\n" % repr(data))
1149 if not data:
1150 self.close()
1151 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001153
1154 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001155 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001156 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001157 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1158
1159 def handle_error(self):
1160 raise
1161
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001162 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001163 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001164 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1165 self.port = support.bind_port(sock, '')
1166 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001167 self.listen(5)
1168
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001169 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001170 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001171 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1172 self.ConnectionHandler(sock_obj, self.certfile)
1173
1174 def handle_error(self):
1175 raise
1176
Trent Nelson78520002008-04-10 20:54:35 +00001177 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001178 self.flag = None
1179 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001180 self.server = self.EchoServer(certfile)
1181 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001182 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001183 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001184
1185 def __str__(self):
1186 return "<%s %s>" % (self.__class__.__name__, self.server)
1187
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001188 def __enter__(self):
1189 self.start(threading.Event())
1190 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001191 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001192
1193 def __exit__(self, *args):
1194 if support.verbose:
1195 sys.stdout.write(" cleanup: stopping server.\n")
1196 self.stop()
1197 if support.verbose:
1198 sys.stdout.write(" cleanup: joining server thread.\n")
1199 self.join()
1200 if support.verbose:
1201 sys.stdout.write(" cleanup: successfully joined.\n")
1202
Bill Janssen54cc54c2007-12-14 22:08:56 +00001203 def start (self, flag=None):
1204 self.flag = flag
1205 threading.Thread.start(self)
1206
Antoine Pitrou480a1242010-04-28 21:37:09 +00001207 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001208 self.active = True
1209 if self.flag:
1210 self.flag.set()
1211 while self.active:
1212 try:
1213 asyncore.loop(1)
1214 except:
1215 pass
1216
Antoine Pitrou480a1242010-04-28 21:37:09 +00001217 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001218 self.active = False
1219 self.server.close()
1220
Antoine Pitrou480a1242010-04-28 21:37:09 +00001221 def bad_cert_test(certfile):
1222 """
1223 Launch a server with CERT_REQUIRED, and check that trying to
1224 connect to it with the given client certificate fails.
1225 """
Trent Nelson78520002008-04-10 20:54:35 +00001226 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001227 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001228 cacerts=CERTFILE, chatty=False,
1229 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001230 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001231 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001232 with socket.socket() as sock:
1233 s = ssl.wrap_socket(sock,
1234 certfile=certfile,
1235 ssl_version=ssl.PROTOCOL_TLSv1)
1236 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001237 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001238 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001239 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001240 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001241 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001242 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001243 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001244 if x.errno != errno.ENOENT:
1245 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001246 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001247 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001248 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001249 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001250
Antoine Pitroub5218772010-05-21 09:56:06 +00001251 def server_params_test(client_context, server_context, indata=b"FOO\n",
1252 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001253 """
1254 Launch a server, connect a client to it and try various reads
1255 and writes.
1256 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001257 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001258 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001259 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001260 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001261 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001262 with client_context.wrap_socket(socket.socket()) as s:
1263 s.connect((HOST, server.port))
1264 for arg in [indata, bytearray(indata), memoryview(indata)]:
1265 if connectionchatty:
1266 if support.verbose:
1267 sys.stdout.write(
1268 " client: sending %r...\n" % indata)
1269 s.write(arg)
1270 outdata = s.read()
1271 if connectionchatty:
1272 if support.verbose:
1273 sys.stdout.write(" client: read %r\n" % outdata)
1274 if outdata != indata.lower():
1275 raise AssertionError(
1276 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1277 % (outdata[:20], len(outdata),
1278 indata[:20].lower(), len(indata)))
1279 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001280 if connectionchatty:
1281 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001282 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001283 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001284 'compression': s.compression(),
1285 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001286 'client_npn_protocol': s.selected_npn_protocol()
1287 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001288 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001289 stats['server_npn_protocols'] = server.selected_protocols
1290 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001291
Antoine Pitroub5218772010-05-21 09:56:06 +00001292 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1293 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001294 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001295 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001296 certtype = {
1297 ssl.CERT_NONE: "CERT_NONE",
1298 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1299 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1300 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001301 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001302 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001303 sys.stdout.write(formatstr %
1304 (ssl.get_protocol_name(client_protocol),
1305 ssl.get_protocol_name(server_protocol),
1306 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001307 client_context = ssl.SSLContext(client_protocol)
1308 client_context.options = ssl.OP_ALL | client_options
1309 server_context = ssl.SSLContext(server_protocol)
1310 server_context.options = ssl.OP_ALL | server_options
1311 for ctx in (client_context, server_context):
1312 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001313 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1314 # will send an SSLv3 hello (rather than SSLv2) starting from
1315 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001316 ctx.set_ciphers("ALL")
1317 ctx.load_cert_chain(CERTFILE)
1318 ctx.load_verify_locations(CERTFILE)
1319 try:
1320 server_params_test(client_context, server_context,
1321 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001322 # Protocol mismatch can result in either an SSLError, or a
1323 # "Connection reset by peer" error.
1324 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001325 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001326 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001327 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001328 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001329 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001330 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001331 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001332 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001333 "Client protocol %s succeeded with server protocol %s!"
1334 % (ssl.get_protocol_name(client_protocol),
1335 ssl.get_protocol_name(server_protocol)))
1336
1337
Bill Janssen6e027db2007-11-15 22:23:56 +00001338 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001339
Antoine Pitrou23df4832010-08-04 17:14:06 +00001340 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 def test_echo(self):
1342 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001343 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001344 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001345 for protocol in PROTOCOLS:
1346 context = ssl.SSLContext(protocol)
1347 context.load_cert_chain(CERTFILE)
1348 server_params_test(context, context,
1349 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001350
Antoine Pitrou480a1242010-04-28 21:37:09 +00001351 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001352 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001353 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001354 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1355 context.verify_mode = ssl.CERT_REQUIRED
1356 context.load_verify_locations(CERTFILE)
1357 context.load_cert_chain(CERTFILE)
1358 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001359 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001360 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001361 s.connect((HOST, server.port))
1362 cert = s.getpeercert()
1363 self.assertTrue(cert, "Can't get peer certificate.")
1364 cipher = s.cipher()
1365 if support.verbose:
1366 sys.stdout.write(pprint.pformat(cert) + '\n')
1367 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1368 if 'subject' not in cert:
1369 self.fail("No subject field in certificate: %s." %
1370 pprint.pformat(cert))
1371 if ((('organizationName', 'Python Software Foundation'),)
1372 not in cert['subject']):
1373 self.fail(
1374 "Missing or invalid 'organizationName' field in certificate subject; "
1375 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001376 self.assertIn('notBefore', cert)
1377 self.assertIn('notAfter', cert)
1378 before = ssl.cert_time_to_seconds(cert['notBefore'])
1379 after = ssl.cert_time_to_seconds(cert['notAfter'])
1380 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001381 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001382
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 def test_empty_cert(self):
1384 """Connecting with an empty cert file"""
1385 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1386 "nullcert.pem"))
1387 def test_malformed_cert(self):
1388 """Connecting with a badly formatted certificate (syntax error)"""
1389 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1390 "badcert.pem"))
1391 def test_nonexisting_cert(self):
1392 """Connecting with a non-existing cert file"""
1393 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1394 "wrongcert.pem"))
1395 def test_malformed_key(self):
1396 """Connecting with a badly formatted key (syntax error)"""
1397 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1398 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001399
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 def test_rude_shutdown(self):
1401 """A brutal shutdown of an SSL server should raise an IOError
1402 in the client when attempting handshake.
1403 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001404 listener_ready = threading.Event()
1405 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001406
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001407 s = socket.socket()
1408 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001409
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001410 # `listener` runs in a thread. It sits in an accept() until
1411 # the main thread connects. Then it rudely closes the socket,
1412 # and sets Event `listener_gone` to let the main thread know
1413 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001414 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001415 s.listen(5)
1416 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001417 newsock, addr = s.accept()
1418 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001419 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001420 listener_gone.set()
1421
1422 def connector():
1423 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001424 with socket.socket() as c:
1425 c.connect((HOST, port))
1426 listener_gone.wait()
1427 try:
1428 ssl_sock = ssl.wrap_socket(c)
1429 except IOError:
1430 pass
1431 else:
1432 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001433
1434 t = threading.Thread(target=listener)
1435 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001436 try:
1437 connector()
1438 finally:
1439 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001440
Antoine Pitrou23df4832010-08-04 17:14:06 +00001441 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001442 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1443 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 def test_protocol_sslv2(self):
1445 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001446 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001447 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1449 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1450 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1451 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1452 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1453 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001454 # SSLv23 client with specific SSL options
1455 if no_sslv2_implies_sslv3_hello():
1456 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1457 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1458 client_options=ssl.OP_NO_SSLv2)
1459 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1460 client_options=ssl.OP_NO_SSLv3)
1461 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1462 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001463
Antoine Pitrou23df4832010-08-04 17:14:06 +00001464 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001465 def test_protocol_sslv23(self):
1466 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001467 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001468 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001469 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1470 try:
1471 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1472 except (ssl.SSLError, socket.error) as x:
1473 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1474 if support.verbose:
1475 sys.stdout.write(
1476 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1477 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001478 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1479 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1480 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001481
Antoine Pitrou480a1242010-04-28 21:37:09 +00001482 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1483 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1484 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001485
Antoine Pitrou480a1242010-04-28 21:37:09 +00001486 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1487 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1488 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001489
Antoine Pitroub5218772010-05-21 09:56:06 +00001490 # Server with specific SSL options
1491 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1492 server_options=ssl.OP_NO_SSLv3)
1493 # Will choose TLSv1
1494 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1495 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1496 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1497 server_options=ssl.OP_NO_TLSv1)
1498
1499
Antoine Pitrou23df4832010-08-04 17:14:06 +00001500 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001501 def test_protocol_sslv3(self):
1502 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001503 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001504 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001505 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1506 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1507 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001508 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1509 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001510 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1511 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001512 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001513 if no_sslv2_implies_sslv3_hello():
1514 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1515 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1516 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001517
Antoine Pitrou23df4832010-08-04 17:14:06 +00001518 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001519 def test_protocol_tlsv1(self):
1520 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001521 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001522 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001523 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1524 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1525 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001526 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1527 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001528 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001529 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1530 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001531
Antoine Pitrou480a1242010-04-28 21:37:09 +00001532 def test_starttls(self):
1533 """Switching from clear text to encrypted and back again."""
1534 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 +00001535
Trent Nelson78520002008-04-10 20:54:35 +00001536 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001537 ssl_version=ssl.PROTOCOL_TLSv1,
1538 starttls_server=True,
1539 chatty=True,
1540 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001541 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001542 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001543 s = socket.socket()
1544 s.setblocking(1)
1545 s.connect((HOST, server.port))
1546 if support.verbose:
1547 sys.stdout.write("\n")
1548 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001549 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001550 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001551 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001552 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001553 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001554 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001555 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001556 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001557 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001558 msg = outdata.strip().lower()
1559 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1560 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001561 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001562 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001563 " client: read %r from server, starting TLS...\n"
1564 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001565 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1566 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1568 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001569 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001570 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 " client: read %r from server, ending TLS...\n"
1572 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001573 s = conn.unwrap()
1574 wrapped = False
1575 else:
1576 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001577 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001578 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001579 if support.verbose:
1580 sys.stdout.write(" client: closing connection.\n")
1581 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001582 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001583 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001584 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001585 if wrapped:
1586 conn.close()
1587 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001588 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001589
Antoine Pitrou480a1242010-04-28 21:37:09 +00001590 def test_socketserver(self):
1591 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001592 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001593 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001594 if support.verbose:
1595 sys.stdout.write('\n')
1596 with open(CERTFILE, 'rb') as f:
1597 d1 = f.read()
1598 d2 = ''
1599 # now fetch the same data from the HTTPS server
1600 url = 'https://%s:%d/%s' % (
1601 HOST, server.port, os.path.split(CERTFILE)[1])
1602 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001603 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001604 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001605 if dlen and (int(dlen) > 0):
1606 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001607 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001608 sys.stdout.write(
1609 " client: read %d bytes from remote server '%s'\n"
1610 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001611 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001612 f.close()
1613 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001614
Antoine Pitrou480a1242010-04-28 21:37:09 +00001615 def test_asyncore_server(self):
1616 """Check the example asyncore integration."""
1617 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001618
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001619 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001620 sys.stdout.write("\n")
1621
Antoine Pitrou480a1242010-04-28 21:37:09 +00001622 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001623 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001624 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001625 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001626 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001627 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001628 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001629 " client: sending %r...\n" % indata)
1630 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001631 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001632 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001633 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001634 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001635 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001636 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1637 % (outdata[:20], len(outdata),
1638 indata[:20].lower(), len(indata)))
1639 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001640 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001641 sys.stdout.write(" client: closing connection.\n")
1642 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001643 if support.verbose:
1644 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001645
Antoine Pitrou480a1242010-04-28 21:37:09 +00001646 def test_recv_send(self):
1647 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001648 if support.verbose:
1649 sys.stdout.write("\n")
1650
1651 server = ThreadedEchoServer(CERTFILE,
1652 certreqs=ssl.CERT_NONE,
1653 ssl_version=ssl.PROTOCOL_TLSv1,
1654 cacerts=CERTFILE,
1655 chatty=True,
1656 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001657 with server:
1658 s = ssl.wrap_socket(socket.socket(),
1659 server_side=False,
1660 certfile=CERTFILE,
1661 ca_certs=CERTFILE,
1662 cert_reqs=ssl.CERT_NONE,
1663 ssl_version=ssl.PROTOCOL_TLSv1)
1664 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001665 # helper methods for standardising recv* method signatures
1666 def _recv_into():
1667 b = bytearray(b"\0"*100)
1668 count = s.recv_into(b)
1669 return b[:count]
1670
1671 def _recvfrom_into():
1672 b = bytearray(b"\0"*100)
1673 count, addr = s.recvfrom_into(b)
1674 return b[:count]
1675
1676 # (name, method, whether to expect success, *args)
1677 send_methods = [
1678 ('send', s.send, True, []),
1679 ('sendto', s.sendto, False, ["some.address"]),
1680 ('sendall', s.sendall, True, []),
1681 ]
1682 recv_methods = [
1683 ('recv', s.recv, True, []),
1684 ('recvfrom', s.recvfrom, False, ["some.address"]),
1685 ('recv_into', _recv_into, True, []),
1686 ('recvfrom_into', _recvfrom_into, False, []),
1687 ]
1688 data_prefix = "PREFIX_"
1689
1690 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001691 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001692 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001693 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001694 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001695 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001696 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001697 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001698 "<<{outdata:r}>> ({nout:d}) received; "
1699 "expected <<{indata:r}>> ({nin:d})\n".format(
1700 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001701 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001702 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001703 )
1704 )
1705 except ValueError as e:
1706 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001707 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001708 "Failed to send with method <<{name:s}>>; "
1709 "expected to succeed.\n".format(name=meth_name)
1710 )
1711 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001712 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001713 "Method <<{name:s}>> failed with unexpected "
1714 "exception message: {exp:s}\n".format(
1715 name=meth_name, exp=e
1716 )
1717 )
1718
1719 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001720 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001721 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001722 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001723 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001724 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001725 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001726 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001727 "<<{outdata:r}>> ({nout:d}) received; "
1728 "expected <<{indata:r}>> ({nin:d})\n".format(
1729 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001730 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001731 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001732 )
1733 )
1734 except ValueError as e:
1735 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001736 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001737 "Failed to receive with method <<{name:s}>>; "
1738 "expected to succeed.\n".format(name=meth_name)
1739 )
1740 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001741 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001742 "Method <<{name:s}>> failed with unexpected "
1743 "exception message: {exp:s}\n".format(
1744 name=meth_name, exp=e
1745 )
1746 )
1747 # consume data
1748 s.read()
1749
Nick Coghlan513886a2011-08-28 00:00:27 +10001750 # Make sure sendmsg et al are disallowed to avoid
1751 # inadvertent disclosure of data and/or corruption
1752 # of the encrypted data stream
1753 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1754 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1755 self.assertRaises(NotImplementedError,
1756 s.recvmsg_into, bytearray(100))
1757
Antoine Pitrou480a1242010-04-28 21:37:09 +00001758 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001759 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001760
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001761 def test_handshake_timeout(self):
1762 # Issue #5103: SSL handshake must respect the socket timeout
1763 server = socket.socket(socket.AF_INET)
1764 host = "127.0.0.1"
1765 port = support.bind_port(server)
1766 started = threading.Event()
1767 finish = False
1768
1769 def serve():
1770 server.listen(5)
1771 started.set()
1772 conns = []
1773 while not finish:
1774 r, w, e = select.select([server], [], [], 0.1)
1775 if server in r:
1776 # Let the socket hang around rather than having
1777 # it closed by garbage collection.
1778 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001779 for sock in conns:
1780 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001781
1782 t = threading.Thread(target=serve)
1783 t.start()
1784 started.wait()
1785
1786 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001787 try:
1788 c = socket.socket(socket.AF_INET)
1789 c.settimeout(0.2)
1790 c.connect((host, port))
1791 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001792 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001793 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001794 finally:
1795 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001796 try:
1797 c = socket.socket(socket.AF_INET)
1798 c = ssl.wrap_socket(c)
1799 c.settimeout(0.2)
1800 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001801 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001802 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001803 finally:
1804 c.close()
1805 finally:
1806 finish = True
1807 t.join()
1808 server.close()
1809
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001810 def test_server_accept(self):
1811 # Issue #16357: accept() on a SSLSocket created through
1812 # SSLContext.wrap_socket().
1813 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1814 context.verify_mode = ssl.CERT_REQUIRED
1815 context.load_verify_locations(CERTFILE)
1816 context.load_cert_chain(CERTFILE)
1817 server = socket.socket(socket.AF_INET)
1818 host = "127.0.0.1"
1819 port = support.bind_port(server)
1820 server = context.wrap_socket(server, server_side=True)
1821
1822 evt = threading.Event()
1823 remote = None
1824 peer = None
1825 def serve():
1826 nonlocal remote, peer
1827 server.listen(5)
1828 # Block on the accept and wait on the connection to close.
1829 evt.set()
1830 remote, peer = server.accept()
1831 remote.recv(1)
1832
1833 t = threading.Thread(target=serve)
1834 t.start()
1835 # Client wait until server setup and perform a connect.
1836 evt.wait()
1837 client = context.wrap_socket(socket.socket())
1838 client.connect((host, port))
1839 client_addr = client.getsockname()
1840 client.close()
1841 t.join()
1842 # Sanity checks.
1843 self.assertIsInstance(remote, ssl.SSLSocket)
1844 self.assertEqual(peer, client_addr)
1845
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001846 def test_default_ciphers(self):
1847 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1848 try:
1849 # Force a set of weak ciphers on our client context
1850 context.set_ciphers("DES")
1851 except ssl.SSLError:
1852 self.skipTest("no DES cipher available")
1853 with ThreadedEchoServer(CERTFILE,
1854 ssl_version=ssl.PROTOCOL_SSLv23,
1855 chatty=False) as server:
1856 with socket.socket() as sock:
1857 s = context.wrap_socket(sock)
1858 with self.assertRaises((OSError, ssl.SSLError)):
1859 s.connect((HOST, server.port))
1860 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1861
Antoine Pitroud6494802011-07-21 01:11:30 +02001862 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1863 "'tls-unique' channel binding not available")
1864 def test_tls_unique_channel_binding(self):
1865 """Test tls-unique channel binding."""
1866 if support.verbose:
1867 sys.stdout.write("\n")
1868
1869 server = ThreadedEchoServer(CERTFILE,
1870 certreqs=ssl.CERT_NONE,
1871 ssl_version=ssl.PROTOCOL_TLSv1,
1872 cacerts=CERTFILE,
1873 chatty=True,
1874 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001875 with server:
1876 s = ssl.wrap_socket(socket.socket(),
1877 server_side=False,
1878 certfile=CERTFILE,
1879 ca_certs=CERTFILE,
1880 cert_reqs=ssl.CERT_NONE,
1881 ssl_version=ssl.PROTOCOL_TLSv1)
1882 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001883 # get the data
1884 cb_data = s.get_channel_binding("tls-unique")
1885 if support.verbose:
1886 sys.stdout.write(" got channel binding data: {0!r}\n"
1887 .format(cb_data))
1888
1889 # check if it is sane
1890 self.assertIsNotNone(cb_data)
1891 self.assertEqual(len(cb_data), 12) # True for TLSv1
1892
1893 # and compare with the peers version
1894 s.write(b"CB tls-unique\n")
1895 peer_data_repr = s.read().strip()
1896 self.assertEqual(peer_data_repr,
1897 repr(cb_data).encode("us-ascii"))
1898 s.close()
1899
1900 # now, again
1901 s = ssl.wrap_socket(socket.socket(),
1902 server_side=False,
1903 certfile=CERTFILE,
1904 ca_certs=CERTFILE,
1905 cert_reqs=ssl.CERT_NONE,
1906 ssl_version=ssl.PROTOCOL_TLSv1)
1907 s.connect((HOST, server.port))
1908 new_cb_data = s.get_channel_binding("tls-unique")
1909 if support.verbose:
1910 sys.stdout.write(" got another channel binding data: {0!r}\n"
1911 .format(new_cb_data))
1912 # is it really unique
1913 self.assertNotEqual(cb_data, new_cb_data)
1914 self.assertIsNotNone(cb_data)
1915 self.assertEqual(len(cb_data), 12) # True for TLSv1
1916 s.write(b"CB tls-unique\n")
1917 peer_data_repr = s.read().strip()
1918 self.assertEqual(peer_data_repr,
1919 repr(new_cb_data).encode("us-ascii"))
1920 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001921
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001922 def test_compression(self):
1923 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1924 context.load_cert_chain(CERTFILE)
1925 stats = server_params_test(context, context,
1926 chatty=True, connectionchatty=True)
1927 if support.verbose:
1928 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1929 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1930
1931 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1932 "ssl.OP_NO_COMPRESSION needed for this test")
1933 def test_compression_disabled(self):
1934 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1935 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001936 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001937 stats = server_params_test(context, context,
1938 chatty=True, connectionchatty=True)
1939 self.assertIs(stats['compression'], None)
1940
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001941 def test_dh_params(self):
1942 # Check we can get a connection with ephemeral Diffie-Hellman
1943 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1944 context.load_cert_chain(CERTFILE)
1945 context.load_dh_params(DHFILE)
1946 context.set_ciphers("kEDH")
1947 stats = server_params_test(context, context,
1948 chatty=True, connectionchatty=True)
1949 cipher = stats["cipher"][0]
1950 parts = cipher.split("-")
1951 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1952 self.fail("Non-DH cipher: " + cipher[0])
1953
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001954 def test_selected_npn_protocol(self):
1955 # selected_npn_protocol() is None unless NPN is used
1956 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1957 context.load_cert_chain(CERTFILE)
1958 stats = server_params_test(context, context,
1959 chatty=True, connectionchatty=True)
1960 self.assertIs(stats['client_npn_protocol'], None)
1961
1962 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1963 def test_npn_protocols(self):
1964 server_protocols = ['http/1.1', 'spdy/2']
1965 protocol_tests = [
1966 (['http/1.1', 'spdy/2'], 'http/1.1'),
1967 (['spdy/2', 'http/1.1'], 'http/1.1'),
1968 (['spdy/2', 'test'], 'spdy/2'),
1969 (['abc', 'def'], 'abc')
1970 ]
1971 for client_protocols, expected in protocol_tests:
1972 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1973 server_context.load_cert_chain(CERTFILE)
1974 server_context.set_npn_protocols(server_protocols)
1975 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1976 client_context.load_cert_chain(CERTFILE)
1977 client_context.set_npn_protocols(client_protocols)
1978 stats = server_params_test(client_context, server_context,
1979 chatty=True, connectionchatty=True)
1980
1981 msg = "failed trying %s (s) and %s (c).\n" \
1982 "was expecting %s, but got %%s from the %%s" \
1983 % (str(server_protocols), str(client_protocols),
1984 str(expected))
1985 client_result = stats['client_npn_protocol']
1986 self.assertEqual(client_result, expected, msg % (client_result, "client"))
1987 server_result = stats['server_npn_protocols'][-1] \
1988 if len(stats['server_npn_protocols']) else 'nothing'
1989 self.assertEqual(server_result, expected, msg % (server_result, "server"))
1990
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001991
Thomas Woutersed03b412007-08-28 21:37:11 +00001992def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001993 if support.verbose:
1994 plats = {
1995 'Linux': platform.linux_distribution,
1996 'Mac': platform.mac_ver,
1997 'Windows': platform.win32_ver,
1998 }
1999 for name, func in plats.items():
2000 plat = func()
2001 if plat and plat[0]:
2002 plat = '%s %r' % (name, plat)
2003 break
2004 else:
2005 plat = repr(platform.platform())
2006 print("test_ssl: testing with %r %r" %
2007 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2008 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002009 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002010
Antoine Pitrou152efa22010-05-16 18:19:27 +00002011 for filename in [
2012 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2013 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2014 BADCERT, BADKEY, EMPTYCERT]:
2015 if not os.path.exists(filename):
2016 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002017
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002018 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002019
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002020 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002021 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002022
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002023 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002024 thread_info = support.threading_setup()
2025 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002026 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002027
Antoine Pitrou480a1242010-04-28 21:37:09 +00002028 try:
2029 support.run_unittest(*tests)
2030 finally:
2031 if _have_threads:
2032 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002033
2034if __name__ == "__main__":
2035 test_main()