blob: 76fb3e777c923debf39bafa9f127d477d29e8041 [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})
Thomas Woutersed03b412007-08-28 21:37:11 +0000106
Antoine Pitrou480a1242010-04-28 21:37:09 +0000107 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000108 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000109 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000110 sys.stdout.write("\n RAND_status is %d (%s)\n"
111 % (v, (v and "sufficient randomness") or
112 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200113
114 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
115 self.assertEqual(len(data), 16)
116 self.assertEqual(is_cryptographic, v == 1)
117 if v:
118 data = ssl.RAND_bytes(16)
119 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200120 else:
121 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200122
Thomas Woutersed03b412007-08-28 21:37:11 +0000123 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000124 ssl.RAND_egd(1)
125 except TypeError:
126 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000127 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128 print("didn't raise TypeError")
129 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000130
Antoine Pitrou480a1242010-04-28 21:37:09 +0000131 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132 # note that this uses an 'unofficial' function in _ssl.c,
133 # provided solely for this test, to exercise the certificate
134 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000135 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000136 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000137 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200138 self.assertEqual(p['issuer'],
139 ((('countryName', 'XY'),),
140 (('localityName', 'Castle Anthrax'),),
141 (('organizationName', 'Python Software Foundation'),),
142 (('commonName', 'localhost'),))
143 )
144 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
145 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
146 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
147 self.assertEqual(p['subject'],
148 ((('countryName', 'XY'),),
149 (('localityName', 'Castle Anthrax'),),
150 (('organizationName', 'Python Software Foundation'),),
151 (('commonName', 'localhost'),))
152 )
153 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
154 # Issue #13034: the subjectAltName in some certificates
155 # (notably projects.developer.nokia.com:443) wasn't parsed
156 p = ssl._ssl._test_decode_cert(NOKIACERT)
157 if support.verbose:
158 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
159 self.assertEqual(p['subjectAltName'],
160 (('DNS', 'projects.developer.nokia.com'),
161 ('DNS', 'projects.forum.nokia.com'))
162 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000163
Antoine Pitrou480a1242010-04-28 21:37:09 +0000164 def test_DER_to_PEM(self):
165 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
166 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000167 d1 = ssl.PEM_cert_to_DER_cert(pem)
168 p2 = ssl.DER_cert_to_PEM_cert(d1)
169 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000170 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000171 if not p2.startswith(ssl.PEM_HEADER + '\n'):
172 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
173 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
174 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000175
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000176 def test_openssl_version(self):
177 n = ssl.OPENSSL_VERSION_NUMBER
178 t = ssl.OPENSSL_VERSION_INFO
179 s = ssl.OPENSSL_VERSION
180 self.assertIsInstance(n, int)
181 self.assertIsInstance(t, tuple)
182 self.assertIsInstance(s, str)
183 # Some sanity checks follow
184 # >= 0.9
185 self.assertGreaterEqual(n, 0x900000)
186 # < 2.0
187 self.assertLess(n, 0x20000000)
188 major, minor, fix, patch, status = t
189 self.assertGreaterEqual(major, 0)
190 self.assertLess(major, 2)
191 self.assertGreaterEqual(minor, 0)
192 self.assertLess(minor, 256)
193 self.assertGreaterEqual(fix, 0)
194 self.assertLess(fix, 256)
195 self.assertGreaterEqual(patch, 0)
196 self.assertLessEqual(patch, 26)
197 self.assertGreaterEqual(status, 0)
198 self.assertLessEqual(status, 15)
199 # Version string as returned by OpenSSL, the format might change
200 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
201 (s, t))
202
Antoine Pitrou9d543662010-04-23 23:10:32 +0000203 @support.cpython_only
204 def test_refcycle(self):
205 # Issue #7943: an SSL object doesn't create reference cycles with
206 # itself.
207 s = socket.socket(socket.AF_INET)
208 ss = ssl.wrap_socket(s)
209 wr = weakref.ref(ss)
210 del ss
211 self.assertEqual(wr(), None)
212
Antoine Pitroua468adc2010-09-14 14:43:44 +0000213 def test_wrapped_unconnected(self):
214 # Methods on an unconnected SSLSocket propagate the original
215 # socket.error raise by the underlying socket object.
216 s = socket.socket(socket.AF_INET)
217 ss = ssl.wrap_socket(s)
218 self.assertRaises(socket.error, ss.recv, 1)
219 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
220 self.assertRaises(socket.error, ss.recvfrom, 1)
221 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
222 self.assertRaises(socket.error, ss.send, b'x')
223 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
224
Antoine Pitrou40f08742010-04-24 22:04:40 +0000225 def test_timeout(self):
226 # Issue #8524: when creating an SSL socket, the timeout of the
227 # original socket should be retained.
228 for timeout in (None, 0.0, 5.0):
229 s = socket.socket(socket.AF_INET)
230 s.settimeout(timeout)
231 ss = ssl.wrap_socket(s)
232 self.assertEqual(timeout, ss.gettimeout())
233
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000234 def test_errors(self):
235 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000236 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000237 "certfile must be specified",
238 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000239 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000240 "certfile must be specified for server-side operations",
241 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000242 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000243 "certfile must be specified for server-side operations",
244 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000245 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000246 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000247 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000248 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000249 with socket.socket() as sock:
250 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000251 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000252 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000253 with socket.socket() as sock:
254 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000255 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000256 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000257 with socket.socket() as sock:
258 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000259 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000260
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000261 def test_match_hostname(self):
262 def ok(cert, hostname):
263 ssl.match_hostname(cert, hostname)
264 def fail(cert, hostname):
265 self.assertRaises(ssl.CertificateError,
266 ssl.match_hostname, cert, hostname)
267
268 cert = {'subject': ((('commonName', 'example.com'),),)}
269 ok(cert, 'example.com')
270 ok(cert, 'ExAmple.cOm')
271 fail(cert, 'www.example.com')
272 fail(cert, '.example.com')
273 fail(cert, 'example.org')
274 fail(cert, 'exampleXcom')
275
276 cert = {'subject': ((('commonName', '*.a.com'),),)}
277 ok(cert, 'foo.a.com')
278 fail(cert, 'bar.foo.a.com')
279 fail(cert, 'a.com')
280 fail(cert, 'Xa.com')
281 fail(cert, '.a.com')
282
283 cert = {'subject': ((('commonName', 'a.*.com'),),)}
284 ok(cert, 'a.foo.com')
285 fail(cert, 'a..com')
286 fail(cert, 'a.com')
287
288 cert = {'subject': ((('commonName', 'f*.com'),),)}
289 ok(cert, 'foo.com')
290 ok(cert, 'f.com')
291 fail(cert, 'bar.com')
292 fail(cert, 'foo.a.com')
293 fail(cert, 'bar.foo.com')
294
295 # Slightly fake real-world example
296 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
297 'subject': ((('commonName', 'linuxfrz.org'),),),
298 'subjectAltName': (('DNS', 'linuxfr.org'),
299 ('DNS', 'linuxfr.com'),
300 ('othername', '<unsupported>'))}
301 ok(cert, 'linuxfr.org')
302 ok(cert, 'linuxfr.com')
303 # Not a "DNS" entry
304 fail(cert, '<unsupported>')
305 # When there is a subjectAltName, commonName isn't used
306 fail(cert, 'linuxfrz.org')
307
308 # A pristine real-world example
309 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
310 'subject': ((('countryName', 'US'),),
311 (('stateOrProvinceName', 'California'),),
312 (('localityName', 'Mountain View'),),
313 (('organizationName', 'Google Inc'),),
314 (('commonName', 'mail.google.com'),))}
315 ok(cert, 'mail.google.com')
316 fail(cert, 'gmail.com')
317 # Only commonName is considered
318 fail(cert, 'California')
319
320 # Neither commonName nor subjectAltName
321 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
322 'subject': ((('countryName', 'US'),),
323 (('stateOrProvinceName', 'California'),),
324 (('localityName', 'Mountain View'),),
325 (('organizationName', 'Google Inc'),))}
326 fail(cert, 'mail.google.com')
327
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200328 # No DNS entry in subjectAltName but a commonName
329 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
330 'subject': ((('countryName', 'US'),),
331 (('stateOrProvinceName', 'California'),),
332 (('localityName', 'Mountain View'),),
333 (('commonName', 'mail.google.com'),)),
334 'subjectAltName': (('othername', 'blabla'), )}
335 ok(cert, 'mail.google.com')
336
337 # No DNS entry subjectAltName and no commonName
338 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
339 'subject': ((('countryName', 'US'),),
340 (('stateOrProvinceName', 'California'),),
341 (('localityName', 'Mountain View'),),
342 (('organizationName', 'Google Inc'),)),
343 'subjectAltName': (('othername', 'blabla'),)}
344 fail(cert, 'google.com')
345
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000346 # Empty cert / no cert
347 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
348 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
349
Antoine Pitroud5323212010-10-22 18:19:07 +0000350 def test_server_side(self):
351 # server_hostname doesn't work for server sockets
352 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000353 with socket.socket() as sock:
354 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
355 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000356
Antoine Pitroud6494802011-07-21 01:11:30 +0200357 def test_unknown_channel_binding(self):
358 # should raise ValueError for unknown type
359 s = socket.socket(socket.AF_INET)
360 ss = ssl.wrap_socket(s)
361 with self.assertRaises(ValueError):
362 ss.get_channel_binding("unknown-type")
363
364 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
365 "'tls-unique' channel binding not available")
366 def test_tls_unique_channel_binding(self):
367 # unconnected should return None for known type
368 s = socket.socket(socket.AF_INET)
369 ss = ssl.wrap_socket(s)
370 self.assertIsNone(ss.get_channel_binding("tls-unique"))
371 # the same for server-side
372 s = socket.socket(socket.AF_INET)
373 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
374 self.assertIsNone(ss.get_channel_binding("tls-unique"))
375
Antoine Pitrou152efa22010-05-16 18:19:27 +0000376class ContextTests(unittest.TestCase):
377
Antoine Pitrou23df4832010-08-04 17:14:06 +0000378 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000379 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200380 if hasattr(ssl, 'PROTOCOL_SSLv2'):
381 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000382 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
383 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
384 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
385 self.assertRaises(TypeError, ssl.SSLContext)
386 self.assertRaises(ValueError, ssl.SSLContext, -1)
387 self.assertRaises(ValueError, ssl.SSLContext, 42)
388
Antoine Pitrou23df4832010-08-04 17:14:06 +0000389 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000390 def test_protocol(self):
391 for proto in PROTOCOLS:
392 ctx = ssl.SSLContext(proto)
393 self.assertEqual(ctx.protocol, proto)
394
395 def test_ciphers(self):
396 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
397 ctx.set_ciphers("ALL")
398 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000399 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000400 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000401
Antoine Pitrou23df4832010-08-04 17:14:06 +0000402 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000403 def test_options(self):
404 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
405 # OP_ALL is the default value
406 self.assertEqual(ssl.OP_ALL, ctx.options)
407 ctx.options |= ssl.OP_NO_SSLv2
408 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
409 ctx.options)
410 ctx.options |= ssl.OP_NO_SSLv3
411 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
412 ctx.options)
413 if can_clear_options():
414 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
415 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
416 ctx.options)
417 ctx.options = 0
418 self.assertEqual(0, ctx.options)
419 else:
420 with self.assertRaises(ValueError):
421 ctx.options = 0
422
Antoine Pitrou152efa22010-05-16 18:19:27 +0000423 def test_verify(self):
424 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
425 # Default value
426 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
427 ctx.verify_mode = ssl.CERT_OPTIONAL
428 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
429 ctx.verify_mode = ssl.CERT_REQUIRED
430 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
431 ctx.verify_mode = ssl.CERT_NONE
432 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
433 with self.assertRaises(TypeError):
434 ctx.verify_mode = None
435 with self.assertRaises(ValueError):
436 ctx.verify_mode = 42
437
438 def test_load_cert_chain(self):
439 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
440 # Combined key and cert in a single file
441 ctx.load_cert_chain(CERTFILE)
442 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
443 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000444 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000445 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000446 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000447 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000448 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000449 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000450 ctx.load_cert_chain(EMPTYCERT)
451 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000452 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000453 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
454 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
455 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000456 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000457 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000458 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000459 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000460 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000461 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
462 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000463 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000464 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000465 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200466 # Password protected key and cert
467 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
468 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
469 ctx.load_cert_chain(CERTFILE_PROTECTED,
470 password=bytearray(KEY_PASSWORD.encode()))
471 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
472 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
473 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
474 bytearray(KEY_PASSWORD.encode()))
475 with self.assertRaisesRegex(TypeError, "should be a string"):
476 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
477 with self.assertRaises(ssl.SSLError):
478 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
479 with self.assertRaisesRegex(ValueError, "cannot be longer"):
480 # openssl has a fixed limit on the password buffer.
481 # PEM_BUFSIZE is generally set to 1kb.
482 # Return a string larger than this.
483 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
484 # Password callback
485 def getpass_unicode():
486 return KEY_PASSWORD
487 def getpass_bytes():
488 return KEY_PASSWORD.encode()
489 def getpass_bytearray():
490 return bytearray(KEY_PASSWORD.encode())
491 def getpass_badpass():
492 return "badpass"
493 def getpass_huge():
494 return b'a' * (1024 * 1024)
495 def getpass_bad_type():
496 return 9
497 def getpass_exception():
498 raise Exception('getpass error')
499 class GetPassCallable:
500 def __call__(self):
501 return KEY_PASSWORD
502 def getpass(self):
503 return KEY_PASSWORD
504 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
505 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
506 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
507 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
508 ctx.load_cert_chain(CERTFILE_PROTECTED,
509 password=GetPassCallable().getpass)
510 with self.assertRaises(ssl.SSLError):
511 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
512 with self.assertRaisesRegex(ValueError, "cannot be longer"):
513 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
514 with self.assertRaisesRegex(TypeError, "must return a string"):
515 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
516 with self.assertRaisesRegex(Exception, "getpass error"):
517 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
518 # Make sure the password function isn't called if it isn't needed
519 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000520
521 def test_load_verify_locations(self):
522 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
523 ctx.load_verify_locations(CERTFILE)
524 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
525 ctx.load_verify_locations(BYTES_CERTFILE)
526 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
527 self.assertRaises(TypeError, ctx.load_verify_locations)
528 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000529 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000530 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000531 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000532 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000533 ctx.load_verify_locations(BADCERT)
534 ctx.load_verify_locations(CERTFILE, CAPATH)
535 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
536
Victor Stinner80f75e62011-01-29 11:31:20 +0000537 # Issue #10989: crash if the second argument type is invalid
538 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
539
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000540 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000541 def test_session_stats(self):
542 for proto in PROTOCOLS:
543 ctx = ssl.SSLContext(proto)
544 self.assertEqual(ctx.session_stats(), {
545 'number': 0,
546 'connect': 0,
547 'connect_good': 0,
548 'connect_renegotiate': 0,
549 'accept': 0,
550 'accept_good': 0,
551 'accept_renegotiate': 0,
552 'hits': 0,
553 'misses': 0,
554 'timeouts': 0,
555 'cache_full': 0,
556 })
557
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000558 def test_set_default_verify_paths(self):
559 # There's not much we can do to test that it acts as expected,
560 # so just check it doesn't crash or raise an exception.
561 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
562 ctx.set_default_verify_paths()
563
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100564 def test_set_ecdh_curve(self):
565 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
566 ctx.set_ecdh_curve("prime256v1")
567 ctx.set_ecdh_curve(b"prime256v1")
568 self.assertRaises(TypeError, ctx.set_ecdh_curve)
569 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
570 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
571 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
572
Antoine Pitrou152efa22010-05-16 18:19:27 +0000573
Bill Janssen6e027db2007-11-15 22:23:56 +0000574class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000575
Antoine Pitrou480a1242010-04-28 21:37:09 +0000576 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000577 with support.transient_internet("svn.python.org"):
578 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
579 cert_reqs=ssl.CERT_NONE)
580 try:
581 s.connect(("svn.python.org", 443))
582 self.assertEqual({}, s.getpeercert())
583 finally:
584 s.close()
585
586 # this should fail because we have no verification certs
587 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
588 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000589 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
590 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000591 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592
Antoine Pitrou350c7222010-09-09 13:31:46 +0000593 # this should succeed because we specify the root cert
594 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
595 cert_reqs=ssl.CERT_REQUIRED,
596 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
597 try:
598 s.connect(("svn.python.org", 443))
599 self.assertTrue(s.getpeercert())
600 finally:
601 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000602
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000603 def test_connect_ex(self):
604 # Issue #11326: check connect_ex() implementation
605 with support.transient_internet("svn.python.org"):
606 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
607 cert_reqs=ssl.CERT_REQUIRED,
608 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
609 try:
610 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
611 self.assertTrue(s.getpeercert())
612 finally:
613 s.close()
614
615 def test_non_blocking_connect_ex(self):
616 # Issue #11326: non-blocking connect_ex() should allow handshake
617 # to proceed after the socket gets ready.
618 with support.transient_internet("svn.python.org"):
619 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
620 cert_reqs=ssl.CERT_REQUIRED,
621 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
622 do_handshake_on_connect=False)
623 try:
624 s.setblocking(False)
625 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000626 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
627 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000628 # Wait for connect to finish
629 select.select([], [s], [], 5.0)
630 # Non-blocking handshake
631 while True:
632 try:
633 s.do_handshake()
634 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200635 except ssl.SSLWantReadError:
636 select.select([s], [], [], 5.0)
637 except ssl.SSLWantWriteError:
638 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000639 # SSL established
640 self.assertTrue(s.getpeercert())
641 finally:
642 s.close()
643
Antoine Pitroub4410db2011-05-18 18:51:06 +0200644 def test_timeout_connect_ex(self):
645 # Issue #12065: on a timeout, connect_ex() should return the original
646 # errno (mimicking the behaviour of non-SSL sockets).
647 with support.transient_internet("svn.python.org"):
648 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
649 cert_reqs=ssl.CERT_REQUIRED,
650 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
651 do_handshake_on_connect=False)
652 try:
653 s.settimeout(0.0000001)
654 rc = s.connect_ex(('svn.python.org', 443))
655 if rc == 0:
656 self.skipTest("svn.python.org responded too quickly")
657 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
658 finally:
659 s.close()
660
Antoine Pitrou152efa22010-05-16 18:19:27 +0000661 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000662 with support.transient_internet("svn.python.org"):
663 # Same as test_connect, but with a separately created context
664 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
665 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
666 s.connect(("svn.python.org", 443))
667 try:
668 self.assertEqual({}, s.getpeercert())
669 finally:
670 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000671 # Same with a server hostname
672 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
673 server_hostname="svn.python.org")
674 if ssl.HAS_SNI:
675 s.connect(("svn.python.org", 443))
676 s.close()
677 else:
678 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000679 # This should fail because we have no verification certs
680 ctx.verify_mode = ssl.CERT_REQUIRED
681 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000682 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000683 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000684 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000685 # This should succeed because we specify the root cert
686 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
687 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
688 s.connect(("svn.python.org", 443))
689 try:
690 cert = s.getpeercert()
691 self.assertTrue(cert)
692 finally:
693 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000694
695 def test_connect_capath(self):
696 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000697 # NOTE: the subject hashing algorithm has been changed between
698 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
699 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000700 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000701 with support.transient_internet("svn.python.org"):
702 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
703 ctx.verify_mode = ssl.CERT_REQUIRED
704 ctx.load_verify_locations(capath=CAPATH)
705 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
706 s.connect(("svn.python.org", 443))
707 try:
708 cert = s.getpeercert()
709 self.assertTrue(cert)
710 finally:
711 s.close()
712 # Same with a bytes `capath` argument
713 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
714 ctx.verify_mode = ssl.CERT_REQUIRED
715 ctx.load_verify_locations(capath=BYTES_CAPATH)
716 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
717 s.connect(("svn.python.org", 443))
718 try:
719 cert = s.getpeercert()
720 self.assertTrue(cert)
721 finally:
722 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000723
Antoine Pitroue3220242010-04-24 11:13:53 +0000724 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
725 def test_makefile_close(self):
726 # Issue #5238: creating a file-like object with makefile() shouldn't
727 # delay closing the underlying "real socket" (here tested with its
728 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000729 with support.transient_internet("svn.python.org"):
730 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
731 ss.connect(("svn.python.org", 443))
732 fd = ss.fileno()
733 f = ss.makefile()
734 f.close()
735 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000736 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000737 # Closing the SSL socket should close the fd too
738 ss.close()
739 gc.collect()
740 with self.assertRaises(OSError) as e:
741 os.read(fd, 0)
742 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000743
Antoine Pitrou480a1242010-04-28 21:37:09 +0000744 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000745 with support.transient_internet("svn.python.org"):
746 s = socket.socket(socket.AF_INET)
747 s.connect(("svn.python.org", 443))
748 s.setblocking(False)
749 s = ssl.wrap_socket(s,
750 cert_reqs=ssl.CERT_NONE,
751 do_handshake_on_connect=False)
752 count = 0
753 while True:
754 try:
755 count += 1
756 s.do_handshake()
757 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200758 except ssl.SSLWantReadError:
759 select.select([s], [], [])
760 except ssl.SSLWantWriteError:
761 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000762 s.close()
763 if support.verbose:
764 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000765
Antoine Pitrou480a1242010-04-28 21:37:09 +0000766 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200767 def _test_get_server_certificate(host, port, cert=None):
768 with support.transient_internet(host):
769 pem = ssl.get_server_certificate((host, port))
770 if not pem:
771 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200772
Antoine Pitrou15399c32011-04-28 19:23:55 +0200773 try:
774 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
775 except ssl.SSLError as x:
776 #should fail
777 if support.verbose:
778 sys.stdout.write("%s\n" % x)
779 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200780 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
781
Antoine Pitrou15399c32011-04-28 19:23:55 +0200782 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
783 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200784 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000785 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200786 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000787
Antoine Pitrou15399c32011-04-28 19:23:55 +0200788 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
789 if support.IPV6_ENABLED:
790 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000791
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000792 def test_ciphers(self):
793 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000794 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000795 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000796 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000797 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000798 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
799 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
800 s.connect(remote)
801 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000802 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000803 with socket.socket(socket.AF_INET) as sock:
804 s = ssl.wrap_socket(sock,
805 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
806 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000807
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000808 def test_algorithms(self):
809 # Issue #8484: all algorithms should be available when verifying a
810 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000811 # SHA256 was added in OpenSSL 0.9.8
812 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
813 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000814 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
815 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000816 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000817 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000818 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
819 cert_reqs=ssl.CERT_REQUIRED,
820 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000821 try:
822 s.connect(remote)
823 if support.verbose:
824 sys.stdout.write("\nCipher with %r is %r\n" %
825 (remote, s.cipher()))
826 sys.stdout.write("Certificate is:\n%s\n" %
827 pprint.pformat(s.getpeercert()))
828 finally:
829 s.close()
830
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000831
832try:
833 import threading
834except ImportError:
835 _have_threads = False
836else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000837 _have_threads = True
838
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000839 from test.ssl_servers import make_https_server
840
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000841 class ThreadedEchoServer(threading.Thread):
842
843 class ConnectionHandler(threading.Thread):
844
845 """A mildly complicated class, because we want it to work both
846 with and without the SSL wrapper around the socket connection, so
847 that we can test the STARTTLS functionality."""
848
Bill Janssen6e027db2007-11-15 22:23:56 +0000849 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850 self.server = server
851 self.running = False
852 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000853 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000854 self.sock.setblocking(1)
855 self.sslconn = None
856 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000857 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000858
Antoine Pitrou480a1242010-04-28 21:37:09 +0000859 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000861 self.sslconn = self.server.context.wrap_socket(
862 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000863 except ssl.SSLError:
864 # XXX Various errors can have happened here, for example
865 # a mismatching protocol version, an invalid certificate,
866 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000867 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000868 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000869 self.running = False
870 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000871 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000874 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000875 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000876 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000877 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
878 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000879 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000880 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
881 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000882 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000883 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
884 return True
885
886 def read(self):
887 if self.sslconn:
888 return self.sslconn.read()
889 else:
890 return self.sock.recv(1024)
891
892 def write(self, bytes):
893 if self.sslconn:
894 return self.sslconn.write(bytes)
895 else:
896 return self.sock.send(bytes)
897
898 def close(self):
899 if self.sslconn:
900 self.sslconn.close()
901 else:
902 self.sock.close()
903
Antoine Pitrou480a1242010-04-28 21:37:09 +0000904 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905 self.running = True
906 if not self.server.starttls_server:
907 if not self.wrap_conn():
908 return
909 while self.running:
910 try:
911 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000912 stripped = msg.strip()
913 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000914 # eof, so quit this handler
915 self.running = False
916 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000917 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000918 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919 sys.stdout.write(" server: client closed connection\n")
920 self.close()
921 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000922 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000923 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000924 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000926 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000927 if not self.wrap_conn():
928 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000929 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000930 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000931 if support.verbose and self.server.connectionchatty:
932 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000933 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000934 self.sock = self.sslconn.unwrap()
935 self.sslconn = None
936 if support.verbose and self.server.connectionchatty:
937 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200938 elif stripped == b'CB tls-unique':
939 if support.verbose and self.server.connectionchatty:
940 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
941 data = self.sslconn.get_channel_binding("tls-unique")
942 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000943 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000944 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000945 self.server.connectionchatty):
946 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000947 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
948 % (msg, ctype, msg.lower(), ctype))
949 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000950 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951 if self.server.chatty:
952 handle_error("Test server failure:\n")
953 self.close()
954 self.running = False
955 # normally, we'd just stop here, but for the test
956 # harness, we want to stop the server
957 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000958
Antoine Pitroub5218772010-05-21 09:56:06 +0000959 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000960 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000961 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000962 ciphers=None, context=None):
963 if context:
964 self.context = context
965 else:
966 self.context = ssl.SSLContext(ssl_version
967 if ssl_version is not None
968 else ssl.PROTOCOL_TLSv1)
969 self.context.verify_mode = (certreqs if certreqs is not None
970 else ssl.CERT_NONE)
971 if cacerts:
972 self.context.load_verify_locations(cacerts)
973 if certificate:
974 self.context.load_cert_chain(certificate)
975 if ciphers:
976 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000977 self.chatty = chatty
978 self.connectionchatty = connectionchatty
979 self.starttls_server = starttls_server
980 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000981 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000982 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000983 self.active = False
984 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000985 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986
Antoine Pitrou480a1242010-04-28 21:37:09 +0000987 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000988 self.flag = flag
989 threading.Thread.start(self)
990
Antoine Pitrou480a1242010-04-28 21:37:09 +0000991 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000992 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000993 self.sock.listen(5)
994 self.active = True
995 if self.flag:
996 # signal an event
997 self.flag.set()
998 while self.active:
999 try:
1000 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001001 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001003 + repr(connaddr) + '\n')
1004 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001005 handler.start()
1006 except socket.timeout:
1007 pass
1008 except KeyboardInterrupt:
1009 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001010 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001011
Antoine Pitrou480a1242010-04-28 21:37:09 +00001012 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001013 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014
Bill Janssen54cc54c2007-12-14 22:08:56 +00001015 class AsyncoreEchoServer(threading.Thread):
1016
1017 # this one's based on asyncore.dispatcher
1018
1019 class EchoServer (asyncore.dispatcher):
1020
1021 class ConnectionHandler (asyncore.dispatcher_with_send):
1022
1023 def __init__(self, conn, certfile):
1024 self.socket = ssl.wrap_socket(conn, server_side=True,
1025 certfile=certfile,
1026 do_handshake_on_connect=False)
1027 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001028 self._ssl_accepting = True
1029 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001030
1031 def readable(self):
1032 if isinstance(self.socket, ssl.SSLSocket):
1033 while self.socket.pending() > 0:
1034 self.handle_read_event()
1035 return True
1036
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001037 def _do_ssl_handshake(self):
1038 try:
1039 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001040 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1041 return
1042 except ssl.SSLEOFError:
1043 return self.handle_close()
1044 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001045 raise
1046 except socket.error as err:
1047 if err.args[0] == errno.ECONNABORTED:
1048 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001049 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001050 self._ssl_accepting = False
1051
1052 def handle_read(self):
1053 if self._ssl_accepting:
1054 self._do_ssl_handshake()
1055 else:
1056 data = self.recv(1024)
1057 if support.verbose:
1058 sys.stdout.write(" server: read %s from client\n" % repr(data))
1059 if not data:
1060 self.close()
1061 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001062 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001063
1064 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001065 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001066 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001067 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1068
1069 def handle_error(self):
1070 raise
1071
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001072 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001073 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001074 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1075 self.port = support.bind_port(sock, '')
1076 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001077 self.listen(5)
1078
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001079 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001080 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001081 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1082 self.ConnectionHandler(sock_obj, self.certfile)
1083
1084 def handle_error(self):
1085 raise
1086
Trent Nelson78520002008-04-10 20:54:35 +00001087 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001088 self.flag = None
1089 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001090 self.server = self.EchoServer(certfile)
1091 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001092 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001093 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001094
1095 def __str__(self):
1096 return "<%s %s>" % (self.__class__.__name__, self.server)
1097
1098 def start (self, flag=None):
1099 self.flag = flag
1100 threading.Thread.start(self)
1101
Antoine Pitrou480a1242010-04-28 21:37:09 +00001102 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001103 self.active = True
1104 if self.flag:
1105 self.flag.set()
1106 while self.active:
1107 try:
1108 asyncore.loop(1)
1109 except:
1110 pass
1111
Antoine Pitrou480a1242010-04-28 21:37:09 +00001112 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001113 self.active = False
1114 self.server.close()
1115
Antoine Pitrou480a1242010-04-28 21:37:09 +00001116 def bad_cert_test(certfile):
1117 """
1118 Launch a server with CERT_REQUIRED, and check that trying to
1119 connect to it with the given client certificate fails.
1120 """
Trent Nelson78520002008-04-10 20:54:35 +00001121 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001122 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001123 cacerts=CERTFILE, chatty=False,
1124 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125 flag = threading.Event()
1126 server.start(flag)
1127 # wait for it to start
1128 flag.wait()
1129 # try to connect
1130 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001131 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001132 with socket.socket() as sock:
1133 s = ssl.wrap_socket(sock,
1134 certfile=certfile,
1135 ssl_version=ssl.PROTOCOL_TLSv1)
1136 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001137 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001138 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001139 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001140 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001142 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001143 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001144 if x.errno != errno.ENOENT:
1145 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001146 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001147 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001149 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 finally:
1151 server.stop()
1152 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001153
Antoine Pitroub5218772010-05-21 09:56:06 +00001154 def server_params_test(client_context, server_context, indata=b"FOO\n",
1155 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001156 """
1157 Launch a server, connect a client to it and try various reads
1158 and writes.
1159 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001160 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001161 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001162 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163 flag = threading.Event()
1164 server.start(flag)
1165 # wait for it to start
1166 flag.wait()
1167 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001168 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001169 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001170 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001171 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001172 if connectionchatty:
1173 if support.verbose:
1174 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001175 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001176 s.write(arg)
1177 outdata = s.read()
1178 if connectionchatty:
1179 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001181 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001182 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001183 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1184 % (outdata[:20], len(outdata),
1185 indata[:20].lower(), len(indata)))
1186 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001187 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001188 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001189 sys.stdout.write(" client: closing connection.\n")
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001190 stats = {
1191 'compression': s.compression(),
1192 'cipher': s.cipher(),
1193 }
Bill Janssen6e027db2007-11-15 22:23:56 +00001194 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001195 return stats
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001196 finally:
1197 server.stop()
1198 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001199
Antoine Pitroub5218772010-05-21 09:56:06 +00001200 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1201 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001202 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001203 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001204 certtype = {
1205 ssl.CERT_NONE: "CERT_NONE",
1206 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1207 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1208 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001209 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001210 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 sys.stdout.write(formatstr %
1212 (ssl.get_protocol_name(client_protocol),
1213 ssl.get_protocol_name(server_protocol),
1214 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001215 client_context = ssl.SSLContext(client_protocol)
1216 client_context.options = ssl.OP_ALL | client_options
1217 server_context = ssl.SSLContext(server_protocol)
1218 server_context.options = ssl.OP_ALL | server_options
1219 for ctx in (client_context, server_context):
1220 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001221 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1222 # will send an SSLv3 hello (rather than SSLv2) starting from
1223 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001224 ctx.set_ciphers("ALL")
1225 ctx.load_cert_chain(CERTFILE)
1226 ctx.load_verify_locations(CERTFILE)
1227 try:
1228 server_params_test(client_context, server_context,
1229 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001230 # Protocol mismatch can result in either an SSLError, or a
1231 # "Connection reset by peer" error.
1232 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001233 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001235 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001236 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001237 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001238 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001239 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001240 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241 "Client protocol %s succeeded with server protocol %s!"
1242 % (ssl.get_protocol_name(client_protocol),
1243 ssl.get_protocol_name(server_protocol)))
1244
1245
Bill Janssen6e027db2007-11-15 22:23:56 +00001246 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001247
Antoine Pitrou23df4832010-08-04 17:14:06 +00001248 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 def test_echo(self):
1250 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001251 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001252 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001253 for protocol in PROTOCOLS:
1254 context = ssl.SSLContext(protocol)
1255 context.load_cert_chain(CERTFILE)
1256 server_params_test(context, context,
1257 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001258
Antoine Pitrou480a1242010-04-28 21:37:09 +00001259 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001260 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001261 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001262 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1263 context.verify_mode = ssl.CERT_REQUIRED
1264 context.load_verify_locations(CERTFILE)
1265 context.load_cert_chain(CERTFILE)
1266 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001267 flag = threading.Event()
1268 server.start(flag)
1269 # wait for it to start
1270 flag.wait()
1271 # try to connect
1272 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001273 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001274 s.connect((HOST, server.port))
1275 cert = s.getpeercert()
1276 self.assertTrue(cert, "Can't get peer certificate.")
1277 cipher = s.cipher()
1278 if support.verbose:
1279 sys.stdout.write(pprint.pformat(cert) + '\n')
1280 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1281 if 'subject' not in cert:
1282 self.fail("No subject field in certificate: %s." %
1283 pprint.pformat(cert))
1284 if ((('organizationName', 'Python Software Foundation'),)
1285 not in cert['subject']):
1286 self.fail(
1287 "Missing or invalid 'organizationName' field in certificate subject; "
1288 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001289 self.assertIn('notBefore', cert)
1290 self.assertIn('notAfter', cert)
1291 before = ssl.cert_time_to_seconds(cert['notBefore'])
1292 after = ssl.cert_time_to_seconds(cert['notAfter'])
1293 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001294 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001295 finally:
1296 server.stop()
1297 server.join()
1298
Antoine Pitrou480a1242010-04-28 21:37:09 +00001299 def test_empty_cert(self):
1300 """Connecting with an empty cert file"""
1301 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1302 "nullcert.pem"))
1303 def test_malformed_cert(self):
1304 """Connecting with a badly formatted certificate (syntax error)"""
1305 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1306 "badcert.pem"))
1307 def test_nonexisting_cert(self):
1308 """Connecting with a non-existing cert file"""
1309 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1310 "wrongcert.pem"))
1311 def test_malformed_key(self):
1312 """Connecting with a badly formatted key (syntax error)"""
1313 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1314 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001315
Antoine Pitrou480a1242010-04-28 21:37:09 +00001316 def test_rude_shutdown(self):
1317 """A brutal shutdown of an SSL server should raise an IOError
1318 in the client when attempting handshake.
1319 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001320 listener_ready = threading.Event()
1321 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001322
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001323 s = socket.socket()
1324 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001325
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001326 # `listener` runs in a thread. It sits in an accept() until
1327 # the main thread connects. Then it rudely closes the socket,
1328 # and sets Event `listener_gone` to let the main thread know
1329 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001330 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001331 s.listen(5)
1332 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001333 newsock, addr = s.accept()
1334 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001335 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001336 listener_gone.set()
1337
1338 def connector():
1339 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001340 with socket.socket() as c:
1341 c.connect((HOST, port))
1342 listener_gone.wait()
1343 try:
1344 ssl_sock = ssl.wrap_socket(c)
1345 except IOError:
1346 pass
1347 else:
1348 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001349
1350 t = threading.Thread(target=listener)
1351 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001352 try:
1353 connector()
1354 finally:
1355 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001356
Antoine Pitrou23df4832010-08-04 17:14:06 +00001357 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001358 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1359 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001360 def test_protocol_sslv2(self):
1361 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001362 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001363 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001364 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1365 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1366 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1367 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1368 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1369 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001370 # SSLv23 client with specific SSL options
1371 if no_sslv2_implies_sslv3_hello():
1372 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1373 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1374 client_options=ssl.OP_NO_SSLv2)
1375 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1376 client_options=ssl.OP_NO_SSLv3)
1377 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1378 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001379
Antoine Pitrou23df4832010-08-04 17:14:06 +00001380 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 def test_protocol_sslv23(self):
1382 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001383 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001384 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001385 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1386 try:
1387 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1388 except (ssl.SSLError, socket.error) as x:
1389 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1390 if support.verbose:
1391 sys.stdout.write(
1392 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1393 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001394 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1395 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1396 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001397
Antoine Pitrou480a1242010-04-28 21:37:09 +00001398 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1399 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1400 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001401
Antoine Pitrou480a1242010-04-28 21:37:09 +00001402 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1403 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1404 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001405
Antoine Pitroub5218772010-05-21 09:56:06 +00001406 # Server with specific SSL options
1407 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1408 server_options=ssl.OP_NO_SSLv3)
1409 # Will choose TLSv1
1410 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1411 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1412 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1413 server_options=ssl.OP_NO_TLSv1)
1414
1415
Antoine Pitrou23df4832010-08-04 17:14:06 +00001416 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001417 def test_protocol_sslv3(self):
1418 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001419 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001420 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001421 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1422 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1423 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001424 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1425 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001426 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1427 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001428 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001429 if no_sslv2_implies_sslv3_hello():
1430 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1431 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1432 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001433
Antoine Pitrou23df4832010-08-04 17:14:06 +00001434 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 def test_protocol_tlsv1(self):
1436 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001437 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001438 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001439 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1440 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1441 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001442 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1443 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001445 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1446 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001447
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 def test_starttls(self):
1449 """Switching from clear text to encrypted and back again."""
1450 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001451
Trent Nelson78520002008-04-10 20:54:35 +00001452 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001453 ssl_version=ssl.PROTOCOL_TLSv1,
1454 starttls_server=True,
1455 chatty=True,
1456 connectionchatty=True)
1457 flag = threading.Event()
1458 server.start(flag)
1459 # wait for it to start
1460 flag.wait()
1461 # try to connect
1462 wrapped = False
1463 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001464 s = socket.socket()
1465 s.setblocking(1)
1466 s.connect((HOST, server.port))
1467 if support.verbose:
1468 sys.stdout.write("\n")
1469 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001470 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001471 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001472 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001473 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001474 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001475 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001476 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001477 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001478 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001479 msg = outdata.strip().lower()
1480 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1481 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001482 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001483 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001484 " client: read %r from server, starting TLS...\n"
1485 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001486 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1487 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001488 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1489 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001490 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001491 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 " client: read %r from server, ending TLS...\n"
1493 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001494 s = conn.unwrap()
1495 wrapped = False
1496 else:
1497 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001498 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001499 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001500 if support.verbose:
1501 sys.stdout.write(" client: closing connection.\n")
1502 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001503 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001504 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001505 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001506 if wrapped:
1507 conn.close()
1508 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001509 s.close()
1510 finally:
1511 server.stop()
1512 server.join()
1513
Antoine Pitrou480a1242010-04-28 21:37:09 +00001514 def test_socketserver(self):
1515 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001516 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001517 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001518 if support.verbose:
1519 sys.stdout.write('\n')
1520 with open(CERTFILE, 'rb') as f:
1521 d1 = f.read()
1522 d2 = ''
1523 # now fetch the same data from the HTTPS server
1524 url = 'https://%s:%d/%s' % (
1525 HOST, server.port, os.path.split(CERTFILE)[1])
1526 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001527 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001528 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001529 if dlen and (int(dlen) > 0):
1530 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001531 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001532 sys.stdout.write(
1533 " client: read %d bytes from remote server '%s'\n"
1534 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001535 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001536 f.close()
1537 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001538
Antoine Pitrou480a1242010-04-28 21:37:09 +00001539 def test_asyncore_server(self):
1540 """Check the example asyncore integration."""
1541 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001542
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001543 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001544 sys.stdout.write("\n")
1545
Antoine Pitrou480a1242010-04-28 21:37:09 +00001546 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001547 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001548 flag = threading.Event()
1549 server.start(flag)
1550 # wait for it to start
1551 flag.wait()
1552 # try to connect
1553 try:
1554 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001555 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001556 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001557 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001558 " client: sending %r...\n" % indata)
1559 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001560 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001561 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001562 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001563 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001564 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001565 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1566 % (outdata[:20], len(outdata),
1567 indata[:20].lower(), len(indata)))
1568 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001569 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001570 sys.stdout.write(" client: closing connection.\n")
1571 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001572 if support.verbose:
1573 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001574 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001575 if support.verbose:
1576 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001577 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001578 if support.verbose:
1579 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001580 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001581 if support.verbose:
1582 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001583
Antoine Pitrou480a1242010-04-28 21:37:09 +00001584 def test_recv_send(self):
1585 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001586 if support.verbose:
1587 sys.stdout.write("\n")
1588
1589 server = ThreadedEchoServer(CERTFILE,
1590 certreqs=ssl.CERT_NONE,
1591 ssl_version=ssl.PROTOCOL_TLSv1,
1592 cacerts=CERTFILE,
1593 chatty=True,
1594 connectionchatty=False)
1595 flag = threading.Event()
1596 server.start(flag)
1597 # wait for it to start
1598 flag.wait()
1599 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001600 s = ssl.wrap_socket(socket.socket(),
1601 server_side=False,
1602 certfile=CERTFILE,
1603 ca_certs=CERTFILE,
1604 cert_reqs=ssl.CERT_NONE,
1605 ssl_version=ssl.PROTOCOL_TLSv1)
1606 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001607 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001608 # helper methods for standardising recv* method signatures
1609 def _recv_into():
1610 b = bytearray(b"\0"*100)
1611 count = s.recv_into(b)
1612 return b[:count]
1613
1614 def _recvfrom_into():
1615 b = bytearray(b"\0"*100)
1616 count, addr = s.recvfrom_into(b)
1617 return b[:count]
1618
1619 # (name, method, whether to expect success, *args)
1620 send_methods = [
1621 ('send', s.send, True, []),
1622 ('sendto', s.sendto, False, ["some.address"]),
1623 ('sendall', s.sendall, True, []),
1624 ]
1625 recv_methods = [
1626 ('recv', s.recv, True, []),
1627 ('recvfrom', s.recvfrom, False, ["some.address"]),
1628 ('recv_into', _recv_into, True, []),
1629 ('recvfrom_into', _recvfrom_into, False, []),
1630 ]
1631 data_prefix = "PREFIX_"
1632
1633 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001634 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001635 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001636 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001637 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001638 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001639 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001640 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001641 "<<{outdata:r}>> ({nout:d}) received; "
1642 "expected <<{indata:r}>> ({nin:d})\n".format(
1643 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001644 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001645 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001646 )
1647 )
1648 except ValueError as e:
1649 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001650 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001651 "Failed to send with method <<{name:s}>>; "
1652 "expected to succeed.\n".format(name=meth_name)
1653 )
1654 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001655 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001656 "Method <<{name:s}>> failed with unexpected "
1657 "exception message: {exp:s}\n".format(
1658 name=meth_name, exp=e
1659 )
1660 )
1661
1662 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001663 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001664 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001665 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001666 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001667 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001668 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001669 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001670 "<<{outdata:r}>> ({nout:d}) received; "
1671 "expected <<{indata:r}>> ({nin:d})\n".format(
1672 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001673 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001674 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001675 )
1676 )
1677 except ValueError as e:
1678 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001679 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001680 "Failed to receive with method <<{name:s}>>; "
1681 "expected to succeed.\n".format(name=meth_name)
1682 )
1683 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001684 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001685 "Method <<{name:s}>> failed with unexpected "
1686 "exception message: {exp:s}\n".format(
1687 name=meth_name, exp=e
1688 )
1689 )
1690 # consume data
1691 s.read()
1692
Nick Coghlan513886a2011-08-28 00:00:27 +10001693 # Make sure sendmsg et al are disallowed to avoid
1694 # inadvertent disclosure of data and/or corruption
1695 # of the encrypted data stream
1696 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1697 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1698 self.assertRaises(NotImplementedError,
1699 s.recvmsg_into, bytearray(100))
1700
Antoine Pitrou480a1242010-04-28 21:37:09 +00001701 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001702 s.close()
1703 finally:
1704 server.stop()
1705 server.join()
1706
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001707 def test_handshake_timeout(self):
1708 # Issue #5103: SSL handshake must respect the socket timeout
1709 server = socket.socket(socket.AF_INET)
1710 host = "127.0.0.1"
1711 port = support.bind_port(server)
1712 started = threading.Event()
1713 finish = False
1714
1715 def serve():
1716 server.listen(5)
1717 started.set()
1718 conns = []
1719 while not finish:
1720 r, w, e = select.select([server], [], [], 0.1)
1721 if server in r:
1722 # Let the socket hang around rather than having
1723 # it closed by garbage collection.
1724 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001725 for sock in conns:
1726 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001727
1728 t = threading.Thread(target=serve)
1729 t.start()
1730 started.wait()
1731
1732 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001733 try:
1734 c = socket.socket(socket.AF_INET)
1735 c.settimeout(0.2)
1736 c.connect((host, port))
1737 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001738 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001739 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001740 finally:
1741 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001742 try:
1743 c = socket.socket(socket.AF_INET)
1744 c = ssl.wrap_socket(c)
1745 c.settimeout(0.2)
1746 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001747 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001748 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001749 finally:
1750 c.close()
1751 finally:
1752 finish = True
1753 t.join()
1754 server.close()
1755
Antoine Pitroud6494802011-07-21 01:11:30 +02001756 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1757 "'tls-unique' channel binding not available")
1758 def test_tls_unique_channel_binding(self):
1759 """Test tls-unique channel binding."""
1760 if support.verbose:
1761 sys.stdout.write("\n")
1762
1763 server = ThreadedEchoServer(CERTFILE,
1764 certreqs=ssl.CERT_NONE,
1765 ssl_version=ssl.PROTOCOL_TLSv1,
1766 cacerts=CERTFILE,
1767 chatty=True,
1768 connectionchatty=False)
1769 flag = threading.Event()
1770 server.start(flag)
1771 # wait for it to start
1772 flag.wait()
1773 # try to connect
1774 s = ssl.wrap_socket(socket.socket(),
1775 server_side=False,
1776 certfile=CERTFILE,
1777 ca_certs=CERTFILE,
1778 cert_reqs=ssl.CERT_NONE,
1779 ssl_version=ssl.PROTOCOL_TLSv1)
1780 s.connect((HOST, server.port))
1781 try:
1782 # get the data
1783 cb_data = s.get_channel_binding("tls-unique")
1784 if support.verbose:
1785 sys.stdout.write(" got channel binding data: {0!r}\n"
1786 .format(cb_data))
1787
1788 # check if it is sane
1789 self.assertIsNotNone(cb_data)
1790 self.assertEqual(len(cb_data), 12) # True for TLSv1
1791
1792 # and compare with the peers version
1793 s.write(b"CB tls-unique\n")
1794 peer_data_repr = s.read().strip()
1795 self.assertEqual(peer_data_repr,
1796 repr(cb_data).encode("us-ascii"))
1797 s.close()
1798
1799 # now, again
1800 s = ssl.wrap_socket(socket.socket(),
1801 server_side=False,
1802 certfile=CERTFILE,
1803 ca_certs=CERTFILE,
1804 cert_reqs=ssl.CERT_NONE,
1805 ssl_version=ssl.PROTOCOL_TLSv1)
1806 s.connect((HOST, server.port))
1807 new_cb_data = s.get_channel_binding("tls-unique")
1808 if support.verbose:
1809 sys.stdout.write(" got another channel binding data: {0!r}\n"
1810 .format(new_cb_data))
1811 # is it really unique
1812 self.assertNotEqual(cb_data, new_cb_data)
1813 self.assertIsNotNone(cb_data)
1814 self.assertEqual(len(cb_data), 12) # True for TLSv1
1815 s.write(b"CB tls-unique\n")
1816 peer_data_repr = s.read().strip()
1817 self.assertEqual(peer_data_repr,
1818 repr(new_cb_data).encode("us-ascii"))
1819 s.close()
1820 finally:
1821 server.stop()
1822 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001823
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001824 def test_compression(self):
1825 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1826 context.load_cert_chain(CERTFILE)
1827 stats = server_params_test(context, context,
1828 chatty=True, connectionchatty=True)
1829 if support.verbose:
1830 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1831 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1832
1833 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1834 "ssl.OP_NO_COMPRESSION needed for this test")
1835 def test_compression_disabled(self):
1836 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1837 context.load_cert_chain(CERTFILE)
1838 stats = server_params_test(context, context,
1839 chatty=True, connectionchatty=True)
1840 self.assertIs(stats['compression'], None)
1841
1842
Thomas Woutersed03b412007-08-28 21:37:11 +00001843def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001844 if support.verbose:
1845 plats = {
1846 'Linux': platform.linux_distribution,
1847 'Mac': platform.mac_ver,
1848 'Windows': platform.win32_ver,
1849 }
1850 for name, func in plats.items():
1851 plat = func()
1852 if plat and plat[0]:
1853 plat = '%s %r' % (name, plat)
1854 break
1855 else:
1856 plat = repr(platform.platform())
1857 print("test_ssl: testing with %r %r" %
1858 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1859 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001860 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001861
Antoine Pitrou152efa22010-05-16 18:19:27 +00001862 for filename in [
1863 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1864 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1865 BADCERT, BADKEY, EMPTYCERT]:
1866 if not os.path.exists(filename):
1867 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001868
Antoine Pitrou152efa22010-05-16 18:19:27 +00001869 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001870
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001871 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001872 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001873
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001874 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001875 thread_info = support.threading_setup()
1876 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001877 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001878
Antoine Pitrou480a1242010-04-28 21:37:09 +00001879 try:
1880 support.run_unittest(*tests)
1881 finally:
1882 if _have_threads:
1883 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001884
1885if __name__ == "__main__":
1886 test_main()