blob: 505550f269fe1cc8790f49883211bc31a8aa097e [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
23PROTOCOLS = [
Victor Stinner3de49192011-05-09 00:42:58 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner3de49192011-05-09 00:42:58 +020027if hasattr(ssl, 'PROTOCOL_SSLv2'):
28 PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
Thomas Woutersed03b412007-08-28 21:37:11 +000029
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Antoine Pitrou81564092010-10-08 23:06:24 +000034# The custom key and certificate files used in test_ssl are generated
35# using Lib/test/make_ssl_certs.py.
36# Other certificates are simply fetched from the Internet servers they
37# are meant to authenticate.
38
Antoine Pitrou152efa22010-05-16 18:19:27 +000039CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020045CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
46ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
47KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000048CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000049BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
52
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020057NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000058
Thomas Woutersed03b412007-08-28 21:37:11 +000059
Thomas Woutersed03b412007-08-28 21:37:11 +000060def handle_error(prefix):
61 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000062 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000063 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000064
Antoine Pitroub5218772010-05-21 09:56:06 +000065def can_clear_options():
66 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020067 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000068
69def no_sslv2_implies_sslv3_hello():
70 # 0.9.7h or higher
71 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
72
Thomas Woutersed03b412007-08-28 21:37:11 +000073
Antoine Pitrou23df4832010-08-04 17:14:06 +000074# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
75def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020076 if hasattr(ssl, 'PROTOCOL_SSLv2'):
77 @functools.wraps(func)
78 def f(*args, **kwargs):
79 try:
80 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
81 except ssl.SSLError:
82 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
83 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
84 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
85 return func(*args, **kwargs)
86 return f
87 else:
88 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000089
90
Antoine Pitrou152efa22010-05-16 18:19:27 +000091class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000092
Antoine Pitrou480a1242010-04-28 21:37:09 +000093 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020094 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000095 ssl.PROTOCOL_SSLv23
96 ssl.PROTOCOL_SSLv3
97 ssl.PROTOCOL_TLSv1
98 ssl.CERT_NONE
99 ssl.CERT_OPTIONAL
100 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100101 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100102 ssl.OP_SINGLE_ECDH_USE
Antoine Pitroud5323212010-10-22 18:19:07 +0000103 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000104
Antoine Pitrou480a1242010-04-28 21:37:09 +0000105 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000107 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000108 sys.stdout.write("\n RAND_status is %d (%s)\n"
109 % (v, (v and "sufficient randomness") or
110 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200111
112 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
113 self.assertEqual(len(data), 16)
114 self.assertEqual(is_cryptographic, v == 1)
115 if v:
116 data = ssl.RAND_bytes(16)
117 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200118 else:
119 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200120
Thomas Woutersed03b412007-08-28 21:37:11 +0000121 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000122 ssl.RAND_egd(1)
123 except TypeError:
124 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000125 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000126 print("didn't raise TypeError")
127 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000128
Antoine Pitrou480a1242010-04-28 21:37:09 +0000129 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000130 # note that this uses an 'unofficial' function in _ssl.c,
131 # provided solely for this test, to exercise the certificate
132 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000133 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000134 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000135 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200136 self.assertEqual(p['issuer'],
137 ((('countryName', 'XY'),),
138 (('localityName', 'Castle Anthrax'),),
139 (('organizationName', 'Python Software Foundation'),),
140 (('commonName', 'localhost'),))
141 )
142 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
143 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
144 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
145 self.assertEqual(p['subject'],
146 ((('countryName', 'XY'),),
147 (('localityName', 'Castle Anthrax'),),
148 (('organizationName', 'Python Software Foundation'),),
149 (('commonName', 'localhost'),))
150 )
151 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
152 # Issue #13034: the subjectAltName in some certificates
153 # (notably projects.developer.nokia.com:443) wasn't parsed
154 p = ssl._ssl._test_decode_cert(NOKIACERT)
155 if support.verbose:
156 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
157 self.assertEqual(p['subjectAltName'],
158 (('DNS', 'projects.developer.nokia.com'),
159 ('DNS', 'projects.forum.nokia.com'))
160 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000161
Antoine Pitrou480a1242010-04-28 21:37:09 +0000162 def test_DER_to_PEM(self):
163 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
164 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000165 d1 = ssl.PEM_cert_to_DER_cert(pem)
166 p2 = ssl.DER_cert_to_PEM_cert(d1)
167 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000168 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000169 if not p2.startswith(ssl.PEM_HEADER + '\n'):
170 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
171 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
172 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000173
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000174 def test_openssl_version(self):
175 n = ssl.OPENSSL_VERSION_NUMBER
176 t = ssl.OPENSSL_VERSION_INFO
177 s = ssl.OPENSSL_VERSION
178 self.assertIsInstance(n, int)
179 self.assertIsInstance(t, tuple)
180 self.assertIsInstance(s, str)
181 # Some sanity checks follow
182 # >= 0.9
183 self.assertGreaterEqual(n, 0x900000)
184 # < 2.0
185 self.assertLess(n, 0x20000000)
186 major, minor, fix, patch, status = t
187 self.assertGreaterEqual(major, 0)
188 self.assertLess(major, 2)
189 self.assertGreaterEqual(minor, 0)
190 self.assertLess(minor, 256)
191 self.assertGreaterEqual(fix, 0)
192 self.assertLess(fix, 256)
193 self.assertGreaterEqual(patch, 0)
194 self.assertLessEqual(patch, 26)
195 self.assertGreaterEqual(status, 0)
196 self.assertLessEqual(status, 15)
197 # Version string as returned by OpenSSL, the format might change
198 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
199 (s, t))
200
Antoine Pitrou9d543662010-04-23 23:10:32 +0000201 @support.cpython_only
202 def test_refcycle(self):
203 # Issue #7943: an SSL object doesn't create reference cycles with
204 # itself.
205 s = socket.socket(socket.AF_INET)
206 ss = ssl.wrap_socket(s)
207 wr = weakref.ref(ss)
208 del ss
209 self.assertEqual(wr(), None)
210
Antoine Pitroua468adc2010-09-14 14:43:44 +0000211 def test_wrapped_unconnected(self):
212 # Methods on an unconnected SSLSocket propagate the original
213 # socket.error raise by the underlying socket object.
214 s = socket.socket(socket.AF_INET)
215 ss = ssl.wrap_socket(s)
216 self.assertRaises(socket.error, ss.recv, 1)
217 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
218 self.assertRaises(socket.error, ss.recvfrom, 1)
219 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
220 self.assertRaises(socket.error, ss.send, b'x')
221 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
222
Antoine Pitrou40f08742010-04-24 22:04:40 +0000223 def test_timeout(self):
224 # Issue #8524: when creating an SSL socket, the timeout of the
225 # original socket should be retained.
226 for timeout in (None, 0.0, 5.0):
227 s = socket.socket(socket.AF_INET)
228 s.settimeout(timeout)
229 ss = ssl.wrap_socket(s)
230 self.assertEqual(timeout, ss.gettimeout())
231
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000232 def test_errors(self):
233 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000234 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000235 "certfile must be specified",
236 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000237 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000238 "certfile must be specified for server-side operations",
239 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000240 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000241 "certfile must be specified for server-side operations",
242 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000243 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000244 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000245 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000246 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000247 with socket.socket() as sock:
248 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000249 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000250 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000251 with socket.socket() as sock:
252 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000253 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000254 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000255 with socket.socket() as sock:
256 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000257 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000258
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000259 def test_match_hostname(self):
260 def ok(cert, hostname):
261 ssl.match_hostname(cert, hostname)
262 def fail(cert, hostname):
263 self.assertRaises(ssl.CertificateError,
264 ssl.match_hostname, cert, hostname)
265
266 cert = {'subject': ((('commonName', 'example.com'),),)}
267 ok(cert, 'example.com')
268 ok(cert, 'ExAmple.cOm')
269 fail(cert, 'www.example.com')
270 fail(cert, '.example.com')
271 fail(cert, 'example.org')
272 fail(cert, 'exampleXcom')
273
274 cert = {'subject': ((('commonName', '*.a.com'),),)}
275 ok(cert, 'foo.a.com')
276 fail(cert, 'bar.foo.a.com')
277 fail(cert, 'a.com')
278 fail(cert, 'Xa.com')
279 fail(cert, '.a.com')
280
281 cert = {'subject': ((('commonName', 'a.*.com'),),)}
282 ok(cert, 'a.foo.com')
283 fail(cert, 'a..com')
284 fail(cert, 'a.com')
285
286 cert = {'subject': ((('commonName', 'f*.com'),),)}
287 ok(cert, 'foo.com')
288 ok(cert, 'f.com')
289 fail(cert, 'bar.com')
290 fail(cert, 'foo.a.com')
291 fail(cert, 'bar.foo.com')
292
293 # Slightly fake real-world example
294 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
295 'subject': ((('commonName', 'linuxfrz.org'),),),
296 'subjectAltName': (('DNS', 'linuxfr.org'),
297 ('DNS', 'linuxfr.com'),
298 ('othername', '<unsupported>'))}
299 ok(cert, 'linuxfr.org')
300 ok(cert, 'linuxfr.com')
301 # Not a "DNS" entry
302 fail(cert, '<unsupported>')
303 # When there is a subjectAltName, commonName isn't used
304 fail(cert, 'linuxfrz.org')
305
306 # A pristine real-world example
307 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
308 'subject': ((('countryName', 'US'),),
309 (('stateOrProvinceName', 'California'),),
310 (('localityName', 'Mountain View'),),
311 (('organizationName', 'Google Inc'),),
312 (('commonName', 'mail.google.com'),))}
313 ok(cert, 'mail.google.com')
314 fail(cert, 'gmail.com')
315 # Only commonName is considered
316 fail(cert, 'California')
317
318 # Neither commonName nor subjectAltName
319 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
320 'subject': ((('countryName', 'US'),),
321 (('stateOrProvinceName', 'California'),),
322 (('localityName', 'Mountain View'),),
323 (('organizationName', 'Google Inc'),))}
324 fail(cert, 'mail.google.com')
325
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200326 # No DNS entry in subjectAltName but a commonName
327 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
328 'subject': ((('countryName', 'US'),),
329 (('stateOrProvinceName', 'California'),),
330 (('localityName', 'Mountain View'),),
331 (('commonName', 'mail.google.com'),)),
332 'subjectAltName': (('othername', 'blabla'), )}
333 ok(cert, 'mail.google.com')
334
335 # No DNS entry subjectAltName and no commonName
336 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
337 'subject': ((('countryName', 'US'),),
338 (('stateOrProvinceName', 'California'),),
339 (('localityName', 'Mountain View'),),
340 (('organizationName', 'Google Inc'),)),
341 'subjectAltName': (('othername', 'blabla'),)}
342 fail(cert, 'google.com')
343
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000344 # Empty cert / no cert
345 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
346 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
347
Antoine Pitroud5323212010-10-22 18:19:07 +0000348 def test_server_side(self):
349 # server_hostname doesn't work for server sockets
350 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000351 with socket.socket() as sock:
352 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
353 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000354
Antoine Pitroud6494802011-07-21 01:11:30 +0200355 def test_unknown_channel_binding(self):
356 # should raise ValueError for unknown type
357 s = socket.socket(socket.AF_INET)
358 ss = ssl.wrap_socket(s)
359 with self.assertRaises(ValueError):
360 ss.get_channel_binding("unknown-type")
361
362 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
363 "'tls-unique' channel binding not available")
364 def test_tls_unique_channel_binding(self):
365 # unconnected should return None for known type
366 s = socket.socket(socket.AF_INET)
367 ss = ssl.wrap_socket(s)
368 self.assertIsNone(ss.get_channel_binding("tls-unique"))
369 # the same for server-side
370 s = socket.socket(socket.AF_INET)
371 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
372 self.assertIsNone(ss.get_channel_binding("tls-unique"))
373
Antoine Pitrou152efa22010-05-16 18:19:27 +0000374class ContextTests(unittest.TestCase):
375
Antoine Pitrou23df4832010-08-04 17:14:06 +0000376 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000377 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200378 if hasattr(ssl, 'PROTOCOL_SSLv2'):
379 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000380 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
381 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
382 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
383 self.assertRaises(TypeError, ssl.SSLContext)
384 self.assertRaises(ValueError, ssl.SSLContext, -1)
385 self.assertRaises(ValueError, ssl.SSLContext, 42)
386
Antoine Pitrou23df4832010-08-04 17:14:06 +0000387 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000388 def test_protocol(self):
389 for proto in PROTOCOLS:
390 ctx = ssl.SSLContext(proto)
391 self.assertEqual(ctx.protocol, proto)
392
393 def test_ciphers(self):
394 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
395 ctx.set_ciphers("ALL")
396 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000397 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000398 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000399
Antoine Pitrou23df4832010-08-04 17:14:06 +0000400 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000401 def test_options(self):
402 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
403 # OP_ALL is the default value
404 self.assertEqual(ssl.OP_ALL, ctx.options)
405 ctx.options |= ssl.OP_NO_SSLv2
406 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
407 ctx.options)
408 ctx.options |= ssl.OP_NO_SSLv3
409 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
410 ctx.options)
411 if can_clear_options():
412 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
413 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
414 ctx.options)
415 ctx.options = 0
416 self.assertEqual(0, ctx.options)
417 else:
418 with self.assertRaises(ValueError):
419 ctx.options = 0
420
Antoine Pitrou152efa22010-05-16 18:19:27 +0000421 def test_verify(self):
422 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
423 # Default value
424 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
425 ctx.verify_mode = ssl.CERT_OPTIONAL
426 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
427 ctx.verify_mode = ssl.CERT_REQUIRED
428 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
429 ctx.verify_mode = ssl.CERT_NONE
430 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
431 with self.assertRaises(TypeError):
432 ctx.verify_mode = None
433 with self.assertRaises(ValueError):
434 ctx.verify_mode = 42
435
436 def test_load_cert_chain(self):
437 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
438 # Combined key and cert in a single file
439 ctx.load_cert_chain(CERTFILE)
440 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
441 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000442 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000443 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000444 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000445 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000446 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000447 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000448 ctx.load_cert_chain(EMPTYCERT)
449 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000450 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000451 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
452 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
453 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
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(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000456 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000457 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000458 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000459 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
460 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000461 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000462 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000463 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200464 # Password protected key and cert
465 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
466 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
467 ctx.load_cert_chain(CERTFILE_PROTECTED,
468 password=bytearray(KEY_PASSWORD.encode()))
469 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
470 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
471 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
472 bytearray(KEY_PASSWORD.encode()))
473 with self.assertRaisesRegex(TypeError, "should be a string"):
474 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
475 with self.assertRaises(ssl.SSLError):
476 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
477 with self.assertRaisesRegex(ValueError, "cannot be longer"):
478 # openssl has a fixed limit on the password buffer.
479 # PEM_BUFSIZE is generally set to 1kb.
480 # Return a string larger than this.
481 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
482 # Password callback
483 def getpass_unicode():
484 return KEY_PASSWORD
485 def getpass_bytes():
486 return KEY_PASSWORD.encode()
487 def getpass_bytearray():
488 return bytearray(KEY_PASSWORD.encode())
489 def getpass_badpass():
490 return "badpass"
491 def getpass_huge():
492 return b'a' * (1024 * 1024)
493 def getpass_bad_type():
494 return 9
495 def getpass_exception():
496 raise Exception('getpass error')
497 class GetPassCallable:
498 def __call__(self):
499 return KEY_PASSWORD
500 def getpass(self):
501 return KEY_PASSWORD
502 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
503 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
504 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
505 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
506 ctx.load_cert_chain(CERTFILE_PROTECTED,
507 password=GetPassCallable().getpass)
508 with self.assertRaises(ssl.SSLError):
509 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
510 with self.assertRaisesRegex(ValueError, "cannot be longer"):
511 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
512 with self.assertRaisesRegex(TypeError, "must return a string"):
513 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
514 with self.assertRaisesRegex(Exception, "getpass error"):
515 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
516 # Make sure the password function isn't called if it isn't needed
517 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000518
519 def test_load_verify_locations(self):
520 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
521 ctx.load_verify_locations(CERTFILE)
522 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
523 ctx.load_verify_locations(BYTES_CERTFILE)
524 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
525 self.assertRaises(TypeError, ctx.load_verify_locations)
526 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000527 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000528 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000529 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000530 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000531 ctx.load_verify_locations(BADCERT)
532 ctx.load_verify_locations(CERTFILE, CAPATH)
533 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
534
Victor Stinner80f75e62011-01-29 11:31:20 +0000535 # Issue #10989: crash if the second argument type is invalid
536 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
537
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000538 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000539 def test_session_stats(self):
540 for proto in PROTOCOLS:
541 ctx = ssl.SSLContext(proto)
542 self.assertEqual(ctx.session_stats(), {
543 'number': 0,
544 'connect': 0,
545 'connect_good': 0,
546 'connect_renegotiate': 0,
547 'accept': 0,
548 'accept_good': 0,
549 'accept_renegotiate': 0,
550 'hits': 0,
551 'misses': 0,
552 'timeouts': 0,
553 'cache_full': 0,
554 })
555
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000556 def test_set_default_verify_paths(self):
557 # There's not much we can do to test that it acts as expected,
558 # so just check it doesn't crash or raise an exception.
559 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
560 ctx.set_default_verify_paths()
561
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100562 def test_set_ecdh_curve(self):
563 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
564 ctx.set_ecdh_curve("prime256v1")
565 ctx.set_ecdh_curve(b"prime256v1")
566 self.assertRaises(TypeError, ctx.set_ecdh_curve)
567 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
568 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
569 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
570
Antoine Pitrou152efa22010-05-16 18:19:27 +0000571
Bill Janssen6e027db2007-11-15 22:23:56 +0000572class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000573
Antoine Pitrou480a1242010-04-28 21:37:09 +0000574 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000575 with support.transient_internet("svn.python.org"):
576 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
577 cert_reqs=ssl.CERT_NONE)
578 try:
579 s.connect(("svn.python.org", 443))
580 self.assertEqual({}, s.getpeercert())
581 finally:
582 s.close()
583
584 # this should fail because we have no verification certs
585 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
586 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000587 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
588 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000589 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000590
Antoine Pitrou350c7222010-09-09 13:31:46 +0000591 # this should succeed because we specify the root cert
592 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
593 cert_reqs=ssl.CERT_REQUIRED,
594 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
595 try:
596 s.connect(("svn.python.org", 443))
597 self.assertTrue(s.getpeercert())
598 finally:
599 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000600
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000601 def test_connect_ex(self):
602 # Issue #11326: check connect_ex() implementation
603 with support.transient_internet("svn.python.org"):
604 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
605 cert_reqs=ssl.CERT_REQUIRED,
606 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
607 try:
608 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
609 self.assertTrue(s.getpeercert())
610 finally:
611 s.close()
612
613 def test_non_blocking_connect_ex(self):
614 # Issue #11326: non-blocking connect_ex() should allow handshake
615 # to proceed after the socket gets ready.
616 with support.transient_internet("svn.python.org"):
617 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
618 cert_reqs=ssl.CERT_REQUIRED,
619 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
620 do_handshake_on_connect=False)
621 try:
622 s.setblocking(False)
623 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000624 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
625 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000626 # Wait for connect to finish
627 select.select([], [s], [], 5.0)
628 # Non-blocking handshake
629 while True:
630 try:
631 s.do_handshake()
632 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200633 except ssl.SSLWantReadError:
634 select.select([s], [], [], 5.0)
635 except ssl.SSLWantWriteError:
636 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000637 # SSL established
638 self.assertTrue(s.getpeercert())
639 finally:
640 s.close()
641
Antoine Pitroub4410db2011-05-18 18:51:06 +0200642 def test_timeout_connect_ex(self):
643 # Issue #12065: on a timeout, connect_ex() should return the original
644 # errno (mimicking the behaviour of non-SSL sockets).
645 with support.transient_internet("svn.python.org"):
646 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
647 cert_reqs=ssl.CERT_REQUIRED,
648 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
649 do_handshake_on_connect=False)
650 try:
651 s.settimeout(0.0000001)
652 rc = s.connect_ex(('svn.python.org', 443))
653 if rc == 0:
654 self.skipTest("svn.python.org responded too quickly")
655 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
656 finally:
657 s.close()
658
Antoine Pitrou152efa22010-05-16 18:19:27 +0000659 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000660 with support.transient_internet("svn.python.org"):
661 # Same as test_connect, but with a separately created context
662 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
663 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
664 s.connect(("svn.python.org", 443))
665 try:
666 self.assertEqual({}, s.getpeercert())
667 finally:
668 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000669 # Same with a server hostname
670 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
671 server_hostname="svn.python.org")
672 if ssl.HAS_SNI:
673 s.connect(("svn.python.org", 443))
674 s.close()
675 else:
676 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000677 # This should fail because we have no verification certs
678 ctx.verify_mode = ssl.CERT_REQUIRED
679 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000680 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000681 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000682 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000683 # This should succeed because we specify the root cert
684 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
685 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
686 s.connect(("svn.python.org", 443))
687 try:
688 cert = s.getpeercert()
689 self.assertTrue(cert)
690 finally:
691 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000692
693 def test_connect_capath(self):
694 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000695 # NOTE: the subject hashing algorithm has been changed between
696 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
697 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000698 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000699 with support.transient_internet("svn.python.org"):
700 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
701 ctx.verify_mode = ssl.CERT_REQUIRED
702 ctx.load_verify_locations(capath=CAPATH)
703 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
704 s.connect(("svn.python.org", 443))
705 try:
706 cert = s.getpeercert()
707 self.assertTrue(cert)
708 finally:
709 s.close()
710 # Same with a bytes `capath` argument
711 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
712 ctx.verify_mode = ssl.CERT_REQUIRED
713 ctx.load_verify_locations(capath=BYTES_CAPATH)
714 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
715 s.connect(("svn.python.org", 443))
716 try:
717 cert = s.getpeercert()
718 self.assertTrue(cert)
719 finally:
720 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000721
Antoine Pitroue3220242010-04-24 11:13:53 +0000722 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
723 def test_makefile_close(self):
724 # Issue #5238: creating a file-like object with makefile() shouldn't
725 # delay closing the underlying "real socket" (here tested with its
726 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000727 with support.transient_internet("svn.python.org"):
728 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
729 ss.connect(("svn.python.org", 443))
730 fd = ss.fileno()
731 f = ss.makefile()
732 f.close()
733 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000734 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000735 # Closing the SSL socket should close the fd too
736 ss.close()
737 gc.collect()
738 with self.assertRaises(OSError) as e:
739 os.read(fd, 0)
740 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000741
Antoine Pitrou480a1242010-04-28 21:37:09 +0000742 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000743 with support.transient_internet("svn.python.org"):
744 s = socket.socket(socket.AF_INET)
745 s.connect(("svn.python.org", 443))
746 s.setblocking(False)
747 s = ssl.wrap_socket(s,
748 cert_reqs=ssl.CERT_NONE,
749 do_handshake_on_connect=False)
750 count = 0
751 while True:
752 try:
753 count += 1
754 s.do_handshake()
755 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200756 except ssl.SSLWantReadError:
757 select.select([s], [], [])
758 except ssl.SSLWantWriteError:
759 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000760 s.close()
761 if support.verbose:
762 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763
Antoine Pitrou480a1242010-04-28 21:37:09 +0000764 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200765 def _test_get_server_certificate(host, port, cert=None):
766 with support.transient_internet(host):
767 pem = ssl.get_server_certificate((host, port))
768 if not pem:
769 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200770
Antoine Pitrou15399c32011-04-28 19:23:55 +0200771 try:
772 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
773 except ssl.SSLError as x:
774 #should fail
775 if support.verbose:
776 sys.stdout.write("%s\n" % x)
777 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200778 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
779
Antoine Pitrou15399c32011-04-28 19:23:55 +0200780 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
781 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200782 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000783 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200784 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000785
Antoine Pitrou15399c32011-04-28 19:23:55 +0200786 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
787 if support.IPV6_ENABLED:
788 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000789
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000790 def test_ciphers(self):
791 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000792 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000793 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000794 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000795 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000796 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
797 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
798 s.connect(remote)
799 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000800 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000801 with socket.socket(socket.AF_INET) as sock:
802 s = ssl.wrap_socket(sock,
803 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
804 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000805
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000806 def test_algorithms(self):
807 # Issue #8484: all algorithms should be available when verifying a
808 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000809 # SHA256 was added in OpenSSL 0.9.8
810 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
811 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000812 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
813 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000814 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000815 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000816 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
817 cert_reqs=ssl.CERT_REQUIRED,
818 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000819 try:
820 s.connect(remote)
821 if support.verbose:
822 sys.stdout.write("\nCipher with %r is %r\n" %
823 (remote, s.cipher()))
824 sys.stdout.write("Certificate is:\n%s\n" %
825 pprint.pformat(s.getpeercert()))
826 finally:
827 s.close()
828
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829
830try:
831 import threading
832except ImportError:
833 _have_threads = False
834else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000835 _have_threads = True
836
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000837 from test.ssl_servers import make_https_server
838
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000839 class ThreadedEchoServer(threading.Thread):
840
841 class ConnectionHandler(threading.Thread):
842
843 """A mildly complicated class, because we want it to work both
844 with and without the SSL wrapper around the socket connection, so
845 that we can test the STARTTLS functionality."""
846
Bill Janssen6e027db2007-11-15 22:23:56 +0000847 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848 self.server = server
849 self.running = False
850 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000851 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000852 self.sock.setblocking(1)
853 self.sslconn = None
854 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000855 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856
Antoine Pitrou480a1242010-04-28 21:37:09 +0000857 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000858 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000859 self.sslconn = self.server.context.wrap_socket(
860 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000861 except ssl.SSLError:
862 # XXX Various errors can have happened here, for example
863 # a mismatching protocol version, an invalid certificate,
864 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000866 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000867 self.running = False
868 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000869 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000871 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000872 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000874 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000875 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
876 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000877 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
879 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000880 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
882 return True
883
884 def read(self):
885 if self.sslconn:
886 return self.sslconn.read()
887 else:
888 return self.sock.recv(1024)
889
890 def write(self, bytes):
891 if self.sslconn:
892 return self.sslconn.write(bytes)
893 else:
894 return self.sock.send(bytes)
895
896 def close(self):
897 if self.sslconn:
898 self.sslconn.close()
899 else:
900 self.sock.close()
901
Antoine Pitrou480a1242010-04-28 21:37:09 +0000902 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903 self.running = True
904 if not self.server.starttls_server:
905 if not self.wrap_conn():
906 return
907 while self.running:
908 try:
909 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000910 stripped = msg.strip()
911 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 # eof, so quit this handler
913 self.running = False
914 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000915 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000916 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000917 sys.stdout.write(" server: client closed connection\n")
918 self.close()
919 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000920 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000921 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000922 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000924 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 if not self.wrap_conn():
926 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000927 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000928 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000929 if support.verbose and self.server.connectionchatty:
930 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000931 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000932 self.sock = self.sslconn.unwrap()
933 self.sslconn = None
934 if support.verbose and self.server.connectionchatty:
935 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200936 elif stripped == b'CB tls-unique':
937 if support.verbose and self.server.connectionchatty:
938 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
939 data = self.sslconn.get_channel_binding("tls-unique")
940 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000942 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000943 self.server.connectionchatty):
944 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000945 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
946 % (msg, ctype, msg.lower(), ctype))
947 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000948 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 if self.server.chatty:
950 handle_error("Test server failure:\n")
951 self.close()
952 self.running = False
953 # normally, we'd just stop here, but for the test
954 # harness, we want to stop the server
955 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000956
Antoine Pitroub5218772010-05-21 09:56:06 +0000957 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000958 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000959 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000960 ciphers=None, context=None):
961 if context:
962 self.context = context
963 else:
964 self.context = ssl.SSLContext(ssl_version
965 if ssl_version is not None
966 else ssl.PROTOCOL_TLSv1)
967 self.context.verify_mode = (certreqs if certreqs is not None
968 else ssl.CERT_NONE)
969 if cacerts:
970 self.context.load_verify_locations(cacerts)
971 if certificate:
972 self.context.load_cert_chain(certificate)
973 if ciphers:
974 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 self.chatty = chatty
976 self.connectionchatty = connectionchatty
977 self.starttls_server = starttls_server
978 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000979 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 self.active = False
982 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000983 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984
Antoine Pitrou480a1242010-04-28 21:37:09 +0000985 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986 self.flag = flag
987 threading.Thread.start(self)
988
Antoine Pitrou480a1242010-04-28 21:37:09 +0000989 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000990 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 self.sock.listen(5)
992 self.active = True
993 if self.flag:
994 # signal an event
995 self.flag.set()
996 while self.active:
997 try:
998 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000999 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001000 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001001 + repr(connaddr) + '\n')
1002 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 handler.start()
1004 except socket.timeout:
1005 pass
1006 except KeyboardInterrupt:
1007 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001008 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001009
Antoine Pitrou480a1242010-04-28 21:37:09 +00001010 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001011 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001012
Bill Janssen54cc54c2007-12-14 22:08:56 +00001013 class AsyncoreEchoServer(threading.Thread):
1014
1015 # this one's based on asyncore.dispatcher
1016
1017 class EchoServer (asyncore.dispatcher):
1018
1019 class ConnectionHandler (asyncore.dispatcher_with_send):
1020
1021 def __init__(self, conn, certfile):
1022 self.socket = ssl.wrap_socket(conn, server_side=True,
1023 certfile=certfile,
1024 do_handshake_on_connect=False)
1025 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001026 self._ssl_accepting = True
1027 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001028
1029 def readable(self):
1030 if isinstance(self.socket, ssl.SSLSocket):
1031 while self.socket.pending() > 0:
1032 self.handle_read_event()
1033 return True
1034
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001035 def _do_ssl_handshake(self):
1036 try:
1037 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001038 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1039 return
1040 except ssl.SSLEOFError:
1041 return self.handle_close()
1042 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001043 raise
1044 except socket.error as err:
1045 if err.args[0] == errno.ECONNABORTED:
1046 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001047 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001048 self._ssl_accepting = False
1049
1050 def handle_read(self):
1051 if self._ssl_accepting:
1052 self._do_ssl_handshake()
1053 else:
1054 data = self.recv(1024)
1055 if support.verbose:
1056 sys.stdout.write(" server: read %s from client\n" % repr(data))
1057 if not data:
1058 self.close()
1059 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001060 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001061
1062 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001063 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001064 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001065 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1066
1067 def handle_error(self):
1068 raise
1069
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001070 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001071 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001072 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1073 self.port = support.bind_port(sock, '')
1074 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001075 self.listen(5)
1076
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001077 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001078 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001079 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1080 self.ConnectionHandler(sock_obj, self.certfile)
1081
1082 def handle_error(self):
1083 raise
1084
Trent Nelson78520002008-04-10 20:54:35 +00001085 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001086 self.flag = None
1087 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001088 self.server = self.EchoServer(certfile)
1089 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001090 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001091 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001092
1093 def __str__(self):
1094 return "<%s %s>" % (self.__class__.__name__, self.server)
1095
1096 def start (self, flag=None):
1097 self.flag = flag
1098 threading.Thread.start(self)
1099
Antoine Pitrou480a1242010-04-28 21:37:09 +00001100 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001101 self.active = True
1102 if self.flag:
1103 self.flag.set()
1104 while self.active:
1105 try:
1106 asyncore.loop(1)
1107 except:
1108 pass
1109
Antoine Pitrou480a1242010-04-28 21:37:09 +00001110 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001111 self.active = False
1112 self.server.close()
1113
Antoine Pitrou480a1242010-04-28 21:37:09 +00001114 def bad_cert_test(certfile):
1115 """
1116 Launch a server with CERT_REQUIRED, and check that trying to
1117 connect to it with the given client certificate fails.
1118 """
Trent Nelson78520002008-04-10 20:54:35 +00001119 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001120 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001121 cacerts=CERTFILE, chatty=False,
1122 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001123 flag = threading.Event()
1124 server.start(flag)
1125 # wait for it to start
1126 flag.wait()
1127 # try to connect
1128 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001129 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001130 with socket.socket() as sock:
1131 s = ssl.wrap_socket(sock,
1132 certfile=certfile,
1133 ssl_version=ssl.PROTOCOL_TLSv1)
1134 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001135 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001136 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001137 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001138 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001140 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001141 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001142 if x.errno != errno.ENOENT:
1143 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001144 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001145 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001146 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001147 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148 finally:
1149 server.stop()
1150 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001151
Antoine Pitroub5218772010-05-21 09:56:06 +00001152 def server_params_test(client_context, server_context, indata=b"FOO\n",
1153 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001154 """
1155 Launch a server, connect a client to it and try various reads
1156 and writes.
1157 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001158 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001159 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001160 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001161 flag = threading.Event()
1162 server.start(flag)
1163 # wait for it to start
1164 flag.wait()
1165 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001167 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001168 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001169 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001170 if connectionchatty:
1171 if support.verbose:
1172 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001174 s.write(arg)
1175 outdata = s.read()
1176 if connectionchatty:
1177 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001178 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001179 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001180 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001181 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1182 % (outdata[:20], len(outdata),
1183 indata[:20].lower(), len(indata)))
1184 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001185 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001186 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001187 sys.stdout.write(" client: closing connection.\n")
1188 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001189 finally:
1190 server.stop()
1191 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001192
Antoine Pitroub5218772010-05-21 09:56:06 +00001193 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1194 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001195 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001196 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001197 certtype = {
1198 ssl.CERT_NONE: "CERT_NONE",
1199 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1200 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1201 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001202 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001204 sys.stdout.write(formatstr %
1205 (ssl.get_protocol_name(client_protocol),
1206 ssl.get_protocol_name(server_protocol),
1207 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001208 client_context = ssl.SSLContext(client_protocol)
1209 client_context.options = ssl.OP_ALL | client_options
1210 server_context = ssl.SSLContext(server_protocol)
1211 server_context.options = ssl.OP_ALL | server_options
1212 for ctx in (client_context, server_context):
1213 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001214 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1215 # will send an SSLv3 hello (rather than SSLv2) starting from
1216 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001217 ctx.set_ciphers("ALL")
1218 ctx.load_cert_chain(CERTFILE)
1219 ctx.load_verify_locations(CERTFILE)
1220 try:
1221 server_params_test(client_context, server_context,
1222 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001223 # Protocol mismatch can result in either an SSLError, or a
1224 # "Connection reset by peer" error.
1225 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001226 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001227 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001228 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001229 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001230 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001232 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001233 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234 "Client protocol %s succeeded with server protocol %s!"
1235 % (ssl.get_protocol_name(client_protocol),
1236 ssl.get_protocol_name(server_protocol)))
1237
1238
Bill Janssen6e027db2007-11-15 22:23:56 +00001239 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001240
Antoine Pitrou23df4832010-08-04 17:14:06 +00001241 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 def test_echo(self):
1243 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001244 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001245 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001246 for protocol in PROTOCOLS:
1247 context = ssl.SSLContext(protocol)
1248 context.load_cert_chain(CERTFILE)
1249 server_params_test(context, context,
1250 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001251
Antoine Pitrou480a1242010-04-28 21:37:09 +00001252 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001253 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001254 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001255 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1256 context.verify_mode = ssl.CERT_REQUIRED
1257 context.load_verify_locations(CERTFILE)
1258 context.load_cert_chain(CERTFILE)
1259 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001260 flag = threading.Event()
1261 server.start(flag)
1262 # wait for it to start
1263 flag.wait()
1264 # try to connect
1265 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001266 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001267 s.connect((HOST, server.port))
1268 cert = s.getpeercert()
1269 self.assertTrue(cert, "Can't get peer certificate.")
1270 cipher = s.cipher()
1271 if support.verbose:
1272 sys.stdout.write(pprint.pformat(cert) + '\n')
1273 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1274 if 'subject' not in cert:
1275 self.fail("No subject field in certificate: %s." %
1276 pprint.pformat(cert))
1277 if ((('organizationName', 'Python Software Foundation'),)
1278 not in cert['subject']):
1279 self.fail(
1280 "Missing or invalid 'organizationName' field in certificate subject; "
1281 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001282 self.assertIn('notBefore', cert)
1283 self.assertIn('notAfter', cert)
1284 before = ssl.cert_time_to_seconds(cert['notBefore'])
1285 after = ssl.cert_time_to_seconds(cert['notAfter'])
1286 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001287 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001288 finally:
1289 server.stop()
1290 server.join()
1291
Antoine Pitrou480a1242010-04-28 21:37:09 +00001292 def test_empty_cert(self):
1293 """Connecting with an empty cert file"""
1294 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1295 "nullcert.pem"))
1296 def test_malformed_cert(self):
1297 """Connecting with a badly formatted certificate (syntax error)"""
1298 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1299 "badcert.pem"))
1300 def test_nonexisting_cert(self):
1301 """Connecting with a non-existing cert file"""
1302 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1303 "wrongcert.pem"))
1304 def test_malformed_key(self):
1305 """Connecting with a badly formatted key (syntax error)"""
1306 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1307 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001308
Antoine Pitrou480a1242010-04-28 21:37:09 +00001309 def test_rude_shutdown(self):
1310 """A brutal shutdown of an SSL server should raise an IOError
1311 in the client when attempting handshake.
1312 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001313 listener_ready = threading.Event()
1314 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001315
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001316 s = socket.socket()
1317 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001318
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001319 # `listener` runs in a thread. It sits in an accept() until
1320 # the main thread connects. Then it rudely closes the socket,
1321 # and sets Event `listener_gone` to let the main thread know
1322 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001323 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001324 s.listen(5)
1325 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001326 newsock, addr = s.accept()
1327 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001328 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001329 listener_gone.set()
1330
1331 def connector():
1332 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001333 with socket.socket() as c:
1334 c.connect((HOST, port))
1335 listener_gone.wait()
1336 try:
1337 ssl_sock = ssl.wrap_socket(c)
1338 except IOError:
1339 pass
1340 else:
1341 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001342
1343 t = threading.Thread(target=listener)
1344 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001345 try:
1346 connector()
1347 finally:
1348 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001349
Antoine Pitrou23df4832010-08-04 17:14:06 +00001350 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001351 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1352 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001353 def test_protocol_sslv2(self):
1354 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001355 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001356 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1358 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1359 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1360 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1361 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1362 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001363 # SSLv23 client with specific SSL options
1364 if no_sslv2_implies_sslv3_hello():
1365 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1366 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1367 client_options=ssl.OP_NO_SSLv2)
1368 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1369 client_options=ssl.OP_NO_SSLv3)
1370 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1371 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001372
Antoine Pitrou23df4832010-08-04 17:14:06 +00001373 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001374 def test_protocol_sslv23(self):
1375 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001376 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001377 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001378 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1379 try:
1380 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1381 except (ssl.SSLError, socket.error) as x:
1382 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1383 if support.verbose:
1384 sys.stdout.write(
1385 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1386 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001387 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1388 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1389 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001390
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1392 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1393 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001394
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1396 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1397 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001398
Antoine Pitroub5218772010-05-21 09:56:06 +00001399 # Server with specific SSL options
1400 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1401 server_options=ssl.OP_NO_SSLv3)
1402 # Will choose TLSv1
1403 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1404 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1405 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1406 server_options=ssl.OP_NO_TLSv1)
1407
1408
Antoine Pitrou23df4832010-08-04 17:14:06 +00001409 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001410 def test_protocol_sslv3(self):
1411 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001412 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001413 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001414 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1415 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1416 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001417 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1418 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001419 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1420 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001421 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001422 if no_sslv2_implies_sslv3_hello():
1423 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1424 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1425 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001426
Antoine Pitrou23df4832010-08-04 17:14:06 +00001427 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001428 def test_protocol_tlsv1(self):
1429 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001430 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001431 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001432 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1433 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1434 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001435 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1436 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001438 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1439 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001440
Antoine Pitrou480a1242010-04-28 21:37:09 +00001441 def test_starttls(self):
1442 """Switching from clear text to encrypted and back again."""
1443 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 +00001444
Trent Nelson78520002008-04-10 20:54:35 +00001445 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001446 ssl_version=ssl.PROTOCOL_TLSv1,
1447 starttls_server=True,
1448 chatty=True,
1449 connectionchatty=True)
1450 flag = threading.Event()
1451 server.start(flag)
1452 # wait for it to start
1453 flag.wait()
1454 # try to connect
1455 wrapped = False
1456 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001457 s = socket.socket()
1458 s.setblocking(1)
1459 s.connect((HOST, server.port))
1460 if support.verbose:
1461 sys.stdout.write("\n")
1462 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001463 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001464 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001465 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001466 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001467 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001468 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001469 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001470 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001471 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001472 msg = outdata.strip().lower()
1473 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1474 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001475 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001476 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001477 " client: read %r from server, starting TLS...\n"
1478 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001479 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1480 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001481 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1482 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001483 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001484 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001485 " client: read %r from server, ending TLS...\n"
1486 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001487 s = conn.unwrap()
1488 wrapped = False
1489 else:
1490 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001491 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001493 if support.verbose:
1494 sys.stdout.write(" client: closing connection.\n")
1495 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001496 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001497 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001498 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001499 if wrapped:
1500 conn.close()
1501 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001502 s.close()
1503 finally:
1504 server.stop()
1505 server.join()
1506
Antoine Pitrou480a1242010-04-28 21:37:09 +00001507 def test_socketserver(self):
1508 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001509 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001510 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001511 if support.verbose:
1512 sys.stdout.write('\n')
1513 with open(CERTFILE, 'rb') as f:
1514 d1 = f.read()
1515 d2 = ''
1516 # now fetch the same data from the HTTPS server
1517 url = 'https://%s:%d/%s' % (
1518 HOST, server.port, os.path.split(CERTFILE)[1])
1519 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001520 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001521 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001522 if dlen and (int(dlen) > 0):
1523 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001524 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001525 sys.stdout.write(
1526 " client: read %d bytes from remote server '%s'\n"
1527 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001528 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001529 f.close()
1530 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001531
Antoine Pitrou480a1242010-04-28 21:37:09 +00001532 def test_asyncore_server(self):
1533 """Check the example asyncore integration."""
1534 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001535
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001536 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001537 sys.stdout.write("\n")
1538
Antoine Pitrou480a1242010-04-28 21:37:09 +00001539 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001540 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001541 flag = threading.Event()
1542 server.start(flag)
1543 # wait for it to start
1544 flag.wait()
1545 # try to connect
1546 try:
1547 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001548 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001549 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001550 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001551 " client: sending %r...\n" % indata)
1552 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001553 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001554 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001555 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001556 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001557 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001558 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1559 % (outdata[:20], len(outdata),
1560 indata[:20].lower(), len(indata)))
1561 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001562 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001563 sys.stdout.write(" client: closing connection.\n")
1564 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001565 if support.verbose:
1566 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001567 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001568 if support.verbose:
1569 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001570 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001571 if support.verbose:
1572 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001573 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001574 if support.verbose:
1575 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001576
Antoine Pitrou480a1242010-04-28 21:37:09 +00001577 def test_recv_send(self):
1578 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001579 if support.verbose:
1580 sys.stdout.write("\n")
1581
1582 server = ThreadedEchoServer(CERTFILE,
1583 certreqs=ssl.CERT_NONE,
1584 ssl_version=ssl.PROTOCOL_TLSv1,
1585 cacerts=CERTFILE,
1586 chatty=True,
1587 connectionchatty=False)
1588 flag = threading.Event()
1589 server.start(flag)
1590 # wait for it to start
1591 flag.wait()
1592 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001593 s = ssl.wrap_socket(socket.socket(),
1594 server_side=False,
1595 certfile=CERTFILE,
1596 ca_certs=CERTFILE,
1597 cert_reqs=ssl.CERT_NONE,
1598 ssl_version=ssl.PROTOCOL_TLSv1)
1599 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001600 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001601 # helper methods for standardising recv* method signatures
1602 def _recv_into():
1603 b = bytearray(b"\0"*100)
1604 count = s.recv_into(b)
1605 return b[:count]
1606
1607 def _recvfrom_into():
1608 b = bytearray(b"\0"*100)
1609 count, addr = s.recvfrom_into(b)
1610 return b[:count]
1611
1612 # (name, method, whether to expect success, *args)
1613 send_methods = [
1614 ('send', s.send, True, []),
1615 ('sendto', s.sendto, False, ["some.address"]),
1616 ('sendall', s.sendall, True, []),
1617 ]
1618 recv_methods = [
1619 ('recv', s.recv, True, []),
1620 ('recvfrom', s.recvfrom, False, ["some.address"]),
1621 ('recv_into', _recv_into, True, []),
1622 ('recvfrom_into', _recvfrom_into, False, []),
1623 ]
1624 data_prefix = "PREFIX_"
1625
1626 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001627 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001628 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001629 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001630 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001631 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001632 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001633 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001634 "<<{outdata:r}>> ({nout:d}) received; "
1635 "expected <<{indata:r}>> ({nin:d})\n".format(
1636 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001637 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001639 )
1640 )
1641 except ValueError as e:
1642 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001643 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001644 "Failed to send with method <<{name:s}>>; "
1645 "expected to succeed.\n".format(name=meth_name)
1646 )
1647 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001648 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001649 "Method <<{name:s}>> failed with unexpected "
1650 "exception message: {exp:s}\n".format(
1651 name=meth_name, exp=e
1652 )
1653 )
1654
1655 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001656 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001657 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001658 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001659 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001660 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001661 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001662 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001663 "<<{outdata:r}>> ({nout:d}) received; "
1664 "expected <<{indata:r}>> ({nin:d})\n".format(
1665 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001666 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001667 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001668 )
1669 )
1670 except ValueError as e:
1671 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001672 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001673 "Failed to receive with method <<{name:s}>>; "
1674 "expected to succeed.\n".format(name=meth_name)
1675 )
1676 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001677 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001678 "Method <<{name:s}>> failed with unexpected "
1679 "exception message: {exp:s}\n".format(
1680 name=meth_name, exp=e
1681 )
1682 )
1683 # consume data
1684 s.read()
1685
Nick Coghlan513886a2011-08-28 00:00:27 +10001686 # Make sure sendmsg et al are disallowed to avoid
1687 # inadvertent disclosure of data and/or corruption
1688 # of the encrypted data stream
1689 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1690 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1691 self.assertRaises(NotImplementedError,
1692 s.recvmsg_into, bytearray(100))
1693
Antoine Pitrou480a1242010-04-28 21:37:09 +00001694 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001695 s.close()
1696 finally:
1697 server.stop()
1698 server.join()
1699
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001700 def test_handshake_timeout(self):
1701 # Issue #5103: SSL handshake must respect the socket timeout
1702 server = socket.socket(socket.AF_INET)
1703 host = "127.0.0.1"
1704 port = support.bind_port(server)
1705 started = threading.Event()
1706 finish = False
1707
1708 def serve():
1709 server.listen(5)
1710 started.set()
1711 conns = []
1712 while not finish:
1713 r, w, e = select.select([server], [], [], 0.1)
1714 if server in r:
1715 # Let the socket hang around rather than having
1716 # it closed by garbage collection.
1717 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001718 for sock in conns:
1719 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001720
1721 t = threading.Thread(target=serve)
1722 t.start()
1723 started.wait()
1724
1725 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001726 try:
1727 c = socket.socket(socket.AF_INET)
1728 c.settimeout(0.2)
1729 c.connect((host, port))
1730 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001731 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001732 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001733 finally:
1734 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001735 try:
1736 c = socket.socket(socket.AF_INET)
1737 c = ssl.wrap_socket(c)
1738 c.settimeout(0.2)
1739 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001740 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001741 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001742 finally:
1743 c.close()
1744 finally:
1745 finish = True
1746 t.join()
1747 server.close()
1748
Antoine Pitroud6494802011-07-21 01:11:30 +02001749 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1750 "'tls-unique' channel binding not available")
1751 def test_tls_unique_channel_binding(self):
1752 """Test tls-unique channel binding."""
1753 if support.verbose:
1754 sys.stdout.write("\n")
1755
1756 server = ThreadedEchoServer(CERTFILE,
1757 certreqs=ssl.CERT_NONE,
1758 ssl_version=ssl.PROTOCOL_TLSv1,
1759 cacerts=CERTFILE,
1760 chatty=True,
1761 connectionchatty=False)
1762 flag = threading.Event()
1763 server.start(flag)
1764 # wait for it to start
1765 flag.wait()
1766 # try to connect
1767 s = ssl.wrap_socket(socket.socket(),
1768 server_side=False,
1769 certfile=CERTFILE,
1770 ca_certs=CERTFILE,
1771 cert_reqs=ssl.CERT_NONE,
1772 ssl_version=ssl.PROTOCOL_TLSv1)
1773 s.connect((HOST, server.port))
1774 try:
1775 # get the data
1776 cb_data = s.get_channel_binding("tls-unique")
1777 if support.verbose:
1778 sys.stdout.write(" got channel binding data: {0!r}\n"
1779 .format(cb_data))
1780
1781 # check if it is sane
1782 self.assertIsNotNone(cb_data)
1783 self.assertEqual(len(cb_data), 12) # True for TLSv1
1784
1785 # and compare with the peers version
1786 s.write(b"CB tls-unique\n")
1787 peer_data_repr = s.read().strip()
1788 self.assertEqual(peer_data_repr,
1789 repr(cb_data).encode("us-ascii"))
1790 s.close()
1791
1792 # now, again
1793 s = ssl.wrap_socket(socket.socket(),
1794 server_side=False,
1795 certfile=CERTFILE,
1796 ca_certs=CERTFILE,
1797 cert_reqs=ssl.CERT_NONE,
1798 ssl_version=ssl.PROTOCOL_TLSv1)
1799 s.connect((HOST, server.port))
1800 new_cb_data = s.get_channel_binding("tls-unique")
1801 if support.verbose:
1802 sys.stdout.write(" got another channel binding data: {0!r}\n"
1803 .format(new_cb_data))
1804 # is it really unique
1805 self.assertNotEqual(cb_data, new_cb_data)
1806 self.assertIsNotNone(cb_data)
1807 self.assertEqual(len(cb_data), 12) # True for TLSv1
1808 s.write(b"CB tls-unique\n")
1809 peer_data_repr = s.read().strip()
1810 self.assertEqual(peer_data_repr,
1811 repr(new_cb_data).encode("us-ascii"))
1812 s.close()
1813 finally:
1814 server.stop()
1815 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001816
Thomas Woutersed03b412007-08-28 21:37:11 +00001817def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001818 if support.verbose:
1819 plats = {
1820 'Linux': platform.linux_distribution,
1821 'Mac': platform.mac_ver,
1822 'Windows': platform.win32_ver,
1823 }
1824 for name, func in plats.items():
1825 plat = func()
1826 if plat and plat[0]:
1827 plat = '%s %r' % (name, plat)
1828 break
1829 else:
1830 plat = repr(platform.platform())
1831 print("test_ssl: testing with %r %r" %
1832 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1833 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001834 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001835
Antoine Pitrou152efa22010-05-16 18:19:27 +00001836 for filename in [
1837 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1838 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1839 BADCERT, BADKEY, EMPTYCERT]:
1840 if not os.path.exists(filename):
1841 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001842
Antoine Pitrou152efa22010-05-16 18:19:27 +00001843 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001844
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001845 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001846 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001847
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001848 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001849 thread_info = support.threading_setup()
1850 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001851 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001852
Antoine Pitrou480a1242010-04-28 21:37:09 +00001853 try:
1854 support.run_unittest(*tests)
1855 finally:
1856 if _have_threads:
1857 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001858
1859if __name__ == "__main__":
1860 test_main()