blob: 25f3e4fe6b9d13bf10141b355c00e9f69caae702 [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
622 except ssl.SSLError as err:
623 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
624 select.select([s], [], [], 5.0)
625 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
626 select.select([], [s], [], 5.0)
627 else:
628 raise
629 # SSL established
630 self.assertTrue(s.getpeercert())
631 finally:
632 s.close()
633
Antoine Pitroub4410db2011-05-18 18:51:06 +0200634 def test_timeout_connect_ex(self):
635 # Issue #12065: on a timeout, connect_ex() should return the original
636 # errno (mimicking the behaviour of non-SSL sockets).
637 with support.transient_internet("svn.python.org"):
638 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
639 cert_reqs=ssl.CERT_REQUIRED,
640 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
641 do_handshake_on_connect=False)
642 try:
643 s.settimeout(0.0000001)
644 rc = s.connect_ex(('svn.python.org', 443))
645 if rc == 0:
646 self.skipTest("svn.python.org responded too quickly")
647 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
648 finally:
649 s.close()
650
Antoine Pitrou152efa22010-05-16 18:19:27 +0000651 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000652 with support.transient_internet("svn.python.org"):
653 # Same as test_connect, but with a separately created context
654 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
655 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
656 s.connect(("svn.python.org", 443))
657 try:
658 self.assertEqual({}, s.getpeercert())
659 finally:
660 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000661 # Same with a server hostname
662 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
663 server_hostname="svn.python.org")
664 if ssl.HAS_SNI:
665 s.connect(("svn.python.org", 443))
666 s.close()
667 else:
668 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000669 # This should fail because we have no verification certs
670 ctx.verify_mode = ssl.CERT_REQUIRED
671 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000672 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000673 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000674 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000675 # This should succeed because we specify the root cert
676 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
677 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
678 s.connect(("svn.python.org", 443))
679 try:
680 cert = s.getpeercert()
681 self.assertTrue(cert)
682 finally:
683 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000684
685 def test_connect_capath(self):
686 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000687 # NOTE: the subject hashing algorithm has been changed between
688 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
689 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000690 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000691 with support.transient_internet("svn.python.org"):
692 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
693 ctx.verify_mode = ssl.CERT_REQUIRED
694 ctx.load_verify_locations(capath=CAPATH)
695 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
696 s.connect(("svn.python.org", 443))
697 try:
698 cert = s.getpeercert()
699 self.assertTrue(cert)
700 finally:
701 s.close()
702 # Same with a bytes `capath` argument
703 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
704 ctx.verify_mode = ssl.CERT_REQUIRED
705 ctx.load_verify_locations(capath=BYTES_CAPATH)
706 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
707 s.connect(("svn.python.org", 443))
708 try:
709 cert = s.getpeercert()
710 self.assertTrue(cert)
711 finally:
712 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000713
Antoine Pitroue3220242010-04-24 11:13:53 +0000714 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
715 def test_makefile_close(self):
716 # Issue #5238: creating a file-like object with makefile() shouldn't
717 # delay closing the underlying "real socket" (here tested with its
718 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000719 with support.transient_internet("svn.python.org"):
720 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
721 ss.connect(("svn.python.org", 443))
722 fd = ss.fileno()
723 f = ss.makefile()
724 f.close()
725 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000726 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000727 # Closing the SSL socket should close the fd too
728 ss.close()
729 gc.collect()
730 with self.assertRaises(OSError) as e:
731 os.read(fd, 0)
732 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000733
Antoine Pitrou480a1242010-04-28 21:37:09 +0000734 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000735 with support.transient_internet("svn.python.org"):
736 s = socket.socket(socket.AF_INET)
737 s.connect(("svn.python.org", 443))
738 s.setblocking(False)
739 s = ssl.wrap_socket(s,
740 cert_reqs=ssl.CERT_NONE,
741 do_handshake_on_connect=False)
742 count = 0
743 while True:
744 try:
745 count += 1
746 s.do_handshake()
747 break
748 except ssl.SSLError as err:
749 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
750 select.select([s], [], [])
751 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
752 select.select([], [s], [])
753 else:
754 raise
755 s.close()
756 if support.verbose:
757 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000758
Antoine Pitrou480a1242010-04-28 21:37:09 +0000759 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200760 def _test_get_server_certificate(host, port, cert=None):
761 with support.transient_internet(host):
762 pem = ssl.get_server_certificate((host, port))
763 if not pem:
764 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200765
Antoine Pitrou15399c32011-04-28 19:23:55 +0200766 try:
767 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
768 except ssl.SSLError as x:
769 #should fail
770 if support.verbose:
771 sys.stdout.write("%s\n" % x)
772 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200773 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
774
Antoine Pitrou15399c32011-04-28 19:23:55 +0200775 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
776 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200777 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000778 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200779 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000780
Antoine Pitrou15399c32011-04-28 19:23:55 +0200781 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
782 if support.IPV6_ENABLED:
783 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000784
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000785 def test_ciphers(self):
786 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000787 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000788 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000789 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000790 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000791 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
792 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
793 s.connect(remote)
794 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000795 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000796 with socket.socket(socket.AF_INET) as sock:
797 s = ssl.wrap_socket(sock,
798 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
799 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000800
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000801 def test_algorithms(self):
802 # Issue #8484: all algorithms should be available when verifying a
803 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000804 # SHA256 was added in OpenSSL 0.9.8
805 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
806 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000807 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
808 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000809 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000810 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000811 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
812 cert_reqs=ssl.CERT_REQUIRED,
813 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000814 try:
815 s.connect(remote)
816 if support.verbose:
817 sys.stdout.write("\nCipher with %r is %r\n" %
818 (remote, s.cipher()))
819 sys.stdout.write("Certificate is:\n%s\n" %
820 pprint.pformat(s.getpeercert()))
821 finally:
822 s.close()
823
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000824
825try:
826 import threading
827except ImportError:
828 _have_threads = False
829else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000830 _have_threads = True
831
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000832 from test.ssl_servers import make_https_server
833
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000834 class ThreadedEchoServer(threading.Thread):
835
836 class ConnectionHandler(threading.Thread):
837
838 """A mildly complicated class, because we want it to work both
839 with and without the SSL wrapper around the socket connection, so
840 that we can test the STARTTLS functionality."""
841
Bill Janssen6e027db2007-11-15 22:23:56 +0000842 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000843 self.server = server
844 self.running = False
845 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000846 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000847 self.sock.setblocking(1)
848 self.sslconn = None
849 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000850 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851
Antoine Pitrou480a1242010-04-28 21:37:09 +0000852 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000854 self.sslconn = self.server.context.wrap_socket(
855 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000856 except ssl.SSLError:
857 # XXX Various errors can have happened here, for example
858 # a mismatching protocol version, an invalid certificate,
859 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000861 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000862 self.running = False
863 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000864 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000867 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868 cert = self.sslconn.getpeercert()
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(" client cert is " + pprint.pformat(cert) + "\n")
871 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000872 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
874 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000875 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000876 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
877 return True
878
879 def read(self):
880 if self.sslconn:
881 return self.sslconn.read()
882 else:
883 return self.sock.recv(1024)
884
885 def write(self, bytes):
886 if self.sslconn:
887 return self.sslconn.write(bytes)
888 else:
889 return self.sock.send(bytes)
890
891 def close(self):
892 if self.sslconn:
893 self.sslconn.close()
894 else:
895 self.sock.close()
896
Antoine Pitrou480a1242010-04-28 21:37:09 +0000897 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 self.running = True
899 if not self.server.starttls_server:
900 if not self.wrap_conn():
901 return
902 while self.running:
903 try:
904 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000905 stripped = msg.strip()
906 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 # eof, so quit this handler
908 self.running = False
909 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000910 elif stripped == b'over':
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: client closed connection\n")
913 self.close()
914 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000915 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000916 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000917 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000919 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000920 if not self.wrap_conn():
921 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000922 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000923 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000924 if support.verbose and self.server.connectionchatty:
925 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000926 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000927 self.sock = self.sslconn.unwrap()
928 self.sslconn = None
929 if support.verbose and self.server.connectionchatty:
930 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200931 elif stripped == b'CB tls-unique':
932 if support.verbose and self.server.connectionchatty:
933 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
934 data = self.sslconn.get_channel_binding("tls-unique")
935 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000936 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000937 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938 self.server.connectionchatty):
939 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000940 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
941 % (msg, ctype, msg.lower(), ctype))
942 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000943 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000944 if self.server.chatty:
945 handle_error("Test server failure:\n")
946 self.close()
947 self.running = False
948 # normally, we'd just stop here, but for the test
949 # harness, we want to stop the server
950 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951
Antoine Pitroub5218772010-05-21 09:56:06 +0000952 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000953 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000954 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000955 ciphers=None, context=None):
956 if context:
957 self.context = context
958 else:
959 self.context = ssl.SSLContext(ssl_version
960 if ssl_version is not None
961 else ssl.PROTOCOL_TLSv1)
962 self.context.verify_mode = (certreqs if certreqs is not None
963 else ssl.CERT_NONE)
964 if cacerts:
965 self.context.load_verify_locations(cacerts)
966 if certificate:
967 self.context.load_cert_chain(certificate)
968 if ciphers:
969 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 self.chatty = chatty
971 self.connectionchatty = connectionchatty
972 self.starttls_server = starttls_server
973 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000974 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000976 self.active = False
977 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000978 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979
Antoine Pitrou480a1242010-04-28 21:37:09 +0000980 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 self.flag = flag
982 threading.Thread.start(self)
983
Antoine Pitrou480a1242010-04-28 21:37:09 +0000984 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000985 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986 self.sock.listen(5)
987 self.active = True
988 if self.flag:
989 # signal an event
990 self.flag.set()
991 while self.active:
992 try:
993 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000994 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000996 + repr(connaddr) + '\n')
997 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 handler.start()
999 except socket.timeout:
1000 pass
1001 except KeyboardInterrupt:
1002 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001003 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004
Antoine Pitrou480a1242010-04-28 21:37:09 +00001005 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001006 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007
Bill Janssen54cc54c2007-12-14 22:08:56 +00001008 class AsyncoreEchoServer(threading.Thread):
1009
1010 # this one's based on asyncore.dispatcher
1011
1012 class EchoServer (asyncore.dispatcher):
1013
1014 class ConnectionHandler (asyncore.dispatcher_with_send):
1015
1016 def __init__(self, conn, certfile):
1017 self.socket = ssl.wrap_socket(conn, server_side=True,
1018 certfile=certfile,
1019 do_handshake_on_connect=False)
1020 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001021 self._ssl_accepting = True
1022 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001023
1024 def readable(self):
1025 if isinstance(self.socket, ssl.SSLSocket):
1026 while self.socket.pending() > 0:
1027 self.handle_read_event()
1028 return True
1029
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001030 def _do_ssl_handshake(self):
1031 try:
1032 self.socket.do_handshake()
1033 except ssl.SSLError as err:
1034 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
1035 ssl.SSL_ERROR_WANT_WRITE):
1036 return
1037 elif err.args[0] == ssl.SSL_ERROR_EOF:
1038 return self.handle_close()
1039 raise
1040 except socket.error as err:
1041 if err.args[0] == errno.ECONNABORTED:
1042 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001043 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001044 self._ssl_accepting = False
1045
1046 def handle_read(self):
1047 if self._ssl_accepting:
1048 self._do_ssl_handshake()
1049 else:
1050 data = self.recv(1024)
1051 if support.verbose:
1052 sys.stdout.write(" server: read %s from client\n" % repr(data))
1053 if not data:
1054 self.close()
1055 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001056 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001057
1058 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001059 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001060 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001061 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1062
1063 def handle_error(self):
1064 raise
1065
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001066 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001067 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001068 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1069 self.port = support.bind_port(sock, '')
1070 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001071 self.listen(5)
1072
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001073 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001074 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001075 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1076 self.ConnectionHandler(sock_obj, self.certfile)
1077
1078 def handle_error(self):
1079 raise
1080
Trent Nelson78520002008-04-10 20:54:35 +00001081 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001082 self.flag = None
1083 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001084 self.server = self.EchoServer(certfile)
1085 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001086 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001087 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001088
1089 def __str__(self):
1090 return "<%s %s>" % (self.__class__.__name__, self.server)
1091
1092 def start (self, flag=None):
1093 self.flag = flag
1094 threading.Thread.start(self)
1095
Antoine Pitrou480a1242010-04-28 21:37:09 +00001096 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001097 self.active = True
1098 if self.flag:
1099 self.flag.set()
1100 while self.active:
1101 try:
1102 asyncore.loop(1)
1103 except:
1104 pass
1105
Antoine Pitrou480a1242010-04-28 21:37:09 +00001106 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001107 self.active = False
1108 self.server.close()
1109
Antoine Pitrou480a1242010-04-28 21:37:09 +00001110 def bad_cert_test(certfile):
1111 """
1112 Launch a server with CERT_REQUIRED, and check that trying to
1113 connect to it with the given client certificate fails.
1114 """
Trent Nelson78520002008-04-10 20:54:35 +00001115 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001116 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001117 cacerts=CERTFILE, chatty=False,
1118 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001119 flag = threading.Event()
1120 server.start(flag)
1121 # wait for it to start
1122 flag.wait()
1123 # try to connect
1124 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001125 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001126 with socket.socket() as sock:
1127 s = ssl.wrap_socket(sock,
1128 certfile=certfile,
1129 ssl_version=ssl.PROTOCOL_TLSv1)
1130 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001131 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001132 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001133 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001134 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001135 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001136 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001137 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001138 if x.errno != errno.ENOENT:
1139 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001140 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001141 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001142 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001143 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144 finally:
1145 server.stop()
1146 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001147
Antoine Pitroub5218772010-05-21 09:56:06 +00001148 def server_params_test(client_context, server_context, indata=b"FOO\n",
1149 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001150 """
1151 Launch a server, connect a client to it and try various reads
1152 and writes.
1153 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001154 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001155 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001156 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001157 flag = threading.Event()
1158 server.start(flag)
1159 # wait for it to start
1160 flag.wait()
1161 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001162 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001163 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001164 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001165 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001166 if connectionchatty:
1167 if support.verbose:
1168 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001169 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001170 s.write(arg)
1171 outdata = s.read()
1172 if connectionchatty:
1173 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001175 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001176 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001177 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1178 % (outdata[:20], len(outdata),
1179 indata[:20].lower(), len(indata)))
1180 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001181 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001182 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001183 sys.stdout.write(" client: closing connection.\n")
1184 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001185 finally:
1186 server.stop()
1187 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001188
Antoine Pitroub5218772010-05-21 09:56:06 +00001189 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1190 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001191 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001192 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001193 certtype = {
1194 ssl.CERT_NONE: "CERT_NONE",
1195 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1196 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1197 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001198 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001199 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001200 sys.stdout.write(formatstr %
1201 (ssl.get_protocol_name(client_protocol),
1202 ssl.get_protocol_name(server_protocol),
1203 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001204 client_context = ssl.SSLContext(client_protocol)
1205 client_context.options = ssl.OP_ALL | client_options
1206 server_context = ssl.SSLContext(server_protocol)
1207 server_context.options = ssl.OP_ALL | server_options
1208 for ctx in (client_context, server_context):
1209 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001210 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1211 # will send an SSLv3 hello (rather than SSLv2) starting from
1212 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001213 ctx.set_ciphers("ALL")
1214 ctx.load_cert_chain(CERTFILE)
1215 ctx.load_verify_locations(CERTFILE)
1216 try:
1217 server_params_test(client_context, server_context,
1218 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001219 # Protocol mismatch can result in either an SSLError, or a
1220 # "Connection reset by peer" error.
1221 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001222 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001223 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001224 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001225 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001226 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001227 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001228 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001229 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001230 "Client protocol %s succeeded with server protocol %s!"
1231 % (ssl.get_protocol_name(client_protocol),
1232 ssl.get_protocol_name(server_protocol)))
1233
1234
Bill Janssen6e027db2007-11-15 22:23:56 +00001235 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001236
Antoine Pitrou23df4832010-08-04 17:14:06 +00001237 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001238 def test_echo(self):
1239 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001240 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001242 for protocol in PROTOCOLS:
1243 context = ssl.SSLContext(protocol)
1244 context.load_cert_chain(CERTFILE)
1245 server_params_test(context, context,
1246 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001247
Antoine Pitrou480a1242010-04-28 21:37:09 +00001248 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001249 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001250 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001251 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1252 context.verify_mode = ssl.CERT_REQUIRED
1253 context.load_verify_locations(CERTFILE)
1254 context.load_cert_chain(CERTFILE)
1255 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001256 flag = threading.Event()
1257 server.start(flag)
1258 # wait for it to start
1259 flag.wait()
1260 # try to connect
1261 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001262 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001263 s.connect((HOST, server.port))
1264 cert = s.getpeercert()
1265 self.assertTrue(cert, "Can't get peer certificate.")
1266 cipher = s.cipher()
1267 if support.verbose:
1268 sys.stdout.write(pprint.pformat(cert) + '\n')
1269 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1270 if 'subject' not in cert:
1271 self.fail("No subject field in certificate: %s." %
1272 pprint.pformat(cert))
1273 if ((('organizationName', 'Python Software Foundation'),)
1274 not in cert['subject']):
1275 self.fail(
1276 "Missing or invalid 'organizationName' field in certificate subject; "
1277 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001278 self.assertIn('notBefore', cert)
1279 self.assertIn('notAfter', cert)
1280 before = ssl.cert_time_to_seconds(cert['notBefore'])
1281 after = ssl.cert_time_to_seconds(cert['notAfter'])
1282 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001283 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001284 finally:
1285 server.stop()
1286 server.join()
1287
Antoine Pitrou480a1242010-04-28 21:37:09 +00001288 def test_empty_cert(self):
1289 """Connecting with an empty cert file"""
1290 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1291 "nullcert.pem"))
1292 def test_malformed_cert(self):
1293 """Connecting with a badly formatted certificate (syntax error)"""
1294 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1295 "badcert.pem"))
1296 def test_nonexisting_cert(self):
1297 """Connecting with a non-existing cert file"""
1298 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1299 "wrongcert.pem"))
1300 def test_malformed_key(self):
1301 """Connecting with a badly formatted key (syntax error)"""
1302 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1303 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001304
Antoine Pitrou480a1242010-04-28 21:37:09 +00001305 def test_rude_shutdown(self):
1306 """A brutal shutdown of an SSL server should raise an IOError
1307 in the client when attempting handshake.
1308 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001309 listener_ready = threading.Event()
1310 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001311
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001312 s = socket.socket()
1313 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001314
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001315 # `listener` runs in a thread. It sits in an accept() until
1316 # the main thread connects. Then it rudely closes the socket,
1317 # and sets Event `listener_gone` to let the main thread know
1318 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001319 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001320 s.listen(5)
1321 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001322 newsock, addr = s.accept()
1323 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001324 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001325 listener_gone.set()
1326
1327 def connector():
1328 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001329 with socket.socket() as c:
1330 c.connect((HOST, port))
1331 listener_gone.wait()
1332 try:
1333 ssl_sock = ssl.wrap_socket(c)
1334 except IOError:
1335 pass
1336 else:
1337 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001338
1339 t = threading.Thread(target=listener)
1340 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001341 try:
1342 connector()
1343 finally:
1344 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001345
Antoine Pitrou23df4832010-08-04 17:14:06 +00001346 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001347 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1348 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001349 def test_protocol_sslv2(self):
1350 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001351 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001352 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001353 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1354 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1355 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1356 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1357 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1358 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001359 # SSLv23 client with specific SSL options
1360 if no_sslv2_implies_sslv3_hello():
1361 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1362 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1363 client_options=ssl.OP_NO_SSLv2)
1364 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1365 client_options=ssl.OP_NO_SSLv3)
1366 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1367 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001368
Antoine Pitrou23df4832010-08-04 17:14:06 +00001369 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001370 def test_protocol_sslv23(self):
1371 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001372 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001373 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001374 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1375 try:
1376 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1377 except (ssl.SSLError, socket.error) as x:
1378 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1379 if support.verbose:
1380 sys.stdout.write(
1381 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1382 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1384 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1385 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001386
Antoine Pitrou480a1242010-04-28 21:37:09 +00001387 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1388 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1389 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001390
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1392 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1393 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001394
Antoine Pitroub5218772010-05-21 09:56:06 +00001395 # Server with specific SSL options
1396 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1397 server_options=ssl.OP_NO_SSLv3)
1398 # Will choose TLSv1
1399 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1400 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1401 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1402 server_options=ssl.OP_NO_TLSv1)
1403
1404
Antoine Pitrou23df4832010-08-04 17:14:06 +00001405 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001406 def test_protocol_sslv3(self):
1407 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001408 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001409 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001410 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1411 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1412 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001413 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1414 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001415 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1416 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001417 if no_sslv2_implies_sslv3_hello():
1418 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1419 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1420 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001421
Antoine Pitrou23df4832010-08-04 17:14:06 +00001422 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001423 def test_protocol_tlsv1(self):
1424 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001425 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001426 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001427 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1428 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1429 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001430 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1431 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001432 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1433 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 def test_starttls(self):
1436 """Switching from clear text to encrypted and back again."""
1437 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 +00001438
Trent Nelson78520002008-04-10 20:54:35 +00001439 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001440 ssl_version=ssl.PROTOCOL_TLSv1,
1441 starttls_server=True,
1442 chatty=True,
1443 connectionchatty=True)
1444 flag = threading.Event()
1445 server.start(flag)
1446 # wait for it to start
1447 flag.wait()
1448 # try to connect
1449 wrapped = False
1450 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001451 s = socket.socket()
1452 s.setblocking(1)
1453 s.connect((HOST, server.port))
1454 if support.verbose:
1455 sys.stdout.write("\n")
1456 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001457 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001458 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001459 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001460 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001461 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001462 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001463 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001464 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001465 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001466 msg = outdata.strip().lower()
1467 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1468 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001469 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001470 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001471 " client: read %r from server, starting TLS...\n"
1472 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001473 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1474 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1476 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001477 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001478 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001479 " client: read %r from server, ending TLS...\n"
1480 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001481 s = conn.unwrap()
1482 wrapped = False
1483 else:
1484 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001485 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001486 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001487 if support.verbose:
1488 sys.stdout.write(" client: closing connection.\n")
1489 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001490 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001491 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001493 if wrapped:
1494 conn.close()
1495 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001496 s.close()
1497 finally:
1498 server.stop()
1499 server.join()
1500
Antoine Pitrou480a1242010-04-28 21:37:09 +00001501 def test_socketserver(self):
1502 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001503 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001504 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001505 if support.verbose:
1506 sys.stdout.write('\n')
1507 with open(CERTFILE, 'rb') as f:
1508 d1 = f.read()
1509 d2 = ''
1510 # now fetch the same data from the HTTPS server
1511 url = 'https://%s:%d/%s' % (
1512 HOST, server.port, os.path.split(CERTFILE)[1])
1513 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001514 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001515 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001516 if dlen and (int(dlen) > 0):
1517 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001518 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001519 sys.stdout.write(
1520 " client: read %d bytes from remote server '%s'\n"
1521 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001522 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001523 f.close()
1524 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001525
Antoine Pitrou480a1242010-04-28 21:37:09 +00001526 def test_asyncore_server(self):
1527 """Check the example asyncore integration."""
1528 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001529
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001530 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001531 sys.stdout.write("\n")
1532
Antoine Pitrou480a1242010-04-28 21:37:09 +00001533 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001534 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001535 flag = threading.Event()
1536 server.start(flag)
1537 # wait for it to start
1538 flag.wait()
1539 # try to connect
1540 try:
1541 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001542 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001543 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001544 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 " client: sending %r...\n" % indata)
1546 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001547 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001548 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001549 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001550 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001551 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001552 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1553 % (outdata[:20], len(outdata),
1554 indata[:20].lower(), len(indata)))
1555 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001556 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001557 sys.stdout.write(" client: closing connection.\n")
1558 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001559 if support.verbose:
1560 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001561 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001562 if support.verbose:
1563 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001564 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001565 if support.verbose:
1566 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001567 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001568 if support.verbose:
1569 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001570
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 def test_recv_send(self):
1572 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001573 if support.verbose:
1574 sys.stdout.write("\n")
1575
1576 server = ThreadedEchoServer(CERTFILE,
1577 certreqs=ssl.CERT_NONE,
1578 ssl_version=ssl.PROTOCOL_TLSv1,
1579 cacerts=CERTFILE,
1580 chatty=True,
1581 connectionchatty=False)
1582 flag = threading.Event()
1583 server.start(flag)
1584 # wait for it to start
1585 flag.wait()
1586 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001587 s = ssl.wrap_socket(socket.socket(),
1588 server_side=False,
1589 certfile=CERTFILE,
1590 ca_certs=CERTFILE,
1591 cert_reqs=ssl.CERT_NONE,
1592 ssl_version=ssl.PROTOCOL_TLSv1)
1593 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001594 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001595 # helper methods for standardising recv* method signatures
1596 def _recv_into():
1597 b = bytearray(b"\0"*100)
1598 count = s.recv_into(b)
1599 return b[:count]
1600
1601 def _recvfrom_into():
1602 b = bytearray(b"\0"*100)
1603 count, addr = s.recvfrom_into(b)
1604 return b[:count]
1605
1606 # (name, method, whether to expect success, *args)
1607 send_methods = [
1608 ('send', s.send, True, []),
1609 ('sendto', s.sendto, False, ["some.address"]),
1610 ('sendall', s.sendall, True, []),
1611 ]
1612 recv_methods = [
1613 ('recv', s.recv, True, []),
1614 ('recvfrom', s.recvfrom, False, ["some.address"]),
1615 ('recv_into', _recv_into, True, []),
1616 ('recvfrom_into', _recvfrom_into, False, []),
1617 ]
1618 data_prefix = "PREFIX_"
1619
1620 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001621 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001622 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001623 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001624 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001625 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001626 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001627 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001628 "<<{outdata:r}>> ({nout:d}) received; "
1629 "expected <<{indata:r}>> ({nin:d})\n".format(
1630 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001631 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001632 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001633 )
1634 )
1635 except ValueError as e:
1636 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001637 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001638 "Failed to send with method <<{name:s}>>; "
1639 "expected to succeed.\n".format(name=meth_name)
1640 )
1641 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001642 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001643 "Method <<{name:s}>> failed with unexpected "
1644 "exception message: {exp:s}\n".format(
1645 name=meth_name, exp=e
1646 )
1647 )
1648
1649 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001650 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001651 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001652 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001653 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001654 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001655 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001656 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001657 "<<{outdata:r}>> ({nout:d}) received; "
1658 "expected <<{indata:r}>> ({nin:d})\n".format(
1659 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001660 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001661 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001662 )
1663 )
1664 except ValueError as e:
1665 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001666 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001667 "Failed to receive with method <<{name:s}>>; "
1668 "expected to succeed.\n".format(name=meth_name)
1669 )
1670 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001671 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001672 "Method <<{name:s}>> failed with unexpected "
1673 "exception message: {exp:s}\n".format(
1674 name=meth_name, exp=e
1675 )
1676 )
1677 # consume data
1678 s.read()
1679
Nick Coghlan513886a2011-08-28 00:00:27 +10001680 # Make sure sendmsg et al are disallowed to avoid
1681 # inadvertent disclosure of data and/or corruption
1682 # of the encrypted data stream
1683 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1684 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1685 self.assertRaises(NotImplementedError,
1686 s.recvmsg_into, bytearray(100))
1687
Antoine Pitrou480a1242010-04-28 21:37:09 +00001688 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001689 s.close()
1690 finally:
1691 server.stop()
1692 server.join()
1693
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001694 def test_handshake_timeout(self):
1695 # Issue #5103: SSL handshake must respect the socket timeout
1696 server = socket.socket(socket.AF_INET)
1697 host = "127.0.0.1"
1698 port = support.bind_port(server)
1699 started = threading.Event()
1700 finish = False
1701
1702 def serve():
1703 server.listen(5)
1704 started.set()
1705 conns = []
1706 while not finish:
1707 r, w, e = select.select([server], [], [], 0.1)
1708 if server in r:
1709 # Let the socket hang around rather than having
1710 # it closed by garbage collection.
1711 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001712 for sock in conns:
1713 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001714
1715 t = threading.Thread(target=serve)
1716 t.start()
1717 started.wait()
1718
1719 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001720 try:
1721 c = socket.socket(socket.AF_INET)
1722 c.settimeout(0.2)
1723 c.connect((host, port))
1724 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001725 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001726 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001727 finally:
1728 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001729 try:
1730 c = socket.socket(socket.AF_INET)
1731 c = ssl.wrap_socket(c)
1732 c.settimeout(0.2)
1733 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001734 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001735 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001736 finally:
1737 c.close()
1738 finally:
1739 finish = True
1740 t.join()
1741 server.close()
1742
Antoine Pitroud6494802011-07-21 01:11:30 +02001743 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1744 "'tls-unique' channel binding not available")
1745 def test_tls_unique_channel_binding(self):
1746 """Test tls-unique channel binding."""
1747 if support.verbose:
1748 sys.stdout.write("\n")
1749
1750 server = ThreadedEchoServer(CERTFILE,
1751 certreqs=ssl.CERT_NONE,
1752 ssl_version=ssl.PROTOCOL_TLSv1,
1753 cacerts=CERTFILE,
1754 chatty=True,
1755 connectionchatty=False)
1756 flag = threading.Event()
1757 server.start(flag)
1758 # wait for it to start
1759 flag.wait()
1760 # try to connect
1761 s = ssl.wrap_socket(socket.socket(),
1762 server_side=False,
1763 certfile=CERTFILE,
1764 ca_certs=CERTFILE,
1765 cert_reqs=ssl.CERT_NONE,
1766 ssl_version=ssl.PROTOCOL_TLSv1)
1767 s.connect((HOST, server.port))
1768 try:
1769 # get the data
1770 cb_data = s.get_channel_binding("tls-unique")
1771 if support.verbose:
1772 sys.stdout.write(" got channel binding data: {0!r}\n"
1773 .format(cb_data))
1774
1775 # check if it is sane
1776 self.assertIsNotNone(cb_data)
1777 self.assertEqual(len(cb_data), 12) # True for TLSv1
1778
1779 # and compare with the peers version
1780 s.write(b"CB tls-unique\n")
1781 peer_data_repr = s.read().strip()
1782 self.assertEqual(peer_data_repr,
1783 repr(cb_data).encode("us-ascii"))
1784 s.close()
1785
1786 # now, again
1787 s = ssl.wrap_socket(socket.socket(),
1788 server_side=False,
1789 certfile=CERTFILE,
1790 ca_certs=CERTFILE,
1791 cert_reqs=ssl.CERT_NONE,
1792 ssl_version=ssl.PROTOCOL_TLSv1)
1793 s.connect((HOST, server.port))
1794 new_cb_data = s.get_channel_binding("tls-unique")
1795 if support.verbose:
1796 sys.stdout.write(" got another channel binding data: {0!r}\n"
1797 .format(new_cb_data))
1798 # is it really unique
1799 self.assertNotEqual(cb_data, new_cb_data)
1800 self.assertIsNotNone(cb_data)
1801 self.assertEqual(len(cb_data), 12) # True for TLSv1
1802 s.write(b"CB tls-unique\n")
1803 peer_data_repr = s.read().strip()
1804 self.assertEqual(peer_data_repr,
1805 repr(new_cb_data).encode("us-ascii"))
1806 s.close()
1807 finally:
1808 server.stop()
1809 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001810
Thomas Woutersed03b412007-08-28 21:37:11 +00001811def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001812 if support.verbose:
1813 plats = {
1814 'Linux': platform.linux_distribution,
1815 'Mac': platform.mac_ver,
1816 'Windows': platform.win32_ver,
1817 }
1818 for name, func in plats.items():
1819 plat = func()
1820 if plat and plat[0]:
1821 plat = '%s %r' % (name, plat)
1822 break
1823 else:
1824 plat = repr(platform.platform())
1825 print("test_ssl: testing with %r %r" %
1826 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1827 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001828 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001829
Antoine Pitrou152efa22010-05-16 18:19:27 +00001830 for filename in [
1831 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1832 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1833 BADCERT, BADKEY, EMPTYCERT]:
1834 if not os.path.exists(filename):
1835 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001836
Antoine Pitrou152efa22010-05-16 18:19:27 +00001837 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001838
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001839 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001840 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001841
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001842 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001843 thread_info = support.threading_setup()
1844 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001845 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001846
Antoine Pitrou480a1242010-04-28 21:37:09 +00001847 try:
1848 support.run_unittest(*tests)
1849 finally:
1850 if _have_threads:
1851 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001852
1853if __name__ == "__main__":
1854 test_main()