blob: e386325341d0d271a600937dd78a2a19e5dd87a7 [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")
57
Thomas Woutersed03b412007-08-28 21:37:11 +000058
Thomas Woutersed03b412007-08-28 21:37:11 +000059def handle_error(prefix):
60 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000061 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000062 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000063
Antoine Pitroub5218772010-05-21 09:56:06 +000064def can_clear_options():
65 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020066 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000067
68def no_sslv2_implies_sslv3_hello():
69 # 0.9.7h or higher
70 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
71
Thomas Woutersed03b412007-08-28 21:37:11 +000072
Antoine Pitrou23df4832010-08-04 17:14:06 +000073# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
74def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020075 if hasattr(ssl, 'PROTOCOL_SSLv2'):
76 @functools.wraps(func)
77 def f(*args, **kwargs):
78 try:
79 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
80 except ssl.SSLError:
81 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
82 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
83 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
84 return func(*args, **kwargs)
85 return f
86 else:
87 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000088
89
Antoine Pitrou152efa22010-05-16 18:19:27 +000090class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000091
Antoine Pitrou480a1242010-04-28 21:37:09 +000092 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020093 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000094 ssl.PROTOCOL_SSLv23
95 ssl.PROTOCOL_SSLv3
96 ssl.PROTOCOL_TLSv1
97 ssl.CERT_NONE
98 ssl.CERT_OPTIONAL
99 ssl.CERT_REQUIRED
Antoine Pitroud5323212010-10-22 18:19:07 +0000100 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000101
Antoine Pitrou480a1242010-04-28 21:37:09 +0000102 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000103 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000104 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 sys.stdout.write("\n RAND_status is %d (%s)\n"
106 % (v, (v and "sufficient randomness") or
107 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200108
109 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
110 self.assertEqual(len(data), 16)
111 self.assertEqual(is_cryptographic, v == 1)
112 if v:
113 data = ssl.RAND_bytes(16)
114 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200115 else:
116 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200117
Thomas Woutersed03b412007-08-28 21:37:11 +0000118 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000119 ssl.RAND_egd(1)
120 except TypeError:
121 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000122 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000123 print("didn't raise TypeError")
124 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000125
Antoine Pitrou480a1242010-04-28 21:37:09 +0000126 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127 # note that this uses an 'unofficial' function in _ssl.c,
128 # provided solely for this test, to exercise the certificate
129 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000130 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000131 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000133
Antoine Pitrou480a1242010-04-28 21:37:09 +0000134 def test_DER_to_PEM(self):
135 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
136 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000137 d1 = ssl.PEM_cert_to_DER_cert(pem)
138 p2 = ssl.DER_cert_to_PEM_cert(d1)
139 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000140 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000141 if not p2.startswith(ssl.PEM_HEADER + '\n'):
142 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
143 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
144 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000145
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000146 def test_openssl_version(self):
147 n = ssl.OPENSSL_VERSION_NUMBER
148 t = ssl.OPENSSL_VERSION_INFO
149 s = ssl.OPENSSL_VERSION
150 self.assertIsInstance(n, int)
151 self.assertIsInstance(t, tuple)
152 self.assertIsInstance(s, str)
153 # Some sanity checks follow
154 # >= 0.9
155 self.assertGreaterEqual(n, 0x900000)
156 # < 2.0
157 self.assertLess(n, 0x20000000)
158 major, minor, fix, patch, status = t
159 self.assertGreaterEqual(major, 0)
160 self.assertLess(major, 2)
161 self.assertGreaterEqual(minor, 0)
162 self.assertLess(minor, 256)
163 self.assertGreaterEqual(fix, 0)
164 self.assertLess(fix, 256)
165 self.assertGreaterEqual(patch, 0)
166 self.assertLessEqual(patch, 26)
167 self.assertGreaterEqual(status, 0)
168 self.assertLessEqual(status, 15)
169 # Version string as returned by OpenSSL, the format might change
170 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
171 (s, t))
172
Antoine Pitrou9d543662010-04-23 23:10:32 +0000173 @support.cpython_only
174 def test_refcycle(self):
175 # Issue #7943: an SSL object doesn't create reference cycles with
176 # itself.
177 s = socket.socket(socket.AF_INET)
178 ss = ssl.wrap_socket(s)
179 wr = weakref.ref(ss)
180 del ss
181 self.assertEqual(wr(), None)
182
Antoine Pitroua468adc2010-09-14 14:43:44 +0000183 def test_wrapped_unconnected(self):
184 # Methods on an unconnected SSLSocket propagate the original
185 # socket.error raise by the underlying socket object.
186 s = socket.socket(socket.AF_INET)
187 ss = ssl.wrap_socket(s)
188 self.assertRaises(socket.error, ss.recv, 1)
189 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
190 self.assertRaises(socket.error, ss.recvfrom, 1)
191 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
192 self.assertRaises(socket.error, ss.send, b'x')
193 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
194
Antoine Pitrou40f08742010-04-24 22:04:40 +0000195 def test_timeout(self):
196 # Issue #8524: when creating an SSL socket, the timeout of the
197 # original socket should be retained.
198 for timeout in (None, 0.0, 5.0):
199 s = socket.socket(socket.AF_INET)
200 s.settimeout(timeout)
201 ss = ssl.wrap_socket(s)
202 self.assertEqual(timeout, ss.gettimeout())
203
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000204 def test_errors(self):
205 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000206 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000207 "certfile must be specified",
208 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000209 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000210 "certfile must be specified for server-side operations",
211 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000212 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000213 "certfile must be specified for server-side operations",
214 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000215 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000216 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000217 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000218 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000219 with socket.socket() as sock:
220 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000221 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000222 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000223 with socket.socket() as sock:
224 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000225 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000226 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000227 with socket.socket() as sock:
228 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000229 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000230
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000231 def test_match_hostname(self):
232 def ok(cert, hostname):
233 ssl.match_hostname(cert, hostname)
234 def fail(cert, hostname):
235 self.assertRaises(ssl.CertificateError,
236 ssl.match_hostname, cert, hostname)
237
238 cert = {'subject': ((('commonName', 'example.com'),),)}
239 ok(cert, 'example.com')
240 ok(cert, 'ExAmple.cOm')
241 fail(cert, 'www.example.com')
242 fail(cert, '.example.com')
243 fail(cert, 'example.org')
244 fail(cert, 'exampleXcom')
245
246 cert = {'subject': ((('commonName', '*.a.com'),),)}
247 ok(cert, 'foo.a.com')
248 fail(cert, 'bar.foo.a.com')
249 fail(cert, 'a.com')
250 fail(cert, 'Xa.com')
251 fail(cert, '.a.com')
252
253 cert = {'subject': ((('commonName', 'a.*.com'),),)}
254 ok(cert, 'a.foo.com')
255 fail(cert, 'a..com')
256 fail(cert, 'a.com')
257
258 cert = {'subject': ((('commonName', 'f*.com'),),)}
259 ok(cert, 'foo.com')
260 ok(cert, 'f.com')
261 fail(cert, 'bar.com')
262 fail(cert, 'foo.a.com')
263 fail(cert, 'bar.foo.com')
264
265 # Slightly fake real-world example
266 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
267 'subject': ((('commonName', 'linuxfrz.org'),),),
268 'subjectAltName': (('DNS', 'linuxfr.org'),
269 ('DNS', 'linuxfr.com'),
270 ('othername', '<unsupported>'))}
271 ok(cert, 'linuxfr.org')
272 ok(cert, 'linuxfr.com')
273 # Not a "DNS" entry
274 fail(cert, '<unsupported>')
275 # When there is a subjectAltName, commonName isn't used
276 fail(cert, 'linuxfrz.org')
277
278 # A pristine real-world example
279 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
280 'subject': ((('countryName', 'US'),),
281 (('stateOrProvinceName', 'California'),),
282 (('localityName', 'Mountain View'),),
283 (('organizationName', 'Google Inc'),),
284 (('commonName', 'mail.google.com'),))}
285 ok(cert, 'mail.google.com')
286 fail(cert, 'gmail.com')
287 # Only commonName is considered
288 fail(cert, 'California')
289
290 # Neither commonName nor subjectAltName
291 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
292 'subject': ((('countryName', 'US'),),
293 (('stateOrProvinceName', 'California'),),
294 (('localityName', 'Mountain View'),),
295 (('organizationName', 'Google Inc'),))}
296 fail(cert, 'mail.google.com')
297
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200298 # No DNS entry in subjectAltName but a commonName
299 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
300 'subject': ((('countryName', 'US'),),
301 (('stateOrProvinceName', 'California'),),
302 (('localityName', 'Mountain View'),),
303 (('commonName', 'mail.google.com'),)),
304 'subjectAltName': (('othername', 'blabla'), )}
305 ok(cert, 'mail.google.com')
306
307 # No DNS entry subjectAltName and no commonName
308 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
309 'subject': ((('countryName', 'US'),),
310 (('stateOrProvinceName', 'California'),),
311 (('localityName', 'Mountain View'),),
312 (('organizationName', 'Google Inc'),)),
313 'subjectAltName': (('othername', 'blabla'),)}
314 fail(cert, 'google.com')
315
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000316 # Empty cert / no cert
317 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
318 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
319
Antoine Pitroud5323212010-10-22 18:19:07 +0000320 def test_server_side(self):
321 # server_hostname doesn't work for server sockets
322 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000323 with socket.socket() as sock:
324 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
325 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000326
Antoine Pitroud6494802011-07-21 01:11:30 +0200327 def test_unknown_channel_binding(self):
328 # should raise ValueError for unknown type
329 s = socket.socket(socket.AF_INET)
330 ss = ssl.wrap_socket(s)
331 with self.assertRaises(ValueError):
332 ss.get_channel_binding("unknown-type")
333
334 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
335 "'tls-unique' channel binding not available")
336 def test_tls_unique_channel_binding(self):
337 # unconnected should return None for known type
338 s = socket.socket(socket.AF_INET)
339 ss = ssl.wrap_socket(s)
340 self.assertIsNone(ss.get_channel_binding("tls-unique"))
341 # the same for server-side
342 s = socket.socket(socket.AF_INET)
343 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
344 self.assertIsNone(ss.get_channel_binding("tls-unique"))
345
Antoine Pitrou152efa22010-05-16 18:19:27 +0000346class ContextTests(unittest.TestCase):
347
Antoine Pitrou23df4832010-08-04 17:14:06 +0000348 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000349 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200350 if hasattr(ssl, 'PROTOCOL_SSLv2'):
351 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000352 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
353 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
354 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
355 self.assertRaises(TypeError, ssl.SSLContext)
356 self.assertRaises(ValueError, ssl.SSLContext, -1)
357 self.assertRaises(ValueError, ssl.SSLContext, 42)
358
Antoine Pitrou23df4832010-08-04 17:14:06 +0000359 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000360 def test_protocol(self):
361 for proto in PROTOCOLS:
362 ctx = ssl.SSLContext(proto)
363 self.assertEqual(ctx.protocol, proto)
364
365 def test_ciphers(self):
366 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
367 ctx.set_ciphers("ALL")
368 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000369 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000370 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000371
Antoine Pitrou23df4832010-08-04 17:14:06 +0000372 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000373 def test_options(self):
374 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
375 # OP_ALL is the default value
376 self.assertEqual(ssl.OP_ALL, ctx.options)
377 ctx.options |= ssl.OP_NO_SSLv2
378 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
379 ctx.options)
380 ctx.options |= ssl.OP_NO_SSLv3
381 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
382 ctx.options)
383 if can_clear_options():
384 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
385 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
386 ctx.options)
387 ctx.options = 0
388 self.assertEqual(0, ctx.options)
389 else:
390 with self.assertRaises(ValueError):
391 ctx.options = 0
392
Antoine Pitrou152efa22010-05-16 18:19:27 +0000393 def test_verify(self):
394 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
395 # Default value
396 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
397 ctx.verify_mode = ssl.CERT_OPTIONAL
398 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
399 ctx.verify_mode = ssl.CERT_REQUIRED
400 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
401 ctx.verify_mode = ssl.CERT_NONE
402 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
403 with self.assertRaises(TypeError):
404 ctx.verify_mode = None
405 with self.assertRaises(ValueError):
406 ctx.verify_mode = 42
407
408 def test_load_cert_chain(self):
409 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
410 # Combined key and cert in a single file
411 ctx.load_cert_chain(CERTFILE)
412 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
413 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000414 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000415 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000416 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000417 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000418 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000419 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000420 ctx.load_cert_chain(EMPTYCERT)
421 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000422 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000423 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
424 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
425 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000426 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000427 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000428 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000429 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000430 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000431 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
432 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000433 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000434 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000435 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200436 # Password protected key and cert
437 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
438 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
439 ctx.load_cert_chain(CERTFILE_PROTECTED,
440 password=bytearray(KEY_PASSWORD.encode()))
441 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
442 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
443 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
444 bytearray(KEY_PASSWORD.encode()))
445 with self.assertRaisesRegex(TypeError, "should be a string"):
446 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
447 with self.assertRaises(ssl.SSLError):
448 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
449 with self.assertRaisesRegex(ValueError, "cannot be longer"):
450 # openssl has a fixed limit on the password buffer.
451 # PEM_BUFSIZE is generally set to 1kb.
452 # Return a string larger than this.
453 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
454 # Password callback
455 def getpass_unicode():
456 return KEY_PASSWORD
457 def getpass_bytes():
458 return KEY_PASSWORD.encode()
459 def getpass_bytearray():
460 return bytearray(KEY_PASSWORD.encode())
461 def getpass_badpass():
462 return "badpass"
463 def getpass_huge():
464 return b'a' * (1024 * 1024)
465 def getpass_bad_type():
466 return 9
467 def getpass_exception():
468 raise Exception('getpass error')
469 class GetPassCallable:
470 def __call__(self):
471 return KEY_PASSWORD
472 def getpass(self):
473 return KEY_PASSWORD
474 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
475 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
476 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
477 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
478 ctx.load_cert_chain(CERTFILE_PROTECTED,
479 password=GetPassCallable().getpass)
480 with self.assertRaises(ssl.SSLError):
481 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
482 with self.assertRaisesRegex(ValueError, "cannot be longer"):
483 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
484 with self.assertRaisesRegex(TypeError, "must return a string"):
485 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
486 with self.assertRaisesRegex(Exception, "getpass error"):
487 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
488 # Make sure the password function isn't called if it isn't needed
489 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000490
491 def test_load_verify_locations(self):
492 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
493 ctx.load_verify_locations(CERTFILE)
494 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
495 ctx.load_verify_locations(BYTES_CERTFILE)
496 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
497 self.assertRaises(TypeError, ctx.load_verify_locations)
498 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000499 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000500 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000501 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000502 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000503 ctx.load_verify_locations(BADCERT)
504 ctx.load_verify_locations(CERTFILE, CAPATH)
505 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
506
Victor Stinner80f75e62011-01-29 11:31:20 +0000507 # Issue #10989: crash if the second argument type is invalid
508 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
509
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000510 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000511 def test_session_stats(self):
512 for proto in PROTOCOLS:
513 ctx = ssl.SSLContext(proto)
514 self.assertEqual(ctx.session_stats(), {
515 'number': 0,
516 'connect': 0,
517 'connect_good': 0,
518 'connect_renegotiate': 0,
519 'accept': 0,
520 'accept_good': 0,
521 'accept_renegotiate': 0,
522 'hits': 0,
523 'misses': 0,
524 'timeouts': 0,
525 'cache_full': 0,
526 })
527
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000528 def test_set_default_verify_paths(self):
529 # There's not much we can do to test that it acts as expected,
530 # so just check it doesn't crash or raise an exception.
531 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
532 ctx.set_default_verify_paths()
533
Antoine Pitrou152efa22010-05-16 18:19:27 +0000534
Bill Janssen6e027db2007-11-15 22:23:56 +0000535class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000536
Antoine Pitrou480a1242010-04-28 21:37:09 +0000537 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000538 with support.transient_internet("svn.python.org"):
539 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
540 cert_reqs=ssl.CERT_NONE)
541 try:
542 s.connect(("svn.python.org", 443))
543 self.assertEqual({}, s.getpeercert())
544 finally:
545 s.close()
546
547 # this should fail because we have no verification certs
548 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
549 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000550 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
551 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000552 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000553
Antoine Pitrou350c7222010-09-09 13:31:46 +0000554 # this should succeed because we specify the root cert
555 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
556 cert_reqs=ssl.CERT_REQUIRED,
557 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
558 try:
559 s.connect(("svn.python.org", 443))
560 self.assertTrue(s.getpeercert())
561 finally:
562 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000563
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000564 def test_connect_ex(self):
565 # Issue #11326: check connect_ex() implementation
566 with support.transient_internet("svn.python.org"):
567 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
568 cert_reqs=ssl.CERT_REQUIRED,
569 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
570 try:
571 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
572 self.assertTrue(s.getpeercert())
573 finally:
574 s.close()
575
576 def test_non_blocking_connect_ex(self):
577 # Issue #11326: non-blocking connect_ex() should allow handshake
578 # to proceed after the socket gets ready.
579 with support.transient_internet("svn.python.org"):
580 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
581 cert_reqs=ssl.CERT_REQUIRED,
582 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
583 do_handshake_on_connect=False)
584 try:
585 s.setblocking(False)
586 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000587 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
588 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000589 # Wait for connect to finish
590 select.select([], [s], [], 5.0)
591 # Non-blocking handshake
592 while True:
593 try:
594 s.do_handshake()
595 break
596 except ssl.SSLError as err:
597 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
598 select.select([s], [], [], 5.0)
599 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
600 select.select([], [s], [], 5.0)
601 else:
602 raise
603 # SSL established
604 self.assertTrue(s.getpeercert())
605 finally:
606 s.close()
607
Antoine Pitroub4410db2011-05-18 18:51:06 +0200608 def test_timeout_connect_ex(self):
609 # Issue #12065: on a timeout, connect_ex() should return the original
610 # errno (mimicking the behaviour of non-SSL sockets).
611 with support.transient_internet("svn.python.org"):
612 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
613 cert_reqs=ssl.CERT_REQUIRED,
614 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
615 do_handshake_on_connect=False)
616 try:
617 s.settimeout(0.0000001)
618 rc = s.connect_ex(('svn.python.org', 443))
619 if rc == 0:
620 self.skipTest("svn.python.org responded too quickly")
621 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
622 finally:
623 s.close()
624
Antoine Pitrou152efa22010-05-16 18:19:27 +0000625 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000626 with support.transient_internet("svn.python.org"):
627 # Same as test_connect, but with a separately created context
628 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
629 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
630 s.connect(("svn.python.org", 443))
631 try:
632 self.assertEqual({}, s.getpeercert())
633 finally:
634 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000635 # Same with a server hostname
636 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
637 server_hostname="svn.python.org")
638 if ssl.HAS_SNI:
639 s.connect(("svn.python.org", 443))
640 s.close()
641 else:
642 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000643 # This should fail because we have no verification certs
644 ctx.verify_mode = ssl.CERT_REQUIRED
645 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000646 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000647 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000648 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000649 # This should succeed because we specify the root cert
650 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
651 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
652 s.connect(("svn.python.org", 443))
653 try:
654 cert = s.getpeercert()
655 self.assertTrue(cert)
656 finally:
657 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000658
659 def test_connect_capath(self):
660 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000661 # NOTE: the subject hashing algorithm has been changed between
662 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
663 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000664 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000665 with support.transient_internet("svn.python.org"):
666 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
667 ctx.verify_mode = ssl.CERT_REQUIRED
668 ctx.load_verify_locations(capath=CAPATH)
669 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
670 s.connect(("svn.python.org", 443))
671 try:
672 cert = s.getpeercert()
673 self.assertTrue(cert)
674 finally:
675 s.close()
676 # Same with a bytes `capath` argument
677 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
678 ctx.verify_mode = ssl.CERT_REQUIRED
679 ctx.load_verify_locations(capath=BYTES_CAPATH)
680 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
681 s.connect(("svn.python.org", 443))
682 try:
683 cert = s.getpeercert()
684 self.assertTrue(cert)
685 finally:
686 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000687
Antoine Pitroue3220242010-04-24 11:13:53 +0000688 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
689 def test_makefile_close(self):
690 # Issue #5238: creating a file-like object with makefile() shouldn't
691 # delay closing the underlying "real socket" (here tested with its
692 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000693 with support.transient_internet("svn.python.org"):
694 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
695 ss.connect(("svn.python.org", 443))
696 fd = ss.fileno()
697 f = ss.makefile()
698 f.close()
699 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000700 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000701 # Closing the SSL socket should close the fd too
702 ss.close()
703 gc.collect()
704 with self.assertRaises(OSError) as e:
705 os.read(fd, 0)
706 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000707
Antoine Pitrou480a1242010-04-28 21:37:09 +0000708 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000709 with support.transient_internet("svn.python.org"):
710 s = socket.socket(socket.AF_INET)
711 s.connect(("svn.python.org", 443))
712 s.setblocking(False)
713 s = ssl.wrap_socket(s,
714 cert_reqs=ssl.CERT_NONE,
715 do_handshake_on_connect=False)
716 count = 0
717 while True:
718 try:
719 count += 1
720 s.do_handshake()
721 break
722 except ssl.SSLError as err:
723 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
724 select.select([s], [], [])
725 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
726 select.select([], [s], [])
727 else:
728 raise
729 s.close()
730 if support.verbose:
731 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000732
Antoine Pitrou480a1242010-04-28 21:37:09 +0000733 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200734 def _test_get_server_certificate(host, port, cert=None):
735 with support.transient_internet(host):
736 pem = ssl.get_server_certificate((host, port))
737 if not pem:
738 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200739
Antoine Pitrou15399c32011-04-28 19:23:55 +0200740 try:
741 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
742 except ssl.SSLError as x:
743 #should fail
744 if support.verbose:
745 sys.stdout.write("%s\n" % x)
746 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200747 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
748
Antoine Pitrou15399c32011-04-28 19:23:55 +0200749 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
750 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200751 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000752 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200753 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000754
Antoine Pitrou15399c32011-04-28 19:23:55 +0200755 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
756 if support.IPV6_ENABLED:
757 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000758
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000759 def test_ciphers(self):
760 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000761 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000762 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000763 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000764 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000765 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
766 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
767 s.connect(remote)
768 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000769 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000770 with socket.socket(socket.AF_INET) as sock:
771 s = ssl.wrap_socket(sock,
772 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
773 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000774
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000775 def test_algorithms(self):
776 # Issue #8484: all algorithms should be available when verifying a
777 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000778 # SHA256 was added in OpenSSL 0.9.8
779 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
780 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000781 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
782 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000783 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000784 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000785 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
786 cert_reqs=ssl.CERT_REQUIRED,
787 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000788 try:
789 s.connect(remote)
790 if support.verbose:
791 sys.stdout.write("\nCipher with %r is %r\n" %
792 (remote, s.cipher()))
793 sys.stdout.write("Certificate is:\n%s\n" %
794 pprint.pformat(s.getpeercert()))
795 finally:
796 s.close()
797
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000798
799try:
800 import threading
801except ImportError:
802 _have_threads = False
803else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000804 _have_threads = True
805
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000806 from test.ssl_servers import make_https_server
807
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000808 class ThreadedEchoServer(threading.Thread):
809
810 class ConnectionHandler(threading.Thread):
811
812 """A mildly complicated class, because we want it to work both
813 with and without the SSL wrapper around the socket connection, so
814 that we can test the STARTTLS functionality."""
815
Bill Janssen6e027db2007-11-15 22:23:56 +0000816 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000817 self.server = server
818 self.running = False
819 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000820 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000821 self.sock.setblocking(1)
822 self.sslconn = None
823 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000824 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000825
Antoine Pitrou480a1242010-04-28 21:37:09 +0000826 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000827 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000828 self.sslconn = self.server.context.wrap_socket(
829 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000830 except ssl.SSLError:
831 # XXX Various errors can have happened here, for example
832 # a mismatching protocol version, an invalid certificate,
833 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000834 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000835 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000836 self.running = False
837 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000838 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000839 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000840 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000841 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000843 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000844 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
845 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000846 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000847 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
848 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000849 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
851 return True
852
853 def read(self):
854 if self.sslconn:
855 return self.sslconn.read()
856 else:
857 return self.sock.recv(1024)
858
859 def write(self, bytes):
860 if self.sslconn:
861 return self.sslconn.write(bytes)
862 else:
863 return self.sock.send(bytes)
864
865 def close(self):
866 if self.sslconn:
867 self.sslconn.close()
868 else:
869 self.sock.close()
870
Antoine Pitrou480a1242010-04-28 21:37:09 +0000871 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 self.running = True
873 if not self.server.starttls_server:
874 if not self.wrap_conn():
875 return
876 while self.running:
877 try:
878 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000879 stripped = msg.strip()
880 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 # eof, so quit this handler
882 self.running = False
883 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000884 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000885 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886 sys.stdout.write(" server: client closed connection\n")
887 self.close()
888 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000889 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000890 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000891 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000893 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000894 if not self.wrap_conn():
895 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000896 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000897 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000898 if support.verbose and self.server.connectionchatty:
899 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000901 self.sock = self.sslconn.unwrap()
902 self.sslconn = None
903 if support.verbose and self.server.connectionchatty:
904 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200905 elif stripped == b'CB tls-unique':
906 if support.verbose and self.server.connectionchatty:
907 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
908 data = self.sslconn.get_channel_binding("tls-unique")
909 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000910 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000911 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 self.server.connectionchatty):
913 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000914 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
915 % (msg, ctype, msg.lower(), ctype))
916 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000917 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918 if self.server.chatty:
919 handle_error("Test server failure:\n")
920 self.close()
921 self.running = False
922 # normally, we'd just stop here, but for the test
923 # harness, we want to stop the server
924 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925
Antoine Pitroub5218772010-05-21 09:56:06 +0000926 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000927 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000928 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000929 ciphers=None, context=None):
930 if context:
931 self.context = context
932 else:
933 self.context = ssl.SSLContext(ssl_version
934 if ssl_version is not None
935 else ssl.PROTOCOL_TLSv1)
936 self.context.verify_mode = (certreqs if certreqs is not None
937 else ssl.CERT_NONE)
938 if cacerts:
939 self.context.load_verify_locations(cacerts)
940 if certificate:
941 self.context.load_cert_chain(certificate)
942 if ciphers:
943 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000944 self.chatty = chatty
945 self.connectionchatty = connectionchatty
946 self.starttls_server = starttls_server
947 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000948 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000950 self.active = False
951 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000952 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953
Antoine Pitrou480a1242010-04-28 21:37:09 +0000954 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 self.flag = flag
956 threading.Thread.start(self)
957
Antoine Pitrou480a1242010-04-28 21:37:09 +0000958 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000959 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960 self.sock.listen(5)
961 self.active = True
962 if self.flag:
963 # signal an event
964 self.flag.set()
965 while self.active:
966 try:
967 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000968 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000969 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000970 + repr(connaddr) + '\n')
971 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000972 handler.start()
973 except socket.timeout:
974 pass
975 except KeyboardInterrupt:
976 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000977 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978
Antoine Pitrou480a1242010-04-28 21:37:09 +0000979 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981
Bill Janssen54cc54c2007-12-14 22:08:56 +0000982 class AsyncoreEchoServer(threading.Thread):
983
984 # this one's based on asyncore.dispatcher
985
986 class EchoServer (asyncore.dispatcher):
987
988 class ConnectionHandler (asyncore.dispatcher_with_send):
989
990 def __init__(self, conn, certfile):
991 self.socket = ssl.wrap_socket(conn, server_side=True,
992 certfile=certfile,
993 do_handshake_on_connect=False)
994 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000995 self._ssl_accepting = True
996 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000997
998 def readable(self):
999 if isinstance(self.socket, ssl.SSLSocket):
1000 while self.socket.pending() > 0:
1001 self.handle_read_event()
1002 return True
1003
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001004 def _do_ssl_handshake(self):
1005 try:
1006 self.socket.do_handshake()
1007 except ssl.SSLError as err:
1008 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
1009 ssl.SSL_ERROR_WANT_WRITE):
1010 return
1011 elif err.args[0] == ssl.SSL_ERROR_EOF:
1012 return self.handle_close()
1013 raise
1014 except socket.error as err:
1015 if err.args[0] == errno.ECONNABORTED:
1016 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001017 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001018 self._ssl_accepting = False
1019
1020 def handle_read(self):
1021 if self._ssl_accepting:
1022 self._do_ssl_handshake()
1023 else:
1024 data = self.recv(1024)
1025 if support.verbose:
1026 sys.stdout.write(" server: read %s from client\n" % repr(data))
1027 if not data:
1028 self.close()
1029 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001030 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001031
1032 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001033 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001034 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001035 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1036
1037 def handle_error(self):
1038 raise
1039
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001040 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001041 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001042 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1043 self.port = support.bind_port(sock, '')
1044 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001045 self.listen(5)
1046
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001047 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001048 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001049 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1050 self.ConnectionHandler(sock_obj, self.certfile)
1051
1052 def handle_error(self):
1053 raise
1054
Trent Nelson78520002008-04-10 20:54:35 +00001055 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001056 self.flag = None
1057 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001058 self.server = self.EchoServer(certfile)
1059 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001060 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001061 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001062
1063 def __str__(self):
1064 return "<%s %s>" % (self.__class__.__name__, self.server)
1065
1066 def start (self, flag=None):
1067 self.flag = flag
1068 threading.Thread.start(self)
1069
Antoine Pitrou480a1242010-04-28 21:37:09 +00001070 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001071 self.active = True
1072 if self.flag:
1073 self.flag.set()
1074 while self.active:
1075 try:
1076 asyncore.loop(1)
1077 except:
1078 pass
1079
Antoine Pitrou480a1242010-04-28 21:37:09 +00001080 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001081 self.active = False
1082 self.server.close()
1083
Antoine Pitrou480a1242010-04-28 21:37:09 +00001084 def bad_cert_test(certfile):
1085 """
1086 Launch a server with CERT_REQUIRED, and check that trying to
1087 connect to it with the given client certificate fails.
1088 """
Trent Nelson78520002008-04-10 20:54:35 +00001089 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001090 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001091 cacerts=CERTFILE, chatty=False,
1092 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093 flag = threading.Event()
1094 server.start(flag)
1095 # wait for it to start
1096 flag.wait()
1097 # try to connect
1098 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001099 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001100 with socket.socket() as sock:
1101 s = ssl.wrap_socket(sock,
1102 certfile=certfile,
1103 ssl_version=ssl.PROTOCOL_TLSv1)
1104 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001105 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001106 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001107 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001108 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001109 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001110 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001111 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001112 if x.errno != errno.ENOENT:
1113 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001114 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001115 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001116 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001117 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001118 finally:
1119 server.stop()
1120 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001121
Antoine Pitroub5218772010-05-21 09:56:06 +00001122 def server_params_test(client_context, server_context, indata=b"FOO\n",
1123 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001124 """
1125 Launch a server, connect a client to it and try various reads
1126 and writes.
1127 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001128 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001129 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001130 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001131 flag = threading.Event()
1132 server.start(flag)
1133 # wait for it to start
1134 flag.wait()
1135 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001136 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001137 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001138 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001140 if connectionchatty:
1141 if support.verbose:
1142 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001143 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001144 s.write(arg)
1145 outdata = s.read()
1146 if connectionchatty:
1147 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001148 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001149 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001150 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001151 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1152 % (outdata[:20], len(outdata),
1153 indata[:20].lower(), len(indata)))
1154 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001155 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001156 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001157 sys.stdout.write(" client: closing connection.\n")
1158 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001159 finally:
1160 server.stop()
1161 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001162
Antoine Pitroub5218772010-05-21 09:56:06 +00001163 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1164 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001165 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001167 certtype = {
1168 ssl.CERT_NONE: "CERT_NONE",
1169 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1170 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1171 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001172 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 sys.stdout.write(formatstr %
1175 (ssl.get_protocol_name(client_protocol),
1176 ssl.get_protocol_name(server_protocol),
1177 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001178 client_context = ssl.SSLContext(client_protocol)
1179 client_context.options = ssl.OP_ALL | client_options
1180 server_context = ssl.SSLContext(server_protocol)
1181 server_context.options = ssl.OP_ALL | server_options
1182 for ctx in (client_context, server_context):
1183 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001184 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1185 # will send an SSLv3 hello (rather than SSLv2) starting from
1186 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001187 ctx.set_ciphers("ALL")
1188 ctx.load_cert_chain(CERTFILE)
1189 ctx.load_verify_locations(CERTFILE)
1190 try:
1191 server_params_test(client_context, server_context,
1192 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001193 # Protocol mismatch can result in either an SSLError, or a
1194 # "Connection reset by peer" error.
1195 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001196 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001197 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001198 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001199 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001200 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001201 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001202 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001203 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001204 "Client protocol %s succeeded with server protocol %s!"
1205 % (ssl.get_protocol_name(client_protocol),
1206 ssl.get_protocol_name(server_protocol)))
1207
1208
Bill Janssen6e027db2007-11-15 22:23:56 +00001209 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001210
Antoine Pitrou23df4832010-08-04 17:14:06 +00001211 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001212 def test_echo(self):
1213 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001214 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001215 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001216 for protocol in PROTOCOLS:
1217 context = ssl.SSLContext(protocol)
1218 context.load_cert_chain(CERTFILE)
1219 server_params_test(context, context,
1220 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001221
Antoine Pitrou480a1242010-04-28 21:37:09 +00001222 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001223 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001224 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001225 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1226 context.verify_mode = ssl.CERT_REQUIRED
1227 context.load_verify_locations(CERTFILE)
1228 context.load_cert_chain(CERTFILE)
1229 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001230 flag = threading.Event()
1231 server.start(flag)
1232 # wait for it to start
1233 flag.wait()
1234 # try to connect
1235 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001236 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001237 s.connect((HOST, server.port))
1238 cert = s.getpeercert()
1239 self.assertTrue(cert, "Can't get peer certificate.")
1240 cipher = s.cipher()
1241 if support.verbose:
1242 sys.stdout.write(pprint.pformat(cert) + '\n')
1243 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1244 if 'subject' not in cert:
1245 self.fail("No subject field in certificate: %s." %
1246 pprint.pformat(cert))
1247 if ((('organizationName', 'Python Software Foundation'),)
1248 not in cert['subject']):
1249 self.fail(
1250 "Missing or invalid 'organizationName' field in certificate subject; "
1251 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001252 self.assertIn('notBefore', cert)
1253 self.assertIn('notAfter', cert)
1254 before = ssl.cert_time_to_seconds(cert['notBefore'])
1255 after = ssl.cert_time_to_seconds(cert['notAfter'])
1256 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001257 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001258 finally:
1259 server.stop()
1260 server.join()
1261
Antoine Pitrou480a1242010-04-28 21:37:09 +00001262 def test_empty_cert(self):
1263 """Connecting with an empty cert file"""
1264 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1265 "nullcert.pem"))
1266 def test_malformed_cert(self):
1267 """Connecting with a badly formatted certificate (syntax error)"""
1268 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1269 "badcert.pem"))
1270 def test_nonexisting_cert(self):
1271 """Connecting with a non-existing cert file"""
1272 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1273 "wrongcert.pem"))
1274 def test_malformed_key(self):
1275 """Connecting with a badly formatted key (syntax error)"""
1276 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1277 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001278
Antoine Pitrou480a1242010-04-28 21:37:09 +00001279 def test_rude_shutdown(self):
1280 """A brutal shutdown of an SSL server should raise an IOError
1281 in the client when attempting handshake.
1282 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001283 listener_ready = threading.Event()
1284 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001285
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001286 s = socket.socket()
1287 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001288
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001289 # `listener` runs in a thread. It sits in an accept() until
1290 # the main thread connects. Then it rudely closes the socket,
1291 # and sets Event `listener_gone` to let the main thread know
1292 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001293 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001294 s.listen(5)
1295 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001296 newsock, addr = s.accept()
1297 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001298 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001299 listener_gone.set()
1300
1301 def connector():
1302 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001303 with socket.socket() as c:
1304 c.connect((HOST, port))
1305 listener_gone.wait()
1306 try:
1307 ssl_sock = ssl.wrap_socket(c)
1308 except IOError:
1309 pass
1310 else:
1311 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001312
1313 t = threading.Thread(target=listener)
1314 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001315 try:
1316 connector()
1317 finally:
1318 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001319
Antoine Pitrou23df4832010-08-04 17:14:06 +00001320 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001321 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1322 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001323 def test_protocol_sslv2(self):
1324 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001325 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001326 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001327 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1328 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1329 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1330 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1331 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1332 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001333 # SSLv23 client with specific SSL options
1334 if no_sslv2_implies_sslv3_hello():
1335 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1336 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1337 client_options=ssl.OP_NO_SSLv2)
1338 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1339 client_options=ssl.OP_NO_SSLv3)
1340 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1341 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001342
Antoine Pitrou23df4832010-08-04 17:14:06 +00001343 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001344 def test_protocol_sslv23(self):
1345 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001346 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001347 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001348 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1349 try:
1350 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1351 except (ssl.SSLError, socket.error) as x:
1352 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1353 if support.verbose:
1354 sys.stdout.write(
1355 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1356 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1358 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1359 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001360
Antoine Pitrou480a1242010-04-28 21:37:09 +00001361 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1362 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1363 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001364
Antoine Pitrou480a1242010-04-28 21:37:09 +00001365 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1366 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1367 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001368
Antoine Pitroub5218772010-05-21 09:56:06 +00001369 # Server with specific SSL options
1370 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1371 server_options=ssl.OP_NO_SSLv3)
1372 # Will choose TLSv1
1373 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1374 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1375 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1376 server_options=ssl.OP_NO_TLSv1)
1377
1378
Antoine Pitrou23df4832010-08-04 17:14:06 +00001379 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 def test_protocol_sslv3(self):
1381 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001382 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001383 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001384 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1385 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1386 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001387 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1388 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1390 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001391 if no_sslv2_implies_sslv3_hello():
1392 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1393 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1394 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395
Antoine Pitrou23df4832010-08-04 17:14:06 +00001396 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001397 def test_protocol_tlsv1(self):
1398 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001399 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001400 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001401 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1402 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1403 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001404 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1405 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001406 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1407 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001408
Antoine Pitrou480a1242010-04-28 21:37:09 +00001409 def test_starttls(self):
1410 """Switching from clear text to encrypted and back again."""
1411 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 +00001412
Trent Nelson78520002008-04-10 20:54:35 +00001413 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001414 ssl_version=ssl.PROTOCOL_TLSv1,
1415 starttls_server=True,
1416 chatty=True,
1417 connectionchatty=True)
1418 flag = threading.Event()
1419 server.start(flag)
1420 # wait for it to start
1421 flag.wait()
1422 # try to connect
1423 wrapped = False
1424 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001425 s = socket.socket()
1426 s.setblocking(1)
1427 s.connect((HOST, server.port))
1428 if support.verbose:
1429 sys.stdout.write("\n")
1430 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001431 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001432 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001433 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001436 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001437 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001438 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001439 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001440 msg = outdata.strip().lower()
1441 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1442 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001443 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001444 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001445 " client: read %r from server, starting TLS...\n"
1446 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001447 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1448 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001449 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1450 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001451 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001452 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001453 " client: read %r from server, ending TLS...\n"
1454 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001455 s = conn.unwrap()
1456 wrapped = False
1457 else:
1458 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001459 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001460 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001461 if support.verbose:
1462 sys.stdout.write(" client: closing connection.\n")
1463 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001464 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001465 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001466 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001467 if wrapped:
1468 conn.close()
1469 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001470 s.close()
1471 finally:
1472 server.stop()
1473 server.join()
1474
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 def test_socketserver(self):
1476 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001477 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001479 if support.verbose:
1480 sys.stdout.write('\n')
1481 with open(CERTFILE, 'rb') as f:
1482 d1 = f.read()
1483 d2 = ''
1484 # now fetch the same data from the HTTPS server
1485 url = 'https://%s:%d/%s' % (
1486 HOST, server.port, os.path.split(CERTFILE)[1])
1487 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001488 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001489 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001490 if dlen and (int(dlen) > 0):
1491 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001492 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001493 sys.stdout.write(
1494 " client: read %d bytes from remote server '%s'\n"
1495 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001496 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001497 f.close()
1498 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001499
Antoine Pitrou480a1242010-04-28 21:37:09 +00001500 def test_asyncore_server(self):
1501 """Check the example asyncore integration."""
1502 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001503
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001504 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001505 sys.stdout.write("\n")
1506
Antoine Pitrou480a1242010-04-28 21:37:09 +00001507 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001508 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001509 flag = threading.Event()
1510 server.start(flag)
1511 # wait for it to start
1512 flag.wait()
1513 # try to connect
1514 try:
1515 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001516 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001517 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001518 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001519 " client: sending %r...\n" % indata)
1520 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001521 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001522 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001523 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001524 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001525 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001526 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1527 % (outdata[:20], len(outdata),
1528 indata[:20].lower(), len(indata)))
1529 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001530 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001531 sys.stdout.write(" client: closing connection.\n")
1532 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001533 if support.verbose:
1534 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001535 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001536 if support.verbose:
1537 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001538 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001539 if support.verbose:
1540 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001541 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001542 if support.verbose:
1543 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001544
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 def test_recv_send(self):
1546 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001547 if support.verbose:
1548 sys.stdout.write("\n")
1549
1550 server = ThreadedEchoServer(CERTFILE,
1551 certreqs=ssl.CERT_NONE,
1552 ssl_version=ssl.PROTOCOL_TLSv1,
1553 cacerts=CERTFILE,
1554 chatty=True,
1555 connectionchatty=False)
1556 flag = threading.Event()
1557 server.start(flag)
1558 # wait for it to start
1559 flag.wait()
1560 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001561 s = ssl.wrap_socket(socket.socket(),
1562 server_side=False,
1563 certfile=CERTFILE,
1564 ca_certs=CERTFILE,
1565 cert_reqs=ssl.CERT_NONE,
1566 ssl_version=ssl.PROTOCOL_TLSv1)
1567 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001568 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001569 # helper methods for standardising recv* method signatures
1570 def _recv_into():
1571 b = bytearray(b"\0"*100)
1572 count = s.recv_into(b)
1573 return b[:count]
1574
1575 def _recvfrom_into():
1576 b = bytearray(b"\0"*100)
1577 count, addr = s.recvfrom_into(b)
1578 return b[:count]
1579
1580 # (name, method, whether to expect success, *args)
1581 send_methods = [
1582 ('send', s.send, True, []),
1583 ('sendto', s.sendto, False, ["some.address"]),
1584 ('sendall', s.sendall, True, []),
1585 ]
1586 recv_methods = [
1587 ('recv', s.recv, True, []),
1588 ('recvfrom', s.recvfrom, False, ["some.address"]),
1589 ('recv_into', _recv_into, True, []),
1590 ('recvfrom_into', _recvfrom_into, False, []),
1591 ]
1592 data_prefix = "PREFIX_"
1593
1594 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001595 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001596 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001597 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001598 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001599 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001600 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001601 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001602 "<<{outdata:r}>> ({nout:d}) received; "
1603 "expected <<{indata:r}>> ({nin:d})\n".format(
1604 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001605 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001606 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001607 )
1608 )
1609 except ValueError as e:
1610 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001611 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001612 "Failed to send with method <<{name:s}>>; "
1613 "expected to succeed.\n".format(name=meth_name)
1614 )
1615 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001616 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001617 "Method <<{name:s}>> failed with unexpected "
1618 "exception message: {exp:s}\n".format(
1619 name=meth_name, exp=e
1620 )
1621 )
1622
1623 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001624 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001625 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001626 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001627 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001628 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001629 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001630 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001631 "<<{outdata:r}>> ({nout:d}) received; "
1632 "expected <<{indata:r}>> ({nin:d})\n".format(
1633 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001634 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001635 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001636 )
1637 )
1638 except ValueError as e:
1639 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001640 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001641 "Failed to receive with method <<{name:s}>>; "
1642 "expected to succeed.\n".format(name=meth_name)
1643 )
1644 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001645 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001646 "Method <<{name:s}>> failed with unexpected "
1647 "exception message: {exp:s}\n".format(
1648 name=meth_name, exp=e
1649 )
1650 )
1651 # consume data
1652 s.read()
1653
Nick Coghlan513886a2011-08-28 00:00:27 +10001654 # Make sure sendmsg et al are disallowed to avoid
1655 # inadvertent disclosure of data and/or corruption
1656 # of the encrypted data stream
1657 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1658 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1659 self.assertRaises(NotImplementedError,
1660 s.recvmsg_into, bytearray(100))
1661
Antoine Pitrou480a1242010-04-28 21:37:09 +00001662 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001663 s.close()
1664 finally:
1665 server.stop()
1666 server.join()
1667
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001668 def test_handshake_timeout(self):
1669 # Issue #5103: SSL handshake must respect the socket timeout
1670 server = socket.socket(socket.AF_INET)
1671 host = "127.0.0.1"
1672 port = support.bind_port(server)
1673 started = threading.Event()
1674 finish = False
1675
1676 def serve():
1677 server.listen(5)
1678 started.set()
1679 conns = []
1680 while not finish:
1681 r, w, e = select.select([server], [], [], 0.1)
1682 if server in r:
1683 # Let the socket hang around rather than having
1684 # it closed by garbage collection.
1685 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001686 for sock in conns:
1687 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001688
1689 t = threading.Thread(target=serve)
1690 t.start()
1691 started.wait()
1692
1693 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001694 try:
1695 c = socket.socket(socket.AF_INET)
1696 c.settimeout(0.2)
1697 c.connect((host, port))
1698 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001699 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001700 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001701 finally:
1702 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001703 try:
1704 c = socket.socket(socket.AF_INET)
1705 c = ssl.wrap_socket(c)
1706 c.settimeout(0.2)
1707 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001708 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001709 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001710 finally:
1711 c.close()
1712 finally:
1713 finish = True
1714 t.join()
1715 server.close()
1716
Antoine Pitroud6494802011-07-21 01:11:30 +02001717 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1718 "'tls-unique' channel binding not available")
1719 def test_tls_unique_channel_binding(self):
1720 """Test tls-unique channel binding."""
1721 if support.verbose:
1722 sys.stdout.write("\n")
1723
1724 server = ThreadedEchoServer(CERTFILE,
1725 certreqs=ssl.CERT_NONE,
1726 ssl_version=ssl.PROTOCOL_TLSv1,
1727 cacerts=CERTFILE,
1728 chatty=True,
1729 connectionchatty=False)
1730 flag = threading.Event()
1731 server.start(flag)
1732 # wait for it to start
1733 flag.wait()
1734 # try to connect
1735 s = ssl.wrap_socket(socket.socket(),
1736 server_side=False,
1737 certfile=CERTFILE,
1738 ca_certs=CERTFILE,
1739 cert_reqs=ssl.CERT_NONE,
1740 ssl_version=ssl.PROTOCOL_TLSv1)
1741 s.connect((HOST, server.port))
1742 try:
1743 # get the data
1744 cb_data = s.get_channel_binding("tls-unique")
1745 if support.verbose:
1746 sys.stdout.write(" got channel binding data: {0!r}\n"
1747 .format(cb_data))
1748
1749 # check if it is sane
1750 self.assertIsNotNone(cb_data)
1751 self.assertEqual(len(cb_data), 12) # True for TLSv1
1752
1753 # and compare with the peers version
1754 s.write(b"CB tls-unique\n")
1755 peer_data_repr = s.read().strip()
1756 self.assertEqual(peer_data_repr,
1757 repr(cb_data).encode("us-ascii"))
1758 s.close()
1759
1760 # now, again
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 new_cb_data = s.get_channel_binding("tls-unique")
1769 if support.verbose:
1770 sys.stdout.write(" got another channel binding data: {0!r}\n"
1771 .format(new_cb_data))
1772 # is it really unique
1773 self.assertNotEqual(cb_data, new_cb_data)
1774 self.assertIsNotNone(cb_data)
1775 self.assertEqual(len(cb_data), 12) # True for TLSv1
1776 s.write(b"CB tls-unique\n")
1777 peer_data_repr = s.read().strip()
1778 self.assertEqual(peer_data_repr,
1779 repr(new_cb_data).encode("us-ascii"))
1780 s.close()
1781 finally:
1782 server.stop()
1783 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001784
Thomas Woutersed03b412007-08-28 21:37:11 +00001785def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001786 if support.verbose:
1787 plats = {
1788 'Linux': platform.linux_distribution,
1789 'Mac': platform.mac_ver,
1790 'Windows': platform.win32_ver,
1791 }
1792 for name, func in plats.items():
1793 plat = func()
1794 if plat and plat[0]:
1795 plat = '%s %r' % (name, plat)
1796 break
1797 else:
1798 plat = repr(platform.platform())
1799 print("test_ssl: testing with %r %r" %
1800 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1801 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001802 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001803
Antoine Pitrou152efa22010-05-16 18:19:27 +00001804 for filename in [
1805 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1806 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1807 BADCERT, BADKEY, EMPTYCERT]:
1808 if not os.path.exists(filename):
1809 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001810
Antoine Pitrou152efa22010-05-16 18:19:27 +00001811 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001812
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001813 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001814 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001815
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001816 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001817 thread_info = support.threading_setup()
1818 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001819 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001820
Antoine Pitrou480a1242010-04-28 21:37:09 +00001821 try:
1822 support.run_unittest(*tests)
1823 finally:
1824 if _have_threads:
1825 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001826
1827if __name__ == "__main__":
1828 test_main()