blob: d2839dd7f8333adcde0318b30297229d2ded8263 [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
Antoine Pitrou0e576f12011-12-22 10:03:38 +010059DHFILE = data_file("dh512.pem")
60BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000061
Thomas Woutersed03b412007-08-28 21:37:11 +000062def handle_error(prefix):
63 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000064 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000065 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000066
Antoine Pitroub5218772010-05-21 09:56:06 +000067def can_clear_options():
68 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020069 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000070
71def no_sslv2_implies_sslv3_hello():
72 # 0.9.7h or higher
73 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
74
Thomas Woutersed03b412007-08-28 21:37:11 +000075
Antoine Pitrou23df4832010-08-04 17:14:06 +000076# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
77def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020078 if hasattr(ssl, 'PROTOCOL_SSLv2'):
79 @functools.wraps(func)
80 def f(*args, **kwargs):
81 try:
82 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
83 except ssl.SSLError:
84 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
85 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
86 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
87 return func(*args, **kwargs)
88 return f
89 else:
90 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000091
92
Antoine Pitrou152efa22010-05-16 18:19:27 +000093class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020096 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 ssl.PROTOCOL_SSLv23
98 ssl.PROTOCOL_SSLv3
99 ssl.PROTOCOL_TLSv1
100 ssl.CERT_NONE
101 ssl.CERT_OPTIONAL
102 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100103 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100104 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100105 if ssl.HAS_ECDH:
106 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100107 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
108 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000109 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100110 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000111
Antoine Pitrou480a1242010-04-28 21:37:09 +0000112 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n RAND_status is %d (%s)\n"
116 % (v, (v and "sufficient randomness") or
117 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200118
119 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
120 self.assertEqual(len(data), 16)
121 self.assertEqual(is_cryptographic, v == 1)
122 if v:
123 data = ssl.RAND_bytes(16)
124 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200125 else:
126 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200127
Thomas Woutersed03b412007-08-28 21:37:11 +0000128 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 ssl.RAND_egd(1)
130 except TypeError:
131 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000132 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000133 print("didn't raise TypeError")
134 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000135
Antoine Pitrou480a1242010-04-28 21:37:09 +0000136 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000137 # note that this uses an 'unofficial' function in _ssl.c,
138 # provided solely for this test, to exercise the certificate
139 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000140 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000141 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000142 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200143 self.assertEqual(p['issuer'],
144 ((('countryName', 'XY'),),
145 (('localityName', 'Castle Anthrax'),),
146 (('organizationName', 'Python Software Foundation'),),
147 (('commonName', 'localhost'),))
148 )
149 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
150 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
151 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
152 self.assertEqual(p['subject'],
153 ((('countryName', 'XY'),),
154 (('localityName', 'Castle Anthrax'),),
155 (('organizationName', 'Python Software Foundation'),),
156 (('commonName', 'localhost'),))
157 )
158 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
159 # Issue #13034: the subjectAltName in some certificates
160 # (notably projects.developer.nokia.com:443) wasn't parsed
161 p = ssl._ssl._test_decode_cert(NOKIACERT)
162 if support.verbose:
163 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
164 self.assertEqual(p['subjectAltName'],
165 (('DNS', 'projects.developer.nokia.com'),
166 ('DNS', 'projects.forum.nokia.com'))
167 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000168
Antoine Pitrou480a1242010-04-28 21:37:09 +0000169 def test_DER_to_PEM(self):
170 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
171 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000172 d1 = ssl.PEM_cert_to_DER_cert(pem)
173 p2 = ssl.DER_cert_to_PEM_cert(d1)
174 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000175 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000176 if not p2.startswith(ssl.PEM_HEADER + '\n'):
177 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
178 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
179 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000180
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000181 def test_openssl_version(self):
182 n = ssl.OPENSSL_VERSION_NUMBER
183 t = ssl.OPENSSL_VERSION_INFO
184 s = ssl.OPENSSL_VERSION
185 self.assertIsInstance(n, int)
186 self.assertIsInstance(t, tuple)
187 self.assertIsInstance(s, str)
188 # Some sanity checks follow
189 # >= 0.9
190 self.assertGreaterEqual(n, 0x900000)
191 # < 2.0
192 self.assertLess(n, 0x20000000)
193 major, minor, fix, patch, status = t
194 self.assertGreaterEqual(major, 0)
195 self.assertLess(major, 2)
196 self.assertGreaterEqual(minor, 0)
197 self.assertLess(minor, 256)
198 self.assertGreaterEqual(fix, 0)
199 self.assertLess(fix, 256)
200 self.assertGreaterEqual(patch, 0)
201 self.assertLessEqual(patch, 26)
202 self.assertGreaterEqual(status, 0)
203 self.assertLessEqual(status, 15)
204 # Version string as returned by OpenSSL, the format might change
205 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
206 (s, t))
207
Antoine Pitrou9d543662010-04-23 23:10:32 +0000208 @support.cpython_only
209 def test_refcycle(self):
210 # Issue #7943: an SSL object doesn't create reference cycles with
211 # itself.
212 s = socket.socket(socket.AF_INET)
213 ss = ssl.wrap_socket(s)
214 wr = weakref.ref(ss)
215 del ss
216 self.assertEqual(wr(), None)
217
Antoine Pitroua468adc2010-09-14 14:43:44 +0000218 def test_wrapped_unconnected(self):
219 # Methods on an unconnected SSLSocket propagate the original
220 # socket.error raise by the underlying socket object.
221 s = socket.socket(socket.AF_INET)
222 ss = ssl.wrap_socket(s)
223 self.assertRaises(socket.error, ss.recv, 1)
224 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
225 self.assertRaises(socket.error, ss.recvfrom, 1)
226 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
227 self.assertRaises(socket.error, ss.send, b'x')
228 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
229
Antoine Pitrou40f08742010-04-24 22:04:40 +0000230 def test_timeout(self):
231 # Issue #8524: when creating an SSL socket, the timeout of the
232 # original socket should be retained.
233 for timeout in (None, 0.0, 5.0):
234 s = socket.socket(socket.AF_INET)
235 s.settimeout(timeout)
236 ss = ssl.wrap_socket(s)
237 self.assertEqual(timeout, ss.gettimeout())
238
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000239 def test_errors(self):
240 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000241 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000242 "certfile must be specified",
243 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000244 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000245 "certfile must be specified for server-side operations",
246 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000247 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000248 "certfile must be specified for server-side operations",
249 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000250 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000251 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000252 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000253 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000254 with socket.socket() as sock:
255 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000256 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000257 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000258 with socket.socket() as sock:
259 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000260 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000261 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000262 with socket.socket() as sock:
263 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000264 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000265
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000266 def test_match_hostname(self):
267 def ok(cert, hostname):
268 ssl.match_hostname(cert, hostname)
269 def fail(cert, hostname):
270 self.assertRaises(ssl.CertificateError,
271 ssl.match_hostname, cert, hostname)
272
273 cert = {'subject': ((('commonName', 'example.com'),),)}
274 ok(cert, 'example.com')
275 ok(cert, 'ExAmple.cOm')
276 fail(cert, 'www.example.com')
277 fail(cert, '.example.com')
278 fail(cert, 'example.org')
279 fail(cert, 'exampleXcom')
280
281 cert = {'subject': ((('commonName', '*.a.com'),),)}
282 ok(cert, 'foo.a.com')
283 fail(cert, 'bar.foo.a.com')
284 fail(cert, 'a.com')
285 fail(cert, 'Xa.com')
286 fail(cert, '.a.com')
287
288 cert = {'subject': ((('commonName', 'a.*.com'),),)}
289 ok(cert, 'a.foo.com')
290 fail(cert, 'a..com')
291 fail(cert, 'a.com')
292
293 cert = {'subject': ((('commonName', 'f*.com'),),)}
294 ok(cert, 'foo.com')
295 ok(cert, 'f.com')
296 fail(cert, 'bar.com')
297 fail(cert, 'foo.a.com')
298 fail(cert, 'bar.foo.com')
299
300 # Slightly fake real-world example
301 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
302 'subject': ((('commonName', 'linuxfrz.org'),),),
303 'subjectAltName': (('DNS', 'linuxfr.org'),
304 ('DNS', 'linuxfr.com'),
305 ('othername', '<unsupported>'))}
306 ok(cert, 'linuxfr.org')
307 ok(cert, 'linuxfr.com')
308 # Not a "DNS" entry
309 fail(cert, '<unsupported>')
310 # When there is a subjectAltName, commonName isn't used
311 fail(cert, 'linuxfrz.org')
312
313 # A pristine real-world example
314 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
315 'subject': ((('countryName', 'US'),),
316 (('stateOrProvinceName', 'California'),),
317 (('localityName', 'Mountain View'),),
318 (('organizationName', 'Google Inc'),),
319 (('commonName', 'mail.google.com'),))}
320 ok(cert, 'mail.google.com')
321 fail(cert, 'gmail.com')
322 # Only commonName is considered
323 fail(cert, 'California')
324
325 # Neither commonName nor subjectAltName
326 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
327 'subject': ((('countryName', 'US'),),
328 (('stateOrProvinceName', 'California'),),
329 (('localityName', 'Mountain View'),),
330 (('organizationName', 'Google Inc'),))}
331 fail(cert, 'mail.google.com')
332
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200333 # No DNS entry in subjectAltName but a commonName
334 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
335 'subject': ((('countryName', 'US'),),
336 (('stateOrProvinceName', 'California'),),
337 (('localityName', 'Mountain View'),),
338 (('commonName', 'mail.google.com'),)),
339 'subjectAltName': (('othername', 'blabla'), )}
340 ok(cert, 'mail.google.com')
341
342 # No DNS entry subjectAltName and no commonName
343 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
344 'subject': ((('countryName', 'US'),),
345 (('stateOrProvinceName', 'California'),),
346 (('localityName', 'Mountain View'),),
347 (('organizationName', 'Google Inc'),)),
348 'subjectAltName': (('othername', 'blabla'),)}
349 fail(cert, 'google.com')
350
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000351 # Empty cert / no cert
352 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
353 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
354
Antoine Pitroud5323212010-10-22 18:19:07 +0000355 def test_server_side(self):
356 # server_hostname doesn't work for server sockets
357 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000358 with socket.socket() as sock:
359 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
360 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000361
Antoine Pitroud6494802011-07-21 01:11:30 +0200362 def test_unknown_channel_binding(self):
363 # should raise ValueError for unknown type
364 s = socket.socket(socket.AF_INET)
365 ss = ssl.wrap_socket(s)
366 with self.assertRaises(ValueError):
367 ss.get_channel_binding("unknown-type")
368
369 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
370 "'tls-unique' channel binding not available")
371 def test_tls_unique_channel_binding(self):
372 # unconnected should return None for known type
373 s = socket.socket(socket.AF_INET)
374 ss = ssl.wrap_socket(s)
375 self.assertIsNone(ss.get_channel_binding("tls-unique"))
376 # the same for server-side
377 s = socket.socket(socket.AF_INET)
378 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
379 self.assertIsNone(ss.get_channel_binding("tls-unique"))
380
Antoine Pitrou152efa22010-05-16 18:19:27 +0000381class ContextTests(unittest.TestCase):
382
Antoine Pitrou23df4832010-08-04 17:14:06 +0000383 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000384 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200385 if hasattr(ssl, 'PROTOCOL_SSLv2'):
386 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000387 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
388 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
389 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
390 self.assertRaises(TypeError, ssl.SSLContext)
391 self.assertRaises(ValueError, ssl.SSLContext, -1)
392 self.assertRaises(ValueError, ssl.SSLContext, 42)
393
Antoine Pitrou23df4832010-08-04 17:14:06 +0000394 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000395 def test_protocol(self):
396 for proto in PROTOCOLS:
397 ctx = ssl.SSLContext(proto)
398 self.assertEqual(ctx.protocol, proto)
399
400 def test_ciphers(self):
401 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
402 ctx.set_ciphers("ALL")
403 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000404 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000405 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000406
Antoine Pitrou23df4832010-08-04 17:14:06 +0000407 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000408 def test_options(self):
409 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
410 # OP_ALL is the default value
411 self.assertEqual(ssl.OP_ALL, ctx.options)
412 ctx.options |= ssl.OP_NO_SSLv2
413 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
414 ctx.options)
415 ctx.options |= ssl.OP_NO_SSLv3
416 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
417 ctx.options)
418 if can_clear_options():
419 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
420 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
421 ctx.options)
422 ctx.options = 0
423 self.assertEqual(0, ctx.options)
424 else:
425 with self.assertRaises(ValueError):
426 ctx.options = 0
427
Antoine Pitrou152efa22010-05-16 18:19:27 +0000428 def test_verify(self):
429 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
430 # Default value
431 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
432 ctx.verify_mode = ssl.CERT_OPTIONAL
433 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
434 ctx.verify_mode = ssl.CERT_REQUIRED
435 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
436 ctx.verify_mode = ssl.CERT_NONE
437 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
438 with self.assertRaises(TypeError):
439 ctx.verify_mode = None
440 with self.assertRaises(ValueError):
441 ctx.verify_mode = 42
442
443 def test_load_cert_chain(self):
444 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
445 # Combined key and cert in a single file
446 ctx.load_cert_chain(CERTFILE)
447 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
448 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000449 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000450 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000451 self.assertEqual(cm.exception.errno, errno.ENOENT)
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(BADCERT)
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(EMPTYCERT)
456 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000457 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000458 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
459 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
460 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000461 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000462 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000463 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000464 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000465 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
467 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000468 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000469 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000470 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200471 # Password protected key and cert
472 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
473 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
474 ctx.load_cert_chain(CERTFILE_PROTECTED,
475 password=bytearray(KEY_PASSWORD.encode()))
476 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
477 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
478 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
479 bytearray(KEY_PASSWORD.encode()))
480 with self.assertRaisesRegex(TypeError, "should be a string"):
481 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
482 with self.assertRaises(ssl.SSLError):
483 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
484 with self.assertRaisesRegex(ValueError, "cannot be longer"):
485 # openssl has a fixed limit on the password buffer.
486 # PEM_BUFSIZE is generally set to 1kb.
487 # Return a string larger than this.
488 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
489 # Password callback
490 def getpass_unicode():
491 return KEY_PASSWORD
492 def getpass_bytes():
493 return KEY_PASSWORD.encode()
494 def getpass_bytearray():
495 return bytearray(KEY_PASSWORD.encode())
496 def getpass_badpass():
497 return "badpass"
498 def getpass_huge():
499 return b'a' * (1024 * 1024)
500 def getpass_bad_type():
501 return 9
502 def getpass_exception():
503 raise Exception('getpass error')
504 class GetPassCallable:
505 def __call__(self):
506 return KEY_PASSWORD
507 def getpass(self):
508 return KEY_PASSWORD
509 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
510 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
511 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
512 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
513 ctx.load_cert_chain(CERTFILE_PROTECTED,
514 password=GetPassCallable().getpass)
515 with self.assertRaises(ssl.SSLError):
516 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
517 with self.assertRaisesRegex(ValueError, "cannot be longer"):
518 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
519 with self.assertRaisesRegex(TypeError, "must return a string"):
520 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
521 with self.assertRaisesRegex(Exception, "getpass error"):
522 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
523 # Make sure the password function isn't called if it isn't needed
524 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000525
526 def test_load_verify_locations(self):
527 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
528 ctx.load_verify_locations(CERTFILE)
529 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
530 ctx.load_verify_locations(BYTES_CERTFILE)
531 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
532 self.assertRaises(TypeError, ctx.load_verify_locations)
533 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000534 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000535 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000536 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000537 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000538 ctx.load_verify_locations(BADCERT)
539 ctx.load_verify_locations(CERTFILE, CAPATH)
540 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
541
Victor Stinner80f75e62011-01-29 11:31:20 +0000542 # Issue #10989: crash if the second argument type is invalid
543 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
544
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100545 def test_load_dh_params(self):
546 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
547 ctx.load_dh_params(DHFILE)
548 if os.name != 'nt':
549 ctx.load_dh_params(BYTES_DHFILE)
550 self.assertRaises(TypeError, ctx.load_dh_params)
551 self.assertRaises(TypeError, ctx.load_dh_params, None)
552 with self.assertRaises(FileNotFoundError) as cm:
553 ctx.load_dh_params(WRONGCERT)
554 self.assertEqual(cm.exception.errno, errno.ENOENT)
555 with self.assertRaisesRegex(ssl.SSLError, "PEM routines"):
556 ctx.load_dh_params(CERTFILE)
557
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000558 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000559 def test_session_stats(self):
560 for proto in PROTOCOLS:
561 ctx = ssl.SSLContext(proto)
562 self.assertEqual(ctx.session_stats(), {
563 'number': 0,
564 'connect': 0,
565 'connect_good': 0,
566 'connect_renegotiate': 0,
567 'accept': 0,
568 'accept_good': 0,
569 'accept_renegotiate': 0,
570 'hits': 0,
571 'misses': 0,
572 'timeouts': 0,
573 'cache_full': 0,
574 })
575
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000576 def test_set_default_verify_paths(self):
577 # There's not much we can do to test that it acts as expected,
578 # so just check it doesn't crash or raise an exception.
579 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
580 ctx.set_default_verify_paths()
581
Antoine Pitrou501da612011-12-21 09:27:41 +0100582 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100583 def test_set_ecdh_curve(self):
584 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
585 ctx.set_ecdh_curve("prime256v1")
586 ctx.set_ecdh_curve(b"prime256v1")
587 self.assertRaises(TypeError, ctx.set_ecdh_curve)
588 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
589 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
590 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
591
Antoine Pitrou152efa22010-05-16 18:19:27 +0000592
Bill Janssen6e027db2007-11-15 22:23:56 +0000593class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000594
Antoine Pitrou480a1242010-04-28 21:37:09 +0000595 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000596 with support.transient_internet("svn.python.org"):
597 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
598 cert_reqs=ssl.CERT_NONE)
599 try:
600 s.connect(("svn.python.org", 443))
601 self.assertEqual({}, s.getpeercert())
602 finally:
603 s.close()
604
605 # this should fail because we have no verification certs
606 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
607 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000608 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
609 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000610 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000611
Antoine Pitrou350c7222010-09-09 13:31:46 +0000612 # this should succeed because we specify the root cert
613 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
614 cert_reqs=ssl.CERT_REQUIRED,
615 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
616 try:
617 s.connect(("svn.python.org", 443))
618 self.assertTrue(s.getpeercert())
619 finally:
620 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000621
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000622 def test_connect_ex(self):
623 # Issue #11326: check connect_ex() implementation
624 with support.transient_internet("svn.python.org"):
625 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
626 cert_reqs=ssl.CERT_REQUIRED,
627 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
628 try:
629 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
630 self.assertTrue(s.getpeercert())
631 finally:
632 s.close()
633
634 def test_non_blocking_connect_ex(self):
635 # Issue #11326: non-blocking connect_ex() should allow handshake
636 # to proceed after the socket gets ready.
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.setblocking(False)
644 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000645 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
646 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000647 # Wait for connect to finish
648 select.select([], [s], [], 5.0)
649 # Non-blocking handshake
650 while True:
651 try:
652 s.do_handshake()
653 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200654 except ssl.SSLWantReadError:
655 select.select([s], [], [], 5.0)
656 except ssl.SSLWantWriteError:
657 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000658 # SSL established
659 self.assertTrue(s.getpeercert())
660 finally:
661 s.close()
662
Antoine Pitroub4410db2011-05-18 18:51:06 +0200663 def test_timeout_connect_ex(self):
664 # Issue #12065: on a timeout, connect_ex() should return the original
665 # errno (mimicking the behaviour of non-SSL sockets).
666 with support.transient_internet("svn.python.org"):
667 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
668 cert_reqs=ssl.CERT_REQUIRED,
669 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
670 do_handshake_on_connect=False)
671 try:
672 s.settimeout(0.0000001)
673 rc = s.connect_ex(('svn.python.org', 443))
674 if rc == 0:
675 self.skipTest("svn.python.org responded too quickly")
676 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
677 finally:
678 s.close()
679
Antoine Pitrou152efa22010-05-16 18:19:27 +0000680 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000681 with support.transient_internet("svn.python.org"):
682 # Same as test_connect, but with a separately created context
683 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
684 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
685 s.connect(("svn.python.org", 443))
686 try:
687 self.assertEqual({}, s.getpeercert())
688 finally:
689 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000690 # Same with a server hostname
691 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
692 server_hostname="svn.python.org")
693 if ssl.HAS_SNI:
694 s.connect(("svn.python.org", 443))
695 s.close()
696 else:
697 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000698 # This should fail because we have no verification certs
699 ctx.verify_mode = ssl.CERT_REQUIRED
700 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000701 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000702 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000703 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000704 # This should succeed because we specify the root cert
705 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
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()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000713
714 def test_connect_capath(self):
715 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000716 # NOTE: the subject hashing algorithm has been changed between
717 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
718 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000719 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000720 with support.transient_internet("svn.python.org"):
721 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
722 ctx.verify_mode = ssl.CERT_REQUIRED
723 ctx.load_verify_locations(capath=CAPATH)
724 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
725 s.connect(("svn.python.org", 443))
726 try:
727 cert = s.getpeercert()
728 self.assertTrue(cert)
729 finally:
730 s.close()
731 # Same with a bytes `capath` argument
732 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
733 ctx.verify_mode = ssl.CERT_REQUIRED
734 ctx.load_verify_locations(capath=BYTES_CAPATH)
735 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
736 s.connect(("svn.python.org", 443))
737 try:
738 cert = s.getpeercert()
739 self.assertTrue(cert)
740 finally:
741 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000742
Antoine Pitroue3220242010-04-24 11:13:53 +0000743 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
744 def test_makefile_close(self):
745 # Issue #5238: creating a file-like object with makefile() shouldn't
746 # delay closing the underlying "real socket" (here tested with its
747 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000748 with support.transient_internet("svn.python.org"):
749 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
750 ss.connect(("svn.python.org", 443))
751 fd = ss.fileno()
752 f = ss.makefile()
753 f.close()
754 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000755 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000756 # Closing the SSL socket should close the fd too
757 ss.close()
758 gc.collect()
759 with self.assertRaises(OSError) as e:
760 os.read(fd, 0)
761 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000762
Antoine Pitrou480a1242010-04-28 21:37:09 +0000763 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000764 with support.transient_internet("svn.python.org"):
765 s = socket.socket(socket.AF_INET)
766 s.connect(("svn.python.org", 443))
767 s.setblocking(False)
768 s = ssl.wrap_socket(s,
769 cert_reqs=ssl.CERT_NONE,
770 do_handshake_on_connect=False)
771 count = 0
772 while True:
773 try:
774 count += 1
775 s.do_handshake()
776 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200777 except ssl.SSLWantReadError:
778 select.select([s], [], [])
779 except ssl.SSLWantWriteError:
780 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000781 s.close()
782 if support.verbose:
783 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000784
Antoine Pitrou480a1242010-04-28 21:37:09 +0000785 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200786 def _test_get_server_certificate(host, port, cert=None):
787 with support.transient_internet(host):
788 pem = ssl.get_server_certificate((host, port))
789 if not pem:
790 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200791
Antoine Pitrou15399c32011-04-28 19:23:55 +0200792 try:
793 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
794 except ssl.SSLError as x:
795 #should fail
796 if support.verbose:
797 sys.stdout.write("%s\n" % x)
798 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200799 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
800
Antoine Pitrou15399c32011-04-28 19:23:55 +0200801 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
802 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200803 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000804 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200805 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000806
Antoine Pitrou15399c32011-04-28 19:23:55 +0200807 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
808 if support.IPV6_ENABLED:
809 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000810
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000811 def test_ciphers(self):
812 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000813 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000814 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000815 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000816 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000817 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
818 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
819 s.connect(remote)
820 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000821 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000822 with socket.socket(socket.AF_INET) as sock:
823 s = ssl.wrap_socket(sock,
824 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
825 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000826
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000827 def test_algorithms(self):
828 # Issue #8484: all algorithms should be available when verifying a
829 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000830 # SHA256 was added in OpenSSL 0.9.8
831 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
832 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200833 # sha256.tbs-internet.com needs SNI to use the correct certificate
834 if not ssl.HAS_SNI:
835 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000836 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
837 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000838 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000839 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200840 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
841 ctx.verify_mode = ssl.CERT_REQUIRED
842 ctx.load_verify_locations(sha256_cert)
843 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
844 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000845 try:
846 s.connect(remote)
847 if support.verbose:
848 sys.stdout.write("\nCipher with %r is %r\n" %
849 (remote, s.cipher()))
850 sys.stdout.write("Certificate is:\n%s\n" %
851 pprint.pformat(s.getpeercert()))
852 finally:
853 s.close()
854
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000855
856try:
857 import threading
858except ImportError:
859 _have_threads = False
860else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 _have_threads = True
862
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000863 from test.ssl_servers import make_https_server
864
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865 class ThreadedEchoServer(threading.Thread):
866
867 class ConnectionHandler(threading.Thread):
868
869 """A mildly complicated class, because we want it to work both
870 with and without the SSL wrapper around the socket connection, so
871 that we can test the STARTTLS functionality."""
872
Bill Janssen6e027db2007-11-15 22:23:56 +0000873 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000874 self.server = server
875 self.running = False
876 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000877 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878 self.sock.setblocking(1)
879 self.sslconn = None
880 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000881 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000882
Antoine Pitrou480a1242010-04-28 21:37:09 +0000883 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000884 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000885 self.sslconn = self.server.context.wrap_socket(
886 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100887 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100888 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000889 # XXX Various errors can have happened here, for example
890 # a mismatching protocol version, an invalid certificate,
891 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100892 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000893 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000894 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000895 self.running = False
896 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000897 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000899 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000900 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000901 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000902 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
904 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000905 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000906 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
907 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000908 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100910 sys.stdout.write(" server: selected protocol is now "
911 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 return True
913
914 def read(self):
915 if self.sslconn:
916 return self.sslconn.read()
917 else:
918 return self.sock.recv(1024)
919
920 def write(self, bytes):
921 if self.sslconn:
922 return self.sslconn.write(bytes)
923 else:
924 return self.sock.send(bytes)
925
926 def close(self):
927 if self.sslconn:
928 self.sslconn.close()
929 else:
930 self.sock.close()
931
Antoine Pitrou480a1242010-04-28 21:37:09 +0000932 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 self.running = True
934 if not self.server.starttls_server:
935 if not self.wrap_conn():
936 return
937 while self.running:
938 try:
939 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000940 stripped = msg.strip()
941 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000942 # eof, so quit this handler
943 self.running = False
944 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000945 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000946 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 sys.stdout.write(" server: client closed connection\n")
948 self.close()
949 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000950 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000951 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000952 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000954 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 if not self.wrap_conn():
956 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000957 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000958 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000959 if support.verbose and self.server.connectionchatty:
960 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000961 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000962 self.sock = self.sslconn.unwrap()
963 self.sslconn = None
964 if support.verbose and self.server.connectionchatty:
965 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200966 elif stripped == b'CB tls-unique':
967 if support.verbose and self.server.connectionchatty:
968 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
969 data = self.sslconn.get_channel_binding("tls-unique")
970 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000971 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000972 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000973 self.server.connectionchatty):
974 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000975 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
976 % (msg, ctype, msg.lower(), ctype))
977 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000978 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979 if self.server.chatty:
980 handle_error("Test server failure:\n")
981 self.close()
982 self.running = False
983 # normally, we'd just stop here, but for the test
984 # harness, we want to stop the server
985 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986
Antoine Pitroub5218772010-05-21 09:56:06 +0000987 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000988 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000989 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100990 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +0000991 if context:
992 self.context = context
993 else:
994 self.context = ssl.SSLContext(ssl_version
995 if ssl_version is not None
996 else ssl.PROTOCOL_TLSv1)
997 self.context.verify_mode = (certreqs if certreqs is not None
998 else ssl.CERT_NONE)
999 if cacerts:
1000 self.context.load_verify_locations(cacerts)
1001 if certificate:
1002 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001003 if npn_protocols:
1004 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001005 if ciphers:
1006 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007 self.chatty = chatty
1008 self.connectionchatty = connectionchatty
1009 self.starttls_server = starttls_server
1010 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001011 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001012 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001013 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001014 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001015 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001016 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001017 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001018
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001019 def __enter__(self):
1020 self.start(threading.Event())
1021 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001022 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001023
1024 def __exit__(self, *args):
1025 self.stop()
1026 self.join()
1027
Antoine Pitrou480a1242010-04-28 21:37:09 +00001028 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001029 self.flag = flag
1030 threading.Thread.start(self)
1031
Antoine Pitrou480a1242010-04-28 21:37:09 +00001032 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001033 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 self.sock.listen(5)
1035 self.active = True
1036 if self.flag:
1037 # signal an event
1038 self.flag.set()
1039 while self.active:
1040 try:
1041 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001042 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001043 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001044 + repr(connaddr) + '\n')
1045 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001046 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001047 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001048 except socket.timeout:
1049 pass
1050 except KeyboardInterrupt:
1051 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001052 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001053
Antoine Pitrou480a1242010-04-28 21:37:09 +00001054 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001055 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001056
Bill Janssen54cc54c2007-12-14 22:08:56 +00001057 class AsyncoreEchoServer(threading.Thread):
1058
1059 # this one's based on asyncore.dispatcher
1060
1061 class EchoServer (asyncore.dispatcher):
1062
1063 class ConnectionHandler (asyncore.dispatcher_with_send):
1064
1065 def __init__(self, conn, certfile):
1066 self.socket = ssl.wrap_socket(conn, server_side=True,
1067 certfile=certfile,
1068 do_handshake_on_connect=False)
1069 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001070 self._ssl_accepting = True
1071 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001072
1073 def readable(self):
1074 if isinstance(self.socket, ssl.SSLSocket):
1075 while self.socket.pending() > 0:
1076 self.handle_read_event()
1077 return True
1078
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001079 def _do_ssl_handshake(self):
1080 try:
1081 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001082 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1083 return
1084 except ssl.SSLEOFError:
1085 return self.handle_close()
1086 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001087 raise
1088 except socket.error as err:
1089 if err.args[0] == errno.ECONNABORTED:
1090 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001091 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001092 self._ssl_accepting = False
1093
1094 def handle_read(self):
1095 if self._ssl_accepting:
1096 self._do_ssl_handshake()
1097 else:
1098 data = self.recv(1024)
1099 if support.verbose:
1100 sys.stdout.write(" server: read %s from client\n" % repr(data))
1101 if not data:
1102 self.close()
1103 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001105
1106 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001107 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001108 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001109 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1110
1111 def handle_error(self):
1112 raise
1113
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001114 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001115 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001116 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1117 self.port = support.bind_port(sock, '')
1118 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001119 self.listen(5)
1120
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001121 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001122 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001123 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1124 self.ConnectionHandler(sock_obj, self.certfile)
1125
1126 def handle_error(self):
1127 raise
1128
Trent Nelson78520002008-04-10 20:54:35 +00001129 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001130 self.flag = None
1131 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001132 self.server = self.EchoServer(certfile)
1133 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001134 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001135 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001136
1137 def __str__(self):
1138 return "<%s %s>" % (self.__class__.__name__, self.server)
1139
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001140 def __enter__(self):
1141 self.start(threading.Event())
1142 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001143 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001144
1145 def __exit__(self, *args):
1146 if support.verbose:
1147 sys.stdout.write(" cleanup: stopping server.\n")
1148 self.stop()
1149 if support.verbose:
1150 sys.stdout.write(" cleanup: joining server thread.\n")
1151 self.join()
1152 if support.verbose:
1153 sys.stdout.write(" cleanup: successfully joined.\n")
1154
Bill Janssen54cc54c2007-12-14 22:08:56 +00001155 def start (self, flag=None):
1156 self.flag = flag
1157 threading.Thread.start(self)
1158
Antoine Pitrou480a1242010-04-28 21:37:09 +00001159 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001160 self.active = True
1161 if self.flag:
1162 self.flag.set()
1163 while self.active:
1164 try:
1165 asyncore.loop(1)
1166 except:
1167 pass
1168
Antoine Pitrou480a1242010-04-28 21:37:09 +00001169 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001170 self.active = False
1171 self.server.close()
1172
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 def bad_cert_test(certfile):
1174 """
1175 Launch a server with CERT_REQUIRED, and check that trying to
1176 connect to it with the given client certificate fails.
1177 """
Trent Nelson78520002008-04-10 20:54:35 +00001178 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001180 cacerts=CERTFILE, chatty=False,
1181 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001182 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001183 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001184 with socket.socket() as sock:
1185 s = ssl.wrap_socket(sock,
1186 certfile=certfile,
1187 ssl_version=ssl.PROTOCOL_TLSv1)
1188 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001189 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001190 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001191 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001192 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001193 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001194 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001195 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001196 if x.errno != errno.ENOENT:
1197 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001198 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001199 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001200 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001201 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001202
Antoine Pitroub5218772010-05-21 09:56:06 +00001203 def server_params_test(client_context, server_context, indata=b"FOO\n",
1204 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 """
1206 Launch a server, connect a client to it and try various reads
1207 and writes.
1208 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001209 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001210 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001212 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001213 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001214 with client_context.wrap_socket(socket.socket()) as s:
1215 s.connect((HOST, server.port))
1216 for arg in [indata, bytearray(indata), memoryview(indata)]:
1217 if connectionchatty:
1218 if support.verbose:
1219 sys.stdout.write(
1220 " client: sending %r...\n" % indata)
1221 s.write(arg)
1222 outdata = s.read()
1223 if connectionchatty:
1224 if support.verbose:
1225 sys.stdout.write(" client: read %r\n" % outdata)
1226 if outdata != indata.lower():
1227 raise AssertionError(
1228 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1229 % (outdata[:20], len(outdata),
1230 indata[:20].lower(), len(indata)))
1231 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001232 if connectionchatty:
1233 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001234 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001235 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001236 'compression': s.compression(),
1237 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001238 'client_npn_protocol': s.selected_npn_protocol()
1239 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001240 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001241 stats['server_npn_protocols'] = server.selected_protocols
1242 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001243
Antoine Pitroub5218772010-05-21 09:56:06 +00001244 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1245 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001246 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001247 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001248 certtype = {
1249 ssl.CERT_NONE: "CERT_NONE",
1250 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1251 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1252 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001253 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001254 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001255 sys.stdout.write(formatstr %
1256 (ssl.get_protocol_name(client_protocol),
1257 ssl.get_protocol_name(server_protocol),
1258 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001259 client_context = ssl.SSLContext(client_protocol)
1260 client_context.options = ssl.OP_ALL | client_options
1261 server_context = ssl.SSLContext(server_protocol)
1262 server_context.options = ssl.OP_ALL | server_options
1263 for ctx in (client_context, server_context):
1264 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001265 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1266 # will send an SSLv3 hello (rather than SSLv2) starting from
1267 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001268 ctx.set_ciphers("ALL")
1269 ctx.load_cert_chain(CERTFILE)
1270 ctx.load_verify_locations(CERTFILE)
1271 try:
1272 server_params_test(client_context, server_context,
1273 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001274 # Protocol mismatch can result in either an SSLError, or a
1275 # "Connection reset by peer" error.
1276 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001277 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001278 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001279 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001280 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001281 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001282 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001283 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001284 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001285 "Client protocol %s succeeded with server protocol %s!"
1286 % (ssl.get_protocol_name(client_protocol),
1287 ssl.get_protocol_name(server_protocol)))
1288
1289
Bill Janssen6e027db2007-11-15 22:23:56 +00001290 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001291
Antoine Pitrou23df4832010-08-04 17:14:06 +00001292 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001293 def test_echo(self):
1294 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001295 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001296 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001297 for protocol in PROTOCOLS:
1298 context = ssl.SSLContext(protocol)
1299 context.load_cert_chain(CERTFILE)
1300 server_params_test(context, context,
1301 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001302
Antoine Pitrou480a1242010-04-28 21:37:09 +00001303 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001304 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001305 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001306 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1307 context.verify_mode = ssl.CERT_REQUIRED
1308 context.load_verify_locations(CERTFILE)
1309 context.load_cert_chain(CERTFILE)
1310 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001311 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001312 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001313 s.connect((HOST, server.port))
1314 cert = s.getpeercert()
1315 self.assertTrue(cert, "Can't get peer certificate.")
1316 cipher = s.cipher()
1317 if support.verbose:
1318 sys.stdout.write(pprint.pformat(cert) + '\n')
1319 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1320 if 'subject' not in cert:
1321 self.fail("No subject field in certificate: %s." %
1322 pprint.pformat(cert))
1323 if ((('organizationName', 'Python Software Foundation'),)
1324 not in cert['subject']):
1325 self.fail(
1326 "Missing or invalid 'organizationName' field in certificate subject; "
1327 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001328 self.assertIn('notBefore', cert)
1329 self.assertIn('notAfter', cert)
1330 before = ssl.cert_time_to_seconds(cert['notBefore'])
1331 after = ssl.cert_time_to_seconds(cert['notAfter'])
1332 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001333 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001334
Antoine Pitrou480a1242010-04-28 21:37:09 +00001335 def test_empty_cert(self):
1336 """Connecting with an empty cert file"""
1337 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1338 "nullcert.pem"))
1339 def test_malformed_cert(self):
1340 """Connecting with a badly formatted certificate (syntax error)"""
1341 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1342 "badcert.pem"))
1343 def test_nonexisting_cert(self):
1344 """Connecting with a non-existing cert file"""
1345 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1346 "wrongcert.pem"))
1347 def test_malformed_key(self):
1348 """Connecting with a badly formatted key (syntax error)"""
1349 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1350 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001351
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 def test_rude_shutdown(self):
1353 """A brutal shutdown of an SSL server should raise an IOError
1354 in the client when attempting handshake.
1355 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001356 listener_ready = threading.Event()
1357 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001358
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001359 s = socket.socket()
1360 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001361
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001362 # `listener` runs in a thread. It sits in an accept() until
1363 # the main thread connects. Then it rudely closes the socket,
1364 # and sets Event `listener_gone` to let the main thread know
1365 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001366 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001367 s.listen(5)
1368 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001369 newsock, addr = s.accept()
1370 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001371 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001372 listener_gone.set()
1373
1374 def connector():
1375 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001376 with socket.socket() as c:
1377 c.connect((HOST, port))
1378 listener_gone.wait()
1379 try:
1380 ssl_sock = ssl.wrap_socket(c)
1381 except IOError:
1382 pass
1383 else:
1384 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001385
1386 t = threading.Thread(target=listener)
1387 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001388 try:
1389 connector()
1390 finally:
1391 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001392
Antoine Pitrou23df4832010-08-04 17:14:06 +00001393 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001394 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1395 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 def test_protocol_sslv2(self):
1397 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001398 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001399 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1401 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1402 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1403 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1404 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1405 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001406 # SSLv23 client with specific SSL options
1407 if no_sslv2_implies_sslv3_hello():
1408 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1409 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1410 client_options=ssl.OP_NO_SSLv2)
1411 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1412 client_options=ssl.OP_NO_SSLv3)
1413 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1414 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001415
Antoine Pitrou23df4832010-08-04 17:14:06 +00001416 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001417 def test_protocol_sslv23(self):
1418 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001419 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001420 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001421 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1422 try:
1423 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1424 except (ssl.SSLError, socket.error) as x:
1425 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1426 if support.verbose:
1427 sys.stdout.write(
1428 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1429 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001430 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1431 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1432 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001433
Antoine Pitrou480a1242010-04-28 21:37:09 +00001434 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1435 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1436 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001437
Antoine Pitrou480a1242010-04-28 21:37:09 +00001438 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1439 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1440 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001441
Antoine Pitroub5218772010-05-21 09:56:06 +00001442 # Server with specific SSL options
1443 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1444 server_options=ssl.OP_NO_SSLv3)
1445 # Will choose TLSv1
1446 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1447 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1448 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1449 server_options=ssl.OP_NO_TLSv1)
1450
1451
Antoine Pitrou23df4832010-08-04 17:14:06 +00001452 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001453 def test_protocol_sslv3(self):
1454 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001455 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001456 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001457 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1458 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1459 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001460 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1461 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001462 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1463 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001464 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001465 if no_sslv2_implies_sslv3_hello():
1466 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1467 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1468 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001469
Antoine Pitrou23df4832010-08-04 17:14:06 +00001470 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001471 def test_protocol_tlsv1(self):
1472 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001473 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001474 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1476 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1477 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001478 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1479 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001480 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001481 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1482 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001483
Antoine Pitrou480a1242010-04-28 21:37:09 +00001484 def test_starttls(self):
1485 """Switching from clear text to encrypted and back again."""
1486 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 +00001487
Trent Nelson78520002008-04-10 20:54:35 +00001488 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001489 ssl_version=ssl.PROTOCOL_TLSv1,
1490 starttls_server=True,
1491 chatty=True,
1492 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001493 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001494 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001495 s = socket.socket()
1496 s.setblocking(1)
1497 s.connect((HOST, server.port))
1498 if support.verbose:
1499 sys.stdout.write("\n")
1500 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001501 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001502 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001503 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001504 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001505 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001506 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001507 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001508 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001509 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001510 msg = outdata.strip().lower()
1511 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1512 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001513 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001514 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001515 " client: read %r from server, starting TLS...\n"
1516 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001517 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1518 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001519 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1520 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001521 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001522 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001523 " client: read %r from server, ending TLS...\n"
1524 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001525 s = conn.unwrap()
1526 wrapped = False
1527 else:
1528 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001529 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001530 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001531 if support.verbose:
1532 sys.stdout.write(" client: closing connection.\n")
1533 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001534 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001535 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001536 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001537 if wrapped:
1538 conn.close()
1539 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001540 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001541
Antoine Pitrou480a1242010-04-28 21:37:09 +00001542 def test_socketserver(self):
1543 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001544 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001545 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001546 if support.verbose:
1547 sys.stdout.write('\n')
1548 with open(CERTFILE, 'rb') as f:
1549 d1 = f.read()
1550 d2 = ''
1551 # now fetch the same data from the HTTPS server
1552 url = 'https://%s:%d/%s' % (
1553 HOST, server.port, os.path.split(CERTFILE)[1])
1554 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001555 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001556 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001557 if dlen and (int(dlen) > 0):
1558 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001559 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001560 sys.stdout.write(
1561 " client: read %d bytes from remote server '%s'\n"
1562 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001563 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001564 f.close()
1565 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001566
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 def test_asyncore_server(self):
1568 """Check the example asyncore integration."""
1569 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001570
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001571 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001572 sys.stdout.write("\n")
1573
Antoine Pitrou480a1242010-04-28 21:37:09 +00001574 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001575 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001576 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001577 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001578 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001579 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001580 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001581 " client: sending %r...\n" % indata)
1582 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001583 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001584 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001585 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001586 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001587 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001588 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1589 % (outdata[:20], len(outdata),
1590 indata[:20].lower(), len(indata)))
1591 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001592 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001593 sys.stdout.write(" client: closing connection.\n")
1594 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001595 if support.verbose:
1596 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001597
Antoine Pitrou480a1242010-04-28 21:37:09 +00001598 def test_recv_send(self):
1599 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001600 if support.verbose:
1601 sys.stdout.write("\n")
1602
1603 server = ThreadedEchoServer(CERTFILE,
1604 certreqs=ssl.CERT_NONE,
1605 ssl_version=ssl.PROTOCOL_TLSv1,
1606 cacerts=CERTFILE,
1607 chatty=True,
1608 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001609 with server:
1610 s = ssl.wrap_socket(socket.socket(),
1611 server_side=False,
1612 certfile=CERTFILE,
1613 ca_certs=CERTFILE,
1614 cert_reqs=ssl.CERT_NONE,
1615 ssl_version=ssl.PROTOCOL_TLSv1)
1616 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001617 # helper methods for standardising recv* method signatures
1618 def _recv_into():
1619 b = bytearray(b"\0"*100)
1620 count = s.recv_into(b)
1621 return b[:count]
1622
1623 def _recvfrom_into():
1624 b = bytearray(b"\0"*100)
1625 count, addr = s.recvfrom_into(b)
1626 return b[:count]
1627
1628 # (name, method, whether to expect success, *args)
1629 send_methods = [
1630 ('send', s.send, True, []),
1631 ('sendto', s.sendto, False, ["some.address"]),
1632 ('sendall', s.sendall, True, []),
1633 ]
1634 recv_methods = [
1635 ('recv', s.recv, True, []),
1636 ('recvfrom', s.recvfrom, False, ["some.address"]),
1637 ('recv_into', _recv_into, True, []),
1638 ('recvfrom_into', _recvfrom_into, False, []),
1639 ]
1640 data_prefix = "PREFIX_"
1641
1642 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001643 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001644 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001645 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001646 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001647 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001648 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001649 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001650 "<<{outdata:r}>> ({nout:d}) received; "
1651 "expected <<{indata:r}>> ({nin:d})\n".format(
1652 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001653 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001654 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001655 )
1656 )
1657 except ValueError as e:
1658 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001659 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001660 "Failed to send with method <<{name:s}>>; "
1661 "expected to succeed.\n".format(name=meth_name)
1662 )
1663 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001664 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001665 "Method <<{name:s}>> failed with unexpected "
1666 "exception message: {exp:s}\n".format(
1667 name=meth_name, exp=e
1668 )
1669 )
1670
1671 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001672 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001673 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001674 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001675 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001676 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001677 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001678 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001679 "<<{outdata:r}>> ({nout:d}) received; "
1680 "expected <<{indata:r}>> ({nin:d})\n".format(
1681 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001682 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001683 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001684 )
1685 )
1686 except ValueError as e:
1687 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001688 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001689 "Failed to receive with method <<{name:s}>>; "
1690 "expected to succeed.\n".format(name=meth_name)
1691 )
1692 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001693 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001694 "Method <<{name:s}>> failed with unexpected "
1695 "exception message: {exp:s}\n".format(
1696 name=meth_name, exp=e
1697 )
1698 )
1699 # consume data
1700 s.read()
1701
Nick Coghlan513886a2011-08-28 00:00:27 +10001702 # Make sure sendmsg et al are disallowed to avoid
1703 # inadvertent disclosure of data and/or corruption
1704 # of the encrypted data stream
1705 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1706 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1707 self.assertRaises(NotImplementedError,
1708 s.recvmsg_into, bytearray(100))
1709
Antoine Pitrou480a1242010-04-28 21:37:09 +00001710 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001711 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001712
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001713 def test_handshake_timeout(self):
1714 # Issue #5103: SSL handshake must respect the socket timeout
1715 server = socket.socket(socket.AF_INET)
1716 host = "127.0.0.1"
1717 port = support.bind_port(server)
1718 started = threading.Event()
1719 finish = False
1720
1721 def serve():
1722 server.listen(5)
1723 started.set()
1724 conns = []
1725 while not finish:
1726 r, w, e = select.select([server], [], [], 0.1)
1727 if server in r:
1728 # Let the socket hang around rather than having
1729 # it closed by garbage collection.
1730 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001731 for sock in conns:
1732 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001733
1734 t = threading.Thread(target=serve)
1735 t.start()
1736 started.wait()
1737
1738 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001739 try:
1740 c = socket.socket(socket.AF_INET)
1741 c.settimeout(0.2)
1742 c.connect((host, port))
1743 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001744 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001745 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001746 finally:
1747 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001748 try:
1749 c = socket.socket(socket.AF_INET)
1750 c = ssl.wrap_socket(c)
1751 c.settimeout(0.2)
1752 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001753 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001754 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001755 finally:
1756 c.close()
1757 finally:
1758 finish = True
1759 t.join()
1760 server.close()
1761
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001762 def test_default_ciphers(self):
1763 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1764 try:
1765 # Force a set of weak ciphers on our client context
1766 context.set_ciphers("DES")
1767 except ssl.SSLError:
1768 self.skipTest("no DES cipher available")
1769 with ThreadedEchoServer(CERTFILE,
1770 ssl_version=ssl.PROTOCOL_SSLv23,
1771 chatty=False) as server:
1772 with socket.socket() as sock:
1773 s = context.wrap_socket(sock)
1774 with self.assertRaises((OSError, ssl.SSLError)):
1775 s.connect((HOST, server.port))
1776 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1777
Antoine Pitroud6494802011-07-21 01:11:30 +02001778 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1779 "'tls-unique' channel binding not available")
1780 def test_tls_unique_channel_binding(self):
1781 """Test tls-unique channel binding."""
1782 if support.verbose:
1783 sys.stdout.write("\n")
1784
1785 server = ThreadedEchoServer(CERTFILE,
1786 certreqs=ssl.CERT_NONE,
1787 ssl_version=ssl.PROTOCOL_TLSv1,
1788 cacerts=CERTFILE,
1789 chatty=True,
1790 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001791 with server:
1792 s = ssl.wrap_socket(socket.socket(),
1793 server_side=False,
1794 certfile=CERTFILE,
1795 ca_certs=CERTFILE,
1796 cert_reqs=ssl.CERT_NONE,
1797 ssl_version=ssl.PROTOCOL_TLSv1)
1798 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001799 # get the data
1800 cb_data = s.get_channel_binding("tls-unique")
1801 if support.verbose:
1802 sys.stdout.write(" got channel binding data: {0!r}\n"
1803 .format(cb_data))
1804
1805 # check if it is sane
1806 self.assertIsNotNone(cb_data)
1807 self.assertEqual(len(cb_data), 12) # True for TLSv1
1808
1809 # and compare with the peers version
1810 s.write(b"CB tls-unique\n")
1811 peer_data_repr = s.read().strip()
1812 self.assertEqual(peer_data_repr,
1813 repr(cb_data).encode("us-ascii"))
1814 s.close()
1815
1816 # now, again
1817 s = ssl.wrap_socket(socket.socket(),
1818 server_side=False,
1819 certfile=CERTFILE,
1820 ca_certs=CERTFILE,
1821 cert_reqs=ssl.CERT_NONE,
1822 ssl_version=ssl.PROTOCOL_TLSv1)
1823 s.connect((HOST, server.port))
1824 new_cb_data = s.get_channel_binding("tls-unique")
1825 if support.verbose:
1826 sys.stdout.write(" got another channel binding data: {0!r}\n"
1827 .format(new_cb_data))
1828 # is it really unique
1829 self.assertNotEqual(cb_data, new_cb_data)
1830 self.assertIsNotNone(cb_data)
1831 self.assertEqual(len(cb_data), 12) # True for TLSv1
1832 s.write(b"CB tls-unique\n")
1833 peer_data_repr = s.read().strip()
1834 self.assertEqual(peer_data_repr,
1835 repr(new_cb_data).encode("us-ascii"))
1836 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001837
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001838 def test_compression(self):
1839 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1840 context.load_cert_chain(CERTFILE)
1841 stats = server_params_test(context, context,
1842 chatty=True, connectionchatty=True)
1843 if support.verbose:
1844 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1845 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1846
1847 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1848 "ssl.OP_NO_COMPRESSION needed for this test")
1849 def test_compression_disabled(self):
1850 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1851 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001852 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001853 stats = server_params_test(context, context,
1854 chatty=True, connectionchatty=True)
1855 self.assertIs(stats['compression'], None)
1856
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001857 def test_dh_params(self):
1858 # Check we can get a connection with ephemeral Diffie-Hellman
1859 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1860 context.load_cert_chain(CERTFILE)
1861 context.load_dh_params(DHFILE)
1862 context.set_ciphers("kEDH")
1863 stats = server_params_test(context, context,
1864 chatty=True, connectionchatty=True)
1865 cipher = stats["cipher"][0]
1866 parts = cipher.split("-")
1867 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1868 self.fail("Non-DH cipher: " + cipher[0])
1869
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001870 def test_selected_npn_protocol(self):
1871 # selected_npn_protocol() is None unless NPN is used
1872 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1873 context.load_cert_chain(CERTFILE)
1874 stats = server_params_test(context, context,
1875 chatty=True, connectionchatty=True)
1876 self.assertIs(stats['client_npn_protocol'], None)
1877
1878 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1879 def test_npn_protocols(self):
1880 server_protocols = ['http/1.1', 'spdy/2']
1881 protocol_tests = [
1882 (['http/1.1', 'spdy/2'], 'http/1.1'),
1883 (['spdy/2', 'http/1.1'], 'http/1.1'),
1884 (['spdy/2', 'test'], 'spdy/2'),
1885 (['abc', 'def'], 'abc')
1886 ]
1887 for client_protocols, expected in protocol_tests:
1888 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1889 server_context.load_cert_chain(CERTFILE)
1890 server_context.set_npn_protocols(server_protocols)
1891 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1892 client_context.load_cert_chain(CERTFILE)
1893 client_context.set_npn_protocols(client_protocols)
1894 stats = server_params_test(client_context, server_context,
1895 chatty=True, connectionchatty=True)
1896
1897 msg = "failed trying %s (s) and %s (c).\n" \
1898 "was expecting %s, but got %%s from the %%s" \
1899 % (str(server_protocols), str(client_protocols),
1900 str(expected))
1901 client_result = stats['client_npn_protocol']
1902 self.assertEqual(client_result, expected, msg % (client_result, "client"))
1903 server_result = stats['server_npn_protocols'][-1] \
1904 if len(stats['server_npn_protocols']) else 'nothing'
1905 self.assertEqual(server_result, expected, msg % (server_result, "server"))
1906
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001907
Thomas Woutersed03b412007-08-28 21:37:11 +00001908def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001909 if support.verbose:
1910 plats = {
1911 'Linux': platform.linux_distribution,
1912 'Mac': platform.mac_ver,
1913 'Windows': platform.win32_ver,
1914 }
1915 for name, func in plats.items():
1916 plat = func()
1917 if plat and plat[0]:
1918 plat = '%s %r' % (name, plat)
1919 break
1920 else:
1921 plat = repr(platform.platform())
1922 print("test_ssl: testing with %r %r" %
1923 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1924 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001925 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001926
Antoine Pitrou152efa22010-05-16 18:19:27 +00001927 for filename in [
1928 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1929 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1930 BADCERT, BADKEY, EMPTYCERT]:
1931 if not os.path.exists(filename):
1932 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001933
Antoine Pitrou152efa22010-05-16 18:19:27 +00001934 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001935
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001936 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001937 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001938
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001939 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001940 thread_info = support.threading_setup()
1941 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001942 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001943
Antoine Pitrou480a1242010-04-28 21:37:09 +00001944 try:
1945 support.run_unittest(*tests)
1946 finally:
1947 if _have_threads:
1948 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001949
1950if __name__ == "__main__":
1951 test_main()