blob: d549799396071402d22925c6d49a749a1023f2c6 [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
Thomas Woutersed03b412007-08-28 21:37:11 +000059
Thomas Woutersed03b412007-08-28 21:37:11 +000060def handle_error(prefix):
61 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000062 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000063 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000064
Antoine Pitroub5218772010-05-21 09:56:06 +000065def can_clear_options():
66 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020067 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000068
69def no_sslv2_implies_sslv3_hello():
70 # 0.9.7h or higher
71 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
72
Thomas Woutersed03b412007-08-28 21:37:11 +000073
Antoine Pitrou23df4832010-08-04 17:14:06 +000074# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
75def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020076 if hasattr(ssl, 'PROTOCOL_SSLv2'):
77 @functools.wraps(func)
78 def f(*args, **kwargs):
79 try:
80 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
81 except ssl.SSLError:
82 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
83 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
84 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
85 return func(*args, **kwargs)
86 return f
87 else:
88 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000089
90
Antoine Pitrou152efa22010-05-16 18:19:27 +000091class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000092
Antoine Pitrou480a1242010-04-28 21:37:09 +000093 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020094 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000095 ssl.PROTOCOL_SSLv23
96 ssl.PROTOCOL_SSLv3
97 ssl.PROTOCOL_TLSv1
98 ssl.CERT_NONE
99 ssl.CERT_OPTIONAL
100 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100101 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100102 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100103 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
104 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000105 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100106 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000107
Antoine Pitrou480a1242010-04-28 21:37:09 +0000108 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000109 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000110 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000111 sys.stdout.write("\n RAND_status is %d (%s)\n"
112 % (v, (v and "sufficient randomness") or
113 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200114
115 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
116 self.assertEqual(len(data), 16)
117 self.assertEqual(is_cryptographic, v == 1)
118 if v:
119 data = ssl.RAND_bytes(16)
120 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200121 else:
122 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200123
Thomas Woutersed03b412007-08-28 21:37:11 +0000124 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000125 ssl.RAND_egd(1)
126 except TypeError:
127 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000128 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 print("didn't raise TypeError")
130 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 Pitroueb585ad2010-10-22 18:24:20 +0000541 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000542 def test_session_stats(self):
543 for proto in PROTOCOLS:
544 ctx = ssl.SSLContext(proto)
545 self.assertEqual(ctx.session_stats(), {
546 'number': 0,
547 'connect': 0,
548 'connect_good': 0,
549 'connect_renegotiate': 0,
550 'accept': 0,
551 'accept_good': 0,
552 'accept_renegotiate': 0,
553 'hits': 0,
554 'misses': 0,
555 'timeouts': 0,
556 'cache_full': 0,
557 })
558
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000559 def test_set_default_verify_paths(self):
560 # There's not much we can do to test that it acts as expected,
561 # so just check it doesn't crash or raise an exception.
562 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
563 ctx.set_default_verify_paths()
564
Antoine Pitrou501da612011-12-21 09:27:41 +0100565 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100566 def test_set_ecdh_curve(self):
567 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
568 ctx.set_ecdh_curve("prime256v1")
569 ctx.set_ecdh_curve(b"prime256v1")
570 self.assertRaises(TypeError, ctx.set_ecdh_curve)
571 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
572 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
573 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
574
Antoine Pitrou152efa22010-05-16 18:19:27 +0000575
Bill Janssen6e027db2007-11-15 22:23:56 +0000576class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000577
Antoine Pitrou480a1242010-04-28 21:37:09 +0000578 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000579 with support.transient_internet("svn.python.org"):
580 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
581 cert_reqs=ssl.CERT_NONE)
582 try:
583 s.connect(("svn.python.org", 443))
584 self.assertEqual({}, s.getpeercert())
585 finally:
586 s.close()
587
588 # this should fail because we have no verification certs
589 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
590 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000591 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
592 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000593 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000594
Antoine Pitrou350c7222010-09-09 13:31:46 +0000595 # this should succeed because we specify the root cert
596 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
597 cert_reqs=ssl.CERT_REQUIRED,
598 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
599 try:
600 s.connect(("svn.python.org", 443))
601 self.assertTrue(s.getpeercert())
602 finally:
603 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000604
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000605 def test_connect_ex(self):
606 # Issue #11326: check connect_ex() implementation
607 with support.transient_internet("svn.python.org"):
608 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
609 cert_reqs=ssl.CERT_REQUIRED,
610 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
611 try:
612 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
613 self.assertTrue(s.getpeercert())
614 finally:
615 s.close()
616
617 def test_non_blocking_connect_ex(self):
618 # Issue #11326: non-blocking connect_ex() should allow handshake
619 # to proceed after the socket gets ready.
620 with support.transient_internet("svn.python.org"):
621 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
622 cert_reqs=ssl.CERT_REQUIRED,
623 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
624 do_handshake_on_connect=False)
625 try:
626 s.setblocking(False)
627 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000628 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
629 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000630 # Wait for connect to finish
631 select.select([], [s], [], 5.0)
632 # Non-blocking handshake
633 while True:
634 try:
635 s.do_handshake()
636 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200637 except ssl.SSLWantReadError:
638 select.select([s], [], [], 5.0)
639 except ssl.SSLWantWriteError:
640 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000641 # SSL established
642 self.assertTrue(s.getpeercert())
643 finally:
644 s.close()
645
Antoine Pitroub4410db2011-05-18 18:51:06 +0200646 def test_timeout_connect_ex(self):
647 # Issue #12065: on a timeout, connect_ex() should return the original
648 # errno (mimicking the behaviour of non-SSL sockets).
649 with support.transient_internet("svn.python.org"):
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 do_handshake_on_connect=False)
654 try:
655 s.settimeout(0.0000001)
656 rc = s.connect_ex(('svn.python.org', 443))
657 if rc == 0:
658 self.skipTest("svn.python.org responded too quickly")
659 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
660 finally:
661 s.close()
662
Antoine Pitrou152efa22010-05-16 18:19:27 +0000663 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000664 with support.transient_internet("svn.python.org"):
665 # Same as test_connect, but with a separately created context
666 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
667 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
668 s.connect(("svn.python.org", 443))
669 try:
670 self.assertEqual({}, s.getpeercert())
671 finally:
672 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000673 # Same with a server hostname
674 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
675 server_hostname="svn.python.org")
676 if ssl.HAS_SNI:
677 s.connect(("svn.python.org", 443))
678 s.close()
679 else:
680 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000681 # This should fail because we have no verification certs
682 ctx.verify_mode = ssl.CERT_REQUIRED
683 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000684 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000685 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000686 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000687 # This should succeed because we specify the root cert
688 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
689 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
690 s.connect(("svn.python.org", 443))
691 try:
692 cert = s.getpeercert()
693 self.assertTrue(cert)
694 finally:
695 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000696
697 def test_connect_capath(self):
698 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000699 # NOTE: the subject hashing algorithm has been changed between
700 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
701 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000702 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000703 with support.transient_internet("svn.python.org"):
704 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
705 ctx.verify_mode = ssl.CERT_REQUIRED
706 ctx.load_verify_locations(capath=CAPATH)
707 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
708 s.connect(("svn.python.org", 443))
709 try:
710 cert = s.getpeercert()
711 self.assertTrue(cert)
712 finally:
713 s.close()
714 # Same with a bytes `capath` argument
715 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
716 ctx.verify_mode = ssl.CERT_REQUIRED
717 ctx.load_verify_locations(capath=BYTES_CAPATH)
718 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
719 s.connect(("svn.python.org", 443))
720 try:
721 cert = s.getpeercert()
722 self.assertTrue(cert)
723 finally:
724 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000725
Antoine Pitroue3220242010-04-24 11:13:53 +0000726 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
727 def test_makefile_close(self):
728 # Issue #5238: creating a file-like object with makefile() shouldn't
729 # delay closing the underlying "real socket" (here tested with its
730 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000731 with support.transient_internet("svn.python.org"):
732 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
733 ss.connect(("svn.python.org", 443))
734 fd = ss.fileno()
735 f = ss.makefile()
736 f.close()
737 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000738 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000739 # Closing the SSL socket should close the fd too
740 ss.close()
741 gc.collect()
742 with self.assertRaises(OSError) as e:
743 os.read(fd, 0)
744 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000745
Antoine Pitrou480a1242010-04-28 21:37:09 +0000746 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000747 with support.transient_internet("svn.python.org"):
748 s = socket.socket(socket.AF_INET)
749 s.connect(("svn.python.org", 443))
750 s.setblocking(False)
751 s = ssl.wrap_socket(s,
752 cert_reqs=ssl.CERT_NONE,
753 do_handshake_on_connect=False)
754 count = 0
755 while True:
756 try:
757 count += 1
758 s.do_handshake()
759 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200760 except ssl.SSLWantReadError:
761 select.select([s], [], [])
762 except ssl.SSLWantWriteError:
763 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000764 s.close()
765 if support.verbose:
766 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000767
Antoine Pitrou480a1242010-04-28 21:37:09 +0000768 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200769 def _test_get_server_certificate(host, port, cert=None):
770 with support.transient_internet(host):
771 pem = ssl.get_server_certificate((host, port))
772 if not pem:
773 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200774
Antoine Pitrou15399c32011-04-28 19:23:55 +0200775 try:
776 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
777 except ssl.SSLError as x:
778 #should fail
779 if support.verbose:
780 sys.stdout.write("%s\n" % x)
781 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200782 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
783
Antoine Pitrou15399c32011-04-28 19:23:55 +0200784 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
785 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200786 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000787 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200788 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000789
Antoine Pitrou15399c32011-04-28 19:23:55 +0200790 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
791 if support.IPV6_ENABLED:
792 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000793
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000794 def test_ciphers(self):
795 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000796 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000797 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000798 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000799 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000800 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
801 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
802 s.connect(remote)
803 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000804 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000805 with socket.socket(socket.AF_INET) as sock:
806 s = ssl.wrap_socket(sock,
807 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
808 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000809
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000810 def test_algorithms(self):
811 # Issue #8484: all algorithms should be available when verifying a
812 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000813 # SHA256 was added in OpenSSL 0.9.8
814 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
815 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000816 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
817 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000818 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000819 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000820 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
821 cert_reqs=ssl.CERT_REQUIRED,
822 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000823 try:
824 s.connect(remote)
825 if support.verbose:
826 sys.stdout.write("\nCipher with %r is %r\n" %
827 (remote, s.cipher()))
828 sys.stdout.write("Certificate is:\n%s\n" %
829 pprint.pformat(s.getpeercert()))
830 finally:
831 s.close()
832
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000833
834try:
835 import threading
836except ImportError:
837 _have_threads = False
838else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000839 _have_threads = True
840
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000841 from test.ssl_servers import make_https_server
842
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000843 class ThreadedEchoServer(threading.Thread):
844
845 class ConnectionHandler(threading.Thread):
846
847 """A mildly complicated class, because we want it to work both
848 with and without the SSL wrapper around the socket connection, so
849 that we can test the STARTTLS functionality."""
850
Bill Janssen6e027db2007-11-15 22:23:56 +0000851 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000852 self.server = server
853 self.running = False
854 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000855 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856 self.sock.setblocking(1)
857 self.sslconn = None
858 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000859 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860
Antoine Pitrou480a1242010-04-28 21:37:09 +0000861 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000863 self.sslconn = self.server.context.wrap_socket(
864 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000865 except ssl.SSLError:
866 # XXX Various errors can have happened here, for example
867 # a mismatching protocol version, an invalid certificate,
868 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000869 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000870 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000871 self.running = False
872 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000873 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000874 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000875 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000876 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000877 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000878 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
880 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000881 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000882 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
883 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000884 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000885 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
886 return True
887
888 def read(self):
889 if self.sslconn:
890 return self.sslconn.read()
891 else:
892 return self.sock.recv(1024)
893
894 def write(self, bytes):
895 if self.sslconn:
896 return self.sslconn.write(bytes)
897 else:
898 return self.sock.send(bytes)
899
900 def close(self):
901 if self.sslconn:
902 self.sslconn.close()
903 else:
904 self.sock.close()
905
Antoine Pitrou480a1242010-04-28 21:37:09 +0000906 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 self.running = True
908 if not self.server.starttls_server:
909 if not self.wrap_conn():
910 return
911 while self.running:
912 try:
913 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000914 stripped = msg.strip()
915 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000916 # eof, so quit this handler
917 self.running = False
918 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000919 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000920 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921 sys.stdout.write(" server: client closed connection\n")
922 self.close()
923 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000924 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000925 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000926 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000927 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000928 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000929 if not self.wrap_conn():
930 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000931 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000932 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000933 if support.verbose and self.server.connectionchatty:
934 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000935 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000936 self.sock = self.sslconn.unwrap()
937 self.sslconn = None
938 if support.verbose and self.server.connectionchatty:
939 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200940 elif stripped == b'CB tls-unique':
941 if support.verbose and self.server.connectionchatty:
942 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
943 data = self.sslconn.get_channel_binding("tls-unique")
944 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000945 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000946 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 self.server.connectionchatty):
948 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000949 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
950 % (msg, ctype, msg.lower(), ctype))
951 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000952 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953 if self.server.chatty:
954 handle_error("Test server failure:\n")
955 self.close()
956 self.running = False
957 # normally, we'd just stop here, but for the test
958 # harness, we want to stop the server
959 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960
Antoine Pitroub5218772010-05-21 09:56:06 +0000961 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000962 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000963 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000964 ciphers=None, context=None):
965 if context:
966 self.context = context
967 else:
968 self.context = ssl.SSLContext(ssl_version
969 if ssl_version is not None
970 else ssl.PROTOCOL_TLSv1)
971 self.context.verify_mode = (certreqs if certreqs is not None
972 else ssl.CERT_NONE)
973 if cacerts:
974 self.context.load_verify_locations(cacerts)
975 if certificate:
976 self.context.load_cert_chain(certificate)
977 if ciphers:
978 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979 self.chatty = chatty
980 self.connectionchatty = connectionchatty
981 self.starttls_server = starttls_server
982 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000983 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000985 self.active = False
986 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000987 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000988
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100989 def __enter__(self):
990 self.start(threading.Event())
991 self.flag.wait()
992
993 def __exit__(self, *args):
994 self.stop()
995 self.join()
996
Antoine Pitrou480a1242010-04-28 21:37:09 +0000997 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 self.flag = flag
999 threading.Thread.start(self)
1000
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001002 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 self.sock.listen(5)
1004 self.active = True
1005 if self.flag:
1006 # signal an event
1007 self.flag.set()
1008 while self.active:
1009 try:
1010 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001011 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001012 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001013 + repr(connaddr) + '\n')
1014 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001015 handler.start()
1016 except socket.timeout:
1017 pass
1018 except KeyboardInterrupt:
1019 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001020 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001021
Antoine Pitrou480a1242010-04-28 21:37:09 +00001022 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001023 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001024
Bill Janssen54cc54c2007-12-14 22:08:56 +00001025 class AsyncoreEchoServer(threading.Thread):
1026
1027 # this one's based on asyncore.dispatcher
1028
1029 class EchoServer (asyncore.dispatcher):
1030
1031 class ConnectionHandler (asyncore.dispatcher_with_send):
1032
1033 def __init__(self, conn, certfile):
1034 self.socket = ssl.wrap_socket(conn, server_side=True,
1035 certfile=certfile,
1036 do_handshake_on_connect=False)
1037 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001038 self._ssl_accepting = True
1039 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001040
1041 def readable(self):
1042 if isinstance(self.socket, ssl.SSLSocket):
1043 while self.socket.pending() > 0:
1044 self.handle_read_event()
1045 return True
1046
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001047 def _do_ssl_handshake(self):
1048 try:
1049 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001050 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1051 return
1052 except ssl.SSLEOFError:
1053 return self.handle_close()
1054 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001055 raise
1056 except socket.error as err:
1057 if err.args[0] == errno.ECONNABORTED:
1058 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001059 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001060 self._ssl_accepting = False
1061
1062 def handle_read(self):
1063 if self._ssl_accepting:
1064 self._do_ssl_handshake()
1065 else:
1066 data = self.recv(1024)
1067 if support.verbose:
1068 sys.stdout.write(" server: read %s from client\n" % repr(data))
1069 if not data:
1070 self.close()
1071 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001072 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001073
1074 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001075 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001076 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001077 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1078
1079 def handle_error(self):
1080 raise
1081
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001082 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001083 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001084 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1085 self.port = support.bind_port(sock, '')
1086 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001087 self.listen(5)
1088
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001089 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001090 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001091 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1092 self.ConnectionHandler(sock_obj, self.certfile)
1093
1094 def handle_error(self):
1095 raise
1096
Trent Nelson78520002008-04-10 20:54:35 +00001097 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001098 self.flag = None
1099 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001100 self.server = self.EchoServer(certfile)
1101 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001102 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001103 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001104
1105 def __str__(self):
1106 return "<%s %s>" % (self.__class__.__name__, self.server)
1107
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001108 def __enter__(self):
1109 self.start(threading.Event())
1110 self.flag.wait()
1111
1112 def __exit__(self, *args):
1113 if support.verbose:
1114 sys.stdout.write(" cleanup: stopping server.\n")
1115 self.stop()
1116 if support.verbose:
1117 sys.stdout.write(" cleanup: joining server thread.\n")
1118 self.join()
1119 if support.verbose:
1120 sys.stdout.write(" cleanup: successfully joined.\n")
1121
Bill Janssen54cc54c2007-12-14 22:08:56 +00001122 def start (self, flag=None):
1123 self.flag = flag
1124 threading.Thread.start(self)
1125
Antoine Pitrou480a1242010-04-28 21:37:09 +00001126 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001127 self.active = True
1128 if self.flag:
1129 self.flag.set()
1130 while self.active:
1131 try:
1132 asyncore.loop(1)
1133 except:
1134 pass
1135
Antoine Pitrou480a1242010-04-28 21:37:09 +00001136 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001137 self.active = False
1138 self.server.close()
1139
Antoine Pitrou480a1242010-04-28 21:37:09 +00001140 def bad_cert_test(certfile):
1141 """
1142 Launch a server with CERT_REQUIRED, and check that trying to
1143 connect to it with the given client certificate fails.
1144 """
Trent Nelson78520002008-04-10 20:54:35 +00001145 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001146 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001147 cacerts=CERTFILE, chatty=False,
1148 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001149 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001150 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001151 with socket.socket() as sock:
1152 s = ssl.wrap_socket(sock,
1153 certfile=certfile,
1154 ssl_version=ssl.PROTOCOL_TLSv1)
1155 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001157 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001158 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001159 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001160 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001161 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001162 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001163 if x.errno != errno.ENOENT:
1164 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001165 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001166 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001168 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001169
Antoine Pitroub5218772010-05-21 09:56:06 +00001170 def server_params_test(client_context, server_context, indata=b"FOO\n",
1171 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001172 """
1173 Launch a server, connect a client to it and try various reads
1174 and writes.
1175 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001176 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001177 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001178 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001179 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001180 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001181 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001183 if connectionchatty:
1184 if support.verbose:
1185 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001186 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001187 s.write(arg)
1188 outdata = s.read()
1189 if connectionchatty:
1190 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001191 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001192 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001193 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001194 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1195 % (outdata[:20], len(outdata),
1196 indata[:20].lower(), len(indata)))
1197 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001198 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001199 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001200 sys.stdout.write(" client: closing connection.\n")
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001201 stats = {
1202 'compression': s.compression(),
1203 'cipher': s.cipher(),
1204 }
Bill Janssen6e027db2007-11-15 22:23:56 +00001205 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001206 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001207
Antoine Pitroub5218772010-05-21 09:56:06 +00001208 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1209 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001210 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001212 certtype = {
1213 ssl.CERT_NONE: "CERT_NONE",
1214 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1215 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1216 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001217 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001218 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001219 sys.stdout.write(formatstr %
1220 (ssl.get_protocol_name(client_protocol),
1221 ssl.get_protocol_name(server_protocol),
1222 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001223 client_context = ssl.SSLContext(client_protocol)
1224 client_context.options = ssl.OP_ALL | client_options
1225 server_context = ssl.SSLContext(server_protocol)
1226 server_context.options = ssl.OP_ALL | server_options
1227 for ctx in (client_context, server_context):
1228 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001229 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1230 # will send an SSLv3 hello (rather than SSLv2) starting from
1231 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001232 ctx.set_ciphers("ALL")
1233 ctx.load_cert_chain(CERTFILE)
1234 ctx.load_verify_locations(CERTFILE)
1235 try:
1236 server_params_test(client_context, server_context,
1237 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001238 # Protocol mismatch can result in either an SSLError, or a
1239 # "Connection reset by peer" error.
1240 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001241 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001242 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001243 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001244 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001245 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001246 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001247 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001248 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001249 "Client protocol %s succeeded with server protocol %s!"
1250 % (ssl.get_protocol_name(client_protocol),
1251 ssl.get_protocol_name(server_protocol)))
1252
1253
Bill Janssen6e027db2007-11-15 22:23:56 +00001254 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001255
Antoine Pitrou23df4832010-08-04 17:14:06 +00001256 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001257 def test_echo(self):
1258 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001259 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001260 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001261 for protocol in PROTOCOLS:
1262 context = ssl.SSLContext(protocol)
1263 context.load_cert_chain(CERTFILE)
1264 server_params_test(context, context,
1265 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001266
Antoine Pitrou480a1242010-04-28 21:37:09 +00001267 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001268 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001269 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001270 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1271 context.verify_mode = ssl.CERT_REQUIRED
1272 context.load_verify_locations(CERTFILE)
1273 context.load_cert_chain(CERTFILE)
1274 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001275 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001276 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001277 s.connect((HOST, server.port))
1278 cert = s.getpeercert()
1279 self.assertTrue(cert, "Can't get peer certificate.")
1280 cipher = s.cipher()
1281 if support.verbose:
1282 sys.stdout.write(pprint.pformat(cert) + '\n')
1283 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1284 if 'subject' not in cert:
1285 self.fail("No subject field in certificate: %s." %
1286 pprint.pformat(cert))
1287 if ((('organizationName', 'Python Software Foundation'),)
1288 not in cert['subject']):
1289 self.fail(
1290 "Missing or invalid 'organizationName' field in certificate subject; "
1291 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001292 self.assertIn('notBefore', cert)
1293 self.assertIn('notAfter', cert)
1294 before = ssl.cert_time_to_seconds(cert['notBefore'])
1295 after = ssl.cert_time_to_seconds(cert['notAfter'])
1296 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001297 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001298
Antoine Pitrou480a1242010-04-28 21:37:09 +00001299 def test_empty_cert(self):
1300 """Connecting with an empty cert file"""
1301 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1302 "nullcert.pem"))
1303 def test_malformed_cert(self):
1304 """Connecting with a badly formatted certificate (syntax error)"""
1305 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1306 "badcert.pem"))
1307 def test_nonexisting_cert(self):
1308 """Connecting with a non-existing cert file"""
1309 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1310 "wrongcert.pem"))
1311 def test_malformed_key(self):
1312 """Connecting with a badly formatted key (syntax error)"""
1313 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1314 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001315
Antoine Pitrou480a1242010-04-28 21:37:09 +00001316 def test_rude_shutdown(self):
1317 """A brutal shutdown of an SSL server should raise an IOError
1318 in the client when attempting handshake.
1319 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001320 listener_ready = threading.Event()
1321 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001322
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001323 s = socket.socket()
1324 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001325
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001326 # `listener` runs in a thread. It sits in an accept() until
1327 # the main thread connects. Then it rudely closes the socket,
1328 # and sets Event `listener_gone` to let the main thread know
1329 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001330 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001331 s.listen(5)
1332 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001333 newsock, addr = s.accept()
1334 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001335 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001336 listener_gone.set()
1337
1338 def connector():
1339 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001340 with socket.socket() as c:
1341 c.connect((HOST, port))
1342 listener_gone.wait()
1343 try:
1344 ssl_sock = ssl.wrap_socket(c)
1345 except IOError:
1346 pass
1347 else:
1348 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001349
1350 t = threading.Thread(target=listener)
1351 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001352 try:
1353 connector()
1354 finally:
1355 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001356
Antoine Pitrou23df4832010-08-04 17:14:06 +00001357 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001358 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1359 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001360 def test_protocol_sslv2(self):
1361 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001362 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001363 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001364 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1365 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1366 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1367 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1368 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1369 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001370 # SSLv23 client with specific SSL options
1371 if no_sslv2_implies_sslv3_hello():
1372 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1373 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1374 client_options=ssl.OP_NO_SSLv2)
1375 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1376 client_options=ssl.OP_NO_SSLv3)
1377 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1378 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001379
Antoine Pitrou23df4832010-08-04 17:14:06 +00001380 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 def test_protocol_sslv23(self):
1382 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001383 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001384 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001385 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1386 try:
1387 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1388 except (ssl.SSLError, socket.error) as x:
1389 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1390 if support.verbose:
1391 sys.stdout.write(
1392 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1393 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001394 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1395 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1396 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001397
Antoine Pitrou480a1242010-04-28 21:37:09 +00001398 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1399 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1400 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001401
Antoine Pitrou480a1242010-04-28 21:37:09 +00001402 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1403 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1404 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001405
Antoine Pitroub5218772010-05-21 09:56:06 +00001406 # Server with specific SSL options
1407 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1408 server_options=ssl.OP_NO_SSLv3)
1409 # Will choose TLSv1
1410 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1411 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1412 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1413 server_options=ssl.OP_NO_TLSv1)
1414
1415
Antoine Pitrou23df4832010-08-04 17:14:06 +00001416 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001417 def test_protocol_sslv3(self):
1418 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001419 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001420 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001421 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1422 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1423 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001424 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1425 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001426 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1427 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001428 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001429 if no_sslv2_implies_sslv3_hello():
1430 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1431 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1432 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001433
Antoine Pitrou23df4832010-08-04 17:14:06 +00001434 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 def test_protocol_tlsv1(self):
1436 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001437 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001438 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001439 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1440 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1441 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001442 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1443 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001445 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1446 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001447
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 def test_starttls(self):
1449 """Switching from clear text to encrypted and back again."""
1450 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 +00001451
Trent Nelson78520002008-04-10 20:54:35 +00001452 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001453 ssl_version=ssl.PROTOCOL_TLSv1,
1454 starttls_server=True,
1455 chatty=True,
1456 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001457 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001458 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001459 s = socket.socket()
1460 s.setblocking(1)
1461 s.connect((HOST, server.port))
1462 if support.verbose:
1463 sys.stdout.write("\n")
1464 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001465 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001466 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001467 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001468 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001469 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001470 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001471 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001472 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001473 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001474 msg = outdata.strip().lower()
1475 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1476 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001477 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001478 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001479 " client: read %r from server, starting TLS...\n"
1480 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001481 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1482 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001483 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1484 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001485 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001486 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001487 " client: read %r from server, ending TLS...\n"
1488 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001489 s = conn.unwrap()
1490 wrapped = False
1491 else:
1492 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001493 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001494 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001495 if support.verbose:
1496 sys.stdout.write(" client: closing connection.\n")
1497 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001498 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001499 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001500 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001501 if wrapped:
1502 conn.close()
1503 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001504 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001505
Antoine Pitrou480a1242010-04-28 21:37:09 +00001506 def test_socketserver(self):
1507 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001508 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001509 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001510 if support.verbose:
1511 sys.stdout.write('\n')
1512 with open(CERTFILE, 'rb') as f:
1513 d1 = f.read()
1514 d2 = ''
1515 # now fetch the same data from the HTTPS server
1516 url = 'https://%s:%d/%s' % (
1517 HOST, server.port, os.path.split(CERTFILE)[1])
1518 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001519 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001520 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001521 if dlen and (int(dlen) > 0):
1522 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001523 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001524 sys.stdout.write(
1525 " client: read %d bytes from remote server '%s'\n"
1526 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001527 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001528 f.close()
1529 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530
Antoine Pitrou480a1242010-04-28 21:37:09 +00001531 def test_asyncore_server(self):
1532 """Check the example asyncore integration."""
1533 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001534
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001535 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001536 sys.stdout.write("\n")
1537
Antoine Pitrou480a1242010-04-28 21:37:09 +00001538 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001539 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001540 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001541 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001542 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001543 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001544 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 " client: sending %r...\n" % indata)
1546 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001547 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001548 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001549 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001550 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001551 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001552 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1553 % (outdata[:20], len(outdata),
1554 indata[:20].lower(), len(indata)))
1555 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001556 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001557 sys.stdout.write(" client: closing connection.\n")
1558 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001559 if support.verbose:
1560 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001561
Antoine Pitrou480a1242010-04-28 21:37:09 +00001562 def test_recv_send(self):
1563 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001564 if support.verbose:
1565 sys.stdout.write("\n")
1566
1567 server = ThreadedEchoServer(CERTFILE,
1568 certreqs=ssl.CERT_NONE,
1569 ssl_version=ssl.PROTOCOL_TLSv1,
1570 cacerts=CERTFILE,
1571 chatty=True,
1572 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001573 with server:
1574 s = ssl.wrap_socket(socket.socket(),
1575 server_side=False,
1576 certfile=CERTFILE,
1577 ca_certs=CERTFILE,
1578 cert_reqs=ssl.CERT_NONE,
1579 ssl_version=ssl.PROTOCOL_TLSv1)
1580 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001581 # helper methods for standardising recv* method signatures
1582 def _recv_into():
1583 b = bytearray(b"\0"*100)
1584 count = s.recv_into(b)
1585 return b[:count]
1586
1587 def _recvfrom_into():
1588 b = bytearray(b"\0"*100)
1589 count, addr = s.recvfrom_into(b)
1590 return b[:count]
1591
1592 # (name, method, whether to expect success, *args)
1593 send_methods = [
1594 ('send', s.send, True, []),
1595 ('sendto', s.sendto, False, ["some.address"]),
1596 ('sendall', s.sendall, True, []),
1597 ]
1598 recv_methods = [
1599 ('recv', s.recv, True, []),
1600 ('recvfrom', s.recvfrom, False, ["some.address"]),
1601 ('recv_into', _recv_into, True, []),
1602 ('recvfrom_into', _recvfrom_into, False, []),
1603 ]
1604 data_prefix = "PREFIX_"
1605
1606 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001607 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001608 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001609 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001610 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001611 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001612 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001613 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001614 "<<{outdata:r}>> ({nout:d}) received; "
1615 "expected <<{indata:r}>> ({nin:d})\n".format(
1616 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001617 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001618 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001619 )
1620 )
1621 except ValueError as e:
1622 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001623 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001624 "Failed to send with method <<{name:s}>>; "
1625 "expected to succeed.\n".format(name=meth_name)
1626 )
1627 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001628 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001629 "Method <<{name:s}>> failed with unexpected "
1630 "exception message: {exp:s}\n".format(
1631 name=meth_name, exp=e
1632 )
1633 )
1634
1635 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001636 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001637 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001639 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001640 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001641 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001642 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001643 "<<{outdata:r}>> ({nout:d}) received; "
1644 "expected <<{indata:r}>> ({nin:d})\n".format(
1645 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001646 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001647 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001648 )
1649 )
1650 except ValueError as e:
1651 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001652 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001653 "Failed to receive with method <<{name:s}>>; "
1654 "expected to succeed.\n".format(name=meth_name)
1655 )
1656 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001657 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001658 "Method <<{name:s}>> failed with unexpected "
1659 "exception message: {exp:s}\n".format(
1660 name=meth_name, exp=e
1661 )
1662 )
1663 # consume data
1664 s.read()
1665
Nick Coghlan513886a2011-08-28 00:00:27 +10001666 # Make sure sendmsg et al are disallowed to avoid
1667 # inadvertent disclosure of data and/or corruption
1668 # of the encrypted data stream
1669 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1670 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1671 self.assertRaises(NotImplementedError,
1672 s.recvmsg_into, bytearray(100))
1673
Antoine Pitrou480a1242010-04-28 21:37:09 +00001674 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001675 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001676
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001677 def test_handshake_timeout(self):
1678 # Issue #5103: SSL handshake must respect the socket timeout
1679 server = socket.socket(socket.AF_INET)
1680 host = "127.0.0.1"
1681 port = support.bind_port(server)
1682 started = threading.Event()
1683 finish = False
1684
1685 def serve():
1686 server.listen(5)
1687 started.set()
1688 conns = []
1689 while not finish:
1690 r, w, e = select.select([server], [], [], 0.1)
1691 if server in r:
1692 # Let the socket hang around rather than having
1693 # it closed by garbage collection.
1694 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001695 for sock in conns:
1696 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001697
1698 t = threading.Thread(target=serve)
1699 t.start()
1700 started.wait()
1701
1702 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001703 try:
1704 c = socket.socket(socket.AF_INET)
1705 c.settimeout(0.2)
1706 c.connect((host, port))
1707 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001708 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001709 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001710 finally:
1711 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001712 try:
1713 c = socket.socket(socket.AF_INET)
1714 c = ssl.wrap_socket(c)
1715 c.settimeout(0.2)
1716 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001717 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001718 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001719 finally:
1720 c.close()
1721 finally:
1722 finish = True
1723 t.join()
1724 server.close()
1725
Antoine Pitroud6494802011-07-21 01:11:30 +02001726 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1727 "'tls-unique' channel binding not available")
1728 def test_tls_unique_channel_binding(self):
1729 """Test tls-unique channel binding."""
1730 if support.verbose:
1731 sys.stdout.write("\n")
1732
1733 server = ThreadedEchoServer(CERTFILE,
1734 certreqs=ssl.CERT_NONE,
1735 ssl_version=ssl.PROTOCOL_TLSv1,
1736 cacerts=CERTFILE,
1737 chatty=True,
1738 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001739 with server:
1740 s = ssl.wrap_socket(socket.socket(),
1741 server_side=False,
1742 certfile=CERTFILE,
1743 ca_certs=CERTFILE,
1744 cert_reqs=ssl.CERT_NONE,
1745 ssl_version=ssl.PROTOCOL_TLSv1)
1746 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001747 # get the data
1748 cb_data = s.get_channel_binding("tls-unique")
1749 if support.verbose:
1750 sys.stdout.write(" got channel binding data: {0!r}\n"
1751 .format(cb_data))
1752
1753 # check if it is sane
1754 self.assertIsNotNone(cb_data)
1755 self.assertEqual(len(cb_data), 12) # True for TLSv1
1756
1757 # and compare with the peers version
1758 s.write(b"CB tls-unique\n")
1759 peer_data_repr = s.read().strip()
1760 self.assertEqual(peer_data_repr,
1761 repr(cb_data).encode("us-ascii"))
1762 s.close()
1763
1764 # now, again
1765 s = ssl.wrap_socket(socket.socket(),
1766 server_side=False,
1767 certfile=CERTFILE,
1768 ca_certs=CERTFILE,
1769 cert_reqs=ssl.CERT_NONE,
1770 ssl_version=ssl.PROTOCOL_TLSv1)
1771 s.connect((HOST, server.port))
1772 new_cb_data = s.get_channel_binding("tls-unique")
1773 if support.verbose:
1774 sys.stdout.write(" got another channel binding data: {0!r}\n"
1775 .format(new_cb_data))
1776 # is it really unique
1777 self.assertNotEqual(cb_data, new_cb_data)
1778 self.assertIsNotNone(cb_data)
1779 self.assertEqual(len(cb_data), 12) # True for TLSv1
1780 s.write(b"CB tls-unique\n")
1781 peer_data_repr = s.read().strip()
1782 self.assertEqual(peer_data_repr,
1783 repr(new_cb_data).encode("us-ascii"))
1784 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001785
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001786 def test_compression(self):
1787 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1788 context.load_cert_chain(CERTFILE)
1789 stats = server_params_test(context, context,
1790 chatty=True, connectionchatty=True)
1791 if support.verbose:
1792 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1793 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1794
1795 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1796 "ssl.OP_NO_COMPRESSION needed for this test")
1797 def test_compression_disabled(self):
1798 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1799 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001800 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001801 stats = server_params_test(context, context,
1802 chatty=True, connectionchatty=True)
1803 self.assertIs(stats['compression'], None)
1804
1805
Thomas Woutersed03b412007-08-28 21:37:11 +00001806def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001807 if support.verbose:
1808 plats = {
1809 'Linux': platform.linux_distribution,
1810 'Mac': platform.mac_ver,
1811 'Windows': platform.win32_ver,
1812 }
1813 for name, func in plats.items():
1814 plat = func()
1815 if plat and plat[0]:
1816 plat = '%s %r' % (name, plat)
1817 break
1818 else:
1819 plat = repr(platform.platform())
1820 print("test_ssl: testing with %r %r" %
1821 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1822 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001823 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001824
Antoine Pitrou152efa22010-05-16 18:19:27 +00001825 for filename in [
1826 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1827 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1828 BADCERT, BADKEY, EMPTYCERT]:
1829 if not os.path.exists(filename):
1830 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001831
Antoine Pitrou152efa22010-05-16 18:19:27 +00001832 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001833
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001834 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001835 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001836
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001837 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001838 thread_info = support.threading_setup()
1839 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001840 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001841
Antoine Pitrou480a1242010-04-28 21:37:09 +00001842 try:
1843 support.run_unittest(*tests)
1844 finally:
1845 if _have_threads:
1846 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001847
1848if __name__ == "__main__":
1849 test_main()