blob: ada3c4b47c79438ec2a1fa234879f85b0840dcb8 [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)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000833 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
834 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000835 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000836 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000837 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
838 cert_reqs=ssl.CERT_REQUIRED,
839 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000840 try:
841 s.connect(remote)
842 if support.verbose:
843 sys.stdout.write("\nCipher with %r is %r\n" %
844 (remote, s.cipher()))
845 sys.stdout.write("Certificate is:\n%s\n" %
846 pprint.pformat(s.getpeercert()))
847 finally:
848 s.close()
849
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850
851try:
852 import threading
853except ImportError:
854 _have_threads = False
855else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856 _have_threads = True
857
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000858 from test.ssl_servers import make_https_server
859
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 class ThreadedEchoServer(threading.Thread):
861
862 class ConnectionHandler(threading.Thread):
863
864 """A mildly complicated class, because we want it to work both
865 with and without the SSL wrapper around the socket connection, so
866 that we can test the STARTTLS functionality."""
867
Bill Janssen6e027db2007-11-15 22:23:56 +0000868 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000869 self.server = server
870 self.running = False
871 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000872 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873 self.sock.setblocking(1)
874 self.sslconn = None
875 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000876 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000877
Antoine Pitrou480a1242010-04-28 21:37:09 +0000878 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000880 self.sslconn = self.server.context.wrap_socket(
881 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100882 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100883 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000884 # XXX Various errors can have happened here, for example
885 # a mismatching protocol version, an invalid certificate,
886 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100887 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000888 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000889 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000890 self.running = False
891 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000892 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000893 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000894 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000895 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000897 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
899 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000900 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000901 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
902 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000903 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000904 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100905 sys.stdout.write(" server: selected protocol is now "
906 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 return True
908
909 def read(self):
910 if self.sslconn:
911 return self.sslconn.read()
912 else:
913 return self.sock.recv(1024)
914
915 def write(self, bytes):
916 if self.sslconn:
917 return self.sslconn.write(bytes)
918 else:
919 return self.sock.send(bytes)
920
921 def close(self):
922 if self.sslconn:
923 self.sslconn.close()
924 else:
925 self.sock.close()
926
Antoine Pitrou480a1242010-04-28 21:37:09 +0000927 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000928 self.running = True
929 if not self.server.starttls_server:
930 if not self.wrap_conn():
931 return
932 while self.running:
933 try:
934 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000935 stripped = msg.strip()
936 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000937 # eof, so quit this handler
938 self.running = False
939 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000940 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000941 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000942 sys.stdout.write(" server: client closed connection\n")
943 self.close()
944 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000945 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000946 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000947 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000948 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000949 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000950 if not self.wrap_conn():
951 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000952 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000953 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000954 if support.verbose and self.server.connectionchatty:
955 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000956 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000957 self.sock = self.sslconn.unwrap()
958 self.sslconn = None
959 if support.verbose and self.server.connectionchatty:
960 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200961 elif stripped == b'CB tls-unique':
962 if support.verbose and self.server.connectionchatty:
963 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
964 data = self.sslconn.get_channel_binding("tls-unique")
965 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000966 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000967 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000968 self.server.connectionchatty):
969 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000970 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
971 % (msg, ctype, msg.lower(), ctype))
972 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000973 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000974 if self.server.chatty:
975 handle_error("Test server failure:\n")
976 self.close()
977 self.running = False
978 # normally, we'd just stop here, but for the test
979 # harness, we want to stop the server
980 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981
Antoine Pitroub5218772010-05-21 09:56:06 +0000982 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000983 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000984 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100985 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +0000986 if context:
987 self.context = context
988 else:
989 self.context = ssl.SSLContext(ssl_version
990 if ssl_version is not None
991 else ssl.PROTOCOL_TLSv1)
992 self.context.verify_mode = (certreqs if certreqs is not None
993 else ssl.CERT_NONE)
994 if cacerts:
995 self.context.load_verify_locations(cacerts)
996 if certificate:
997 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100998 if npn_protocols:
999 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001000 if ciphers:
1001 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002 self.chatty = chatty
1003 self.connectionchatty = connectionchatty
1004 self.starttls_server = starttls_server
1005 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001006 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001008 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001009 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001010 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001011 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001012 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001013
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001014 def __enter__(self):
1015 self.start(threading.Event())
1016 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001017 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001018
1019 def __exit__(self, *args):
1020 self.stop()
1021 self.join()
1022
Antoine Pitrou480a1242010-04-28 21:37:09 +00001023 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001024 self.flag = flag
1025 threading.Thread.start(self)
1026
Antoine Pitrou480a1242010-04-28 21:37:09 +00001027 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001028 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001029 self.sock.listen(5)
1030 self.active = True
1031 if self.flag:
1032 # signal an event
1033 self.flag.set()
1034 while self.active:
1035 try:
1036 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001037 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001038 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001039 + repr(connaddr) + '\n')
1040 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001041 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001042 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001043 except socket.timeout:
1044 pass
1045 except KeyboardInterrupt:
1046 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001047 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001048
Antoine Pitrou480a1242010-04-28 21:37:09 +00001049 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001050 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001051
Bill Janssen54cc54c2007-12-14 22:08:56 +00001052 class AsyncoreEchoServer(threading.Thread):
1053
1054 # this one's based on asyncore.dispatcher
1055
1056 class EchoServer (asyncore.dispatcher):
1057
1058 class ConnectionHandler (asyncore.dispatcher_with_send):
1059
1060 def __init__(self, conn, certfile):
1061 self.socket = ssl.wrap_socket(conn, server_side=True,
1062 certfile=certfile,
1063 do_handshake_on_connect=False)
1064 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001065 self._ssl_accepting = True
1066 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001067
1068 def readable(self):
1069 if isinstance(self.socket, ssl.SSLSocket):
1070 while self.socket.pending() > 0:
1071 self.handle_read_event()
1072 return True
1073
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001074 def _do_ssl_handshake(self):
1075 try:
1076 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001077 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1078 return
1079 except ssl.SSLEOFError:
1080 return self.handle_close()
1081 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001082 raise
1083 except socket.error as err:
1084 if err.args[0] == errno.ECONNABORTED:
1085 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001086 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001087 self._ssl_accepting = False
1088
1089 def handle_read(self):
1090 if self._ssl_accepting:
1091 self._do_ssl_handshake()
1092 else:
1093 data = self.recv(1024)
1094 if support.verbose:
1095 sys.stdout.write(" server: read %s from client\n" % repr(data))
1096 if not data:
1097 self.close()
1098 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001099 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001100
1101 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001102 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001103 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001104 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1105
1106 def handle_error(self):
1107 raise
1108
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001109 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001110 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001111 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1112 self.port = support.bind_port(sock, '')
1113 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001114 self.listen(5)
1115
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001116 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001117 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001118 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1119 self.ConnectionHandler(sock_obj, self.certfile)
1120
1121 def handle_error(self):
1122 raise
1123
Trent Nelson78520002008-04-10 20:54:35 +00001124 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001125 self.flag = None
1126 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001127 self.server = self.EchoServer(certfile)
1128 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001129 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001130 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001131
1132 def __str__(self):
1133 return "<%s %s>" % (self.__class__.__name__, self.server)
1134
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001135 def __enter__(self):
1136 self.start(threading.Event())
1137 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001138 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001139
1140 def __exit__(self, *args):
1141 if support.verbose:
1142 sys.stdout.write(" cleanup: stopping server.\n")
1143 self.stop()
1144 if support.verbose:
1145 sys.stdout.write(" cleanup: joining server thread.\n")
1146 self.join()
1147 if support.verbose:
1148 sys.stdout.write(" cleanup: successfully joined.\n")
1149
Bill Janssen54cc54c2007-12-14 22:08:56 +00001150 def start (self, flag=None):
1151 self.flag = flag
1152 threading.Thread.start(self)
1153
Antoine Pitrou480a1242010-04-28 21:37:09 +00001154 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001155 self.active = True
1156 if self.flag:
1157 self.flag.set()
1158 while self.active:
1159 try:
1160 asyncore.loop(1)
1161 except:
1162 pass
1163
Antoine Pitrou480a1242010-04-28 21:37:09 +00001164 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001165 self.active = False
1166 self.server.close()
1167
Antoine Pitrou480a1242010-04-28 21:37:09 +00001168 def bad_cert_test(certfile):
1169 """
1170 Launch a server with CERT_REQUIRED, and check that trying to
1171 connect to it with the given client certificate fails.
1172 """
Trent Nelson78520002008-04-10 20:54:35 +00001173 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001175 cacerts=CERTFILE, chatty=False,
1176 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001177 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001178 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001179 with socket.socket() as sock:
1180 s = ssl.wrap_socket(sock,
1181 certfile=certfile,
1182 ssl_version=ssl.PROTOCOL_TLSv1)
1183 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001184 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001185 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001186 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001187 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001188 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001189 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001190 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001191 if x.errno != errno.ENOENT:
1192 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001193 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001194 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001195 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001196 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001197
Antoine Pitroub5218772010-05-21 09:56:06 +00001198 def server_params_test(client_context, server_context, indata=b"FOO\n",
1199 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001200 """
1201 Launch a server, connect a client to it and try various reads
1202 and writes.
1203 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001204 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001205 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001206 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001207 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001208 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001209 with client_context.wrap_socket(socket.socket()) as s:
1210 s.connect((HOST, server.port))
1211 for arg in [indata, bytearray(indata), memoryview(indata)]:
1212 if connectionchatty:
1213 if support.verbose:
1214 sys.stdout.write(
1215 " client: sending %r...\n" % indata)
1216 s.write(arg)
1217 outdata = s.read()
1218 if connectionchatty:
1219 if support.verbose:
1220 sys.stdout.write(" client: read %r\n" % outdata)
1221 if outdata != indata.lower():
1222 raise AssertionError(
1223 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1224 % (outdata[:20], len(outdata),
1225 indata[:20].lower(), len(indata)))
1226 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001227 if connectionchatty:
1228 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001229 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001230 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001231 'compression': s.compression(),
1232 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001233 'client_npn_protocol': s.selected_npn_protocol()
1234 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001235 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001236 stats['server_npn_protocols'] = server.selected_protocols
1237 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001238
Antoine Pitroub5218772010-05-21 09:56:06 +00001239 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1240 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001241 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001242 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001243 certtype = {
1244 ssl.CERT_NONE: "CERT_NONE",
1245 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1246 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1247 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001248 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001250 sys.stdout.write(formatstr %
1251 (ssl.get_protocol_name(client_protocol),
1252 ssl.get_protocol_name(server_protocol),
1253 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001254 client_context = ssl.SSLContext(client_protocol)
1255 client_context.options = ssl.OP_ALL | client_options
1256 server_context = ssl.SSLContext(server_protocol)
1257 server_context.options = ssl.OP_ALL | server_options
1258 for ctx in (client_context, server_context):
1259 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001260 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1261 # will send an SSLv3 hello (rather than SSLv2) starting from
1262 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001263 ctx.set_ciphers("ALL")
1264 ctx.load_cert_chain(CERTFILE)
1265 ctx.load_verify_locations(CERTFILE)
1266 try:
1267 server_params_test(client_context, server_context,
1268 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001269 # Protocol mismatch can result in either an SSLError, or a
1270 # "Connection reset by peer" error.
1271 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001272 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001273 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001274 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001275 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001276 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001277 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001278 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001279 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001280 "Client protocol %s succeeded with server protocol %s!"
1281 % (ssl.get_protocol_name(client_protocol),
1282 ssl.get_protocol_name(server_protocol)))
1283
1284
Bill Janssen6e027db2007-11-15 22:23:56 +00001285 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001286
Antoine Pitrou23df4832010-08-04 17:14:06 +00001287 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001288 def test_echo(self):
1289 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001290 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001291 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001292 for protocol in PROTOCOLS:
1293 context = ssl.SSLContext(protocol)
1294 context.load_cert_chain(CERTFILE)
1295 server_params_test(context, context,
1296 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001297
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001299 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001300 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001301 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1302 context.verify_mode = ssl.CERT_REQUIRED
1303 context.load_verify_locations(CERTFILE)
1304 context.load_cert_chain(CERTFILE)
1305 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001306 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001307 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001308 s.connect((HOST, server.port))
1309 cert = s.getpeercert()
1310 self.assertTrue(cert, "Can't get peer certificate.")
1311 cipher = s.cipher()
1312 if support.verbose:
1313 sys.stdout.write(pprint.pformat(cert) + '\n')
1314 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1315 if 'subject' not in cert:
1316 self.fail("No subject field in certificate: %s." %
1317 pprint.pformat(cert))
1318 if ((('organizationName', 'Python Software Foundation'),)
1319 not in cert['subject']):
1320 self.fail(
1321 "Missing or invalid 'organizationName' field in certificate subject; "
1322 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001323 self.assertIn('notBefore', cert)
1324 self.assertIn('notAfter', cert)
1325 before = ssl.cert_time_to_seconds(cert['notBefore'])
1326 after = ssl.cert_time_to_seconds(cert['notAfter'])
1327 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001328 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001329
Antoine Pitrou480a1242010-04-28 21:37:09 +00001330 def test_empty_cert(self):
1331 """Connecting with an empty cert file"""
1332 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1333 "nullcert.pem"))
1334 def test_malformed_cert(self):
1335 """Connecting with a badly formatted certificate (syntax error)"""
1336 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1337 "badcert.pem"))
1338 def test_nonexisting_cert(self):
1339 """Connecting with a non-existing cert file"""
1340 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1341 "wrongcert.pem"))
1342 def test_malformed_key(self):
1343 """Connecting with a badly formatted key (syntax error)"""
1344 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1345 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001346
Antoine Pitrou480a1242010-04-28 21:37:09 +00001347 def test_rude_shutdown(self):
1348 """A brutal shutdown of an SSL server should raise an IOError
1349 in the client when attempting handshake.
1350 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001351 listener_ready = threading.Event()
1352 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001353
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001354 s = socket.socket()
1355 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001356
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001357 # `listener` runs in a thread. It sits in an accept() until
1358 # the main thread connects. Then it rudely closes the socket,
1359 # and sets Event `listener_gone` to let the main thread know
1360 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001361 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001362 s.listen(5)
1363 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001364 newsock, addr = s.accept()
1365 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001366 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001367 listener_gone.set()
1368
1369 def connector():
1370 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001371 with socket.socket() as c:
1372 c.connect((HOST, port))
1373 listener_gone.wait()
1374 try:
1375 ssl_sock = ssl.wrap_socket(c)
1376 except IOError:
1377 pass
1378 else:
1379 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001380
1381 t = threading.Thread(target=listener)
1382 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001383 try:
1384 connector()
1385 finally:
1386 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001387
Antoine Pitrou23df4832010-08-04 17:14:06 +00001388 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001389 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1390 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 def test_protocol_sslv2(self):
1392 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001393 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001394 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1396 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1397 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1398 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1399 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1400 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001401 # SSLv23 client with specific SSL options
1402 if no_sslv2_implies_sslv3_hello():
1403 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1404 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1405 client_options=ssl.OP_NO_SSLv2)
1406 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1407 client_options=ssl.OP_NO_SSLv3)
1408 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1409 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001410
Antoine Pitrou23df4832010-08-04 17:14:06 +00001411 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001412 def test_protocol_sslv23(self):
1413 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001414 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001415 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001416 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1417 try:
1418 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1419 except (ssl.SSLError, socket.error) as x:
1420 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1421 if support.verbose:
1422 sys.stdout.write(
1423 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1424 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001425 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1426 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1427 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001428
Antoine Pitrou480a1242010-04-28 21:37:09 +00001429 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1430 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1431 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001432
Antoine Pitrou480a1242010-04-28 21:37:09 +00001433 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1434 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1435 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001436
Antoine Pitroub5218772010-05-21 09:56:06 +00001437 # Server with specific SSL options
1438 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1439 server_options=ssl.OP_NO_SSLv3)
1440 # Will choose TLSv1
1441 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1442 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1443 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1444 server_options=ssl.OP_NO_TLSv1)
1445
1446
Antoine Pitrou23df4832010-08-04 17:14:06 +00001447 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 def test_protocol_sslv3(self):
1449 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001450 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001451 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001452 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1453 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1454 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001455 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1456 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001457 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1458 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001459 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001460 if no_sslv2_implies_sslv3_hello():
1461 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1462 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1463 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001464
Antoine Pitrou23df4832010-08-04 17:14:06 +00001465 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001466 def test_protocol_tlsv1(self):
1467 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001468 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001469 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001470 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1471 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1472 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001473 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1474 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001476 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1477 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478
Antoine Pitrou480a1242010-04-28 21:37:09 +00001479 def test_starttls(self):
1480 """Switching from clear text to encrypted and back again."""
1481 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 +00001482
Trent Nelson78520002008-04-10 20:54:35 +00001483 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001484 ssl_version=ssl.PROTOCOL_TLSv1,
1485 starttls_server=True,
1486 chatty=True,
1487 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001488 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001489 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001490 s = socket.socket()
1491 s.setblocking(1)
1492 s.connect((HOST, server.port))
1493 if support.verbose:
1494 sys.stdout.write("\n")
1495 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001496 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001497 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001498 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001499 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001500 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001501 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001502 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001503 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001504 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001505 msg = outdata.strip().lower()
1506 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1507 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001508 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001509 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001510 " client: read %r from server, starting TLS...\n"
1511 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001512 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1513 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001514 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1515 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001516 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001517 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001518 " client: read %r from server, ending TLS...\n"
1519 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001520 s = conn.unwrap()
1521 wrapped = False
1522 else:
1523 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001524 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001525 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001526 if support.verbose:
1527 sys.stdout.write(" client: closing connection.\n")
1528 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001529 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001530 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001531 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001532 if wrapped:
1533 conn.close()
1534 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001535 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001536
Antoine Pitrou480a1242010-04-28 21:37:09 +00001537 def test_socketserver(self):
1538 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001539 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001540 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001541 if support.verbose:
1542 sys.stdout.write('\n')
1543 with open(CERTFILE, 'rb') as f:
1544 d1 = f.read()
1545 d2 = ''
1546 # now fetch the same data from the HTTPS server
1547 url = 'https://%s:%d/%s' % (
1548 HOST, server.port, os.path.split(CERTFILE)[1])
1549 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001550 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001551 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001552 if dlen and (int(dlen) > 0):
1553 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001554 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001555 sys.stdout.write(
1556 " client: read %d bytes from remote server '%s'\n"
1557 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001558 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001559 f.close()
1560 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001561
Antoine Pitrou480a1242010-04-28 21:37:09 +00001562 def test_asyncore_server(self):
1563 """Check the example asyncore integration."""
1564 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001565
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001566 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001567 sys.stdout.write("\n")
1568
Antoine Pitrou480a1242010-04-28 21:37:09 +00001569 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001570 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001571 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001572 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001573 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001574 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001575 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001576 " client: sending %r...\n" % indata)
1577 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001578 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001579 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001580 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001581 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001582 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001583 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1584 % (outdata[:20], len(outdata),
1585 indata[:20].lower(), len(indata)))
1586 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001587 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001588 sys.stdout.write(" client: closing connection.\n")
1589 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001590 if support.verbose:
1591 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001592
Antoine Pitrou480a1242010-04-28 21:37:09 +00001593 def test_recv_send(self):
1594 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001595 if support.verbose:
1596 sys.stdout.write("\n")
1597
1598 server = ThreadedEchoServer(CERTFILE,
1599 certreqs=ssl.CERT_NONE,
1600 ssl_version=ssl.PROTOCOL_TLSv1,
1601 cacerts=CERTFILE,
1602 chatty=True,
1603 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001604 with server:
1605 s = ssl.wrap_socket(socket.socket(),
1606 server_side=False,
1607 certfile=CERTFILE,
1608 ca_certs=CERTFILE,
1609 cert_reqs=ssl.CERT_NONE,
1610 ssl_version=ssl.PROTOCOL_TLSv1)
1611 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001612 # helper methods for standardising recv* method signatures
1613 def _recv_into():
1614 b = bytearray(b"\0"*100)
1615 count = s.recv_into(b)
1616 return b[:count]
1617
1618 def _recvfrom_into():
1619 b = bytearray(b"\0"*100)
1620 count, addr = s.recvfrom_into(b)
1621 return b[:count]
1622
1623 # (name, method, whether to expect success, *args)
1624 send_methods = [
1625 ('send', s.send, True, []),
1626 ('sendto', s.sendto, False, ["some.address"]),
1627 ('sendall', s.sendall, True, []),
1628 ]
1629 recv_methods = [
1630 ('recv', s.recv, True, []),
1631 ('recvfrom', s.recvfrom, False, ["some.address"]),
1632 ('recv_into', _recv_into, True, []),
1633 ('recvfrom_into', _recvfrom_into, False, []),
1634 ]
1635 data_prefix = "PREFIX_"
1636
1637 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001639 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001640 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001641 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001642 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001643 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001644 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001645 "<<{outdata:r}>> ({nout:d}) received; "
1646 "expected <<{indata:r}>> ({nin:d})\n".format(
1647 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001648 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001649 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001650 )
1651 )
1652 except ValueError as e:
1653 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001654 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001655 "Failed to send with method <<{name:s}>>; "
1656 "expected to succeed.\n".format(name=meth_name)
1657 )
1658 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001659 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001660 "Method <<{name:s}>> failed with unexpected "
1661 "exception message: {exp:s}\n".format(
1662 name=meth_name, exp=e
1663 )
1664 )
1665
1666 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001667 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001668 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001669 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001670 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001671 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001672 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001673 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001674 "<<{outdata:r}>> ({nout:d}) received; "
1675 "expected <<{indata:r}>> ({nin:d})\n".format(
1676 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001677 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001678 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001679 )
1680 )
1681 except ValueError as e:
1682 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001683 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001684 "Failed to receive with method <<{name:s}>>; "
1685 "expected to succeed.\n".format(name=meth_name)
1686 )
1687 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001688 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001689 "Method <<{name:s}>> failed with unexpected "
1690 "exception message: {exp:s}\n".format(
1691 name=meth_name, exp=e
1692 )
1693 )
1694 # consume data
1695 s.read()
1696
Nick Coghlan513886a2011-08-28 00:00:27 +10001697 # Make sure sendmsg et al are disallowed to avoid
1698 # inadvertent disclosure of data and/or corruption
1699 # of the encrypted data stream
1700 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1701 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1702 self.assertRaises(NotImplementedError,
1703 s.recvmsg_into, bytearray(100))
1704
Antoine Pitrou480a1242010-04-28 21:37:09 +00001705 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001706 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001707
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001708 def test_handshake_timeout(self):
1709 # Issue #5103: SSL handshake must respect the socket timeout
1710 server = socket.socket(socket.AF_INET)
1711 host = "127.0.0.1"
1712 port = support.bind_port(server)
1713 started = threading.Event()
1714 finish = False
1715
1716 def serve():
1717 server.listen(5)
1718 started.set()
1719 conns = []
1720 while not finish:
1721 r, w, e = select.select([server], [], [], 0.1)
1722 if server in r:
1723 # Let the socket hang around rather than having
1724 # it closed by garbage collection.
1725 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001726 for sock in conns:
1727 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001728
1729 t = threading.Thread(target=serve)
1730 t.start()
1731 started.wait()
1732
1733 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001734 try:
1735 c = socket.socket(socket.AF_INET)
1736 c.settimeout(0.2)
1737 c.connect((host, port))
1738 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001739 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001740 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001741 finally:
1742 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001743 try:
1744 c = socket.socket(socket.AF_INET)
1745 c = ssl.wrap_socket(c)
1746 c.settimeout(0.2)
1747 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001748 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001749 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001750 finally:
1751 c.close()
1752 finally:
1753 finish = True
1754 t.join()
1755 server.close()
1756
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001757 def test_default_ciphers(self):
1758 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1759 try:
1760 # Force a set of weak ciphers on our client context
1761 context.set_ciphers("DES")
1762 except ssl.SSLError:
1763 self.skipTest("no DES cipher available")
1764 with ThreadedEchoServer(CERTFILE,
1765 ssl_version=ssl.PROTOCOL_SSLv23,
1766 chatty=False) as server:
1767 with socket.socket() as sock:
1768 s = context.wrap_socket(sock)
1769 with self.assertRaises((OSError, ssl.SSLError)):
1770 s.connect((HOST, server.port))
1771 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1772
Antoine Pitroud6494802011-07-21 01:11:30 +02001773 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1774 "'tls-unique' channel binding not available")
1775 def test_tls_unique_channel_binding(self):
1776 """Test tls-unique channel binding."""
1777 if support.verbose:
1778 sys.stdout.write("\n")
1779
1780 server = ThreadedEchoServer(CERTFILE,
1781 certreqs=ssl.CERT_NONE,
1782 ssl_version=ssl.PROTOCOL_TLSv1,
1783 cacerts=CERTFILE,
1784 chatty=True,
1785 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001786 with server:
1787 s = ssl.wrap_socket(socket.socket(),
1788 server_side=False,
1789 certfile=CERTFILE,
1790 ca_certs=CERTFILE,
1791 cert_reqs=ssl.CERT_NONE,
1792 ssl_version=ssl.PROTOCOL_TLSv1)
1793 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001794 # get the data
1795 cb_data = s.get_channel_binding("tls-unique")
1796 if support.verbose:
1797 sys.stdout.write(" got channel binding data: {0!r}\n"
1798 .format(cb_data))
1799
1800 # check if it is sane
1801 self.assertIsNotNone(cb_data)
1802 self.assertEqual(len(cb_data), 12) # True for TLSv1
1803
1804 # and compare with the peers version
1805 s.write(b"CB tls-unique\n")
1806 peer_data_repr = s.read().strip()
1807 self.assertEqual(peer_data_repr,
1808 repr(cb_data).encode("us-ascii"))
1809 s.close()
1810
1811 # now, again
1812 s = ssl.wrap_socket(socket.socket(),
1813 server_side=False,
1814 certfile=CERTFILE,
1815 ca_certs=CERTFILE,
1816 cert_reqs=ssl.CERT_NONE,
1817 ssl_version=ssl.PROTOCOL_TLSv1)
1818 s.connect((HOST, server.port))
1819 new_cb_data = s.get_channel_binding("tls-unique")
1820 if support.verbose:
1821 sys.stdout.write(" got another channel binding data: {0!r}\n"
1822 .format(new_cb_data))
1823 # is it really unique
1824 self.assertNotEqual(cb_data, new_cb_data)
1825 self.assertIsNotNone(cb_data)
1826 self.assertEqual(len(cb_data), 12) # True for TLSv1
1827 s.write(b"CB tls-unique\n")
1828 peer_data_repr = s.read().strip()
1829 self.assertEqual(peer_data_repr,
1830 repr(new_cb_data).encode("us-ascii"))
1831 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001832
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001833 def test_compression(self):
1834 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1835 context.load_cert_chain(CERTFILE)
1836 stats = server_params_test(context, context,
1837 chatty=True, connectionchatty=True)
1838 if support.verbose:
1839 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1840 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1841
1842 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1843 "ssl.OP_NO_COMPRESSION needed for this test")
1844 def test_compression_disabled(self):
1845 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1846 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001847 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001848 stats = server_params_test(context, context,
1849 chatty=True, connectionchatty=True)
1850 self.assertIs(stats['compression'], None)
1851
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001852 def test_dh_params(self):
1853 # Check we can get a connection with ephemeral Diffie-Hellman
1854 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1855 context.load_cert_chain(CERTFILE)
1856 context.load_dh_params(DHFILE)
1857 context.set_ciphers("kEDH")
1858 stats = server_params_test(context, context,
1859 chatty=True, connectionchatty=True)
1860 cipher = stats["cipher"][0]
1861 parts = cipher.split("-")
1862 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1863 self.fail("Non-DH cipher: " + cipher[0])
1864
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001865 def test_selected_npn_protocol(self):
1866 # selected_npn_protocol() is None unless NPN is used
1867 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1868 context.load_cert_chain(CERTFILE)
1869 stats = server_params_test(context, context,
1870 chatty=True, connectionchatty=True)
1871 self.assertIs(stats['client_npn_protocol'], None)
1872
1873 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1874 def test_npn_protocols(self):
1875 server_protocols = ['http/1.1', 'spdy/2']
1876 protocol_tests = [
1877 (['http/1.1', 'spdy/2'], 'http/1.1'),
1878 (['spdy/2', 'http/1.1'], 'http/1.1'),
1879 (['spdy/2', 'test'], 'spdy/2'),
1880 (['abc', 'def'], 'abc')
1881 ]
1882 for client_protocols, expected in protocol_tests:
1883 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1884 server_context.load_cert_chain(CERTFILE)
1885 server_context.set_npn_protocols(server_protocols)
1886 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1887 client_context.load_cert_chain(CERTFILE)
1888 client_context.set_npn_protocols(client_protocols)
1889 stats = server_params_test(client_context, server_context,
1890 chatty=True, connectionchatty=True)
1891
1892 msg = "failed trying %s (s) and %s (c).\n" \
1893 "was expecting %s, but got %%s from the %%s" \
1894 % (str(server_protocols), str(client_protocols),
1895 str(expected))
1896 client_result = stats['client_npn_protocol']
1897 self.assertEqual(client_result, expected, msg % (client_result, "client"))
1898 server_result = stats['server_npn_protocols'][-1] \
1899 if len(stats['server_npn_protocols']) else 'nothing'
1900 self.assertEqual(server_result, expected, msg % (server_result, "server"))
1901
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001902
Thomas Woutersed03b412007-08-28 21:37:11 +00001903def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001904 if support.verbose:
1905 plats = {
1906 'Linux': platform.linux_distribution,
1907 'Mac': platform.mac_ver,
1908 'Windows': platform.win32_ver,
1909 }
1910 for name, func in plats.items():
1911 plat = func()
1912 if plat and plat[0]:
1913 plat = '%s %r' % (name, plat)
1914 break
1915 else:
1916 plat = repr(platform.platform())
1917 print("test_ssl: testing with %r %r" %
1918 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1919 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001920 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001921
Antoine Pitrou152efa22010-05-16 18:19:27 +00001922 for filename in [
1923 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1924 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1925 BADCERT, BADKEY, EMPTYCERT]:
1926 if not os.path.exists(filename):
1927 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001928
Antoine Pitrou152efa22010-05-16 18:19:27 +00001929 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001930
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001931 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001932 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001933
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001934 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001935 thread_info = support.threading_setup()
1936 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001937 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001938
Antoine Pitrou480a1242010-04-28 21:37:09 +00001939 try:
1940 support.run_unittest(*tests)
1941 finally:
1942 if _have_threads:
1943 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001944
1945if __name__ == "__main__":
1946 test_main()