blob: 74abbd23b340dab289d928a4ed89e6eb1a5bf5de [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 Pitrou152efa22010-05-16 18:19:27 +0000717 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000718 with support.transient_internet("svn.python.org"):
719 # Same as test_connect, but with a separately created context
720 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
721 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
722 s.connect(("svn.python.org", 443))
723 try:
724 self.assertEqual({}, s.getpeercert())
725 finally:
726 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000727 # Same with a server hostname
728 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
729 server_hostname="svn.python.org")
730 if ssl.HAS_SNI:
731 s.connect(("svn.python.org", 443))
732 s.close()
733 else:
734 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000735 # This should fail because we have no verification certs
736 ctx.verify_mode = ssl.CERT_REQUIRED
737 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000738 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000739 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000740 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000741 # This should succeed because we specify the root cert
742 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
743 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
744 s.connect(("svn.python.org", 443))
745 try:
746 cert = s.getpeercert()
747 self.assertTrue(cert)
748 finally:
749 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000750
751 def test_connect_capath(self):
752 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000753 # NOTE: the subject hashing algorithm has been changed between
754 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
755 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000756 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000757 with support.transient_internet("svn.python.org"):
758 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
759 ctx.verify_mode = ssl.CERT_REQUIRED
760 ctx.load_verify_locations(capath=CAPATH)
761 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
762 s.connect(("svn.python.org", 443))
763 try:
764 cert = s.getpeercert()
765 self.assertTrue(cert)
766 finally:
767 s.close()
768 # Same with a bytes `capath` argument
769 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
770 ctx.verify_mode = ssl.CERT_REQUIRED
771 ctx.load_verify_locations(capath=BYTES_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()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000779
Antoine Pitroue3220242010-04-24 11:13:53 +0000780 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
781 def test_makefile_close(self):
782 # Issue #5238: creating a file-like object with makefile() shouldn't
783 # delay closing the underlying "real socket" (here tested with its
784 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000785 with support.transient_internet("svn.python.org"):
786 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
787 ss.connect(("svn.python.org", 443))
788 fd = ss.fileno()
789 f = ss.makefile()
790 f.close()
791 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000792 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000793 # Closing the SSL socket should close the fd too
794 ss.close()
795 gc.collect()
796 with self.assertRaises(OSError) as e:
797 os.read(fd, 0)
798 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000799
Antoine Pitrou480a1242010-04-28 21:37:09 +0000800 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000801 with support.transient_internet("svn.python.org"):
802 s = socket.socket(socket.AF_INET)
803 s.connect(("svn.python.org", 443))
804 s.setblocking(False)
805 s = ssl.wrap_socket(s,
806 cert_reqs=ssl.CERT_NONE,
807 do_handshake_on_connect=False)
808 count = 0
809 while True:
810 try:
811 count += 1
812 s.do_handshake()
813 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200814 except ssl.SSLWantReadError:
815 select.select([s], [], [])
816 except ssl.SSLWantWriteError:
817 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000818 s.close()
819 if support.verbose:
820 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000821
Antoine Pitrou480a1242010-04-28 21:37:09 +0000822 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200823 def _test_get_server_certificate(host, port, cert=None):
824 with support.transient_internet(host):
825 pem = ssl.get_server_certificate((host, port))
826 if not pem:
827 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200828
Antoine Pitrou15399c32011-04-28 19:23:55 +0200829 try:
830 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
831 except ssl.SSLError as x:
832 #should fail
833 if support.verbose:
834 sys.stdout.write("%s\n" % x)
835 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200836 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
837
Antoine Pitrou15399c32011-04-28 19:23:55 +0200838 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
839 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200840 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000841 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200842 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000843
Antoine Pitrou15399c32011-04-28 19:23:55 +0200844 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
845 if support.IPV6_ENABLED:
846 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000847
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000848 def test_ciphers(self):
849 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000850 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000851 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000852 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000853 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000854 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
855 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
856 s.connect(remote)
857 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000858 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000859 with socket.socket(socket.AF_INET) as sock:
860 s = ssl.wrap_socket(sock,
861 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
862 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000863
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000864 def test_algorithms(self):
865 # Issue #8484: all algorithms should be available when verifying a
866 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000867 # SHA256 was added in OpenSSL 0.9.8
868 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
869 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200870 # sha256.tbs-internet.com needs SNI to use the correct certificate
871 if not ssl.HAS_SNI:
872 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000873 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
874 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000875 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000876 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200877 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
878 ctx.verify_mode = ssl.CERT_REQUIRED
879 ctx.load_verify_locations(sha256_cert)
880 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
881 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000882 try:
883 s.connect(remote)
884 if support.verbose:
885 sys.stdout.write("\nCipher with %r is %r\n" %
886 (remote, s.cipher()))
887 sys.stdout.write("Certificate is:\n%s\n" %
888 pprint.pformat(s.getpeercert()))
889 finally:
890 s.close()
891
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892
893try:
894 import threading
895except ImportError:
896 _have_threads = False
897else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 _have_threads = True
899
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000900 from test.ssl_servers import make_https_server
901
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000902 class ThreadedEchoServer(threading.Thread):
903
904 class ConnectionHandler(threading.Thread):
905
906 """A mildly complicated class, because we want it to work both
907 with and without the SSL wrapper around the socket connection, so
908 that we can test the STARTTLS functionality."""
909
Bill Janssen6e027db2007-11-15 22:23:56 +0000910 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911 self.server = server
912 self.running = False
913 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000914 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 self.sock.setblocking(1)
916 self.sslconn = None
917 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000918 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919
Antoine Pitrou480a1242010-04-28 21:37:09 +0000920 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000922 self.sslconn = self.server.context.wrap_socket(
923 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100924 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100925 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000926 # XXX Various errors can have happened here, for example
927 # a mismatching protocol version, an invalid certificate,
928 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100929 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000931 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000932 self.running = False
933 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000934 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000936 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000937 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000939 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000940 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
941 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000942 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000943 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
944 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000945 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000946 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100947 sys.stdout.write(" server: selected protocol is now "
948 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 return True
950
951 def read(self):
952 if self.sslconn:
953 return self.sslconn.read()
954 else:
955 return self.sock.recv(1024)
956
957 def write(self, bytes):
958 if self.sslconn:
959 return self.sslconn.write(bytes)
960 else:
961 return self.sock.send(bytes)
962
963 def close(self):
964 if self.sslconn:
965 self.sslconn.close()
966 else:
967 self.sock.close()
968
Antoine Pitrou480a1242010-04-28 21:37:09 +0000969 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 self.running = True
971 if not self.server.starttls_server:
972 if not self.wrap_conn():
973 return
974 while self.running:
975 try:
976 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000977 stripped = msg.strip()
978 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979 # eof, so quit this handler
980 self.running = False
981 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000982 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000983 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 sys.stdout.write(" server: client closed connection\n")
985 self.close()
986 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000987 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000988 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000989 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000991 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000992 if not self.wrap_conn():
993 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000994 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000995 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000996 if support.verbose and self.server.connectionchatty:
997 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000998 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000999 self.sock = self.sslconn.unwrap()
1000 self.sslconn = None
1001 if support.verbose and self.server.connectionchatty:
1002 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001003 elif stripped == b'CB tls-unique':
1004 if support.verbose and self.server.connectionchatty:
1005 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1006 data = self.sslconn.get_channel_binding("tls-unique")
1007 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001008 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001009 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001010 self.server.connectionchatty):
1011 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001012 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1013 % (msg, ctype, msg.lower(), ctype))
1014 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001015 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001016 if self.server.chatty:
1017 handle_error("Test server failure:\n")
1018 self.close()
1019 self.running = False
1020 # normally, we'd just stop here, but for the test
1021 # harness, we want to stop the server
1022 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001023
Antoine Pitroub5218772010-05-21 09:56:06 +00001024 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001025 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001026 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001027 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001028 if context:
1029 self.context = context
1030 else:
1031 self.context = ssl.SSLContext(ssl_version
1032 if ssl_version is not None
1033 else ssl.PROTOCOL_TLSv1)
1034 self.context.verify_mode = (certreqs if certreqs is not None
1035 else ssl.CERT_NONE)
1036 if cacerts:
1037 self.context.load_verify_locations(cacerts)
1038 if certificate:
1039 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001040 if npn_protocols:
1041 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001042 if ciphers:
1043 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001044 self.chatty = chatty
1045 self.connectionchatty = connectionchatty
1046 self.starttls_server = starttls_server
1047 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001048 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001049 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001050 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001051 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001052 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001053 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001054 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001055
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001056 def __enter__(self):
1057 self.start(threading.Event())
1058 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001059 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001060
1061 def __exit__(self, *args):
1062 self.stop()
1063 self.join()
1064
Antoine Pitrou480a1242010-04-28 21:37:09 +00001065 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 self.flag = flag
1067 threading.Thread.start(self)
1068
Antoine Pitrou480a1242010-04-28 21:37:09 +00001069 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001070 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001071 self.sock.listen(5)
1072 self.active = True
1073 if self.flag:
1074 # signal an event
1075 self.flag.set()
1076 while self.active:
1077 try:
1078 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001079 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001080 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001081 + repr(connaddr) + '\n')
1082 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001083 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001084 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001085 except socket.timeout:
1086 pass
1087 except KeyboardInterrupt:
1088 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001089 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001090
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001092 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093
Bill Janssen54cc54c2007-12-14 22:08:56 +00001094 class AsyncoreEchoServer(threading.Thread):
1095
1096 # this one's based on asyncore.dispatcher
1097
1098 class EchoServer (asyncore.dispatcher):
1099
1100 class ConnectionHandler (asyncore.dispatcher_with_send):
1101
1102 def __init__(self, conn, certfile):
1103 self.socket = ssl.wrap_socket(conn, server_side=True,
1104 certfile=certfile,
1105 do_handshake_on_connect=False)
1106 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001107 self._ssl_accepting = True
1108 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001109
1110 def readable(self):
1111 if isinstance(self.socket, ssl.SSLSocket):
1112 while self.socket.pending() > 0:
1113 self.handle_read_event()
1114 return True
1115
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001116 def _do_ssl_handshake(self):
1117 try:
1118 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001119 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1120 return
1121 except ssl.SSLEOFError:
1122 return self.handle_close()
1123 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001124 raise
1125 except socket.error as err:
1126 if err.args[0] == errno.ECONNABORTED:
1127 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001128 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001129 self._ssl_accepting = False
1130
1131 def handle_read(self):
1132 if self._ssl_accepting:
1133 self._do_ssl_handshake()
1134 else:
1135 data = self.recv(1024)
1136 if support.verbose:
1137 sys.stdout.write(" server: read %s from client\n" % repr(data))
1138 if not data:
1139 self.close()
1140 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001142
1143 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001144 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001145 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001146 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1147
1148 def handle_error(self):
1149 raise
1150
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001151 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001152 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001153 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1154 self.port = support.bind_port(sock, '')
1155 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001156 self.listen(5)
1157
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001158 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001159 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001160 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1161 self.ConnectionHandler(sock_obj, self.certfile)
1162
1163 def handle_error(self):
1164 raise
1165
Trent Nelson78520002008-04-10 20:54:35 +00001166 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001167 self.flag = None
1168 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001169 self.server = self.EchoServer(certfile)
1170 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001171 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001172 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001173
1174 def __str__(self):
1175 return "<%s %s>" % (self.__class__.__name__, self.server)
1176
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001177 def __enter__(self):
1178 self.start(threading.Event())
1179 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001180 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001181
1182 def __exit__(self, *args):
1183 if support.verbose:
1184 sys.stdout.write(" cleanup: stopping server.\n")
1185 self.stop()
1186 if support.verbose:
1187 sys.stdout.write(" cleanup: joining server thread.\n")
1188 self.join()
1189 if support.verbose:
1190 sys.stdout.write(" cleanup: successfully joined.\n")
1191
Bill Janssen54cc54c2007-12-14 22:08:56 +00001192 def start (self, flag=None):
1193 self.flag = flag
1194 threading.Thread.start(self)
1195
Antoine Pitrou480a1242010-04-28 21:37:09 +00001196 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001197 self.active = True
1198 if self.flag:
1199 self.flag.set()
1200 while self.active:
1201 try:
1202 asyncore.loop(1)
1203 except:
1204 pass
1205
Antoine Pitrou480a1242010-04-28 21:37:09 +00001206 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001207 self.active = False
1208 self.server.close()
1209
Antoine Pitrou480a1242010-04-28 21:37:09 +00001210 def bad_cert_test(certfile):
1211 """
1212 Launch a server with CERT_REQUIRED, and check that trying to
1213 connect to it with the given client certificate fails.
1214 """
Trent Nelson78520002008-04-10 20:54:35 +00001215 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001216 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001217 cacerts=CERTFILE, chatty=False,
1218 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001219 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001220 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001221 with socket.socket() as sock:
1222 s = ssl.wrap_socket(sock,
1223 certfile=certfile,
1224 ssl_version=ssl.PROTOCOL_TLSv1)
1225 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001226 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001227 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001228 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001229 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001230 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001231 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001232 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001233 if x.errno != errno.ENOENT:
1234 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001235 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001236 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001237 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001238 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001239
Antoine Pitroub5218772010-05-21 09:56:06 +00001240 def server_params_test(client_context, server_context, indata=b"FOO\n",
1241 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 """
1243 Launch a server, connect a client to it and try various reads
1244 and writes.
1245 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001246 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001247 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001248 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001249 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001250 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001251 with client_context.wrap_socket(socket.socket()) as s:
1252 s.connect((HOST, server.port))
1253 for arg in [indata, bytearray(indata), memoryview(indata)]:
1254 if connectionchatty:
1255 if support.verbose:
1256 sys.stdout.write(
1257 " client: sending %r...\n" % indata)
1258 s.write(arg)
1259 outdata = s.read()
1260 if connectionchatty:
1261 if support.verbose:
1262 sys.stdout.write(" client: read %r\n" % outdata)
1263 if outdata != indata.lower():
1264 raise AssertionError(
1265 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1266 % (outdata[:20], len(outdata),
1267 indata[:20].lower(), len(indata)))
1268 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001269 if connectionchatty:
1270 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001271 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001272 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001273 'compression': s.compression(),
1274 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001275 'client_npn_protocol': s.selected_npn_protocol()
1276 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001277 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001278 stats['server_npn_protocols'] = server.selected_protocols
1279 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001280
Antoine Pitroub5218772010-05-21 09:56:06 +00001281 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1282 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001283 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001284 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001285 certtype = {
1286 ssl.CERT_NONE: "CERT_NONE",
1287 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1288 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1289 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001290 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001291 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001292 sys.stdout.write(formatstr %
1293 (ssl.get_protocol_name(client_protocol),
1294 ssl.get_protocol_name(server_protocol),
1295 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001296 client_context = ssl.SSLContext(client_protocol)
1297 client_context.options = ssl.OP_ALL | client_options
1298 server_context = ssl.SSLContext(server_protocol)
1299 server_context.options = ssl.OP_ALL | server_options
1300 for ctx in (client_context, server_context):
1301 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001302 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1303 # will send an SSLv3 hello (rather than SSLv2) starting from
1304 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001305 ctx.set_ciphers("ALL")
1306 ctx.load_cert_chain(CERTFILE)
1307 ctx.load_verify_locations(CERTFILE)
1308 try:
1309 server_params_test(client_context, server_context,
1310 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001311 # Protocol mismatch can result in either an SSLError, or a
1312 # "Connection reset by peer" error.
1313 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001314 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001315 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001316 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001317 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001318 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001319 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001320 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001321 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001322 "Client protocol %s succeeded with server protocol %s!"
1323 % (ssl.get_protocol_name(client_protocol),
1324 ssl.get_protocol_name(server_protocol)))
1325
1326
Bill Janssen6e027db2007-11-15 22:23:56 +00001327 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001328
Antoine Pitrou23df4832010-08-04 17:14:06 +00001329 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001330 def test_echo(self):
1331 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001332 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001333 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001334 for protocol in PROTOCOLS:
1335 context = ssl.SSLContext(protocol)
1336 context.load_cert_chain(CERTFILE)
1337 server_params_test(context, context,
1338 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001339
Antoine Pitrou480a1242010-04-28 21:37:09 +00001340 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001341 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001342 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001343 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1344 context.verify_mode = ssl.CERT_REQUIRED
1345 context.load_verify_locations(CERTFILE)
1346 context.load_cert_chain(CERTFILE)
1347 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001348 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001349 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001350 s.connect((HOST, server.port))
1351 cert = s.getpeercert()
1352 self.assertTrue(cert, "Can't get peer certificate.")
1353 cipher = s.cipher()
1354 if support.verbose:
1355 sys.stdout.write(pprint.pformat(cert) + '\n')
1356 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1357 if 'subject' not in cert:
1358 self.fail("No subject field in certificate: %s." %
1359 pprint.pformat(cert))
1360 if ((('organizationName', 'Python Software Foundation'),)
1361 not in cert['subject']):
1362 self.fail(
1363 "Missing or invalid 'organizationName' field in certificate subject; "
1364 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001365 self.assertIn('notBefore', cert)
1366 self.assertIn('notAfter', cert)
1367 before = ssl.cert_time_to_seconds(cert['notBefore'])
1368 after = ssl.cert_time_to_seconds(cert['notAfter'])
1369 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001370 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001371
Antoine Pitrou480a1242010-04-28 21:37:09 +00001372 def test_empty_cert(self):
1373 """Connecting with an empty cert file"""
1374 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1375 "nullcert.pem"))
1376 def test_malformed_cert(self):
1377 """Connecting with a badly formatted certificate (syntax error)"""
1378 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1379 "badcert.pem"))
1380 def test_nonexisting_cert(self):
1381 """Connecting with a non-existing cert file"""
1382 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1383 "wrongcert.pem"))
1384 def test_malformed_key(self):
1385 """Connecting with a badly formatted key (syntax error)"""
1386 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1387 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001388
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 def test_rude_shutdown(self):
1390 """A brutal shutdown of an SSL server should raise an IOError
1391 in the client when attempting handshake.
1392 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001393 listener_ready = threading.Event()
1394 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001396 s = socket.socket()
1397 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001398
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001399 # `listener` runs in a thread. It sits in an accept() until
1400 # the main thread connects. Then it rudely closes the socket,
1401 # and sets Event `listener_gone` to let the main thread know
1402 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001403 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001404 s.listen(5)
1405 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001406 newsock, addr = s.accept()
1407 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001408 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001409 listener_gone.set()
1410
1411 def connector():
1412 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001413 with socket.socket() as c:
1414 c.connect((HOST, port))
1415 listener_gone.wait()
1416 try:
1417 ssl_sock = ssl.wrap_socket(c)
1418 except IOError:
1419 pass
1420 else:
1421 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001422
1423 t = threading.Thread(target=listener)
1424 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001425 try:
1426 connector()
1427 finally:
1428 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001429
Antoine Pitrou23df4832010-08-04 17:14:06 +00001430 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001431 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1432 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001433 def test_protocol_sslv2(self):
1434 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001435 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001436 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1438 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1439 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1440 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1441 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1442 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001443 # SSLv23 client with specific SSL options
1444 if no_sslv2_implies_sslv3_hello():
1445 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1446 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1447 client_options=ssl.OP_NO_SSLv2)
1448 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1449 client_options=ssl.OP_NO_SSLv3)
1450 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1451 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001452
Antoine Pitrou23df4832010-08-04 17:14:06 +00001453 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001454 def test_protocol_sslv23(self):
1455 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001456 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001457 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001458 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1459 try:
1460 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1461 except (ssl.SSLError, socket.error) as x:
1462 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1463 if support.verbose:
1464 sys.stdout.write(
1465 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1466 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001467 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1468 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1469 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001470
Antoine Pitrou480a1242010-04-28 21:37:09 +00001471 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1472 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1473 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001474
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1476 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1477 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478
Antoine Pitroub5218772010-05-21 09:56:06 +00001479 # Server with specific SSL options
1480 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1481 server_options=ssl.OP_NO_SSLv3)
1482 # Will choose TLSv1
1483 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1484 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1485 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1486 server_options=ssl.OP_NO_TLSv1)
1487
1488
Antoine Pitrou23df4832010-08-04 17:14:06 +00001489 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001490 def test_protocol_sslv3(self):
1491 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001492 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001493 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001494 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1495 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1496 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001497 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1498 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001499 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1500 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001501 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001502 if no_sslv2_implies_sslv3_hello():
1503 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1504 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1505 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001506
Antoine Pitrou23df4832010-08-04 17:14:06 +00001507 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001508 def test_protocol_tlsv1(self):
1509 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001510 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001511 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001512 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1513 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1514 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001515 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1516 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001517 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001518 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1519 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001520
Antoine Pitrou480a1242010-04-28 21:37:09 +00001521 def test_starttls(self):
1522 """Switching from clear text to encrypted and back again."""
1523 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 +00001524
Trent Nelson78520002008-04-10 20:54:35 +00001525 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001526 ssl_version=ssl.PROTOCOL_TLSv1,
1527 starttls_server=True,
1528 chatty=True,
1529 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001531 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001532 s = socket.socket()
1533 s.setblocking(1)
1534 s.connect((HOST, server.port))
1535 if support.verbose:
1536 sys.stdout.write("\n")
1537 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001538 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001539 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001540 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001541 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001542 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001543 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001544 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001546 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001547 msg = outdata.strip().lower()
1548 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1549 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001550 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001551 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001552 " client: read %r from server, starting TLS...\n"
1553 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001554 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1555 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001556 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1557 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001558 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001559 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001560 " client: read %r from server, ending TLS...\n"
1561 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001562 s = conn.unwrap()
1563 wrapped = False
1564 else:
1565 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001566 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001568 if support.verbose:
1569 sys.stdout.write(" client: closing connection.\n")
1570 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001572 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001573 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001574 if wrapped:
1575 conn.close()
1576 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001577 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001578
Antoine Pitrou480a1242010-04-28 21:37:09 +00001579 def test_socketserver(self):
1580 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001581 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001582 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001583 if support.verbose:
1584 sys.stdout.write('\n')
1585 with open(CERTFILE, 'rb') as f:
1586 d1 = f.read()
1587 d2 = ''
1588 # now fetch the same data from the HTTPS server
1589 url = 'https://%s:%d/%s' % (
1590 HOST, server.port, os.path.split(CERTFILE)[1])
1591 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001592 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001593 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001594 if dlen and (int(dlen) > 0):
1595 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001596 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001597 sys.stdout.write(
1598 " client: read %d bytes from remote server '%s'\n"
1599 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001600 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001601 f.close()
1602 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001603
Antoine Pitrou480a1242010-04-28 21:37:09 +00001604 def test_asyncore_server(self):
1605 """Check the example asyncore integration."""
1606 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001607
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001608 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001609 sys.stdout.write("\n")
1610
Antoine Pitrou480a1242010-04-28 21:37:09 +00001611 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001612 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001613 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001614 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001615 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001616 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001617 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001618 " client: sending %r...\n" % indata)
1619 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001620 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001621 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001622 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001623 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001624 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001625 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1626 % (outdata[:20], len(outdata),
1627 indata[:20].lower(), len(indata)))
1628 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001629 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001630 sys.stdout.write(" client: closing connection.\n")
1631 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001632 if support.verbose:
1633 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001634
Antoine Pitrou480a1242010-04-28 21:37:09 +00001635 def test_recv_send(self):
1636 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001637 if support.verbose:
1638 sys.stdout.write("\n")
1639
1640 server = ThreadedEchoServer(CERTFILE,
1641 certreqs=ssl.CERT_NONE,
1642 ssl_version=ssl.PROTOCOL_TLSv1,
1643 cacerts=CERTFILE,
1644 chatty=True,
1645 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001646 with server:
1647 s = ssl.wrap_socket(socket.socket(),
1648 server_side=False,
1649 certfile=CERTFILE,
1650 ca_certs=CERTFILE,
1651 cert_reqs=ssl.CERT_NONE,
1652 ssl_version=ssl.PROTOCOL_TLSv1)
1653 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001654 # helper methods for standardising recv* method signatures
1655 def _recv_into():
1656 b = bytearray(b"\0"*100)
1657 count = s.recv_into(b)
1658 return b[:count]
1659
1660 def _recvfrom_into():
1661 b = bytearray(b"\0"*100)
1662 count, addr = s.recvfrom_into(b)
1663 return b[:count]
1664
1665 # (name, method, whether to expect success, *args)
1666 send_methods = [
1667 ('send', s.send, True, []),
1668 ('sendto', s.sendto, False, ["some.address"]),
1669 ('sendall', s.sendall, True, []),
1670 ]
1671 recv_methods = [
1672 ('recv', s.recv, True, []),
1673 ('recvfrom', s.recvfrom, False, ["some.address"]),
1674 ('recv_into', _recv_into, True, []),
1675 ('recvfrom_into', _recvfrom_into, False, []),
1676 ]
1677 data_prefix = "PREFIX_"
1678
1679 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001680 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001681 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001682 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001683 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001684 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001685 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001686 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001687 "<<{outdata:r}>> ({nout:d}) received; "
1688 "expected <<{indata:r}>> ({nin:d})\n".format(
1689 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001690 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001691 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001692 )
1693 )
1694 except ValueError as e:
1695 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001696 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001697 "Failed to send with method <<{name:s}>>; "
1698 "expected to succeed.\n".format(name=meth_name)
1699 )
1700 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001701 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001702 "Method <<{name:s}>> failed with unexpected "
1703 "exception message: {exp:s}\n".format(
1704 name=meth_name, exp=e
1705 )
1706 )
1707
1708 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001709 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001710 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001711 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001712 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001713 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001714 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001715 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001716 "<<{outdata:r}>> ({nout:d}) received; "
1717 "expected <<{indata:r}>> ({nin:d})\n".format(
1718 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001719 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001720 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001721 )
1722 )
1723 except ValueError as e:
1724 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001725 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001726 "Failed to receive with method <<{name:s}>>; "
1727 "expected to succeed.\n".format(name=meth_name)
1728 )
1729 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001730 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001731 "Method <<{name:s}>> failed with unexpected "
1732 "exception message: {exp:s}\n".format(
1733 name=meth_name, exp=e
1734 )
1735 )
1736 # consume data
1737 s.read()
1738
Nick Coghlan513886a2011-08-28 00:00:27 +10001739 # Make sure sendmsg et al are disallowed to avoid
1740 # inadvertent disclosure of data and/or corruption
1741 # of the encrypted data stream
1742 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1743 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1744 self.assertRaises(NotImplementedError,
1745 s.recvmsg_into, bytearray(100))
1746
Antoine Pitrou480a1242010-04-28 21:37:09 +00001747 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001748 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001749
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001750 def test_handshake_timeout(self):
1751 # Issue #5103: SSL handshake must respect the socket timeout
1752 server = socket.socket(socket.AF_INET)
1753 host = "127.0.0.1"
1754 port = support.bind_port(server)
1755 started = threading.Event()
1756 finish = False
1757
1758 def serve():
1759 server.listen(5)
1760 started.set()
1761 conns = []
1762 while not finish:
1763 r, w, e = select.select([server], [], [], 0.1)
1764 if server in r:
1765 # Let the socket hang around rather than having
1766 # it closed by garbage collection.
1767 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001768 for sock in conns:
1769 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001770
1771 t = threading.Thread(target=serve)
1772 t.start()
1773 started.wait()
1774
1775 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001776 try:
1777 c = socket.socket(socket.AF_INET)
1778 c.settimeout(0.2)
1779 c.connect((host, port))
1780 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001781 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001782 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001783 finally:
1784 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001785 try:
1786 c = socket.socket(socket.AF_INET)
1787 c = ssl.wrap_socket(c)
1788 c.settimeout(0.2)
1789 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001790 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001791 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001792 finally:
1793 c.close()
1794 finally:
1795 finish = True
1796 t.join()
1797 server.close()
1798
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001799 def test_server_accept(self):
1800 # Issue #16357: accept() on a SSLSocket created through
1801 # SSLContext.wrap_socket().
1802 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1803 context.verify_mode = ssl.CERT_REQUIRED
1804 context.load_verify_locations(CERTFILE)
1805 context.load_cert_chain(CERTFILE)
1806 server = socket.socket(socket.AF_INET)
1807 host = "127.0.0.1"
1808 port = support.bind_port(server)
1809 server = context.wrap_socket(server, server_side=True)
1810
1811 evt = threading.Event()
1812 remote = None
1813 peer = None
1814 def serve():
1815 nonlocal remote, peer
1816 server.listen(5)
1817 # Block on the accept and wait on the connection to close.
1818 evt.set()
1819 remote, peer = server.accept()
1820 remote.recv(1)
1821
1822 t = threading.Thread(target=serve)
1823 t.start()
1824 # Client wait until server setup and perform a connect.
1825 evt.wait()
1826 client = context.wrap_socket(socket.socket())
1827 client.connect((host, port))
1828 client_addr = client.getsockname()
1829 client.close()
1830 t.join()
1831 # Sanity checks.
1832 self.assertIsInstance(remote, ssl.SSLSocket)
1833 self.assertEqual(peer, client_addr)
1834
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001835 def test_default_ciphers(self):
1836 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1837 try:
1838 # Force a set of weak ciphers on our client context
1839 context.set_ciphers("DES")
1840 except ssl.SSLError:
1841 self.skipTest("no DES cipher available")
1842 with ThreadedEchoServer(CERTFILE,
1843 ssl_version=ssl.PROTOCOL_SSLv23,
1844 chatty=False) as server:
1845 with socket.socket() as sock:
1846 s = context.wrap_socket(sock)
1847 with self.assertRaises((OSError, ssl.SSLError)):
1848 s.connect((HOST, server.port))
1849 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1850
Antoine Pitroud6494802011-07-21 01:11:30 +02001851 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1852 "'tls-unique' channel binding not available")
1853 def test_tls_unique_channel_binding(self):
1854 """Test tls-unique channel binding."""
1855 if support.verbose:
1856 sys.stdout.write("\n")
1857
1858 server = ThreadedEchoServer(CERTFILE,
1859 certreqs=ssl.CERT_NONE,
1860 ssl_version=ssl.PROTOCOL_TLSv1,
1861 cacerts=CERTFILE,
1862 chatty=True,
1863 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001864 with server:
1865 s = ssl.wrap_socket(socket.socket(),
1866 server_side=False,
1867 certfile=CERTFILE,
1868 ca_certs=CERTFILE,
1869 cert_reqs=ssl.CERT_NONE,
1870 ssl_version=ssl.PROTOCOL_TLSv1)
1871 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001872 # get the data
1873 cb_data = s.get_channel_binding("tls-unique")
1874 if support.verbose:
1875 sys.stdout.write(" got channel binding data: {0!r}\n"
1876 .format(cb_data))
1877
1878 # check if it is sane
1879 self.assertIsNotNone(cb_data)
1880 self.assertEqual(len(cb_data), 12) # True for TLSv1
1881
1882 # and compare with the peers version
1883 s.write(b"CB tls-unique\n")
1884 peer_data_repr = s.read().strip()
1885 self.assertEqual(peer_data_repr,
1886 repr(cb_data).encode("us-ascii"))
1887 s.close()
1888
1889 # now, again
1890 s = ssl.wrap_socket(socket.socket(),
1891 server_side=False,
1892 certfile=CERTFILE,
1893 ca_certs=CERTFILE,
1894 cert_reqs=ssl.CERT_NONE,
1895 ssl_version=ssl.PROTOCOL_TLSv1)
1896 s.connect((HOST, server.port))
1897 new_cb_data = s.get_channel_binding("tls-unique")
1898 if support.verbose:
1899 sys.stdout.write(" got another channel binding data: {0!r}\n"
1900 .format(new_cb_data))
1901 # is it really unique
1902 self.assertNotEqual(cb_data, new_cb_data)
1903 self.assertIsNotNone(cb_data)
1904 self.assertEqual(len(cb_data), 12) # True for TLSv1
1905 s.write(b"CB tls-unique\n")
1906 peer_data_repr = s.read().strip()
1907 self.assertEqual(peer_data_repr,
1908 repr(new_cb_data).encode("us-ascii"))
1909 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001910
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001911 def test_compression(self):
1912 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1913 context.load_cert_chain(CERTFILE)
1914 stats = server_params_test(context, context,
1915 chatty=True, connectionchatty=True)
1916 if support.verbose:
1917 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1918 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1919
1920 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1921 "ssl.OP_NO_COMPRESSION needed for this test")
1922 def test_compression_disabled(self):
1923 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1924 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001925 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001926 stats = server_params_test(context, context,
1927 chatty=True, connectionchatty=True)
1928 self.assertIs(stats['compression'], None)
1929
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001930 def test_dh_params(self):
1931 # Check we can get a connection with ephemeral Diffie-Hellman
1932 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1933 context.load_cert_chain(CERTFILE)
1934 context.load_dh_params(DHFILE)
1935 context.set_ciphers("kEDH")
1936 stats = server_params_test(context, context,
1937 chatty=True, connectionchatty=True)
1938 cipher = stats["cipher"][0]
1939 parts = cipher.split("-")
1940 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1941 self.fail("Non-DH cipher: " + cipher[0])
1942
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001943 def test_selected_npn_protocol(self):
1944 # selected_npn_protocol() is None unless NPN is used
1945 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1946 context.load_cert_chain(CERTFILE)
1947 stats = server_params_test(context, context,
1948 chatty=True, connectionchatty=True)
1949 self.assertIs(stats['client_npn_protocol'], None)
1950
1951 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1952 def test_npn_protocols(self):
1953 server_protocols = ['http/1.1', 'spdy/2']
1954 protocol_tests = [
1955 (['http/1.1', 'spdy/2'], 'http/1.1'),
1956 (['spdy/2', 'http/1.1'], 'http/1.1'),
1957 (['spdy/2', 'test'], 'spdy/2'),
1958 (['abc', 'def'], 'abc')
1959 ]
1960 for client_protocols, expected in protocol_tests:
1961 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1962 server_context.load_cert_chain(CERTFILE)
1963 server_context.set_npn_protocols(server_protocols)
1964 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1965 client_context.load_cert_chain(CERTFILE)
1966 client_context.set_npn_protocols(client_protocols)
1967 stats = server_params_test(client_context, server_context,
1968 chatty=True, connectionchatty=True)
1969
1970 msg = "failed trying %s (s) and %s (c).\n" \
1971 "was expecting %s, but got %%s from the %%s" \
1972 % (str(server_protocols), str(client_protocols),
1973 str(expected))
1974 client_result = stats['client_npn_protocol']
1975 self.assertEqual(client_result, expected, msg % (client_result, "client"))
1976 server_result = stats['server_npn_protocols'][-1] \
1977 if len(stats['server_npn_protocols']) else 'nothing'
1978 self.assertEqual(server_result, expected, msg % (server_result, "server"))
1979
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001980
Thomas Woutersed03b412007-08-28 21:37:11 +00001981def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001982 if support.verbose:
1983 plats = {
1984 'Linux': platform.linux_distribution,
1985 'Mac': platform.mac_ver,
1986 'Windows': platform.win32_ver,
1987 }
1988 for name, func in plats.items():
1989 plat = func()
1990 if plat and plat[0]:
1991 plat = '%s %r' % (name, plat)
1992 break
1993 else:
1994 plat = repr(platform.platform())
1995 print("test_ssl: testing with %r %r" %
1996 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1997 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001998 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001999
Antoine Pitrou152efa22010-05-16 18:19:27 +00002000 for filename in [
2001 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2002 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2003 BADCERT, BADKEY, EMPTYCERT]:
2004 if not os.path.exists(filename):
2005 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002006
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002007 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002008
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002009 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002010 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002011
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002012 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002013 thread_info = support.threading_setup()
2014 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002015 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002016
Antoine Pitrou480a1242010-04-28 21:37:09 +00002017 try:
2018 support.run_unittest(*tests)
2019 finally:
2020 if _have_threads:
2021 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002022
2023if __name__ == "__main__":
2024 test_main()