blob: a2b4040a9c452a548269acc5f7fcb7ee3d866d24 [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 Pitroud5323212010-10-22 18:19:07 +0000101 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000102
Antoine Pitrou480a1242010-04-28 21:37:09 +0000103 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000104 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000105 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 sys.stdout.write("\n RAND_status is %d (%s)\n"
107 % (v, (v and "sufficient randomness") or
108 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200109
110 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
111 self.assertEqual(len(data), 16)
112 self.assertEqual(is_cryptographic, v == 1)
113 if v:
114 data = ssl.RAND_bytes(16)
115 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200116 else:
117 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200118
Thomas Woutersed03b412007-08-28 21:37:11 +0000119 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 ssl.RAND_egd(1)
121 except TypeError:
122 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000123 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000124 print("didn't raise TypeError")
125 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000126
Antoine Pitrou480a1242010-04-28 21:37:09 +0000127 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128 # note that this uses an 'unofficial' function in _ssl.c,
129 # provided solely for this test, to exercise the certificate
130 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000131 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000132 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000133 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200134 self.assertEqual(p['issuer'],
135 ((('countryName', 'XY'),),
136 (('localityName', 'Castle Anthrax'),),
137 (('organizationName', 'Python Software Foundation'),),
138 (('commonName', 'localhost'),))
139 )
140 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
141 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
142 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
143 self.assertEqual(p['subject'],
144 ((('countryName', 'XY'),),
145 (('localityName', 'Castle Anthrax'),),
146 (('organizationName', 'Python Software Foundation'),),
147 (('commonName', 'localhost'),))
148 )
149 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
150 # Issue #13034: the subjectAltName in some certificates
151 # (notably projects.developer.nokia.com:443) wasn't parsed
152 p = ssl._ssl._test_decode_cert(NOKIACERT)
153 if support.verbose:
154 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
155 self.assertEqual(p['subjectAltName'],
156 (('DNS', 'projects.developer.nokia.com'),
157 ('DNS', 'projects.forum.nokia.com'))
158 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000159
Antoine Pitrou480a1242010-04-28 21:37:09 +0000160 def test_DER_to_PEM(self):
161 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
162 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000163 d1 = ssl.PEM_cert_to_DER_cert(pem)
164 p2 = ssl.DER_cert_to_PEM_cert(d1)
165 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000166 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000167 if not p2.startswith(ssl.PEM_HEADER + '\n'):
168 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
169 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
170 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000171
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000172 def test_openssl_version(self):
173 n = ssl.OPENSSL_VERSION_NUMBER
174 t = ssl.OPENSSL_VERSION_INFO
175 s = ssl.OPENSSL_VERSION
176 self.assertIsInstance(n, int)
177 self.assertIsInstance(t, tuple)
178 self.assertIsInstance(s, str)
179 # Some sanity checks follow
180 # >= 0.9
181 self.assertGreaterEqual(n, 0x900000)
182 # < 2.0
183 self.assertLess(n, 0x20000000)
184 major, minor, fix, patch, status = t
185 self.assertGreaterEqual(major, 0)
186 self.assertLess(major, 2)
187 self.assertGreaterEqual(minor, 0)
188 self.assertLess(minor, 256)
189 self.assertGreaterEqual(fix, 0)
190 self.assertLess(fix, 256)
191 self.assertGreaterEqual(patch, 0)
192 self.assertLessEqual(patch, 26)
193 self.assertGreaterEqual(status, 0)
194 self.assertLessEqual(status, 15)
195 # Version string as returned by OpenSSL, the format might change
196 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
197 (s, t))
198
Antoine Pitrou9d543662010-04-23 23:10:32 +0000199 @support.cpython_only
200 def test_refcycle(self):
201 # Issue #7943: an SSL object doesn't create reference cycles with
202 # itself.
203 s = socket.socket(socket.AF_INET)
204 ss = ssl.wrap_socket(s)
205 wr = weakref.ref(ss)
206 del ss
207 self.assertEqual(wr(), None)
208
Antoine Pitroua468adc2010-09-14 14:43:44 +0000209 def test_wrapped_unconnected(self):
210 # Methods on an unconnected SSLSocket propagate the original
211 # socket.error raise by the underlying socket object.
212 s = socket.socket(socket.AF_INET)
213 ss = ssl.wrap_socket(s)
214 self.assertRaises(socket.error, ss.recv, 1)
215 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
216 self.assertRaises(socket.error, ss.recvfrom, 1)
217 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
218 self.assertRaises(socket.error, ss.send, b'x')
219 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
220
Antoine Pitrou40f08742010-04-24 22:04:40 +0000221 def test_timeout(self):
222 # Issue #8524: when creating an SSL socket, the timeout of the
223 # original socket should be retained.
224 for timeout in (None, 0.0, 5.0):
225 s = socket.socket(socket.AF_INET)
226 s.settimeout(timeout)
227 ss = ssl.wrap_socket(s)
228 self.assertEqual(timeout, ss.gettimeout())
229
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000230 def test_errors(self):
231 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000232 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000233 "certfile must be specified",
234 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000235 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000236 "certfile must be specified for server-side operations",
237 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000238 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000239 "certfile must be specified for server-side operations",
240 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000241 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000242 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000243 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000244 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000245 with socket.socket() as sock:
246 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000247 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +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=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000251 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +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=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000255 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000256
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000257 def test_match_hostname(self):
258 def ok(cert, hostname):
259 ssl.match_hostname(cert, hostname)
260 def fail(cert, hostname):
261 self.assertRaises(ssl.CertificateError,
262 ssl.match_hostname, cert, hostname)
263
264 cert = {'subject': ((('commonName', 'example.com'),),)}
265 ok(cert, 'example.com')
266 ok(cert, 'ExAmple.cOm')
267 fail(cert, 'www.example.com')
268 fail(cert, '.example.com')
269 fail(cert, 'example.org')
270 fail(cert, 'exampleXcom')
271
272 cert = {'subject': ((('commonName', '*.a.com'),),)}
273 ok(cert, 'foo.a.com')
274 fail(cert, 'bar.foo.a.com')
275 fail(cert, 'a.com')
276 fail(cert, 'Xa.com')
277 fail(cert, '.a.com')
278
279 cert = {'subject': ((('commonName', 'a.*.com'),),)}
280 ok(cert, 'a.foo.com')
281 fail(cert, 'a..com')
282 fail(cert, 'a.com')
283
284 cert = {'subject': ((('commonName', 'f*.com'),),)}
285 ok(cert, 'foo.com')
286 ok(cert, 'f.com')
287 fail(cert, 'bar.com')
288 fail(cert, 'foo.a.com')
289 fail(cert, 'bar.foo.com')
290
291 # Slightly fake real-world example
292 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
293 'subject': ((('commonName', 'linuxfrz.org'),),),
294 'subjectAltName': (('DNS', 'linuxfr.org'),
295 ('DNS', 'linuxfr.com'),
296 ('othername', '<unsupported>'))}
297 ok(cert, 'linuxfr.org')
298 ok(cert, 'linuxfr.com')
299 # Not a "DNS" entry
300 fail(cert, '<unsupported>')
301 # When there is a subjectAltName, commonName isn't used
302 fail(cert, 'linuxfrz.org')
303
304 # A pristine real-world example
305 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
306 'subject': ((('countryName', 'US'),),
307 (('stateOrProvinceName', 'California'),),
308 (('localityName', 'Mountain View'),),
309 (('organizationName', 'Google Inc'),),
310 (('commonName', 'mail.google.com'),))}
311 ok(cert, 'mail.google.com')
312 fail(cert, 'gmail.com')
313 # Only commonName is considered
314 fail(cert, 'California')
315
316 # Neither commonName nor subjectAltName
317 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
318 'subject': ((('countryName', 'US'),),
319 (('stateOrProvinceName', 'California'),),
320 (('localityName', 'Mountain View'),),
321 (('organizationName', 'Google Inc'),))}
322 fail(cert, 'mail.google.com')
323
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200324 # No DNS entry in subjectAltName but a commonName
325 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
326 'subject': ((('countryName', 'US'),),
327 (('stateOrProvinceName', 'California'),),
328 (('localityName', 'Mountain View'),),
329 (('commonName', 'mail.google.com'),)),
330 'subjectAltName': (('othername', 'blabla'), )}
331 ok(cert, 'mail.google.com')
332
333 # No DNS entry subjectAltName and no commonName
334 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
335 'subject': ((('countryName', 'US'),),
336 (('stateOrProvinceName', 'California'),),
337 (('localityName', 'Mountain View'),),
338 (('organizationName', 'Google Inc'),)),
339 'subjectAltName': (('othername', 'blabla'),)}
340 fail(cert, 'google.com')
341
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000342 # Empty cert / no cert
343 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
344 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
345
Antoine Pitroud5323212010-10-22 18:19:07 +0000346 def test_server_side(self):
347 # server_hostname doesn't work for server sockets
348 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000349 with socket.socket() as sock:
350 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
351 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000352
Antoine Pitroud6494802011-07-21 01:11:30 +0200353 def test_unknown_channel_binding(self):
354 # should raise ValueError for unknown type
355 s = socket.socket(socket.AF_INET)
356 ss = ssl.wrap_socket(s)
357 with self.assertRaises(ValueError):
358 ss.get_channel_binding("unknown-type")
359
360 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
361 "'tls-unique' channel binding not available")
362 def test_tls_unique_channel_binding(self):
363 # unconnected should return None for known type
364 s = socket.socket(socket.AF_INET)
365 ss = ssl.wrap_socket(s)
366 self.assertIsNone(ss.get_channel_binding("tls-unique"))
367 # the same for server-side
368 s = socket.socket(socket.AF_INET)
369 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
370 self.assertIsNone(ss.get_channel_binding("tls-unique"))
371
Antoine Pitrou152efa22010-05-16 18:19:27 +0000372class ContextTests(unittest.TestCase):
373
Antoine Pitrou23df4832010-08-04 17:14:06 +0000374 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000375 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200376 if hasattr(ssl, 'PROTOCOL_SSLv2'):
377 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000378 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
379 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
380 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
381 self.assertRaises(TypeError, ssl.SSLContext)
382 self.assertRaises(ValueError, ssl.SSLContext, -1)
383 self.assertRaises(ValueError, ssl.SSLContext, 42)
384
Antoine Pitrou23df4832010-08-04 17:14:06 +0000385 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000386 def test_protocol(self):
387 for proto in PROTOCOLS:
388 ctx = ssl.SSLContext(proto)
389 self.assertEqual(ctx.protocol, proto)
390
391 def test_ciphers(self):
392 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
393 ctx.set_ciphers("ALL")
394 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000395 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000396 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000397
Antoine Pitrou23df4832010-08-04 17:14:06 +0000398 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000399 def test_options(self):
400 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
401 # OP_ALL is the default value
402 self.assertEqual(ssl.OP_ALL, ctx.options)
403 ctx.options |= ssl.OP_NO_SSLv2
404 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
405 ctx.options)
406 ctx.options |= ssl.OP_NO_SSLv3
407 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
408 ctx.options)
409 if can_clear_options():
410 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
411 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
412 ctx.options)
413 ctx.options = 0
414 self.assertEqual(0, ctx.options)
415 else:
416 with self.assertRaises(ValueError):
417 ctx.options = 0
418
Antoine Pitrou152efa22010-05-16 18:19:27 +0000419 def test_verify(self):
420 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
421 # Default value
422 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
423 ctx.verify_mode = ssl.CERT_OPTIONAL
424 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
425 ctx.verify_mode = ssl.CERT_REQUIRED
426 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
427 ctx.verify_mode = ssl.CERT_NONE
428 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
429 with self.assertRaises(TypeError):
430 ctx.verify_mode = None
431 with self.assertRaises(ValueError):
432 ctx.verify_mode = 42
433
434 def test_load_cert_chain(self):
435 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
436 # Combined key and cert in a single file
437 ctx.load_cert_chain(CERTFILE)
438 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
439 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000440 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000441 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000442 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000443 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000444 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000445 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000446 ctx.load_cert_chain(EMPTYCERT)
447 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000448 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000449 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
450 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
451 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000452 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000453 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000454 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000455 ctx.load_cert_chain(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(certfile=ONLYKEY, keyfile=ONLYCERT)
458 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000459 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000460 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000461 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200462 # Password protected key and cert
463 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
464 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
465 ctx.load_cert_chain(CERTFILE_PROTECTED,
466 password=bytearray(KEY_PASSWORD.encode()))
467 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
468 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
469 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
470 bytearray(KEY_PASSWORD.encode()))
471 with self.assertRaisesRegex(TypeError, "should be a string"):
472 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
473 with self.assertRaises(ssl.SSLError):
474 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
475 with self.assertRaisesRegex(ValueError, "cannot be longer"):
476 # openssl has a fixed limit on the password buffer.
477 # PEM_BUFSIZE is generally set to 1kb.
478 # Return a string larger than this.
479 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
480 # Password callback
481 def getpass_unicode():
482 return KEY_PASSWORD
483 def getpass_bytes():
484 return KEY_PASSWORD.encode()
485 def getpass_bytearray():
486 return bytearray(KEY_PASSWORD.encode())
487 def getpass_badpass():
488 return "badpass"
489 def getpass_huge():
490 return b'a' * (1024 * 1024)
491 def getpass_bad_type():
492 return 9
493 def getpass_exception():
494 raise Exception('getpass error')
495 class GetPassCallable:
496 def __call__(self):
497 return KEY_PASSWORD
498 def getpass(self):
499 return KEY_PASSWORD
500 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
501 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
502 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
503 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
504 ctx.load_cert_chain(CERTFILE_PROTECTED,
505 password=GetPassCallable().getpass)
506 with self.assertRaises(ssl.SSLError):
507 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
508 with self.assertRaisesRegex(ValueError, "cannot be longer"):
509 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
510 with self.assertRaisesRegex(TypeError, "must return a string"):
511 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
512 with self.assertRaisesRegex(Exception, "getpass error"):
513 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
514 # Make sure the password function isn't called if it isn't needed
515 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000516
517 def test_load_verify_locations(self):
518 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
519 ctx.load_verify_locations(CERTFILE)
520 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
521 ctx.load_verify_locations(BYTES_CERTFILE)
522 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
523 self.assertRaises(TypeError, ctx.load_verify_locations)
524 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000525 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000526 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000527 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000528 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000529 ctx.load_verify_locations(BADCERT)
530 ctx.load_verify_locations(CERTFILE, CAPATH)
531 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
532
Victor Stinner80f75e62011-01-29 11:31:20 +0000533 # Issue #10989: crash if the second argument type is invalid
534 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
535
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000536 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000537 def test_session_stats(self):
538 for proto in PROTOCOLS:
539 ctx = ssl.SSLContext(proto)
540 self.assertEqual(ctx.session_stats(), {
541 'number': 0,
542 'connect': 0,
543 'connect_good': 0,
544 'connect_renegotiate': 0,
545 'accept': 0,
546 'accept_good': 0,
547 'accept_renegotiate': 0,
548 'hits': 0,
549 'misses': 0,
550 'timeouts': 0,
551 'cache_full': 0,
552 })
553
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000554 def test_set_default_verify_paths(self):
555 # There's not much we can do to test that it acts as expected,
556 # so just check it doesn't crash or raise an exception.
557 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
558 ctx.set_default_verify_paths()
559
Antoine Pitrou152efa22010-05-16 18:19:27 +0000560
Bill Janssen6e027db2007-11-15 22:23:56 +0000561class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000562
Antoine Pitrou480a1242010-04-28 21:37:09 +0000563 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000564 with support.transient_internet("svn.python.org"):
565 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
566 cert_reqs=ssl.CERT_NONE)
567 try:
568 s.connect(("svn.python.org", 443))
569 self.assertEqual({}, s.getpeercert())
570 finally:
571 s.close()
572
573 # this should fail because we have no verification certs
574 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
575 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000576 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
577 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000578 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000579
Antoine Pitrou350c7222010-09-09 13:31:46 +0000580 # this should succeed because we specify the root cert
581 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
582 cert_reqs=ssl.CERT_REQUIRED,
583 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
584 try:
585 s.connect(("svn.python.org", 443))
586 self.assertTrue(s.getpeercert())
587 finally:
588 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000589
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000590 def test_connect_ex(self):
591 # Issue #11326: check connect_ex() implementation
592 with support.transient_internet("svn.python.org"):
593 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
594 cert_reqs=ssl.CERT_REQUIRED,
595 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
596 try:
597 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
598 self.assertTrue(s.getpeercert())
599 finally:
600 s.close()
601
602 def test_non_blocking_connect_ex(self):
603 # Issue #11326: non-blocking connect_ex() should allow handshake
604 # to proceed after the socket gets ready.
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 do_handshake_on_connect=False)
610 try:
611 s.setblocking(False)
612 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000613 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
614 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000615 # Wait for connect to finish
616 select.select([], [s], [], 5.0)
617 # Non-blocking handshake
618 while True:
619 try:
620 s.do_handshake()
621 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200622 except ssl.SSLWantReadError:
623 select.select([s], [], [], 5.0)
624 except ssl.SSLWantWriteError:
625 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000626 # SSL established
627 self.assertTrue(s.getpeercert())
628 finally:
629 s.close()
630
Antoine Pitroub4410db2011-05-18 18:51:06 +0200631 def test_timeout_connect_ex(self):
632 # Issue #12065: on a timeout, connect_ex() should return the original
633 # errno (mimicking the behaviour of non-SSL sockets).
634 with support.transient_internet("svn.python.org"):
635 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
636 cert_reqs=ssl.CERT_REQUIRED,
637 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
638 do_handshake_on_connect=False)
639 try:
640 s.settimeout(0.0000001)
641 rc = s.connect_ex(('svn.python.org', 443))
642 if rc == 0:
643 self.skipTest("svn.python.org responded too quickly")
644 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
645 finally:
646 s.close()
647
Antoine Pitrou152efa22010-05-16 18:19:27 +0000648 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000649 with support.transient_internet("svn.python.org"):
650 # Same as test_connect, but with a separately created context
651 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
652 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
653 s.connect(("svn.python.org", 443))
654 try:
655 self.assertEqual({}, s.getpeercert())
656 finally:
657 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000658 # Same with a server hostname
659 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
660 server_hostname="svn.python.org")
661 if ssl.HAS_SNI:
662 s.connect(("svn.python.org", 443))
663 s.close()
664 else:
665 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000666 # This should fail because we have no verification certs
667 ctx.verify_mode = ssl.CERT_REQUIRED
668 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000669 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000670 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000671 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000672 # This should succeed because we specify the root cert
673 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
674 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
675 s.connect(("svn.python.org", 443))
676 try:
677 cert = s.getpeercert()
678 self.assertTrue(cert)
679 finally:
680 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000681
682 def test_connect_capath(self):
683 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000684 # NOTE: the subject hashing algorithm has been changed between
685 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
686 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000687 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000688 with support.transient_internet("svn.python.org"):
689 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
690 ctx.verify_mode = ssl.CERT_REQUIRED
691 ctx.load_verify_locations(capath=CAPATH)
692 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
693 s.connect(("svn.python.org", 443))
694 try:
695 cert = s.getpeercert()
696 self.assertTrue(cert)
697 finally:
698 s.close()
699 # Same with a bytes `capath` argument
700 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
701 ctx.verify_mode = ssl.CERT_REQUIRED
702 ctx.load_verify_locations(capath=BYTES_CAPATH)
703 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
704 s.connect(("svn.python.org", 443))
705 try:
706 cert = s.getpeercert()
707 self.assertTrue(cert)
708 finally:
709 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000710
Antoine Pitroue3220242010-04-24 11:13:53 +0000711 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
712 def test_makefile_close(self):
713 # Issue #5238: creating a file-like object with makefile() shouldn't
714 # delay closing the underlying "real socket" (here tested with its
715 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000716 with support.transient_internet("svn.python.org"):
717 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
718 ss.connect(("svn.python.org", 443))
719 fd = ss.fileno()
720 f = ss.makefile()
721 f.close()
722 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000723 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000724 # Closing the SSL socket should close the fd too
725 ss.close()
726 gc.collect()
727 with self.assertRaises(OSError) as e:
728 os.read(fd, 0)
729 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000730
Antoine Pitrou480a1242010-04-28 21:37:09 +0000731 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000732 with support.transient_internet("svn.python.org"):
733 s = socket.socket(socket.AF_INET)
734 s.connect(("svn.python.org", 443))
735 s.setblocking(False)
736 s = ssl.wrap_socket(s,
737 cert_reqs=ssl.CERT_NONE,
738 do_handshake_on_connect=False)
739 count = 0
740 while True:
741 try:
742 count += 1
743 s.do_handshake()
744 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200745 except ssl.SSLWantReadError:
746 select.select([s], [], [])
747 except ssl.SSLWantWriteError:
748 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000749 s.close()
750 if support.verbose:
751 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000752
Antoine Pitrou480a1242010-04-28 21:37:09 +0000753 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200754 def _test_get_server_certificate(host, port, cert=None):
755 with support.transient_internet(host):
756 pem = ssl.get_server_certificate((host, port))
757 if not pem:
758 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200759
Antoine Pitrou15399c32011-04-28 19:23:55 +0200760 try:
761 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
762 except ssl.SSLError as x:
763 #should fail
764 if support.verbose:
765 sys.stdout.write("%s\n" % x)
766 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200767 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
768
Antoine Pitrou15399c32011-04-28 19:23:55 +0200769 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
770 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200771 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000772 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200773 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000774
Antoine Pitrou15399c32011-04-28 19:23:55 +0200775 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
776 if support.IPV6_ENABLED:
777 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000778
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000779 def test_ciphers(self):
780 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000781 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000782 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000783 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000784 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000785 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
786 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
787 s.connect(remote)
788 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000789 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000790 with socket.socket(socket.AF_INET) as sock:
791 s = ssl.wrap_socket(sock,
792 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
793 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000794
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000795 def test_algorithms(self):
796 # Issue #8484: all algorithms should be available when verifying a
797 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000798 # SHA256 was added in OpenSSL 0.9.8
799 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
800 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000801 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
802 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000803 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000804 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000805 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
806 cert_reqs=ssl.CERT_REQUIRED,
807 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000808 try:
809 s.connect(remote)
810 if support.verbose:
811 sys.stdout.write("\nCipher with %r is %r\n" %
812 (remote, s.cipher()))
813 sys.stdout.write("Certificate is:\n%s\n" %
814 pprint.pformat(s.getpeercert()))
815 finally:
816 s.close()
817
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000818
819try:
820 import threading
821except ImportError:
822 _have_threads = False
823else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000824 _have_threads = True
825
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000826 from test.ssl_servers import make_https_server
827
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000828 class ThreadedEchoServer(threading.Thread):
829
830 class ConnectionHandler(threading.Thread):
831
832 """A mildly complicated class, because we want it to work both
833 with and without the SSL wrapper around the socket connection, so
834 that we can test the STARTTLS functionality."""
835
Bill Janssen6e027db2007-11-15 22:23:56 +0000836 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000837 self.server = server
838 self.running = False
839 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000840 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000841 self.sock.setblocking(1)
842 self.sslconn = None
843 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000844 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000845
Antoine Pitrou480a1242010-04-28 21:37:09 +0000846 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000847 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000848 self.sslconn = self.server.context.wrap_socket(
849 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000850 except ssl.SSLError:
851 # XXX Various errors can have happened here, for example
852 # a mismatching protocol version, an invalid certificate,
853 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000854 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000855 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000856 self.running = False
857 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000858 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000859 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000861 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000863 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000864 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
865 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000866 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000867 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
868 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000869 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
871 return True
872
873 def read(self):
874 if self.sslconn:
875 return self.sslconn.read()
876 else:
877 return self.sock.recv(1024)
878
879 def write(self, bytes):
880 if self.sslconn:
881 return self.sslconn.write(bytes)
882 else:
883 return self.sock.send(bytes)
884
885 def close(self):
886 if self.sslconn:
887 self.sslconn.close()
888 else:
889 self.sock.close()
890
Antoine Pitrou480a1242010-04-28 21:37:09 +0000891 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892 self.running = True
893 if not self.server.starttls_server:
894 if not self.wrap_conn():
895 return
896 while self.running:
897 try:
898 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000899 stripped = msg.strip()
900 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000901 # eof, so quit this handler
902 self.running = False
903 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000904 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000905 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000906 sys.stdout.write(" server: client closed connection\n")
907 self.close()
908 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000909 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000910 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000911 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000913 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000914 if not self.wrap_conn():
915 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000916 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000917 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000918 if support.verbose and self.server.connectionchatty:
919 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000920 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000921 self.sock = self.sslconn.unwrap()
922 self.sslconn = None
923 if support.verbose and self.server.connectionchatty:
924 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200925 elif stripped == b'CB tls-unique':
926 if support.verbose and self.server.connectionchatty:
927 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
928 data = self.sslconn.get_channel_binding("tls-unique")
929 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000931 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000932 self.server.connectionchatty):
933 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000934 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
935 % (msg, ctype, msg.lower(), ctype))
936 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000937 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938 if self.server.chatty:
939 handle_error("Test server failure:\n")
940 self.close()
941 self.running = False
942 # normally, we'd just stop here, but for the test
943 # harness, we want to stop the server
944 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000945
Antoine Pitroub5218772010-05-21 09:56:06 +0000946 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000947 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000948 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000949 ciphers=None, context=None):
950 if context:
951 self.context = context
952 else:
953 self.context = ssl.SSLContext(ssl_version
954 if ssl_version is not None
955 else ssl.PROTOCOL_TLSv1)
956 self.context.verify_mode = (certreqs if certreqs is not None
957 else ssl.CERT_NONE)
958 if cacerts:
959 self.context.load_verify_locations(cacerts)
960 if certificate:
961 self.context.load_cert_chain(certificate)
962 if ciphers:
963 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000964 self.chatty = chatty
965 self.connectionchatty = connectionchatty
966 self.starttls_server = starttls_server
967 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000968 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000969 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 self.active = False
971 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000972 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000973
Antoine Pitrou480a1242010-04-28 21:37:09 +0000974 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 self.flag = flag
976 threading.Thread.start(self)
977
Antoine Pitrou480a1242010-04-28 21:37:09 +0000978 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000979 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980 self.sock.listen(5)
981 self.active = True
982 if self.flag:
983 # signal an event
984 self.flag.set()
985 while self.active:
986 try:
987 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000988 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000989 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000990 + repr(connaddr) + '\n')
991 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000992 handler.start()
993 except socket.timeout:
994 pass
995 except KeyboardInterrupt:
996 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000997 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998
Antoine Pitrou480a1242010-04-28 21:37:09 +0000999 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001000 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001
Bill Janssen54cc54c2007-12-14 22:08:56 +00001002 class AsyncoreEchoServer(threading.Thread):
1003
1004 # this one's based on asyncore.dispatcher
1005
1006 class EchoServer (asyncore.dispatcher):
1007
1008 class ConnectionHandler (asyncore.dispatcher_with_send):
1009
1010 def __init__(self, conn, certfile):
1011 self.socket = ssl.wrap_socket(conn, server_side=True,
1012 certfile=certfile,
1013 do_handshake_on_connect=False)
1014 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001015 self._ssl_accepting = True
1016 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001017
1018 def readable(self):
1019 if isinstance(self.socket, ssl.SSLSocket):
1020 while self.socket.pending() > 0:
1021 self.handle_read_event()
1022 return True
1023
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001024 def _do_ssl_handshake(self):
1025 try:
1026 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001027 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1028 return
1029 except ssl.SSLEOFError:
1030 return self.handle_close()
1031 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001032 raise
1033 except socket.error as err:
1034 if err.args[0] == errno.ECONNABORTED:
1035 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001036 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001037 self._ssl_accepting = False
1038
1039 def handle_read(self):
1040 if self._ssl_accepting:
1041 self._do_ssl_handshake()
1042 else:
1043 data = self.recv(1024)
1044 if support.verbose:
1045 sys.stdout.write(" server: read %s from client\n" % repr(data))
1046 if not data:
1047 self.close()
1048 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001049 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001050
1051 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001052 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001053 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001054 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1055
1056 def handle_error(self):
1057 raise
1058
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001059 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001060 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001061 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1062 self.port = support.bind_port(sock, '')
1063 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001064 self.listen(5)
1065
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001066 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001067 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001068 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1069 self.ConnectionHandler(sock_obj, self.certfile)
1070
1071 def handle_error(self):
1072 raise
1073
Trent Nelson78520002008-04-10 20:54:35 +00001074 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001075 self.flag = None
1076 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001077 self.server = self.EchoServer(certfile)
1078 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001079 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001080 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001081
1082 def __str__(self):
1083 return "<%s %s>" % (self.__class__.__name__, self.server)
1084
1085 def start (self, flag=None):
1086 self.flag = flag
1087 threading.Thread.start(self)
1088
Antoine Pitrou480a1242010-04-28 21:37:09 +00001089 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001090 self.active = True
1091 if self.flag:
1092 self.flag.set()
1093 while self.active:
1094 try:
1095 asyncore.loop(1)
1096 except:
1097 pass
1098
Antoine Pitrou480a1242010-04-28 21:37:09 +00001099 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001100 self.active = False
1101 self.server.close()
1102
Antoine Pitrou480a1242010-04-28 21:37:09 +00001103 def bad_cert_test(certfile):
1104 """
1105 Launch a server with CERT_REQUIRED, and check that trying to
1106 connect to it with the given client certificate fails.
1107 """
Trent Nelson78520002008-04-10 20:54:35 +00001108 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001110 cacerts=CERTFILE, chatty=False,
1111 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112 flag = threading.Event()
1113 server.start(flag)
1114 # wait for it to start
1115 flag.wait()
1116 # try to connect
1117 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001118 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001119 with socket.socket() as sock:
1120 s = ssl.wrap_socket(sock,
1121 certfile=certfile,
1122 ssl_version=ssl.PROTOCOL_TLSv1)
1123 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001124 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001125 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001126 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001127 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001128 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001129 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001130 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001131 if x.errno != errno.ENOENT:
1132 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001133 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001134 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001135 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001136 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001137 finally:
1138 server.stop()
1139 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001140
Antoine Pitroub5218772010-05-21 09:56:06 +00001141 def server_params_test(client_context, server_context, indata=b"FOO\n",
1142 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001143 """
1144 Launch a server, connect a client to it and try various reads
1145 and writes.
1146 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001147 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001149 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 flag = threading.Event()
1151 server.start(flag)
1152 # wait for it to start
1153 flag.wait()
1154 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001155 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001156 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001157 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001158 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001159 if connectionchatty:
1160 if support.verbose:
1161 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001162 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001163 s.write(arg)
1164 outdata = s.read()
1165 if connectionchatty:
1166 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001167 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001168 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001169 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001170 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1171 % (outdata[:20], len(outdata),
1172 indata[:20].lower(), len(indata)))
1173 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001174 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001175 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001176 sys.stdout.write(" client: closing connection.\n")
1177 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001178 finally:
1179 server.stop()
1180 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001181
Antoine Pitroub5218772010-05-21 09:56:06 +00001182 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1183 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001184 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001185 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001186 certtype = {
1187 ssl.CERT_NONE: "CERT_NONE",
1188 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1189 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1190 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001191 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001192 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001193 sys.stdout.write(formatstr %
1194 (ssl.get_protocol_name(client_protocol),
1195 ssl.get_protocol_name(server_protocol),
1196 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001197 client_context = ssl.SSLContext(client_protocol)
1198 client_context.options = ssl.OP_ALL | client_options
1199 server_context = ssl.SSLContext(server_protocol)
1200 server_context.options = ssl.OP_ALL | server_options
1201 for ctx in (client_context, server_context):
1202 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001203 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1204 # will send an SSLv3 hello (rather than SSLv2) starting from
1205 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001206 ctx.set_ciphers("ALL")
1207 ctx.load_cert_chain(CERTFILE)
1208 ctx.load_verify_locations(CERTFILE)
1209 try:
1210 server_params_test(client_context, server_context,
1211 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001212 # Protocol mismatch can result in either an SSLError, or a
1213 # "Connection reset by peer" error.
1214 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001215 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001216 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001217 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001218 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001219 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001220 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001221 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001222 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001223 "Client protocol %s succeeded with server protocol %s!"
1224 % (ssl.get_protocol_name(client_protocol),
1225 ssl.get_protocol_name(server_protocol)))
1226
1227
Bill Janssen6e027db2007-11-15 22:23:56 +00001228 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001229
Antoine Pitrou23df4832010-08-04 17:14:06 +00001230 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 def test_echo(self):
1232 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001233 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001235 for protocol in PROTOCOLS:
1236 context = ssl.SSLContext(protocol)
1237 context.load_cert_chain(CERTFILE)
1238 server_params_test(context, context,
1239 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001240
Antoine Pitrou480a1242010-04-28 21:37:09 +00001241 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001242 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001244 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1245 context.verify_mode = ssl.CERT_REQUIRED
1246 context.load_verify_locations(CERTFILE)
1247 context.load_cert_chain(CERTFILE)
1248 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001249 flag = threading.Event()
1250 server.start(flag)
1251 # wait for it to start
1252 flag.wait()
1253 # try to connect
1254 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001255 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001256 s.connect((HOST, server.port))
1257 cert = s.getpeercert()
1258 self.assertTrue(cert, "Can't get peer certificate.")
1259 cipher = s.cipher()
1260 if support.verbose:
1261 sys.stdout.write(pprint.pformat(cert) + '\n')
1262 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1263 if 'subject' not in cert:
1264 self.fail("No subject field in certificate: %s." %
1265 pprint.pformat(cert))
1266 if ((('organizationName', 'Python Software Foundation'),)
1267 not in cert['subject']):
1268 self.fail(
1269 "Missing or invalid 'organizationName' field in certificate subject; "
1270 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001271 self.assertIn('notBefore', cert)
1272 self.assertIn('notAfter', cert)
1273 before = ssl.cert_time_to_seconds(cert['notBefore'])
1274 after = ssl.cert_time_to_seconds(cert['notAfter'])
1275 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001276 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001277 finally:
1278 server.stop()
1279 server.join()
1280
Antoine Pitrou480a1242010-04-28 21:37:09 +00001281 def test_empty_cert(self):
1282 """Connecting with an empty cert file"""
1283 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1284 "nullcert.pem"))
1285 def test_malformed_cert(self):
1286 """Connecting with a badly formatted certificate (syntax error)"""
1287 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1288 "badcert.pem"))
1289 def test_nonexisting_cert(self):
1290 """Connecting with a non-existing cert file"""
1291 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1292 "wrongcert.pem"))
1293 def test_malformed_key(self):
1294 """Connecting with a badly formatted key (syntax error)"""
1295 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1296 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001297
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 def test_rude_shutdown(self):
1299 """A brutal shutdown of an SSL server should raise an IOError
1300 in the client when attempting handshake.
1301 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001302 listener_ready = threading.Event()
1303 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001304
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001305 s = socket.socket()
1306 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001307
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001308 # `listener` runs in a thread. It sits in an accept() until
1309 # the main thread connects. Then it rudely closes the socket,
1310 # and sets Event `listener_gone` to let the main thread know
1311 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001312 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001313 s.listen(5)
1314 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001315 newsock, addr = s.accept()
1316 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001317 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001318 listener_gone.set()
1319
1320 def connector():
1321 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001322 with socket.socket() as c:
1323 c.connect((HOST, port))
1324 listener_gone.wait()
1325 try:
1326 ssl_sock = ssl.wrap_socket(c)
1327 except IOError:
1328 pass
1329 else:
1330 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001331
1332 t = threading.Thread(target=listener)
1333 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001334 try:
1335 connector()
1336 finally:
1337 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001338
Antoine Pitrou23df4832010-08-04 17:14:06 +00001339 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001340 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1341 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001342 def test_protocol_sslv2(self):
1343 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001344 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001345 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001346 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1347 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1348 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1349 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1350 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1351 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001352 # SSLv23 client with specific SSL options
1353 if no_sslv2_implies_sslv3_hello():
1354 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1355 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1356 client_options=ssl.OP_NO_SSLv2)
1357 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1358 client_options=ssl.OP_NO_SSLv3)
1359 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1360 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001361
Antoine Pitrou23df4832010-08-04 17:14:06 +00001362 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001363 def test_protocol_sslv23(self):
1364 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001365 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001366 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001367 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1368 try:
1369 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1370 except (ssl.SSLError, socket.error) as x:
1371 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1372 if support.verbose:
1373 sys.stdout.write(
1374 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1375 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1377 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1378 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001379
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1381 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1382 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001383
Antoine Pitrou480a1242010-04-28 21:37:09 +00001384 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1385 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1386 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001387
Antoine Pitroub5218772010-05-21 09:56:06 +00001388 # Server with specific SSL options
1389 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1390 server_options=ssl.OP_NO_SSLv3)
1391 # Will choose TLSv1
1392 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1393 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1394 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1395 server_options=ssl.OP_NO_TLSv1)
1396
1397
Antoine Pitrou23df4832010-08-04 17:14:06 +00001398 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001399 def test_protocol_sslv3(self):
1400 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001401 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001402 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001403 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1404 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1405 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001406 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1407 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001408 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1409 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001410 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001411 if no_sslv2_implies_sslv3_hello():
1412 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1413 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1414 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001415
Antoine Pitrou23df4832010-08-04 17:14:06 +00001416 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001417 def test_protocol_tlsv1(self):
1418 """Connecting to a TLSv1 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_TLSv1, ssl.PROTOCOL_TLSv1, True)
1422 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1423 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001424 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1425 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001426 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001427 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1428 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001429
Antoine Pitrou480a1242010-04-28 21:37:09 +00001430 def test_starttls(self):
1431 """Switching from clear text to encrypted and back again."""
1432 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 +00001433
Trent Nelson78520002008-04-10 20:54:35 +00001434 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001435 ssl_version=ssl.PROTOCOL_TLSv1,
1436 starttls_server=True,
1437 chatty=True,
1438 connectionchatty=True)
1439 flag = threading.Event()
1440 server.start(flag)
1441 # wait for it to start
1442 flag.wait()
1443 # try to connect
1444 wrapped = False
1445 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001446 s = socket.socket()
1447 s.setblocking(1)
1448 s.connect((HOST, server.port))
1449 if support.verbose:
1450 sys.stdout.write("\n")
1451 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001452 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001453 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001454 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001455 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001456 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001457 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001458 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001459 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001460 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001461 msg = outdata.strip().lower()
1462 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1463 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001464 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001465 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001466 " client: read %r from server, starting TLS...\n"
1467 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001468 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1469 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001470 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1471 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001472 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001473 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001474 " client: read %r from server, ending TLS...\n"
1475 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001476 s = conn.unwrap()
1477 wrapped = False
1478 else:
1479 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001480 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001481 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001482 if support.verbose:
1483 sys.stdout.write(" client: closing connection.\n")
1484 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001485 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001486 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001487 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001488 if wrapped:
1489 conn.close()
1490 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001491 s.close()
1492 finally:
1493 server.stop()
1494 server.join()
1495
Antoine Pitrou480a1242010-04-28 21:37:09 +00001496 def test_socketserver(self):
1497 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001498 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001499 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001500 if support.verbose:
1501 sys.stdout.write('\n')
1502 with open(CERTFILE, 'rb') as f:
1503 d1 = f.read()
1504 d2 = ''
1505 # now fetch the same data from the HTTPS server
1506 url = 'https://%s:%d/%s' % (
1507 HOST, server.port, os.path.split(CERTFILE)[1])
1508 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001509 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001510 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001511 if dlen and (int(dlen) > 0):
1512 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001513 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001514 sys.stdout.write(
1515 " client: read %d bytes from remote server '%s'\n"
1516 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001517 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001518 f.close()
1519 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001520
Antoine Pitrou480a1242010-04-28 21:37:09 +00001521 def test_asyncore_server(self):
1522 """Check the example asyncore integration."""
1523 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001524
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001525 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001526 sys.stdout.write("\n")
1527
Antoine Pitrou480a1242010-04-28 21:37:09 +00001528 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001529 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001530 flag = threading.Event()
1531 server.start(flag)
1532 # wait for it to start
1533 flag.wait()
1534 # try to connect
1535 try:
1536 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001537 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001538 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001539 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001540 " client: sending %r...\n" % indata)
1541 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001542 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001543 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001544 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001545 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001546 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001547 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1548 % (outdata[:20], len(outdata),
1549 indata[:20].lower(), len(indata)))
1550 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001551 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001552 sys.stdout.write(" client: closing connection.\n")
1553 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001554 if support.verbose:
1555 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001556 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001557 if support.verbose:
1558 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001559 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001560 if support.verbose:
1561 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001562 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001563 if support.verbose:
1564 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001565
Antoine Pitrou480a1242010-04-28 21:37:09 +00001566 def test_recv_send(self):
1567 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001568 if support.verbose:
1569 sys.stdout.write("\n")
1570
1571 server = ThreadedEchoServer(CERTFILE,
1572 certreqs=ssl.CERT_NONE,
1573 ssl_version=ssl.PROTOCOL_TLSv1,
1574 cacerts=CERTFILE,
1575 chatty=True,
1576 connectionchatty=False)
1577 flag = threading.Event()
1578 server.start(flag)
1579 # wait for it to start
1580 flag.wait()
1581 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001582 s = ssl.wrap_socket(socket.socket(),
1583 server_side=False,
1584 certfile=CERTFILE,
1585 ca_certs=CERTFILE,
1586 cert_reqs=ssl.CERT_NONE,
1587 ssl_version=ssl.PROTOCOL_TLSv1)
1588 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001589 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001590 # helper methods for standardising recv* method signatures
1591 def _recv_into():
1592 b = bytearray(b"\0"*100)
1593 count = s.recv_into(b)
1594 return b[:count]
1595
1596 def _recvfrom_into():
1597 b = bytearray(b"\0"*100)
1598 count, addr = s.recvfrom_into(b)
1599 return b[:count]
1600
1601 # (name, method, whether to expect success, *args)
1602 send_methods = [
1603 ('send', s.send, True, []),
1604 ('sendto', s.sendto, False, ["some.address"]),
1605 ('sendall', s.sendall, True, []),
1606 ]
1607 recv_methods = [
1608 ('recv', s.recv, True, []),
1609 ('recvfrom', s.recvfrom, False, ["some.address"]),
1610 ('recv_into', _recv_into, True, []),
1611 ('recvfrom_into', _recvfrom_into, False, []),
1612 ]
1613 data_prefix = "PREFIX_"
1614
1615 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001616 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001617 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001618 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001619 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001620 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001621 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001622 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001623 "<<{outdata:r}>> ({nout:d}) received; "
1624 "expected <<{indata:r}>> ({nin:d})\n".format(
1625 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001626 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001627 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001628 )
1629 )
1630 except ValueError as e:
1631 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001632 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001633 "Failed to send with method <<{name:s}>>; "
1634 "expected to succeed.\n".format(name=meth_name)
1635 )
1636 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001637 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001638 "Method <<{name:s}>> failed with unexpected "
1639 "exception message: {exp:s}\n".format(
1640 name=meth_name, exp=e
1641 )
1642 )
1643
1644 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001645 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001646 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001647 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001648 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001649 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001650 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001651 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001652 "<<{outdata:r}>> ({nout:d}) received; "
1653 "expected <<{indata:r}>> ({nin:d})\n".format(
1654 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001655 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001656 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001657 )
1658 )
1659 except ValueError as e:
1660 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001661 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001662 "Failed to receive with method <<{name:s}>>; "
1663 "expected to succeed.\n".format(name=meth_name)
1664 )
1665 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001666 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001667 "Method <<{name:s}>> failed with unexpected "
1668 "exception message: {exp:s}\n".format(
1669 name=meth_name, exp=e
1670 )
1671 )
1672 # consume data
1673 s.read()
1674
Nick Coghlan513886a2011-08-28 00:00:27 +10001675 # Make sure sendmsg et al are disallowed to avoid
1676 # inadvertent disclosure of data and/or corruption
1677 # of the encrypted data stream
1678 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1679 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1680 self.assertRaises(NotImplementedError,
1681 s.recvmsg_into, bytearray(100))
1682
Antoine Pitrou480a1242010-04-28 21:37:09 +00001683 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001684 s.close()
1685 finally:
1686 server.stop()
1687 server.join()
1688
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001689 def test_handshake_timeout(self):
1690 # Issue #5103: SSL handshake must respect the socket timeout
1691 server = socket.socket(socket.AF_INET)
1692 host = "127.0.0.1"
1693 port = support.bind_port(server)
1694 started = threading.Event()
1695 finish = False
1696
1697 def serve():
1698 server.listen(5)
1699 started.set()
1700 conns = []
1701 while not finish:
1702 r, w, e = select.select([server], [], [], 0.1)
1703 if server in r:
1704 # Let the socket hang around rather than having
1705 # it closed by garbage collection.
1706 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001707 for sock in conns:
1708 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001709
1710 t = threading.Thread(target=serve)
1711 t.start()
1712 started.wait()
1713
1714 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001715 try:
1716 c = socket.socket(socket.AF_INET)
1717 c.settimeout(0.2)
1718 c.connect((host, port))
1719 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001720 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001721 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001722 finally:
1723 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001724 try:
1725 c = socket.socket(socket.AF_INET)
1726 c = ssl.wrap_socket(c)
1727 c.settimeout(0.2)
1728 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001729 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001730 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001731 finally:
1732 c.close()
1733 finally:
1734 finish = True
1735 t.join()
1736 server.close()
1737
Antoine Pitroud6494802011-07-21 01:11:30 +02001738 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1739 "'tls-unique' channel binding not available")
1740 def test_tls_unique_channel_binding(self):
1741 """Test tls-unique channel binding."""
1742 if support.verbose:
1743 sys.stdout.write("\n")
1744
1745 server = ThreadedEchoServer(CERTFILE,
1746 certreqs=ssl.CERT_NONE,
1747 ssl_version=ssl.PROTOCOL_TLSv1,
1748 cacerts=CERTFILE,
1749 chatty=True,
1750 connectionchatty=False)
1751 flag = threading.Event()
1752 server.start(flag)
1753 # wait for it to start
1754 flag.wait()
1755 # try to connect
1756 s = ssl.wrap_socket(socket.socket(),
1757 server_side=False,
1758 certfile=CERTFILE,
1759 ca_certs=CERTFILE,
1760 cert_reqs=ssl.CERT_NONE,
1761 ssl_version=ssl.PROTOCOL_TLSv1)
1762 s.connect((HOST, server.port))
1763 try:
1764 # get the data
1765 cb_data = s.get_channel_binding("tls-unique")
1766 if support.verbose:
1767 sys.stdout.write(" got channel binding data: {0!r}\n"
1768 .format(cb_data))
1769
1770 # check if it is sane
1771 self.assertIsNotNone(cb_data)
1772 self.assertEqual(len(cb_data), 12) # True for TLSv1
1773
1774 # and compare with the peers version
1775 s.write(b"CB tls-unique\n")
1776 peer_data_repr = s.read().strip()
1777 self.assertEqual(peer_data_repr,
1778 repr(cb_data).encode("us-ascii"))
1779 s.close()
1780
1781 # now, again
1782 s = ssl.wrap_socket(socket.socket(),
1783 server_side=False,
1784 certfile=CERTFILE,
1785 ca_certs=CERTFILE,
1786 cert_reqs=ssl.CERT_NONE,
1787 ssl_version=ssl.PROTOCOL_TLSv1)
1788 s.connect((HOST, server.port))
1789 new_cb_data = s.get_channel_binding("tls-unique")
1790 if support.verbose:
1791 sys.stdout.write(" got another channel binding data: {0!r}\n"
1792 .format(new_cb_data))
1793 # is it really unique
1794 self.assertNotEqual(cb_data, new_cb_data)
1795 self.assertIsNotNone(cb_data)
1796 self.assertEqual(len(cb_data), 12) # True for TLSv1
1797 s.write(b"CB tls-unique\n")
1798 peer_data_repr = s.read().strip()
1799 self.assertEqual(peer_data_repr,
1800 repr(new_cb_data).encode("us-ascii"))
1801 s.close()
1802 finally:
1803 server.stop()
1804 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001805
Thomas Woutersed03b412007-08-28 21:37:11 +00001806def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001807 if support.verbose:
1808 plats = {
1809 'Linux': platform.linux_distribution,
1810 'Mac': platform.mac_ver,
1811 'Windows': platform.win32_ver,
1812 }
1813 for name, func in plats.items():
1814 plat = func()
1815 if plat and plat[0]:
1816 plat = '%s %r' % (name, plat)
1817 break
1818 else:
1819 plat = repr(platform.platform())
1820 print("test_ssl: testing with %r %r" %
1821 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1822 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001823 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001824
Antoine Pitrou152efa22010-05-16 18:19:27 +00001825 for filename in [
1826 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1827 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1828 BADCERT, BADKEY, EMPTYCERT]:
1829 if not os.path.exists(filename):
1830 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001831
Antoine Pitrou152efa22010-05-16 18:19:27 +00001832 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001833
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001834 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001835 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001836
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001837 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001838 thread_info = support.threading_setup()
1839 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001840 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001841
Antoine Pitrou480a1242010-04-28 21:37:09 +00001842 try:
1843 support.run_unittest(*tests)
1844 finally:
1845 if _have_threads:
1846 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001847
1848if __name__ == "__main__":
1849 test_main()