blob: 51762cffc8c16892e2abb94446f0cff2216509e6 [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)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200555 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100556 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
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200593class SSLErrorTests(unittest.TestCase):
594
595 def test_str(self):
596 # The str() of a SSLError doesn't include the errno
597 e = ssl.SSLError(1, "foo")
598 self.assertEqual(str(e), "foo")
599 self.assertEqual(e.errno, 1)
600 # Same for a subclass
601 e = ssl.SSLZeroReturnError(1, "foo")
602 self.assertEqual(str(e), "foo")
603 self.assertEqual(e.errno, 1)
604
605 def test_lib_reason(self):
606 # Test the library and reason attributes
607 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
608 with self.assertRaises(ssl.SSLError) as cm:
609 ctx.load_dh_params(CERTFILE)
610 self.assertEqual(cm.exception.library, 'PEM')
611 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
612 s = str(cm.exception)
613 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
614
615 def test_subclass(self):
616 # Check that the appropriate SSLError subclass is raised
617 # (this only tests one of them)
618 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
619 with socket.socket() as s:
620 s.bind(("127.0.0.1", 0))
621 s.listen(5)
622 with socket.socket() as c:
623 c.connect(s.getsockname())
624 c.setblocking(False)
625 c = ctx.wrap_socket(c, False, do_handshake_on_connect=False)
626 with self.assertRaises(ssl.SSLWantReadError) as cm:
627 c.do_handshake()
628 s = str(cm.exception)
629 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
630 # For compatibility
631 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
632
633
Bill Janssen6e027db2007-11-15 22:23:56 +0000634class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000635
Antoine Pitrou480a1242010-04-28 21:37:09 +0000636 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000637 with support.transient_internet("svn.python.org"):
638 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
639 cert_reqs=ssl.CERT_NONE)
640 try:
641 s.connect(("svn.python.org", 443))
642 self.assertEqual({}, s.getpeercert())
643 finally:
644 s.close()
645
646 # this should fail because we have no verification certs
647 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
648 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000649 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
650 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000651 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000652
Antoine Pitrou350c7222010-09-09 13:31:46 +0000653 # this should succeed because we specify the root cert
654 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
655 cert_reqs=ssl.CERT_REQUIRED,
656 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
657 try:
658 s.connect(("svn.python.org", 443))
659 self.assertTrue(s.getpeercert())
660 finally:
661 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000662
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000663 def test_connect_ex(self):
664 # Issue #11326: check connect_ex() implementation
665 with support.transient_internet("svn.python.org"):
666 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
667 cert_reqs=ssl.CERT_REQUIRED,
668 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
669 try:
670 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
671 self.assertTrue(s.getpeercert())
672 finally:
673 s.close()
674
675 def test_non_blocking_connect_ex(self):
676 # Issue #11326: non-blocking connect_ex() should allow handshake
677 # to proceed after the socket gets ready.
678 with support.transient_internet("svn.python.org"):
679 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
680 cert_reqs=ssl.CERT_REQUIRED,
681 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
682 do_handshake_on_connect=False)
683 try:
684 s.setblocking(False)
685 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000686 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
687 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000688 # Wait for connect to finish
689 select.select([], [s], [], 5.0)
690 # Non-blocking handshake
691 while True:
692 try:
693 s.do_handshake()
694 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200695 except ssl.SSLWantReadError:
696 select.select([s], [], [], 5.0)
697 except ssl.SSLWantWriteError:
698 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000699 # SSL established
700 self.assertTrue(s.getpeercert())
701 finally:
702 s.close()
703
Antoine Pitroub4410db2011-05-18 18:51:06 +0200704 def test_timeout_connect_ex(self):
705 # Issue #12065: on a timeout, connect_ex() should return the original
706 # errno (mimicking the behaviour of non-SSL sockets).
707 with support.transient_internet("svn.python.org"):
708 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
709 cert_reqs=ssl.CERT_REQUIRED,
710 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
711 do_handshake_on_connect=False)
712 try:
713 s.settimeout(0.0000001)
714 rc = s.connect_ex(('svn.python.org', 443))
715 if rc == 0:
716 self.skipTest("svn.python.org responded too quickly")
717 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
718 finally:
719 s.close()
720
Antoine Pitrou152efa22010-05-16 18:19:27 +0000721 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000722 with support.transient_internet("svn.python.org"):
723 # Same as test_connect, but with a separately created context
724 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
725 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
726 s.connect(("svn.python.org", 443))
727 try:
728 self.assertEqual({}, s.getpeercert())
729 finally:
730 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000731 # Same with a server hostname
732 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
733 server_hostname="svn.python.org")
734 if ssl.HAS_SNI:
735 s.connect(("svn.python.org", 443))
736 s.close()
737 else:
738 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000739 # This should fail because we have no verification certs
740 ctx.verify_mode = ssl.CERT_REQUIRED
741 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000742 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000743 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000744 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000745 # This should succeed because we specify the root cert
746 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
747 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
748 s.connect(("svn.python.org", 443))
749 try:
750 cert = s.getpeercert()
751 self.assertTrue(cert)
752 finally:
753 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000754
755 def test_connect_capath(self):
756 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000757 # NOTE: the subject hashing algorithm has been changed between
758 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
759 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000760 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000761 with support.transient_internet("svn.python.org"):
762 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
763 ctx.verify_mode = ssl.CERT_REQUIRED
764 ctx.load_verify_locations(capath=CAPATH)
765 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
766 s.connect(("svn.python.org", 443))
767 try:
768 cert = s.getpeercert()
769 self.assertTrue(cert)
770 finally:
771 s.close()
772 # Same with a bytes `capath` argument
773 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
774 ctx.verify_mode = ssl.CERT_REQUIRED
775 ctx.load_verify_locations(capath=BYTES_CAPATH)
776 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
777 s.connect(("svn.python.org", 443))
778 try:
779 cert = s.getpeercert()
780 self.assertTrue(cert)
781 finally:
782 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783
Antoine Pitroue3220242010-04-24 11:13:53 +0000784 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
785 def test_makefile_close(self):
786 # Issue #5238: creating a file-like object with makefile() shouldn't
787 # delay closing the underlying "real socket" (here tested with its
788 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000789 with support.transient_internet("svn.python.org"):
790 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
791 ss.connect(("svn.python.org", 443))
792 fd = ss.fileno()
793 f = ss.makefile()
794 f.close()
795 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000796 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000797 # Closing the SSL socket should close the fd too
798 ss.close()
799 gc.collect()
800 with self.assertRaises(OSError) as e:
801 os.read(fd, 0)
802 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000803
Antoine Pitrou480a1242010-04-28 21:37:09 +0000804 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000805 with support.transient_internet("svn.python.org"):
806 s = socket.socket(socket.AF_INET)
807 s.connect(("svn.python.org", 443))
808 s.setblocking(False)
809 s = ssl.wrap_socket(s,
810 cert_reqs=ssl.CERT_NONE,
811 do_handshake_on_connect=False)
812 count = 0
813 while True:
814 try:
815 count += 1
816 s.do_handshake()
817 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200818 except ssl.SSLWantReadError:
819 select.select([s], [], [])
820 except ssl.SSLWantWriteError:
821 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000822 s.close()
823 if support.verbose:
824 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000825
Antoine Pitrou480a1242010-04-28 21:37:09 +0000826 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200827 def _test_get_server_certificate(host, port, cert=None):
828 with support.transient_internet(host):
829 pem = ssl.get_server_certificate((host, port))
830 if not pem:
831 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200832
Antoine Pitrou15399c32011-04-28 19:23:55 +0200833 try:
834 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
835 except ssl.SSLError as x:
836 #should fail
837 if support.verbose:
838 sys.stdout.write("%s\n" % x)
839 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200840 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
841
Antoine Pitrou15399c32011-04-28 19:23:55 +0200842 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
843 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200844 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000845 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200846 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000847
Antoine Pitrou15399c32011-04-28 19:23:55 +0200848 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
849 if support.IPV6_ENABLED:
850 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000851
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000852 def test_ciphers(self):
853 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000854 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000855 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000856 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000857 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000858 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
859 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
860 s.connect(remote)
861 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000862 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000863 with socket.socket(socket.AF_INET) as sock:
864 s = ssl.wrap_socket(sock,
865 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
866 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000867
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000868 def test_algorithms(self):
869 # Issue #8484: all algorithms should be available when verifying a
870 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000871 # SHA256 was added in OpenSSL 0.9.8
872 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
873 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200874 # sha256.tbs-internet.com needs SNI to use the correct certificate
875 if not ssl.HAS_SNI:
876 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000877 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
878 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000879 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000880 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200881 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
882 ctx.verify_mode = ssl.CERT_REQUIRED
883 ctx.load_verify_locations(sha256_cert)
884 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
885 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000886 try:
887 s.connect(remote)
888 if support.verbose:
889 sys.stdout.write("\nCipher with %r is %r\n" %
890 (remote, s.cipher()))
891 sys.stdout.write("Certificate is:\n%s\n" %
892 pprint.pformat(s.getpeercert()))
893 finally:
894 s.close()
895
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896
897try:
898 import threading
899except ImportError:
900 _have_threads = False
901else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000902 _have_threads = True
903
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000904 from test.ssl_servers import make_https_server
905
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000906 class ThreadedEchoServer(threading.Thread):
907
908 class ConnectionHandler(threading.Thread):
909
910 """A mildly complicated class, because we want it to work both
911 with and without the SSL wrapper around the socket connection, so
912 that we can test the STARTTLS functionality."""
913
Bill Janssen6e027db2007-11-15 22:23:56 +0000914 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 self.server = server
916 self.running = False
917 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000918 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919 self.sock.setblocking(1)
920 self.sslconn = None
921 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000922 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923
Antoine Pitrou480a1242010-04-28 21:37:09 +0000924 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000926 self.sslconn = self.server.context.wrap_socket(
927 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100928 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100929 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000930 # XXX Various errors can have happened here, for example
931 # a mismatching protocol version, an invalid certificate,
932 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100933 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000934 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000935 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000936 self.running = False
937 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000938 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000939 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000940 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000941 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000942 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000943 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000944 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
945 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000946 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
948 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000949 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000950 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100951 sys.stdout.write(" server: selected protocol is now "
952 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953 return True
954
955 def read(self):
956 if self.sslconn:
957 return self.sslconn.read()
958 else:
959 return self.sock.recv(1024)
960
961 def write(self, bytes):
962 if self.sslconn:
963 return self.sslconn.write(bytes)
964 else:
965 return self.sock.send(bytes)
966
967 def close(self):
968 if self.sslconn:
969 self.sslconn.close()
970 else:
971 self.sock.close()
972
Antoine Pitrou480a1242010-04-28 21:37:09 +0000973 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000974 self.running = True
975 if not self.server.starttls_server:
976 if not self.wrap_conn():
977 return
978 while self.running:
979 try:
980 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000981 stripped = msg.strip()
982 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000983 # eof, so quit this handler
984 self.running = False
985 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000986 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000987 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000988 sys.stdout.write(" server: client closed connection\n")
989 self.close()
990 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000991 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000992 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000993 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000994 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000995 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000996 if not self.wrap_conn():
997 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000998 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000999 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001000 if support.verbose and self.server.connectionchatty:
1001 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001002 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001003 self.sock = self.sslconn.unwrap()
1004 self.sslconn = None
1005 if support.verbose and self.server.connectionchatty:
1006 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001007 elif stripped == b'CB tls-unique':
1008 if support.verbose and self.server.connectionchatty:
1009 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1010 data = self.sslconn.get_channel_binding("tls-unique")
1011 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001012 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001013 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014 self.server.connectionchatty):
1015 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001016 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1017 % (msg, ctype, msg.lower(), ctype))
1018 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001019 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001020 if self.server.chatty:
1021 handle_error("Test server failure:\n")
1022 self.close()
1023 self.running = False
1024 # normally, we'd just stop here, but for the test
1025 # harness, we want to stop the server
1026 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027
Antoine Pitroub5218772010-05-21 09:56:06 +00001028 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001029 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001030 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001031 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001032 if context:
1033 self.context = context
1034 else:
1035 self.context = ssl.SSLContext(ssl_version
1036 if ssl_version is not None
1037 else ssl.PROTOCOL_TLSv1)
1038 self.context.verify_mode = (certreqs if certreqs is not None
1039 else ssl.CERT_NONE)
1040 if cacerts:
1041 self.context.load_verify_locations(cacerts)
1042 if certificate:
1043 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001044 if npn_protocols:
1045 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001046 if ciphers:
1047 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001048 self.chatty = chatty
1049 self.connectionchatty = connectionchatty
1050 self.starttls_server = starttls_server
1051 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001052 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001053 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001054 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001055 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001056 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001057 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001058 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001059
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001060 def __enter__(self):
1061 self.start(threading.Event())
1062 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001063 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001064
1065 def __exit__(self, *args):
1066 self.stop()
1067 self.join()
1068
Antoine Pitrou480a1242010-04-28 21:37:09 +00001069 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001070 self.flag = flag
1071 threading.Thread.start(self)
1072
Antoine Pitrou480a1242010-04-28 21:37:09 +00001073 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001074 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001075 self.sock.listen(5)
1076 self.active = True
1077 if self.flag:
1078 # signal an event
1079 self.flag.set()
1080 while self.active:
1081 try:
1082 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001083 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001084 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001085 + repr(connaddr) + '\n')
1086 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001087 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001088 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001089 except socket.timeout:
1090 pass
1091 except KeyboardInterrupt:
1092 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001093 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001094
Antoine Pitrou480a1242010-04-28 21:37:09 +00001095 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001096 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001097
Bill Janssen54cc54c2007-12-14 22:08:56 +00001098 class AsyncoreEchoServer(threading.Thread):
1099
1100 # this one's based on asyncore.dispatcher
1101
1102 class EchoServer (asyncore.dispatcher):
1103
1104 class ConnectionHandler (asyncore.dispatcher_with_send):
1105
1106 def __init__(self, conn, certfile):
1107 self.socket = ssl.wrap_socket(conn, server_side=True,
1108 certfile=certfile,
1109 do_handshake_on_connect=False)
1110 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001111 self._ssl_accepting = True
1112 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001113
1114 def readable(self):
1115 if isinstance(self.socket, ssl.SSLSocket):
1116 while self.socket.pending() > 0:
1117 self.handle_read_event()
1118 return True
1119
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001120 def _do_ssl_handshake(self):
1121 try:
1122 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001123 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1124 return
1125 except ssl.SSLEOFError:
1126 return self.handle_close()
1127 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001128 raise
1129 except socket.error as err:
1130 if err.args[0] == errno.ECONNABORTED:
1131 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001132 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001133 self._ssl_accepting = False
1134
1135 def handle_read(self):
1136 if self._ssl_accepting:
1137 self._do_ssl_handshake()
1138 else:
1139 data = self.recv(1024)
1140 if support.verbose:
1141 sys.stdout.write(" server: read %s from client\n" % repr(data))
1142 if not data:
1143 self.close()
1144 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001146
1147 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001148 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001149 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001150 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1151
1152 def handle_error(self):
1153 raise
1154
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001155 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001156 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001157 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1158 self.port = support.bind_port(sock, '')
1159 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001160 self.listen(5)
1161
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001162 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001163 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001164 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1165 self.ConnectionHandler(sock_obj, self.certfile)
1166
1167 def handle_error(self):
1168 raise
1169
Trent Nelson78520002008-04-10 20:54:35 +00001170 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001171 self.flag = None
1172 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001173 self.server = self.EchoServer(certfile)
1174 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001175 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001176 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001177
1178 def __str__(self):
1179 return "<%s %s>" % (self.__class__.__name__, self.server)
1180
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001181 def __enter__(self):
1182 self.start(threading.Event())
1183 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001184 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001185
1186 def __exit__(self, *args):
1187 if support.verbose:
1188 sys.stdout.write(" cleanup: stopping server.\n")
1189 self.stop()
1190 if support.verbose:
1191 sys.stdout.write(" cleanup: joining server thread.\n")
1192 self.join()
1193 if support.verbose:
1194 sys.stdout.write(" cleanup: successfully joined.\n")
1195
Bill Janssen54cc54c2007-12-14 22:08:56 +00001196 def start (self, flag=None):
1197 self.flag = flag
1198 threading.Thread.start(self)
1199
Antoine Pitrou480a1242010-04-28 21:37:09 +00001200 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001201 self.active = True
1202 if self.flag:
1203 self.flag.set()
1204 while self.active:
1205 try:
1206 asyncore.loop(1)
1207 except:
1208 pass
1209
Antoine Pitrou480a1242010-04-28 21:37:09 +00001210 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001211 self.active = False
1212 self.server.close()
1213
Antoine Pitrou480a1242010-04-28 21:37:09 +00001214 def bad_cert_test(certfile):
1215 """
1216 Launch a server with CERT_REQUIRED, and check that trying to
1217 connect to it with the given client certificate fails.
1218 """
Trent Nelson78520002008-04-10 20:54:35 +00001219 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001220 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001221 cacerts=CERTFILE, chatty=False,
1222 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001223 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001224 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001225 with socket.socket() as sock:
1226 s = ssl.wrap_socket(sock,
1227 certfile=certfile,
1228 ssl_version=ssl.PROTOCOL_TLSv1)
1229 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001230 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001231 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001232 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001233 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001234 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001235 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001236 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001237 if x.errno != errno.ENOENT:
1238 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001239 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001240 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001242 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001243
Antoine Pitroub5218772010-05-21 09:56:06 +00001244 def server_params_test(client_context, server_context, indata=b"FOO\n",
1245 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001246 """
1247 Launch a server, connect a client to it and try various reads
1248 and writes.
1249 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001250 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001251 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001252 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001253 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001254 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001255 with client_context.wrap_socket(socket.socket()) as s:
1256 s.connect((HOST, server.port))
1257 for arg in [indata, bytearray(indata), memoryview(indata)]:
1258 if connectionchatty:
1259 if support.verbose:
1260 sys.stdout.write(
1261 " client: sending %r...\n" % indata)
1262 s.write(arg)
1263 outdata = s.read()
1264 if connectionchatty:
1265 if support.verbose:
1266 sys.stdout.write(" client: read %r\n" % outdata)
1267 if outdata != indata.lower():
1268 raise AssertionError(
1269 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1270 % (outdata[:20], len(outdata),
1271 indata[:20].lower(), len(indata)))
1272 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001273 if connectionchatty:
1274 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001275 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001276 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001277 'compression': s.compression(),
1278 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001279 'client_npn_protocol': s.selected_npn_protocol()
1280 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001281 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001282 stats['server_npn_protocols'] = server.selected_protocols
1283 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001284
Antoine Pitroub5218772010-05-21 09:56:06 +00001285 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1286 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001287 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001288 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001289 certtype = {
1290 ssl.CERT_NONE: "CERT_NONE",
1291 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1292 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1293 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001294 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001295 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001296 sys.stdout.write(formatstr %
1297 (ssl.get_protocol_name(client_protocol),
1298 ssl.get_protocol_name(server_protocol),
1299 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001300 client_context = ssl.SSLContext(client_protocol)
1301 client_context.options = ssl.OP_ALL | client_options
1302 server_context = ssl.SSLContext(server_protocol)
1303 server_context.options = ssl.OP_ALL | server_options
1304 for ctx in (client_context, server_context):
1305 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001306 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1307 # will send an SSLv3 hello (rather than SSLv2) starting from
1308 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001309 ctx.set_ciphers("ALL")
1310 ctx.load_cert_chain(CERTFILE)
1311 ctx.load_verify_locations(CERTFILE)
1312 try:
1313 server_params_test(client_context, server_context,
1314 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001315 # Protocol mismatch can result in either an SSLError, or a
1316 # "Connection reset by peer" error.
1317 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001318 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001319 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001320 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001321 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001322 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001323 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001324 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001325 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001326 "Client protocol %s succeeded with server protocol %s!"
1327 % (ssl.get_protocol_name(client_protocol),
1328 ssl.get_protocol_name(server_protocol)))
1329
1330
Bill Janssen6e027db2007-11-15 22:23:56 +00001331 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001332
Antoine Pitrou23df4832010-08-04 17:14:06 +00001333 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001334 def test_echo(self):
1335 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001336 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001337 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001338 for protocol in PROTOCOLS:
1339 context = ssl.SSLContext(protocol)
1340 context.load_cert_chain(CERTFILE)
1341 server_params_test(context, context,
1342 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001343
Antoine Pitrou480a1242010-04-28 21:37:09 +00001344 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001345 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001346 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001347 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1348 context.verify_mode = ssl.CERT_REQUIRED
1349 context.load_verify_locations(CERTFILE)
1350 context.load_cert_chain(CERTFILE)
1351 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001352 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001353 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001354 s.connect((HOST, server.port))
1355 cert = s.getpeercert()
1356 self.assertTrue(cert, "Can't get peer certificate.")
1357 cipher = s.cipher()
1358 if support.verbose:
1359 sys.stdout.write(pprint.pformat(cert) + '\n')
1360 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1361 if 'subject' not in cert:
1362 self.fail("No subject field in certificate: %s." %
1363 pprint.pformat(cert))
1364 if ((('organizationName', 'Python Software Foundation'),)
1365 not in cert['subject']):
1366 self.fail(
1367 "Missing or invalid 'organizationName' field in certificate subject; "
1368 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001369 self.assertIn('notBefore', cert)
1370 self.assertIn('notAfter', cert)
1371 before = ssl.cert_time_to_seconds(cert['notBefore'])
1372 after = ssl.cert_time_to_seconds(cert['notAfter'])
1373 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001374 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001375
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 def test_empty_cert(self):
1377 """Connecting with an empty cert file"""
1378 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1379 "nullcert.pem"))
1380 def test_malformed_cert(self):
1381 """Connecting with a badly formatted certificate (syntax error)"""
1382 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1383 "badcert.pem"))
1384 def test_nonexisting_cert(self):
1385 """Connecting with a non-existing cert file"""
1386 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1387 "wrongcert.pem"))
1388 def test_malformed_key(self):
1389 """Connecting with a badly formatted key (syntax error)"""
1390 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1391 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001392
Antoine Pitrou480a1242010-04-28 21:37:09 +00001393 def test_rude_shutdown(self):
1394 """A brutal shutdown of an SSL server should raise an IOError
1395 in the client when attempting handshake.
1396 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001397 listener_ready = threading.Event()
1398 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001399
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001400 s = socket.socket()
1401 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001402
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001403 # `listener` runs in a thread. It sits in an accept() until
1404 # the main thread connects. Then it rudely closes the socket,
1405 # and sets Event `listener_gone` to let the main thread know
1406 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001407 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001408 s.listen(5)
1409 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001410 newsock, addr = s.accept()
1411 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001412 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001413 listener_gone.set()
1414
1415 def connector():
1416 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001417 with socket.socket() as c:
1418 c.connect((HOST, port))
1419 listener_gone.wait()
1420 try:
1421 ssl_sock = ssl.wrap_socket(c)
1422 except IOError:
1423 pass
1424 else:
1425 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001426
1427 t = threading.Thread(target=listener)
1428 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001429 try:
1430 connector()
1431 finally:
1432 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001433
Antoine Pitrou23df4832010-08-04 17:14:06 +00001434 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001435 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1436 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 def test_protocol_sslv2(self):
1438 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001439 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001440 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001441 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1442 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1443 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1444 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1445 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1446 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001447 # SSLv23 client with specific SSL options
1448 if no_sslv2_implies_sslv3_hello():
1449 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1450 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1451 client_options=ssl.OP_NO_SSLv2)
1452 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1453 client_options=ssl.OP_NO_SSLv3)
1454 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1455 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001456
Antoine Pitrou23df4832010-08-04 17:14:06 +00001457 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001458 def test_protocol_sslv23(self):
1459 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001460 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001461 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001462 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1463 try:
1464 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1465 except (ssl.SSLError, socket.error) as x:
1466 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1467 if support.verbose:
1468 sys.stdout.write(
1469 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1470 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001471 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1472 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1473 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001474
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1476 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1477 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478
Antoine Pitrou480a1242010-04-28 21:37:09 +00001479 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1480 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1481 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001482
Antoine Pitroub5218772010-05-21 09:56:06 +00001483 # Server with specific SSL options
1484 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1485 server_options=ssl.OP_NO_SSLv3)
1486 # Will choose TLSv1
1487 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1488 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1489 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1490 server_options=ssl.OP_NO_TLSv1)
1491
1492
Antoine Pitrou23df4832010-08-04 17:14:06 +00001493 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001494 def test_protocol_sslv3(self):
1495 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001496 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001497 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001498 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1499 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1500 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001501 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1502 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001503 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1504 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001505 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001506 if no_sslv2_implies_sslv3_hello():
1507 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1508 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1509 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001510
Antoine Pitrou23df4832010-08-04 17:14:06 +00001511 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001512 def test_protocol_tlsv1(self):
1513 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001514 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001515 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001516 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1517 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1518 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001519 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1520 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001521 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001522 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1523 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001524
Antoine Pitrou480a1242010-04-28 21:37:09 +00001525 def test_starttls(self):
1526 """Switching from clear text to encrypted and back again."""
1527 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 +00001528
Trent Nelson78520002008-04-10 20:54:35 +00001529 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530 ssl_version=ssl.PROTOCOL_TLSv1,
1531 starttls_server=True,
1532 chatty=True,
1533 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001534 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001535 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001536 s = socket.socket()
1537 s.setblocking(1)
1538 s.connect((HOST, server.port))
1539 if support.verbose:
1540 sys.stdout.write("\n")
1541 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001542 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001543 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001544 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001545 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001546 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001547 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001548 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001549 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001550 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001551 msg = outdata.strip().lower()
1552 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1553 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001554 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001555 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001556 " client: read %r from server, starting TLS...\n"
1557 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001558 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1559 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001560 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1561 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001562 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001563 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001564 " client: read %r from server, ending TLS...\n"
1565 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001566 s = conn.unwrap()
1567 wrapped = False
1568 else:
1569 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001570 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001572 if support.verbose:
1573 sys.stdout.write(" client: closing connection.\n")
1574 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001575 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001576 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001577 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001578 if wrapped:
1579 conn.close()
1580 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001581 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001582
Antoine Pitrou480a1242010-04-28 21:37:09 +00001583 def test_socketserver(self):
1584 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001585 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001586 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001587 if support.verbose:
1588 sys.stdout.write('\n')
1589 with open(CERTFILE, 'rb') as f:
1590 d1 = f.read()
1591 d2 = ''
1592 # now fetch the same data from the HTTPS server
1593 url = 'https://%s:%d/%s' % (
1594 HOST, server.port, os.path.split(CERTFILE)[1])
1595 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001596 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001597 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001598 if dlen and (int(dlen) > 0):
1599 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001600 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001601 sys.stdout.write(
1602 " client: read %d bytes from remote server '%s'\n"
1603 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001604 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001605 f.close()
1606 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001607
Antoine Pitrou480a1242010-04-28 21:37:09 +00001608 def test_asyncore_server(self):
1609 """Check the example asyncore integration."""
1610 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001611
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001612 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001613 sys.stdout.write("\n")
1614
Antoine Pitrou480a1242010-04-28 21:37:09 +00001615 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001616 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001617 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001618 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001619 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001620 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001621 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001622 " client: sending %r...\n" % indata)
1623 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001624 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001625 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001626 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001627 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001628 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001629 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1630 % (outdata[:20], len(outdata),
1631 indata[:20].lower(), len(indata)))
1632 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001633 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001634 sys.stdout.write(" client: closing connection.\n")
1635 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001636 if support.verbose:
1637 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001638
Antoine Pitrou480a1242010-04-28 21:37:09 +00001639 def test_recv_send(self):
1640 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001641 if support.verbose:
1642 sys.stdout.write("\n")
1643
1644 server = ThreadedEchoServer(CERTFILE,
1645 certreqs=ssl.CERT_NONE,
1646 ssl_version=ssl.PROTOCOL_TLSv1,
1647 cacerts=CERTFILE,
1648 chatty=True,
1649 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001650 with server:
1651 s = ssl.wrap_socket(socket.socket(),
1652 server_side=False,
1653 certfile=CERTFILE,
1654 ca_certs=CERTFILE,
1655 cert_reqs=ssl.CERT_NONE,
1656 ssl_version=ssl.PROTOCOL_TLSv1)
1657 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001658 # helper methods for standardising recv* method signatures
1659 def _recv_into():
1660 b = bytearray(b"\0"*100)
1661 count = s.recv_into(b)
1662 return b[:count]
1663
1664 def _recvfrom_into():
1665 b = bytearray(b"\0"*100)
1666 count, addr = s.recvfrom_into(b)
1667 return b[:count]
1668
1669 # (name, method, whether to expect success, *args)
1670 send_methods = [
1671 ('send', s.send, True, []),
1672 ('sendto', s.sendto, False, ["some.address"]),
1673 ('sendall', s.sendall, True, []),
1674 ]
1675 recv_methods = [
1676 ('recv', s.recv, True, []),
1677 ('recvfrom', s.recvfrom, False, ["some.address"]),
1678 ('recv_into', _recv_into, True, []),
1679 ('recvfrom_into', _recvfrom_into, False, []),
1680 ]
1681 data_prefix = "PREFIX_"
1682
1683 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001684 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001685 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001686 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001687 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001688 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001689 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001690 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001691 "<<{outdata:r}>> ({nout:d}) received; "
1692 "expected <<{indata:r}>> ({nin:d})\n".format(
1693 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001694 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001695 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001696 )
1697 )
1698 except ValueError as e:
1699 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001700 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001701 "Failed to send with method <<{name:s}>>; "
1702 "expected to succeed.\n".format(name=meth_name)
1703 )
1704 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001705 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001706 "Method <<{name:s}>> failed with unexpected "
1707 "exception message: {exp:s}\n".format(
1708 name=meth_name, exp=e
1709 )
1710 )
1711
1712 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001713 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001714 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001715 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001716 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001717 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001718 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001719 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001720 "<<{outdata:r}>> ({nout:d}) received; "
1721 "expected <<{indata:r}>> ({nin:d})\n".format(
1722 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001723 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001724 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001725 )
1726 )
1727 except ValueError as e:
1728 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001729 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001730 "Failed to receive with method <<{name:s}>>; "
1731 "expected to succeed.\n".format(name=meth_name)
1732 )
1733 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001734 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001735 "Method <<{name:s}>> failed with unexpected "
1736 "exception message: {exp:s}\n".format(
1737 name=meth_name, exp=e
1738 )
1739 )
1740 # consume data
1741 s.read()
1742
Nick Coghlan513886a2011-08-28 00:00:27 +10001743 # Make sure sendmsg et al are disallowed to avoid
1744 # inadvertent disclosure of data and/or corruption
1745 # of the encrypted data stream
1746 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1747 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1748 self.assertRaises(NotImplementedError,
1749 s.recvmsg_into, bytearray(100))
1750
Antoine Pitrou480a1242010-04-28 21:37:09 +00001751 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001752 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001753
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001754 def test_handshake_timeout(self):
1755 # Issue #5103: SSL handshake must respect the socket timeout
1756 server = socket.socket(socket.AF_INET)
1757 host = "127.0.0.1"
1758 port = support.bind_port(server)
1759 started = threading.Event()
1760 finish = False
1761
1762 def serve():
1763 server.listen(5)
1764 started.set()
1765 conns = []
1766 while not finish:
1767 r, w, e = select.select([server], [], [], 0.1)
1768 if server in r:
1769 # Let the socket hang around rather than having
1770 # it closed by garbage collection.
1771 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001772 for sock in conns:
1773 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001774
1775 t = threading.Thread(target=serve)
1776 t.start()
1777 started.wait()
1778
1779 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001780 try:
1781 c = socket.socket(socket.AF_INET)
1782 c.settimeout(0.2)
1783 c.connect((host, port))
1784 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001785 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001786 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001787 finally:
1788 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001789 try:
1790 c = socket.socket(socket.AF_INET)
1791 c = ssl.wrap_socket(c)
1792 c.settimeout(0.2)
1793 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001794 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001795 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001796 finally:
1797 c.close()
1798 finally:
1799 finish = True
1800 t.join()
1801 server.close()
1802
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001803 def test_default_ciphers(self):
1804 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1805 try:
1806 # Force a set of weak ciphers on our client context
1807 context.set_ciphers("DES")
1808 except ssl.SSLError:
1809 self.skipTest("no DES cipher available")
1810 with ThreadedEchoServer(CERTFILE,
1811 ssl_version=ssl.PROTOCOL_SSLv23,
1812 chatty=False) as server:
1813 with socket.socket() as sock:
1814 s = context.wrap_socket(sock)
1815 with self.assertRaises((OSError, ssl.SSLError)):
1816 s.connect((HOST, server.port))
1817 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1818
Antoine Pitroud6494802011-07-21 01:11:30 +02001819 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1820 "'tls-unique' channel binding not available")
1821 def test_tls_unique_channel_binding(self):
1822 """Test tls-unique channel binding."""
1823 if support.verbose:
1824 sys.stdout.write("\n")
1825
1826 server = ThreadedEchoServer(CERTFILE,
1827 certreqs=ssl.CERT_NONE,
1828 ssl_version=ssl.PROTOCOL_TLSv1,
1829 cacerts=CERTFILE,
1830 chatty=True,
1831 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001832 with server:
1833 s = ssl.wrap_socket(socket.socket(),
1834 server_side=False,
1835 certfile=CERTFILE,
1836 ca_certs=CERTFILE,
1837 cert_reqs=ssl.CERT_NONE,
1838 ssl_version=ssl.PROTOCOL_TLSv1)
1839 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001840 # get the data
1841 cb_data = s.get_channel_binding("tls-unique")
1842 if support.verbose:
1843 sys.stdout.write(" got channel binding data: {0!r}\n"
1844 .format(cb_data))
1845
1846 # check if it is sane
1847 self.assertIsNotNone(cb_data)
1848 self.assertEqual(len(cb_data), 12) # True for TLSv1
1849
1850 # and compare with the peers version
1851 s.write(b"CB tls-unique\n")
1852 peer_data_repr = s.read().strip()
1853 self.assertEqual(peer_data_repr,
1854 repr(cb_data).encode("us-ascii"))
1855 s.close()
1856
1857 # now, again
1858 s = ssl.wrap_socket(socket.socket(),
1859 server_side=False,
1860 certfile=CERTFILE,
1861 ca_certs=CERTFILE,
1862 cert_reqs=ssl.CERT_NONE,
1863 ssl_version=ssl.PROTOCOL_TLSv1)
1864 s.connect((HOST, server.port))
1865 new_cb_data = s.get_channel_binding("tls-unique")
1866 if support.verbose:
1867 sys.stdout.write(" got another channel binding data: {0!r}\n"
1868 .format(new_cb_data))
1869 # is it really unique
1870 self.assertNotEqual(cb_data, new_cb_data)
1871 self.assertIsNotNone(cb_data)
1872 self.assertEqual(len(cb_data), 12) # True for TLSv1
1873 s.write(b"CB tls-unique\n")
1874 peer_data_repr = s.read().strip()
1875 self.assertEqual(peer_data_repr,
1876 repr(new_cb_data).encode("us-ascii"))
1877 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001878
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001879 def test_compression(self):
1880 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1881 context.load_cert_chain(CERTFILE)
1882 stats = server_params_test(context, context,
1883 chatty=True, connectionchatty=True)
1884 if support.verbose:
1885 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1886 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1887
1888 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1889 "ssl.OP_NO_COMPRESSION needed for this test")
1890 def test_compression_disabled(self):
1891 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1892 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001893 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001894 stats = server_params_test(context, context,
1895 chatty=True, connectionchatty=True)
1896 self.assertIs(stats['compression'], None)
1897
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001898 def test_dh_params(self):
1899 # Check we can get a connection with ephemeral Diffie-Hellman
1900 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1901 context.load_cert_chain(CERTFILE)
1902 context.load_dh_params(DHFILE)
1903 context.set_ciphers("kEDH")
1904 stats = server_params_test(context, context,
1905 chatty=True, connectionchatty=True)
1906 cipher = stats["cipher"][0]
1907 parts = cipher.split("-")
1908 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1909 self.fail("Non-DH cipher: " + cipher[0])
1910
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001911 def test_selected_npn_protocol(self):
1912 # selected_npn_protocol() is None unless NPN is used
1913 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1914 context.load_cert_chain(CERTFILE)
1915 stats = server_params_test(context, context,
1916 chatty=True, connectionchatty=True)
1917 self.assertIs(stats['client_npn_protocol'], None)
1918
1919 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1920 def test_npn_protocols(self):
1921 server_protocols = ['http/1.1', 'spdy/2']
1922 protocol_tests = [
1923 (['http/1.1', 'spdy/2'], 'http/1.1'),
1924 (['spdy/2', 'http/1.1'], 'http/1.1'),
1925 (['spdy/2', 'test'], 'spdy/2'),
1926 (['abc', 'def'], 'abc')
1927 ]
1928 for client_protocols, expected in protocol_tests:
1929 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1930 server_context.load_cert_chain(CERTFILE)
1931 server_context.set_npn_protocols(server_protocols)
1932 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1933 client_context.load_cert_chain(CERTFILE)
1934 client_context.set_npn_protocols(client_protocols)
1935 stats = server_params_test(client_context, server_context,
1936 chatty=True, connectionchatty=True)
1937
1938 msg = "failed trying %s (s) and %s (c).\n" \
1939 "was expecting %s, but got %%s from the %%s" \
1940 % (str(server_protocols), str(client_protocols),
1941 str(expected))
1942 client_result = stats['client_npn_protocol']
1943 self.assertEqual(client_result, expected, msg % (client_result, "client"))
1944 server_result = stats['server_npn_protocols'][-1] \
1945 if len(stats['server_npn_protocols']) else 'nothing'
1946 self.assertEqual(server_result, expected, msg % (server_result, "server"))
1947
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001948
Thomas Woutersed03b412007-08-28 21:37:11 +00001949def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001950 if support.verbose:
1951 plats = {
1952 'Linux': platform.linux_distribution,
1953 'Mac': platform.mac_ver,
1954 'Windows': platform.win32_ver,
1955 }
1956 for name, func in plats.items():
1957 plat = func()
1958 if plat and plat[0]:
1959 plat = '%s %r' % (name, plat)
1960 break
1961 else:
1962 plat = repr(platform.platform())
1963 print("test_ssl: testing with %r %r" %
1964 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1965 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001966 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001967
Antoine Pitrou152efa22010-05-16 18:19:27 +00001968 for filename in [
1969 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1970 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1971 BADCERT, BADKEY, EMPTYCERT]:
1972 if not os.path.exists(filename):
1973 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001974
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001975 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001976
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001977 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001978 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001979
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001980 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001981 thread_info = support.threading_setup()
1982 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001983 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001984
Antoine Pitrou480a1242010-04-28 21:37:09 +00001985 try:
1986 support.run_unittest(*tests)
1987 finally:
1988 if _have_threads:
1989 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001990
1991if __name__ == "__main__":
1992 test_main()