blob: 1960e143473134764aec6e409541aaa7ec27f34e [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 Pitrou480a1242010-04-28 21:37:09 +0000989 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 self.flag = flag
991 threading.Thread.start(self)
992
Antoine Pitrou480a1242010-04-28 21:37:09 +0000993 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000994 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995 self.sock.listen(5)
996 self.active = True
997 if self.flag:
998 # signal an event
999 self.flag.set()
1000 while self.active:
1001 try:
1002 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001003 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001005 + repr(connaddr) + '\n')
1006 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007 handler.start()
1008 except socket.timeout:
1009 pass
1010 except KeyboardInterrupt:
1011 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001012 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001013
Antoine Pitrou480a1242010-04-28 21:37:09 +00001014 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001015 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001016
Bill Janssen54cc54c2007-12-14 22:08:56 +00001017 class AsyncoreEchoServer(threading.Thread):
1018
1019 # this one's based on asyncore.dispatcher
1020
1021 class EchoServer (asyncore.dispatcher):
1022
1023 class ConnectionHandler (asyncore.dispatcher_with_send):
1024
1025 def __init__(self, conn, certfile):
1026 self.socket = ssl.wrap_socket(conn, server_side=True,
1027 certfile=certfile,
1028 do_handshake_on_connect=False)
1029 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001030 self._ssl_accepting = True
1031 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001032
1033 def readable(self):
1034 if isinstance(self.socket, ssl.SSLSocket):
1035 while self.socket.pending() > 0:
1036 self.handle_read_event()
1037 return True
1038
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001039 def _do_ssl_handshake(self):
1040 try:
1041 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001042 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1043 return
1044 except ssl.SSLEOFError:
1045 return self.handle_close()
1046 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001047 raise
1048 except socket.error as err:
1049 if err.args[0] == errno.ECONNABORTED:
1050 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001051 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001052 self._ssl_accepting = False
1053
1054 def handle_read(self):
1055 if self._ssl_accepting:
1056 self._do_ssl_handshake()
1057 else:
1058 data = self.recv(1024)
1059 if support.verbose:
1060 sys.stdout.write(" server: read %s from client\n" % repr(data))
1061 if not data:
1062 self.close()
1063 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001064 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001065
1066 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001067 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001068 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001069 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1070
1071 def handle_error(self):
1072 raise
1073
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001074 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001075 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001076 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1077 self.port = support.bind_port(sock, '')
1078 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001079 self.listen(5)
1080
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001081 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001082 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001083 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1084 self.ConnectionHandler(sock_obj, self.certfile)
1085
1086 def handle_error(self):
1087 raise
1088
Trent Nelson78520002008-04-10 20:54:35 +00001089 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001090 self.flag = None
1091 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001092 self.server = self.EchoServer(certfile)
1093 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001094 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001095 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001096
1097 def __str__(self):
1098 return "<%s %s>" % (self.__class__.__name__, self.server)
1099
1100 def start (self, flag=None):
1101 self.flag = flag
1102 threading.Thread.start(self)
1103
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001105 self.active = True
1106 if self.flag:
1107 self.flag.set()
1108 while self.active:
1109 try:
1110 asyncore.loop(1)
1111 except:
1112 pass
1113
Antoine Pitrou480a1242010-04-28 21:37:09 +00001114 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001115 self.active = False
1116 self.server.close()
1117
Antoine Pitrou480a1242010-04-28 21:37:09 +00001118 def bad_cert_test(certfile):
1119 """
1120 Launch a server with CERT_REQUIRED, and check that trying to
1121 connect to it with the given client certificate fails.
1122 """
Trent Nelson78520002008-04-10 20:54:35 +00001123 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001124 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001125 cacerts=CERTFILE, chatty=False,
1126 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127 flag = threading.Event()
1128 server.start(flag)
1129 # wait for it to start
1130 flag.wait()
1131 # try to connect
1132 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001133 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001134 with socket.socket() as sock:
1135 s = ssl.wrap_socket(sock,
1136 certfile=certfile,
1137 ssl_version=ssl.PROTOCOL_TLSv1)
1138 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001139 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001140 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001141 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001142 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001143 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001144 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001145 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001146 if x.errno != errno.ENOENT:
1147 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001148 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001149 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001151 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001152 finally:
1153 server.stop()
1154 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001155
Antoine Pitroub5218772010-05-21 09:56:06 +00001156 def server_params_test(client_context, server_context, indata=b"FOO\n",
1157 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001158 """
1159 Launch a server, connect a client to it and try various reads
1160 and writes.
1161 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001162 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001164 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001165 flag = threading.Event()
1166 server.start(flag)
1167 # wait for it to start
1168 flag.wait()
1169 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001170 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001171 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001172 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001174 if connectionchatty:
1175 if support.verbose:
1176 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001177 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001178 s.write(arg)
1179 outdata = s.read()
1180 if connectionchatty:
1181 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001183 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001184 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001185 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1186 % (outdata[:20], len(outdata),
1187 indata[:20].lower(), len(indata)))
1188 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001189 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001190 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001191 sys.stdout.write(" client: closing connection.\n")
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001192 stats = {
1193 'compression': s.compression(),
1194 'cipher': s.cipher(),
1195 }
Bill Janssen6e027db2007-11-15 22:23:56 +00001196 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001197 return stats
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001198 finally:
1199 server.stop()
1200 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001201
Antoine Pitroub5218772010-05-21 09:56:06 +00001202 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1203 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001204 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001205 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001206 certtype = {
1207 ssl.CERT_NONE: "CERT_NONE",
1208 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1209 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1210 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001211 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001212 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001213 sys.stdout.write(formatstr %
1214 (ssl.get_protocol_name(client_protocol),
1215 ssl.get_protocol_name(server_protocol),
1216 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001217 client_context = ssl.SSLContext(client_protocol)
1218 client_context.options = ssl.OP_ALL | client_options
1219 server_context = ssl.SSLContext(server_protocol)
1220 server_context.options = ssl.OP_ALL | server_options
1221 for ctx in (client_context, server_context):
1222 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001223 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1224 # will send an SSLv3 hello (rather than SSLv2) starting from
1225 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001226 ctx.set_ciphers("ALL")
1227 ctx.load_cert_chain(CERTFILE)
1228 ctx.load_verify_locations(CERTFILE)
1229 try:
1230 server_params_test(client_context, server_context,
1231 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001232 # Protocol mismatch can result in either an SSLError, or a
1233 # "Connection reset by peer" error.
1234 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001235 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001236 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001237 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001238 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001239 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001240 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001241 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001242 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 "Client protocol %s succeeded with server protocol %s!"
1244 % (ssl.get_protocol_name(client_protocol),
1245 ssl.get_protocol_name(server_protocol)))
1246
1247
Bill Janssen6e027db2007-11-15 22:23:56 +00001248 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001249
Antoine Pitrou23df4832010-08-04 17:14:06 +00001250 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001251 def test_echo(self):
1252 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001253 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001254 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001255 for protocol in PROTOCOLS:
1256 context = ssl.SSLContext(protocol)
1257 context.load_cert_chain(CERTFILE)
1258 server_params_test(context, context,
1259 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001260
Antoine Pitrou480a1242010-04-28 21:37:09 +00001261 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001262 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001263 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001264 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1265 context.verify_mode = ssl.CERT_REQUIRED
1266 context.load_verify_locations(CERTFILE)
1267 context.load_cert_chain(CERTFILE)
1268 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001269 flag = threading.Event()
1270 server.start(flag)
1271 # wait for it to start
1272 flag.wait()
1273 # try to connect
1274 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001275 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001276 s.connect((HOST, server.port))
1277 cert = s.getpeercert()
1278 self.assertTrue(cert, "Can't get peer certificate.")
1279 cipher = s.cipher()
1280 if support.verbose:
1281 sys.stdout.write(pprint.pformat(cert) + '\n')
1282 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1283 if 'subject' not in cert:
1284 self.fail("No subject field in certificate: %s." %
1285 pprint.pformat(cert))
1286 if ((('organizationName', 'Python Software Foundation'),)
1287 not in cert['subject']):
1288 self.fail(
1289 "Missing or invalid 'organizationName' field in certificate subject; "
1290 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001291 self.assertIn('notBefore', cert)
1292 self.assertIn('notAfter', cert)
1293 before = ssl.cert_time_to_seconds(cert['notBefore'])
1294 after = ssl.cert_time_to_seconds(cert['notAfter'])
1295 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001296 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001297 finally:
1298 server.stop()
1299 server.join()
1300
Antoine Pitrou480a1242010-04-28 21:37:09 +00001301 def test_empty_cert(self):
1302 """Connecting with an empty cert file"""
1303 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1304 "nullcert.pem"))
1305 def test_malformed_cert(self):
1306 """Connecting with a badly formatted certificate (syntax error)"""
1307 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1308 "badcert.pem"))
1309 def test_nonexisting_cert(self):
1310 """Connecting with a non-existing cert file"""
1311 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1312 "wrongcert.pem"))
1313 def test_malformed_key(self):
1314 """Connecting with a badly formatted key (syntax error)"""
1315 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1316 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001317
Antoine Pitrou480a1242010-04-28 21:37:09 +00001318 def test_rude_shutdown(self):
1319 """A brutal shutdown of an SSL server should raise an IOError
1320 in the client when attempting handshake.
1321 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001322 listener_ready = threading.Event()
1323 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001324
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001325 s = socket.socket()
1326 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001327
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001328 # `listener` runs in a thread. It sits in an accept() until
1329 # the main thread connects. Then it rudely closes the socket,
1330 # and sets Event `listener_gone` to let the main thread know
1331 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001332 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001333 s.listen(5)
1334 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001335 newsock, addr = s.accept()
1336 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001337 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001338 listener_gone.set()
1339
1340 def connector():
1341 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001342 with socket.socket() as c:
1343 c.connect((HOST, port))
1344 listener_gone.wait()
1345 try:
1346 ssl_sock = ssl.wrap_socket(c)
1347 except IOError:
1348 pass
1349 else:
1350 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001351
1352 t = threading.Thread(target=listener)
1353 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001354 try:
1355 connector()
1356 finally:
1357 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001358
Antoine Pitrou23df4832010-08-04 17:14:06 +00001359 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001360 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1361 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001362 def test_protocol_sslv2(self):
1363 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001364 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001365 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001366 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1367 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1368 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1369 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1370 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1371 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001372 # SSLv23 client with specific SSL options
1373 if no_sslv2_implies_sslv3_hello():
1374 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1375 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1376 client_options=ssl.OP_NO_SSLv2)
1377 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1378 client_options=ssl.OP_NO_SSLv3)
1379 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1380 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001381
Antoine Pitrou23df4832010-08-04 17:14:06 +00001382 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 def test_protocol_sslv23(self):
1384 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001385 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001386 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001387 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1388 try:
1389 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1390 except (ssl.SSLError, socket.error) as x:
1391 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1392 if support.verbose:
1393 sys.stdout.write(
1394 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1395 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1397 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1398 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001399
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1401 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1402 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001403
Antoine Pitrou480a1242010-04-28 21:37:09 +00001404 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1405 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1406 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001407
Antoine Pitroub5218772010-05-21 09:56:06 +00001408 # Server with specific SSL options
1409 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1410 server_options=ssl.OP_NO_SSLv3)
1411 # Will choose TLSv1
1412 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1413 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1414 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1415 server_options=ssl.OP_NO_TLSv1)
1416
1417
Antoine Pitrou23df4832010-08-04 17:14:06 +00001418 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001419 def test_protocol_sslv3(self):
1420 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001421 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001422 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001423 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1424 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1425 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001426 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1427 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001428 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1429 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001430 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001431 if no_sslv2_implies_sslv3_hello():
1432 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1433 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1434 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001435
Antoine Pitrou23df4832010-08-04 17:14:06 +00001436 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 def test_protocol_tlsv1(self):
1438 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001439 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001440 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001441 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1442 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1443 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001444 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1445 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001446 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001447 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1448 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001449
Antoine Pitrou480a1242010-04-28 21:37:09 +00001450 def test_starttls(self):
1451 """Switching from clear text to encrypted and back again."""
1452 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 +00001453
Trent Nelson78520002008-04-10 20:54:35 +00001454 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001455 ssl_version=ssl.PROTOCOL_TLSv1,
1456 starttls_server=True,
1457 chatty=True,
1458 connectionchatty=True)
1459 flag = threading.Event()
1460 server.start(flag)
1461 # wait for it to start
1462 flag.wait()
1463 # try to connect
1464 wrapped = False
1465 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001466 s = socket.socket()
1467 s.setblocking(1)
1468 s.connect((HOST, server.port))
1469 if support.verbose:
1470 sys.stdout.write("\n")
1471 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001472 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001473 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001474 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001475 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001476 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001477 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001479 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001480 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001481 msg = outdata.strip().lower()
1482 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1483 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001484 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001485 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001486 " client: read %r from server, starting TLS...\n"
1487 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001488 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1489 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001490 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1491 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001492 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, ending TLS...\n"
1495 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001496 s = conn.unwrap()
1497 wrapped = False
1498 else:
1499 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001500 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001501 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001502 if support.verbose:
1503 sys.stdout.write(" client: closing connection.\n")
1504 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001505 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001506 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001507 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001508 if wrapped:
1509 conn.close()
1510 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001511 s.close()
1512 finally:
1513 server.stop()
1514 server.join()
1515
Antoine Pitrou480a1242010-04-28 21:37:09 +00001516 def test_socketserver(self):
1517 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001518 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001519 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001520 if support.verbose:
1521 sys.stdout.write('\n')
1522 with open(CERTFILE, 'rb') as f:
1523 d1 = f.read()
1524 d2 = ''
1525 # now fetch the same data from the HTTPS server
1526 url = 'https://%s:%d/%s' % (
1527 HOST, server.port, os.path.split(CERTFILE)[1])
1528 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001529 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001530 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001531 if dlen and (int(dlen) > 0):
1532 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001533 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001534 sys.stdout.write(
1535 " client: read %d bytes from remote server '%s'\n"
1536 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001537 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001538 f.close()
1539 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001540
Antoine Pitrou480a1242010-04-28 21:37:09 +00001541 def test_asyncore_server(self):
1542 """Check the example asyncore integration."""
1543 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001544
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001545 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001546 sys.stdout.write("\n")
1547
Antoine Pitrou480a1242010-04-28 21:37:09 +00001548 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001549 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001550 flag = threading.Event()
1551 server.start(flag)
1552 # wait for it to start
1553 flag.wait()
1554 # try to connect
1555 try:
1556 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001557 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001558 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001559 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001560 " client: sending %r...\n" % indata)
1561 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001562 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001563 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001564 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001565 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001566 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1568 % (outdata[:20], len(outdata),
1569 indata[:20].lower(), len(indata)))
1570 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001571 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001572 sys.stdout.write(" client: closing connection.\n")
1573 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001574 if support.verbose:
1575 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001576 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001577 if support.verbose:
1578 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001579 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001580 if support.verbose:
1581 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001582 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001583 if support.verbose:
1584 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001585
Antoine Pitrou480a1242010-04-28 21:37:09 +00001586 def test_recv_send(self):
1587 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001588 if support.verbose:
1589 sys.stdout.write("\n")
1590
1591 server = ThreadedEchoServer(CERTFILE,
1592 certreqs=ssl.CERT_NONE,
1593 ssl_version=ssl.PROTOCOL_TLSv1,
1594 cacerts=CERTFILE,
1595 chatty=True,
1596 connectionchatty=False)
1597 flag = threading.Event()
1598 server.start(flag)
1599 # wait for it to start
1600 flag.wait()
1601 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001602 s = ssl.wrap_socket(socket.socket(),
1603 server_side=False,
1604 certfile=CERTFILE,
1605 ca_certs=CERTFILE,
1606 cert_reqs=ssl.CERT_NONE,
1607 ssl_version=ssl.PROTOCOL_TLSv1)
1608 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001609 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001610 # helper methods for standardising recv* method signatures
1611 def _recv_into():
1612 b = bytearray(b"\0"*100)
1613 count = s.recv_into(b)
1614 return b[:count]
1615
1616 def _recvfrom_into():
1617 b = bytearray(b"\0"*100)
1618 count, addr = s.recvfrom_into(b)
1619 return b[:count]
1620
1621 # (name, method, whether to expect success, *args)
1622 send_methods = [
1623 ('send', s.send, True, []),
1624 ('sendto', s.sendto, False, ["some.address"]),
1625 ('sendall', s.sendall, True, []),
1626 ]
1627 recv_methods = [
1628 ('recv', s.recv, True, []),
1629 ('recvfrom', s.recvfrom, False, ["some.address"]),
1630 ('recv_into', _recv_into, True, []),
1631 ('recvfrom_into', _recvfrom_into, False, []),
1632 ]
1633 data_prefix = "PREFIX_"
1634
1635 for meth_name, send_meth, expect_success, args in send_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 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001639 outdata = s.read()
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 sending 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 send 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
1664 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001665 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001666 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001667 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001668 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001669 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001670 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001671 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001672 "<<{outdata:r}>> ({nout:d}) received; "
1673 "expected <<{indata:r}>> ({nin:d})\n".format(
1674 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001675 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001676 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001677 )
1678 )
1679 except ValueError as e:
1680 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001681 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001682 "Failed to receive with method <<{name:s}>>; "
1683 "expected to succeed.\n".format(name=meth_name)
1684 )
1685 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001686 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001687 "Method <<{name:s}>> failed with unexpected "
1688 "exception message: {exp:s}\n".format(
1689 name=meth_name, exp=e
1690 )
1691 )
1692 # consume data
1693 s.read()
1694
Nick Coghlan513886a2011-08-28 00:00:27 +10001695 # Make sure sendmsg et al are disallowed to avoid
1696 # inadvertent disclosure of data and/or corruption
1697 # of the encrypted data stream
1698 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1699 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1700 self.assertRaises(NotImplementedError,
1701 s.recvmsg_into, bytearray(100))
1702
Antoine Pitrou480a1242010-04-28 21:37:09 +00001703 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001704 s.close()
1705 finally:
1706 server.stop()
1707 server.join()
1708
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001709 def test_handshake_timeout(self):
1710 # Issue #5103: SSL handshake must respect the socket timeout
1711 server = socket.socket(socket.AF_INET)
1712 host = "127.0.0.1"
1713 port = support.bind_port(server)
1714 started = threading.Event()
1715 finish = False
1716
1717 def serve():
1718 server.listen(5)
1719 started.set()
1720 conns = []
1721 while not finish:
1722 r, w, e = select.select([server], [], [], 0.1)
1723 if server in r:
1724 # Let the socket hang around rather than having
1725 # it closed by garbage collection.
1726 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001727 for sock in conns:
1728 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001729
1730 t = threading.Thread(target=serve)
1731 t.start()
1732 started.wait()
1733
1734 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001735 try:
1736 c = socket.socket(socket.AF_INET)
1737 c.settimeout(0.2)
1738 c.connect((host, port))
1739 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001740 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001741 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001742 finally:
1743 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001744 try:
1745 c = socket.socket(socket.AF_INET)
1746 c = ssl.wrap_socket(c)
1747 c.settimeout(0.2)
1748 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001749 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001750 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001751 finally:
1752 c.close()
1753 finally:
1754 finish = True
1755 t.join()
1756 server.close()
1757
Antoine Pitroud6494802011-07-21 01:11:30 +02001758 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1759 "'tls-unique' channel binding not available")
1760 def test_tls_unique_channel_binding(self):
1761 """Test tls-unique channel binding."""
1762 if support.verbose:
1763 sys.stdout.write("\n")
1764
1765 server = ThreadedEchoServer(CERTFILE,
1766 certreqs=ssl.CERT_NONE,
1767 ssl_version=ssl.PROTOCOL_TLSv1,
1768 cacerts=CERTFILE,
1769 chatty=True,
1770 connectionchatty=False)
1771 flag = threading.Event()
1772 server.start(flag)
1773 # wait for it to start
1774 flag.wait()
1775 # try to connect
1776 s = ssl.wrap_socket(socket.socket(),
1777 server_side=False,
1778 certfile=CERTFILE,
1779 ca_certs=CERTFILE,
1780 cert_reqs=ssl.CERT_NONE,
1781 ssl_version=ssl.PROTOCOL_TLSv1)
1782 s.connect((HOST, server.port))
1783 try:
1784 # get the data
1785 cb_data = s.get_channel_binding("tls-unique")
1786 if support.verbose:
1787 sys.stdout.write(" got channel binding data: {0!r}\n"
1788 .format(cb_data))
1789
1790 # check if it is sane
1791 self.assertIsNotNone(cb_data)
1792 self.assertEqual(len(cb_data), 12) # True for TLSv1
1793
1794 # and compare with the peers version
1795 s.write(b"CB tls-unique\n")
1796 peer_data_repr = s.read().strip()
1797 self.assertEqual(peer_data_repr,
1798 repr(cb_data).encode("us-ascii"))
1799 s.close()
1800
1801 # now, again
1802 s = ssl.wrap_socket(socket.socket(),
1803 server_side=False,
1804 certfile=CERTFILE,
1805 ca_certs=CERTFILE,
1806 cert_reqs=ssl.CERT_NONE,
1807 ssl_version=ssl.PROTOCOL_TLSv1)
1808 s.connect((HOST, server.port))
1809 new_cb_data = s.get_channel_binding("tls-unique")
1810 if support.verbose:
1811 sys.stdout.write(" got another channel binding data: {0!r}\n"
1812 .format(new_cb_data))
1813 # is it really unique
1814 self.assertNotEqual(cb_data, new_cb_data)
1815 self.assertIsNotNone(cb_data)
1816 self.assertEqual(len(cb_data), 12) # True for TLSv1
1817 s.write(b"CB tls-unique\n")
1818 peer_data_repr = s.read().strip()
1819 self.assertEqual(peer_data_repr,
1820 repr(new_cb_data).encode("us-ascii"))
1821 s.close()
1822 finally:
1823 server.stop()
1824 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001825
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001826 def test_compression(self):
1827 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1828 context.load_cert_chain(CERTFILE)
1829 stats = server_params_test(context, context,
1830 chatty=True, connectionchatty=True)
1831 if support.verbose:
1832 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1833 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1834
1835 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1836 "ssl.OP_NO_COMPRESSION needed for this test")
1837 def test_compression_disabled(self):
1838 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1839 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001840 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001841 stats = server_params_test(context, context,
1842 chatty=True, connectionchatty=True)
1843 self.assertIs(stats['compression'], None)
1844
1845
Thomas Woutersed03b412007-08-28 21:37:11 +00001846def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001847 if support.verbose:
1848 plats = {
1849 'Linux': platform.linux_distribution,
1850 'Mac': platform.mac_ver,
1851 'Windows': platform.win32_ver,
1852 }
1853 for name, func in plats.items():
1854 plat = func()
1855 if plat and plat[0]:
1856 plat = '%s %r' % (name, plat)
1857 break
1858 else:
1859 plat = repr(platform.platform())
1860 print("test_ssl: testing with %r %r" %
1861 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1862 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001863 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001864
Antoine Pitrou152efa22010-05-16 18:19:27 +00001865 for filename in [
1866 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1867 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1868 BADCERT, BADKEY, EMPTYCERT]:
1869 if not os.path.exists(filename):
1870 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001871
Antoine Pitrou152efa22010-05-16 18:19:27 +00001872 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001873
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001874 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001875 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001876
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001877 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001878 thread_info = support.threading_setup()
1879 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001880 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001881
Antoine Pitrou480a1242010-04-28 21:37:09 +00001882 try:
1883 support.run_unittest(*tests)
1884 finally:
1885 if _have_threads:
1886 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001887
1888if __name__ == "__main__":
1889 test_main()