blob: 288b714cebc4e83c5c574a2cb3760d8fc66bb219 [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 Pitroud5323212010-10-22 18:19:07 +0000102 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000103
Antoine Pitrou480a1242010-04-28 21:37:09 +0000104 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000106 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000107 sys.stdout.write("\n RAND_status is %d (%s)\n"
108 % (v, (v and "sufficient randomness") or
109 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200110
111 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
112 self.assertEqual(len(data), 16)
113 self.assertEqual(is_cryptographic, v == 1)
114 if v:
115 data = ssl.RAND_bytes(16)
116 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200117 else:
118 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200119
Thomas Woutersed03b412007-08-28 21:37:11 +0000120 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000121 ssl.RAND_egd(1)
122 except TypeError:
123 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000124 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000125 print("didn't raise TypeError")
126 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000127
Antoine Pitrou480a1242010-04-28 21:37:09 +0000128 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 # note that this uses an 'unofficial' function in _ssl.c,
130 # provided solely for this test, to exercise the certificate
131 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000132 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000133 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000134 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200135 self.assertEqual(p['issuer'],
136 ((('countryName', 'XY'),),
137 (('localityName', 'Castle Anthrax'),),
138 (('organizationName', 'Python Software Foundation'),),
139 (('commonName', 'localhost'),))
140 )
141 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
142 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
143 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
144 self.assertEqual(p['subject'],
145 ((('countryName', 'XY'),),
146 (('localityName', 'Castle Anthrax'),),
147 (('organizationName', 'Python Software Foundation'),),
148 (('commonName', 'localhost'),))
149 )
150 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
151 # Issue #13034: the subjectAltName in some certificates
152 # (notably projects.developer.nokia.com:443) wasn't parsed
153 p = ssl._ssl._test_decode_cert(NOKIACERT)
154 if support.verbose:
155 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
156 self.assertEqual(p['subjectAltName'],
157 (('DNS', 'projects.developer.nokia.com'),
158 ('DNS', 'projects.forum.nokia.com'))
159 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000160
Antoine Pitrou480a1242010-04-28 21:37:09 +0000161 def test_DER_to_PEM(self):
162 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
163 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000164 d1 = ssl.PEM_cert_to_DER_cert(pem)
165 p2 = ssl.DER_cert_to_PEM_cert(d1)
166 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000167 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000168 if not p2.startswith(ssl.PEM_HEADER + '\n'):
169 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
170 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
171 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000172
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000173 def test_openssl_version(self):
174 n = ssl.OPENSSL_VERSION_NUMBER
175 t = ssl.OPENSSL_VERSION_INFO
176 s = ssl.OPENSSL_VERSION
177 self.assertIsInstance(n, int)
178 self.assertIsInstance(t, tuple)
179 self.assertIsInstance(s, str)
180 # Some sanity checks follow
181 # >= 0.9
182 self.assertGreaterEqual(n, 0x900000)
183 # < 2.0
184 self.assertLess(n, 0x20000000)
185 major, minor, fix, patch, status = t
186 self.assertGreaterEqual(major, 0)
187 self.assertLess(major, 2)
188 self.assertGreaterEqual(minor, 0)
189 self.assertLess(minor, 256)
190 self.assertGreaterEqual(fix, 0)
191 self.assertLess(fix, 256)
192 self.assertGreaterEqual(patch, 0)
193 self.assertLessEqual(patch, 26)
194 self.assertGreaterEqual(status, 0)
195 self.assertLessEqual(status, 15)
196 # Version string as returned by OpenSSL, the format might change
197 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
198 (s, t))
199
Antoine Pitrou9d543662010-04-23 23:10:32 +0000200 @support.cpython_only
201 def test_refcycle(self):
202 # Issue #7943: an SSL object doesn't create reference cycles with
203 # itself.
204 s = socket.socket(socket.AF_INET)
205 ss = ssl.wrap_socket(s)
206 wr = weakref.ref(ss)
207 del ss
208 self.assertEqual(wr(), None)
209
Antoine Pitroua468adc2010-09-14 14:43:44 +0000210 def test_wrapped_unconnected(self):
211 # Methods on an unconnected SSLSocket propagate the original
212 # socket.error raise by the underlying socket object.
213 s = socket.socket(socket.AF_INET)
214 ss = ssl.wrap_socket(s)
215 self.assertRaises(socket.error, ss.recv, 1)
216 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
217 self.assertRaises(socket.error, ss.recvfrom, 1)
218 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
219 self.assertRaises(socket.error, ss.send, b'x')
220 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
221
Antoine Pitrou40f08742010-04-24 22:04:40 +0000222 def test_timeout(self):
223 # Issue #8524: when creating an SSL socket, the timeout of the
224 # original socket should be retained.
225 for timeout in (None, 0.0, 5.0):
226 s = socket.socket(socket.AF_INET)
227 s.settimeout(timeout)
228 ss = ssl.wrap_socket(s)
229 self.assertEqual(timeout, ss.gettimeout())
230
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000231 def test_errors(self):
232 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000233 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000234 "certfile must be specified",
235 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000236 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000237 "certfile must be specified for server-side operations",
238 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000239 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000240 "certfile must be specified for server-side operations",
241 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000242 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000243 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000244 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000245 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000246 with socket.socket() as sock:
247 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000248 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000249 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000250 with socket.socket() as sock:
251 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000252 self.assertEqual(cm.exception.errno, errno.ENOENT)
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, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000256 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000257
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000258 def test_match_hostname(self):
259 def ok(cert, hostname):
260 ssl.match_hostname(cert, hostname)
261 def fail(cert, hostname):
262 self.assertRaises(ssl.CertificateError,
263 ssl.match_hostname, cert, hostname)
264
265 cert = {'subject': ((('commonName', 'example.com'),),)}
266 ok(cert, 'example.com')
267 ok(cert, 'ExAmple.cOm')
268 fail(cert, 'www.example.com')
269 fail(cert, '.example.com')
270 fail(cert, 'example.org')
271 fail(cert, 'exampleXcom')
272
273 cert = {'subject': ((('commonName', '*.a.com'),),)}
274 ok(cert, 'foo.a.com')
275 fail(cert, 'bar.foo.a.com')
276 fail(cert, 'a.com')
277 fail(cert, 'Xa.com')
278 fail(cert, '.a.com')
279
280 cert = {'subject': ((('commonName', 'a.*.com'),),)}
281 ok(cert, 'a.foo.com')
282 fail(cert, 'a..com')
283 fail(cert, 'a.com')
284
285 cert = {'subject': ((('commonName', 'f*.com'),),)}
286 ok(cert, 'foo.com')
287 ok(cert, 'f.com')
288 fail(cert, 'bar.com')
289 fail(cert, 'foo.a.com')
290 fail(cert, 'bar.foo.com')
291
292 # Slightly fake real-world example
293 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
294 'subject': ((('commonName', 'linuxfrz.org'),),),
295 'subjectAltName': (('DNS', 'linuxfr.org'),
296 ('DNS', 'linuxfr.com'),
297 ('othername', '<unsupported>'))}
298 ok(cert, 'linuxfr.org')
299 ok(cert, 'linuxfr.com')
300 # Not a "DNS" entry
301 fail(cert, '<unsupported>')
302 # When there is a subjectAltName, commonName isn't used
303 fail(cert, 'linuxfrz.org')
304
305 # A pristine real-world example
306 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
307 'subject': ((('countryName', 'US'),),
308 (('stateOrProvinceName', 'California'),),
309 (('localityName', 'Mountain View'),),
310 (('organizationName', 'Google Inc'),),
311 (('commonName', 'mail.google.com'),))}
312 ok(cert, 'mail.google.com')
313 fail(cert, 'gmail.com')
314 # Only commonName is considered
315 fail(cert, 'California')
316
317 # Neither commonName nor subjectAltName
318 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
319 'subject': ((('countryName', 'US'),),
320 (('stateOrProvinceName', 'California'),),
321 (('localityName', 'Mountain View'),),
322 (('organizationName', 'Google Inc'),))}
323 fail(cert, 'mail.google.com')
324
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200325 # No DNS entry in subjectAltName but a commonName
326 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
327 'subject': ((('countryName', 'US'),),
328 (('stateOrProvinceName', 'California'),),
329 (('localityName', 'Mountain View'),),
330 (('commonName', 'mail.google.com'),)),
331 'subjectAltName': (('othername', 'blabla'), )}
332 ok(cert, 'mail.google.com')
333
334 # No DNS entry subjectAltName and no commonName
335 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
336 'subject': ((('countryName', 'US'),),
337 (('stateOrProvinceName', 'California'),),
338 (('localityName', 'Mountain View'),),
339 (('organizationName', 'Google Inc'),)),
340 'subjectAltName': (('othername', 'blabla'),)}
341 fail(cert, 'google.com')
342
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000343 # Empty cert / no cert
344 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
345 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
346
Antoine Pitroud5323212010-10-22 18:19:07 +0000347 def test_server_side(self):
348 # server_hostname doesn't work for server sockets
349 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000350 with socket.socket() as sock:
351 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
352 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000353
Antoine Pitroud6494802011-07-21 01:11:30 +0200354 def test_unknown_channel_binding(self):
355 # should raise ValueError for unknown type
356 s = socket.socket(socket.AF_INET)
357 ss = ssl.wrap_socket(s)
358 with self.assertRaises(ValueError):
359 ss.get_channel_binding("unknown-type")
360
361 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
362 "'tls-unique' channel binding not available")
363 def test_tls_unique_channel_binding(self):
364 # unconnected should return None for known type
365 s = socket.socket(socket.AF_INET)
366 ss = ssl.wrap_socket(s)
367 self.assertIsNone(ss.get_channel_binding("tls-unique"))
368 # the same for server-side
369 s = socket.socket(socket.AF_INET)
370 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
371 self.assertIsNone(ss.get_channel_binding("tls-unique"))
372
Antoine Pitrou152efa22010-05-16 18:19:27 +0000373class ContextTests(unittest.TestCase):
374
Antoine Pitrou23df4832010-08-04 17:14:06 +0000375 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000376 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200377 if hasattr(ssl, 'PROTOCOL_SSLv2'):
378 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000379 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
380 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
381 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
382 self.assertRaises(TypeError, ssl.SSLContext)
383 self.assertRaises(ValueError, ssl.SSLContext, -1)
384 self.assertRaises(ValueError, ssl.SSLContext, 42)
385
Antoine Pitrou23df4832010-08-04 17:14:06 +0000386 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000387 def test_protocol(self):
388 for proto in PROTOCOLS:
389 ctx = ssl.SSLContext(proto)
390 self.assertEqual(ctx.protocol, proto)
391
392 def test_ciphers(self):
393 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
394 ctx.set_ciphers("ALL")
395 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000396 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000397 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000398
Antoine Pitrou23df4832010-08-04 17:14:06 +0000399 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000400 def test_options(self):
401 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
402 # OP_ALL is the default value
403 self.assertEqual(ssl.OP_ALL, ctx.options)
404 ctx.options |= ssl.OP_NO_SSLv2
405 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
406 ctx.options)
407 ctx.options |= ssl.OP_NO_SSLv3
408 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
409 ctx.options)
410 if can_clear_options():
411 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
412 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
413 ctx.options)
414 ctx.options = 0
415 self.assertEqual(0, ctx.options)
416 else:
417 with self.assertRaises(ValueError):
418 ctx.options = 0
419
Antoine Pitrou152efa22010-05-16 18:19:27 +0000420 def test_verify(self):
421 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
422 # Default value
423 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
424 ctx.verify_mode = ssl.CERT_OPTIONAL
425 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
426 ctx.verify_mode = ssl.CERT_REQUIRED
427 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
428 ctx.verify_mode = ssl.CERT_NONE
429 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
430 with self.assertRaises(TypeError):
431 ctx.verify_mode = None
432 with self.assertRaises(ValueError):
433 ctx.verify_mode = 42
434
435 def test_load_cert_chain(self):
436 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
437 # Combined key and cert in a single file
438 ctx.load_cert_chain(CERTFILE)
439 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
440 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000441 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000442 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000443 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000444 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000445 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000446 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000447 ctx.load_cert_chain(EMPTYCERT)
448 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000449 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000450 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
451 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
452 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000453 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000454 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000455 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000456 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000457 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000458 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
459 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000460 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000461 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000462 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200463 # Password protected key and cert
464 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
465 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
466 ctx.load_cert_chain(CERTFILE_PROTECTED,
467 password=bytearray(KEY_PASSWORD.encode()))
468 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
469 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
470 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
471 bytearray(KEY_PASSWORD.encode()))
472 with self.assertRaisesRegex(TypeError, "should be a string"):
473 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
474 with self.assertRaises(ssl.SSLError):
475 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
476 with self.assertRaisesRegex(ValueError, "cannot be longer"):
477 # openssl has a fixed limit on the password buffer.
478 # PEM_BUFSIZE is generally set to 1kb.
479 # Return a string larger than this.
480 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
481 # Password callback
482 def getpass_unicode():
483 return KEY_PASSWORD
484 def getpass_bytes():
485 return KEY_PASSWORD.encode()
486 def getpass_bytearray():
487 return bytearray(KEY_PASSWORD.encode())
488 def getpass_badpass():
489 return "badpass"
490 def getpass_huge():
491 return b'a' * (1024 * 1024)
492 def getpass_bad_type():
493 return 9
494 def getpass_exception():
495 raise Exception('getpass error')
496 class GetPassCallable:
497 def __call__(self):
498 return KEY_PASSWORD
499 def getpass(self):
500 return KEY_PASSWORD
501 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
502 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
503 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
504 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
505 ctx.load_cert_chain(CERTFILE_PROTECTED,
506 password=GetPassCallable().getpass)
507 with self.assertRaises(ssl.SSLError):
508 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
509 with self.assertRaisesRegex(ValueError, "cannot be longer"):
510 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
511 with self.assertRaisesRegex(TypeError, "must return a string"):
512 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
513 with self.assertRaisesRegex(Exception, "getpass error"):
514 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
515 # Make sure the password function isn't called if it isn't needed
516 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000517
518 def test_load_verify_locations(self):
519 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
520 ctx.load_verify_locations(CERTFILE)
521 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
522 ctx.load_verify_locations(BYTES_CERTFILE)
523 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
524 self.assertRaises(TypeError, ctx.load_verify_locations)
525 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000526 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000527 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000528 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000529 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000530 ctx.load_verify_locations(BADCERT)
531 ctx.load_verify_locations(CERTFILE, CAPATH)
532 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
533
Victor Stinner80f75e62011-01-29 11:31:20 +0000534 # Issue #10989: crash if the second argument type is invalid
535 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
536
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000537 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000538 def test_session_stats(self):
539 for proto in PROTOCOLS:
540 ctx = ssl.SSLContext(proto)
541 self.assertEqual(ctx.session_stats(), {
542 'number': 0,
543 'connect': 0,
544 'connect_good': 0,
545 'connect_renegotiate': 0,
546 'accept': 0,
547 'accept_good': 0,
548 'accept_renegotiate': 0,
549 'hits': 0,
550 'misses': 0,
551 'timeouts': 0,
552 'cache_full': 0,
553 })
554
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000555 def test_set_default_verify_paths(self):
556 # There's not much we can do to test that it acts as expected,
557 # so just check it doesn't crash or raise an exception.
558 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
559 ctx.set_default_verify_paths()
560
Antoine Pitrou152efa22010-05-16 18:19:27 +0000561
Bill Janssen6e027db2007-11-15 22:23:56 +0000562class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000563
Antoine Pitrou480a1242010-04-28 21:37:09 +0000564 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000565 with support.transient_internet("svn.python.org"):
566 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
567 cert_reqs=ssl.CERT_NONE)
568 try:
569 s.connect(("svn.python.org", 443))
570 self.assertEqual({}, s.getpeercert())
571 finally:
572 s.close()
573
574 # this should fail because we have no verification certs
575 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
576 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000577 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
578 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000579 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000580
Antoine Pitrou350c7222010-09-09 13:31:46 +0000581 # this should succeed because we specify the root cert
582 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
583 cert_reqs=ssl.CERT_REQUIRED,
584 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
585 try:
586 s.connect(("svn.python.org", 443))
587 self.assertTrue(s.getpeercert())
588 finally:
589 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000590
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000591 def test_connect_ex(self):
592 # Issue #11326: check connect_ex() implementation
593 with support.transient_internet("svn.python.org"):
594 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
595 cert_reqs=ssl.CERT_REQUIRED,
596 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
597 try:
598 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
599 self.assertTrue(s.getpeercert())
600 finally:
601 s.close()
602
603 def test_non_blocking_connect_ex(self):
604 # Issue #11326: non-blocking connect_ex() should allow handshake
605 # to proceed after the socket gets ready.
606 with support.transient_internet("svn.python.org"):
607 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
608 cert_reqs=ssl.CERT_REQUIRED,
609 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
610 do_handshake_on_connect=False)
611 try:
612 s.setblocking(False)
613 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000614 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
615 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000616 # Wait for connect to finish
617 select.select([], [s], [], 5.0)
618 # Non-blocking handshake
619 while True:
620 try:
621 s.do_handshake()
622 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200623 except ssl.SSLWantReadError:
624 select.select([s], [], [], 5.0)
625 except ssl.SSLWantWriteError:
626 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000627 # SSL established
628 self.assertTrue(s.getpeercert())
629 finally:
630 s.close()
631
Antoine Pitroub4410db2011-05-18 18:51:06 +0200632 def test_timeout_connect_ex(self):
633 # Issue #12065: on a timeout, connect_ex() should return the original
634 # errno (mimicking the behaviour of non-SSL sockets).
635 with support.transient_internet("svn.python.org"):
636 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
637 cert_reqs=ssl.CERT_REQUIRED,
638 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
639 do_handshake_on_connect=False)
640 try:
641 s.settimeout(0.0000001)
642 rc = s.connect_ex(('svn.python.org', 443))
643 if rc == 0:
644 self.skipTest("svn.python.org responded too quickly")
645 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
646 finally:
647 s.close()
648
Antoine Pitrou152efa22010-05-16 18:19:27 +0000649 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000650 with support.transient_internet("svn.python.org"):
651 # Same as test_connect, but with a separately created context
652 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
653 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
654 s.connect(("svn.python.org", 443))
655 try:
656 self.assertEqual({}, s.getpeercert())
657 finally:
658 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000659 # Same with a server hostname
660 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
661 server_hostname="svn.python.org")
662 if ssl.HAS_SNI:
663 s.connect(("svn.python.org", 443))
664 s.close()
665 else:
666 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000667 # This should fail because we have no verification certs
668 ctx.verify_mode = ssl.CERT_REQUIRED
669 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000670 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000671 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000672 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000673 # This should succeed because we specify the root cert
674 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
675 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
676 s.connect(("svn.python.org", 443))
677 try:
678 cert = s.getpeercert()
679 self.assertTrue(cert)
680 finally:
681 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000682
683 def test_connect_capath(self):
684 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000685 # NOTE: the subject hashing algorithm has been changed between
686 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
687 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000688 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000689 with support.transient_internet("svn.python.org"):
690 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
691 ctx.verify_mode = ssl.CERT_REQUIRED
692 ctx.load_verify_locations(capath=CAPATH)
693 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
694 s.connect(("svn.python.org", 443))
695 try:
696 cert = s.getpeercert()
697 self.assertTrue(cert)
698 finally:
699 s.close()
700 # Same with a bytes `capath` argument
701 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
702 ctx.verify_mode = ssl.CERT_REQUIRED
703 ctx.load_verify_locations(capath=BYTES_CAPATH)
704 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
705 s.connect(("svn.python.org", 443))
706 try:
707 cert = s.getpeercert()
708 self.assertTrue(cert)
709 finally:
710 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000711
Antoine Pitroue3220242010-04-24 11:13:53 +0000712 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
713 def test_makefile_close(self):
714 # Issue #5238: creating a file-like object with makefile() shouldn't
715 # delay closing the underlying "real socket" (here tested with its
716 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000717 with support.transient_internet("svn.python.org"):
718 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
719 ss.connect(("svn.python.org", 443))
720 fd = ss.fileno()
721 f = ss.makefile()
722 f.close()
723 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000724 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000725 # Closing the SSL socket should close the fd too
726 ss.close()
727 gc.collect()
728 with self.assertRaises(OSError) as e:
729 os.read(fd, 0)
730 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000731
Antoine Pitrou480a1242010-04-28 21:37:09 +0000732 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000733 with support.transient_internet("svn.python.org"):
734 s = socket.socket(socket.AF_INET)
735 s.connect(("svn.python.org", 443))
736 s.setblocking(False)
737 s = ssl.wrap_socket(s,
738 cert_reqs=ssl.CERT_NONE,
739 do_handshake_on_connect=False)
740 count = 0
741 while True:
742 try:
743 count += 1
744 s.do_handshake()
745 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200746 except ssl.SSLWantReadError:
747 select.select([s], [], [])
748 except ssl.SSLWantWriteError:
749 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000750 s.close()
751 if support.verbose:
752 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000753
Antoine Pitrou480a1242010-04-28 21:37:09 +0000754 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200755 def _test_get_server_certificate(host, port, cert=None):
756 with support.transient_internet(host):
757 pem = ssl.get_server_certificate((host, port))
758 if not pem:
759 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200760
Antoine Pitrou15399c32011-04-28 19:23:55 +0200761 try:
762 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
763 except ssl.SSLError as x:
764 #should fail
765 if support.verbose:
766 sys.stdout.write("%s\n" % x)
767 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200768 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
769
Antoine Pitrou15399c32011-04-28 19:23:55 +0200770 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
771 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200772 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000773 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200774 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000775
Antoine Pitrou15399c32011-04-28 19:23:55 +0200776 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
777 if support.IPV6_ENABLED:
778 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000779
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000780 def test_ciphers(self):
781 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000782 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000783 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000784 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000785 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000786 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
787 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
788 s.connect(remote)
789 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000790 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000791 with socket.socket(socket.AF_INET) as sock:
792 s = ssl.wrap_socket(sock,
793 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
794 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000795
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000796 def test_algorithms(self):
797 # Issue #8484: all algorithms should be available when verifying a
798 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000799 # SHA256 was added in OpenSSL 0.9.8
800 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
801 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000802 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
803 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000804 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000805 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000806 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
807 cert_reqs=ssl.CERT_REQUIRED,
808 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000809 try:
810 s.connect(remote)
811 if support.verbose:
812 sys.stdout.write("\nCipher with %r is %r\n" %
813 (remote, s.cipher()))
814 sys.stdout.write("Certificate is:\n%s\n" %
815 pprint.pformat(s.getpeercert()))
816 finally:
817 s.close()
818
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000819
820try:
821 import threading
822except ImportError:
823 _have_threads = False
824else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000825 _have_threads = True
826
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000827 from test.ssl_servers import make_https_server
828
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829 class ThreadedEchoServer(threading.Thread):
830
831 class ConnectionHandler(threading.Thread):
832
833 """A mildly complicated class, because we want it to work both
834 with and without the SSL wrapper around the socket connection, so
835 that we can test the STARTTLS functionality."""
836
Bill Janssen6e027db2007-11-15 22:23:56 +0000837 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000838 self.server = server
839 self.running = False
840 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000841 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842 self.sock.setblocking(1)
843 self.sslconn = None
844 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000845 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846
Antoine Pitrou480a1242010-04-28 21:37:09 +0000847 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000849 self.sslconn = self.server.context.wrap_socket(
850 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000851 except ssl.SSLError:
852 # XXX Various errors can have happened here, for example
853 # a mismatching protocol version, an invalid certificate,
854 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000855 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000856 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000857 self.running = False
858 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000859 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000862 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000863 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000864 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
866 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000867 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
869 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000870 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000871 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
872 return True
873
874 def read(self):
875 if self.sslconn:
876 return self.sslconn.read()
877 else:
878 return self.sock.recv(1024)
879
880 def write(self, bytes):
881 if self.sslconn:
882 return self.sslconn.write(bytes)
883 else:
884 return self.sock.send(bytes)
885
886 def close(self):
887 if self.sslconn:
888 self.sslconn.close()
889 else:
890 self.sock.close()
891
Antoine Pitrou480a1242010-04-28 21:37:09 +0000892 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000893 self.running = True
894 if not self.server.starttls_server:
895 if not self.wrap_conn():
896 return
897 while self.running:
898 try:
899 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 stripped = msg.strip()
901 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000902 # eof, so quit this handler
903 self.running = False
904 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000905 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000906 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 sys.stdout.write(" server: client closed connection\n")
908 self.close()
909 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000910 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000911 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000912 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000913 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000914 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 if not self.wrap_conn():
916 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000917 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000918 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000919 if support.verbose and self.server.connectionchatty:
920 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000921 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000922 self.sock = self.sslconn.unwrap()
923 self.sslconn = None
924 if support.verbose and self.server.connectionchatty:
925 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200926 elif stripped == b'CB tls-unique':
927 if support.verbose and self.server.connectionchatty:
928 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
929 data = self.sslconn.get_channel_binding("tls-unique")
930 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000931 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000932 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 self.server.connectionchatty):
934 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000935 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
936 % (msg, ctype, msg.lower(), ctype))
937 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000938 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000939 if self.server.chatty:
940 handle_error("Test server failure:\n")
941 self.close()
942 self.running = False
943 # normally, we'd just stop here, but for the test
944 # harness, we want to stop the server
945 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000946
Antoine Pitroub5218772010-05-21 09:56:06 +0000947 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000948 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000949 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000950 ciphers=None, context=None):
951 if context:
952 self.context = context
953 else:
954 self.context = ssl.SSLContext(ssl_version
955 if ssl_version is not None
956 else ssl.PROTOCOL_TLSv1)
957 self.context.verify_mode = (certreqs if certreqs is not None
958 else ssl.CERT_NONE)
959 if cacerts:
960 self.context.load_verify_locations(cacerts)
961 if certificate:
962 self.context.load_cert_chain(certificate)
963 if ciphers:
964 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000965 self.chatty = chatty
966 self.connectionchatty = connectionchatty
967 self.starttls_server = starttls_server
968 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000969 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000971 self.active = False
972 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000973 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000974
Antoine Pitrou480a1242010-04-28 21:37:09 +0000975 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000976 self.flag = flag
977 threading.Thread.start(self)
978
Antoine Pitrou480a1242010-04-28 21:37:09 +0000979 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000980 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 self.sock.listen(5)
982 self.active = True
983 if self.flag:
984 # signal an event
985 self.flag.set()
986 while self.active:
987 try:
988 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000989 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000991 + repr(connaddr) + '\n')
992 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000993 handler.start()
994 except socket.timeout:
995 pass
996 except KeyboardInterrupt:
997 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000998 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000999
Antoine Pitrou480a1242010-04-28 21:37:09 +00001000 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002
Bill Janssen54cc54c2007-12-14 22:08:56 +00001003 class AsyncoreEchoServer(threading.Thread):
1004
1005 # this one's based on asyncore.dispatcher
1006
1007 class EchoServer (asyncore.dispatcher):
1008
1009 class ConnectionHandler (asyncore.dispatcher_with_send):
1010
1011 def __init__(self, conn, certfile):
1012 self.socket = ssl.wrap_socket(conn, server_side=True,
1013 certfile=certfile,
1014 do_handshake_on_connect=False)
1015 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001016 self._ssl_accepting = True
1017 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001018
1019 def readable(self):
1020 if isinstance(self.socket, ssl.SSLSocket):
1021 while self.socket.pending() > 0:
1022 self.handle_read_event()
1023 return True
1024
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001025 def _do_ssl_handshake(self):
1026 try:
1027 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001028 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1029 return
1030 except ssl.SSLEOFError:
1031 return self.handle_close()
1032 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001033 raise
1034 except socket.error as err:
1035 if err.args[0] == errno.ECONNABORTED:
1036 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001037 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001038 self._ssl_accepting = False
1039
1040 def handle_read(self):
1041 if self._ssl_accepting:
1042 self._do_ssl_handshake()
1043 else:
1044 data = self.recv(1024)
1045 if support.verbose:
1046 sys.stdout.write(" server: read %s from client\n" % repr(data))
1047 if not data:
1048 self.close()
1049 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001050 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001051
1052 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001053 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001054 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001055 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1056
1057 def handle_error(self):
1058 raise
1059
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001060 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001061 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001062 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1063 self.port = support.bind_port(sock, '')
1064 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001065 self.listen(5)
1066
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001067 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001068 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001069 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1070 self.ConnectionHandler(sock_obj, self.certfile)
1071
1072 def handle_error(self):
1073 raise
1074
Trent Nelson78520002008-04-10 20:54:35 +00001075 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001076 self.flag = None
1077 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001078 self.server = self.EchoServer(certfile)
1079 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001080 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001081 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001082
1083 def __str__(self):
1084 return "<%s %s>" % (self.__class__.__name__, self.server)
1085
1086 def start (self, flag=None):
1087 self.flag = flag
1088 threading.Thread.start(self)
1089
Antoine Pitrou480a1242010-04-28 21:37:09 +00001090 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001091 self.active = True
1092 if self.flag:
1093 self.flag.set()
1094 while self.active:
1095 try:
1096 asyncore.loop(1)
1097 except:
1098 pass
1099
Antoine Pitrou480a1242010-04-28 21:37:09 +00001100 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001101 self.active = False
1102 self.server.close()
1103
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 def bad_cert_test(certfile):
1105 """
1106 Launch a server with CERT_REQUIRED, and check that trying to
1107 connect to it with the given client certificate fails.
1108 """
Trent Nelson78520002008-04-10 20:54:35 +00001109 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001110 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001111 cacerts=CERTFILE, chatty=False,
1112 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001113 flag = threading.Event()
1114 server.start(flag)
1115 # wait for it to start
1116 flag.wait()
1117 # try to connect
1118 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001119 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001120 with socket.socket() as sock:
1121 s = ssl.wrap_socket(sock,
1122 certfile=certfile,
1123 ssl_version=ssl.PROTOCOL_TLSv1)
1124 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001126 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001127 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001128 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001129 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001130 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001131 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001132 if x.errno != errno.ENOENT:
1133 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001134 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001135 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001136 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001137 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001138 finally:
1139 server.stop()
1140 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001141
Antoine Pitroub5218772010-05-21 09:56:06 +00001142 def server_params_test(client_context, server_context, indata=b"FOO\n",
1143 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001144 """
1145 Launch a server, connect a client to it and try various reads
1146 and writes.
1147 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001148 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001149 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001150 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001151 flag = threading.Event()
1152 server.start(flag)
1153 # wait for it to start
1154 flag.wait()
1155 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001157 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001158 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001159 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001160 if connectionchatty:
1161 if support.verbose:
1162 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001163 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001164 s.write(arg)
1165 outdata = s.read()
1166 if connectionchatty:
1167 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001168 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001169 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001170 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001171 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1172 % (outdata[:20], len(outdata),
1173 indata[:20].lower(), len(indata)))
1174 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001175 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001176 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001177 sys.stdout.write(" client: closing connection.\n")
1178 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 finally:
1180 server.stop()
1181 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001182
Antoine Pitroub5218772010-05-21 09:56:06 +00001183 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1184 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001185 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001186 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001187 certtype = {
1188 ssl.CERT_NONE: "CERT_NONE",
1189 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1190 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1191 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001192 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001193 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001194 sys.stdout.write(formatstr %
1195 (ssl.get_protocol_name(client_protocol),
1196 ssl.get_protocol_name(server_protocol),
1197 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001198 client_context = ssl.SSLContext(client_protocol)
1199 client_context.options = ssl.OP_ALL | client_options
1200 server_context = ssl.SSLContext(server_protocol)
1201 server_context.options = ssl.OP_ALL | server_options
1202 for ctx in (client_context, server_context):
1203 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001204 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1205 # will send an SSLv3 hello (rather than SSLv2) starting from
1206 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001207 ctx.set_ciphers("ALL")
1208 ctx.load_cert_chain(CERTFILE)
1209 ctx.load_verify_locations(CERTFILE)
1210 try:
1211 server_params_test(client_context, server_context,
1212 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001213 # Protocol mismatch can result in either an SSLError, or a
1214 # "Connection reset by peer" error.
1215 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001217 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001218 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001219 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001220 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001221 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001222 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001223 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001224 "Client protocol %s succeeded with server protocol %s!"
1225 % (ssl.get_protocol_name(client_protocol),
1226 ssl.get_protocol_name(server_protocol)))
1227
1228
Bill Janssen6e027db2007-11-15 22:23:56 +00001229 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001230
Antoine Pitrou23df4832010-08-04 17:14:06 +00001231 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001232 def test_echo(self):
1233 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001234 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001235 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001236 for protocol in PROTOCOLS:
1237 context = ssl.SSLContext(protocol)
1238 context.load_cert_chain(CERTFILE)
1239 server_params_test(context, context,
1240 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001243 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001244 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001245 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1246 context.verify_mode = ssl.CERT_REQUIRED
1247 context.load_verify_locations(CERTFILE)
1248 context.load_cert_chain(CERTFILE)
1249 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001250 flag = threading.Event()
1251 server.start(flag)
1252 # wait for it to start
1253 flag.wait()
1254 # try to connect
1255 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001256 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001257 s.connect((HOST, server.port))
1258 cert = s.getpeercert()
1259 self.assertTrue(cert, "Can't get peer certificate.")
1260 cipher = s.cipher()
1261 if support.verbose:
1262 sys.stdout.write(pprint.pformat(cert) + '\n')
1263 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1264 if 'subject' not in cert:
1265 self.fail("No subject field in certificate: %s." %
1266 pprint.pformat(cert))
1267 if ((('organizationName', 'Python Software Foundation'),)
1268 not in cert['subject']):
1269 self.fail(
1270 "Missing or invalid 'organizationName' field in certificate subject; "
1271 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001272 self.assertIn('notBefore', cert)
1273 self.assertIn('notAfter', cert)
1274 before = ssl.cert_time_to_seconds(cert['notBefore'])
1275 after = ssl.cert_time_to_seconds(cert['notAfter'])
1276 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001277 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001278 finally:
1279 server.stop()
1280 server.join()
1281
Antoine Pitrou480a1242010-04-28 21:37:09 +00001282 def test_empty_cert(self):
1283 """Connecting with an empty cert file"""
1284 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1285 "nullcert.pem"))
1286 def test_malformed_cert(self):
1287 """Connecting with a badly formatted certificate (syntax error)"""
1288 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1289 "badcert.pem"))
1290 def test_nonexisting_cert(self):
1291 """Connecting with a non-existing cert file"""
1292 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1293 "wrongcert.pem"))
1294 def test_malformed_key(self):
1295 """Connecting with a badly formatted key (syntax error)"""
1296 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1297 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001298
Antoine Pitrou480a1242010-04-28 21:37:09 +00001299 def test_rude_shutdown(self):
1300 """A brutal shutdown of an SSL server should raise an IOError
1301 in the client when attempting handshake.
1302 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001303 listener_ready = threading.Event()
1304 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001305
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001306 s = socket.socket()
1307 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001308
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001309 # `listener` runs in a thread. It sits in an accept() until
1310 # the main thread connects. Then it rudely closes the socket,
1311 # and sets Event `listener_gone` to let the main thread know
1312 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001313 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001314 s.listen(5)
1315 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001316 newsock, addr = s.accept()
1317 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001318 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001319 listener_gone.set()
1320
1321 def connector():
1322 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001323 with socket.socket() as c:
1324 c.connect((HOST, port))
1325 listener_gone.wait()
1326 try:
1327 ssl_sock = ssl.wrap_socket(c)
1328 except IOError:
1329 pass
1330 else:
1331 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001332
1333 t = threading.Thread(target=listener)
1334 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001335 try:
1336 connector()
1337 finally:
1338 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001339
Antoine Pitrou23df4832010-08-04 17:14:06 +00001340 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001341 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1342 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001343 def test_protocol_sslv2(self):
1344 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001345 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001346 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001347 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1348 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1349 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1350 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1351 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1352 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001353 # SSLv23 client with specific SSL options
1354 if no_sslv2_implies_sslv3_hello():
1355 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1356 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1357 client_options=ssl.OP_NO_SSLv2)
1358 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1359 client_options=ssl.OP_NO_SSLv3)
1360 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1361 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001362
Antoine Pitrou23df4832010-08-04 17:14:06 +00001363 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001364 def test_protocol_sslv23(self):
1365 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001366 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001367 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001368 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1369 try:
1370 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1371 except (ssl.SSLError, socket.error) as x:
1372 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1373 if support.verbose:
1374 sys.stdout.write(
1375 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1376 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001377 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1378 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1379 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001380
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1382 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1383 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001384
Antoine Pitrou480a1242010-04-28 21:37:09 +00001385 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1386 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1387 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001388
Antoine Pitroub5218772010-05-21 09:56:06 +00001389 # Server with specific SSL options
1390 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1391 server_options=ssl.OP_NO_SSLv3)
1392 # Will choose TLSv1
1393 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1394 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1395 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1396 server_options=ssl.OP_NO_TLSv1)
1397
1398
Antoine Pitrou23df4832010-08-04 17:14:06 +00001399 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 def test_protocol_sslv3(self):
1401 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001402 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001403 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001404 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1405 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1406 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001407 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1408 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001409 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1410 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001411 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001412 if no_sslv2_implies_sslv3_hello():
1413 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1414 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1415 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001416
Antoine Pitrou23df4832010-08-04 17:14:06 +00001417 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 def test_protocol_tlsv1(self):
1419 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001420 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001421 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001422 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1423 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1424 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001425 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1426 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001427 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001428 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1429 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001430
Antoine Pitrou480a1242010-04-28 21:37:09 +00001431 def test_starttls(self):
1432 """Switching from clear text to encrypted and back again."""
1433 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 +00001434
Trent Nelson78520002008-04-10 20:54:35 +00001435 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001436 ssl_version=ssl.PROTOCOL_TLSv1,
1437 starttls_server=True,
1438 chatty=True,
1439 connectionchatty=True)
1440 flag = threading.Event()
1441 server.start(flag)
1442 # wait for it to start
1443 flag.wait()
1444 # try to connect
1445 wrapped = False
1446 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001447 s = socket.socket()
1448 s.setblocking(1)
1449 s.connect((HOST, server.port))
1450 if support.verbose:
1451 sys.stdout.write("\n")
1452 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001453 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001454 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001455 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001456 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001457 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001458 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001459 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001460 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001461 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001462 msg = outdata.strip().lower()
1463 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1464 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001465 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001466 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001467 " client: read %r from server, starting TLS...\n"
1468 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001469 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1470 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001471 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1472 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001473 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001474 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 " client: read %r from server, ending TLS...\n"
1476 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001477 s = conn.unwrap()
1478 wrapped = False
1479 else:
1480 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001481 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001482 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001483 if support.verbose:
1484 sys.stdout.write(" client: closing connection.\n")
1485 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001486 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001487 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001488 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001489 if wrapped:
1490 conn.close()
1491 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001492 s.close()
1493 finally:
1494 server.stop()
1495 server.join()
1496
Antoine Pitrou480a1242010-04-28 21:37:09 +00001497 def test_socketserver(self):
1498 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001499 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001500 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001501 if support.verbose:
1502 sys.stdout.write('\n')
1503 with open(CERTFILE, 'rb') as f:
1504 d1 = f.read()
1505 d2 = ''
1506 # now fetch the same data from the HTTPS server
1507 url = 'https://%s:%d/%s' % (
1508 HOST, server.port, os.path.split(CERTFILE)[1])
1509 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001510 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001511 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001512 if dlen and (int(dlen) > 0):
1513 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001514 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001515 sys.stdout.write(
1516 " client: read %d bytes from remote server '%s'\n"
1517 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001518 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001519 f.close()
1520 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001521
Antoine Pitrou480a1242010-04-28 21:37:09 +00001522 def test_asyncore_server(self):
1523 """Check the example asyncore integration."""
1524 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001525
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001526 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001527 sys.stdout.write("\n")
1528
Antoine Pitrou480a1242010-04-28 21:37:09 +00001529 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001530 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001531 flag = threading.Event()
1532 server.start(flag)
1533 # wait for it to start
1534 flag.wait()
1535 # try to connect
1536 try:
1537 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001538 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001539 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001540 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001541 " client: sending %r...\n" % indata)
1542 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001543 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001544 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001546 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001547 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001548 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1549 % (outdata[:20], len(outdata),
1550 indata[:20].lower(), len(indata)))
1551 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001552 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001553 sys.stdout.write(" client: closing connection.\n")
1554 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001555 if support.verbose:
1556 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001557 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001558 if support.verbose:
1559 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001560 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001561 if support.verbose:
1562 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001563 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001564 if support.verbose:
1565 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001566
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 def test_recv_send(self):
1568 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001569 if support.verbose:
1570 sys.stdout.write("\n")
1571
1572 server = ThreadedEchoServer(CERTFILE,
1573 certreqs=ssl.CERT_NONE,
1574 ssl_version=ssl.PROTOCOL_TLSv1,
1575 cacerts=CERTFILE,
1576 chatty=True,
1577 connectionchatty=False)
1578 flag = threading.Event()
1579 server.start(flag)
1580 # wait for it to start
1581 flag.wait()
1582 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001583 s = ssl.wrap_socket(socket.socket(),
1584 server_side=False,
1585 certfile=CERTFILE,
1586 ca_certs=CERTFILE,
1587 cert_reqs=ssl.CERT_NONE,
1588 ssl_version=ssl.PROTOCOL_TLSv1)
1589 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001590 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001591 # helper methods for standardising recv* method signatures
1592 def _recv_into():
1593 b = bytearray(b"\0"*100)
1594 count = s.recv_into(b)
1595 return b[:count]
1596
1597 def _recvfrom_into():
1598 b = bytearray(b"\0"*100)
1599 count, addr = s.recvfrom_into(b)
1600 return b[:count]
1601
1602 # (name, method, whether to expect success, *args)
1603 send_methods = [
1604 ('send', s.send, True, []),
1605 ('sendto', s.sendto, False, ["some.address"]),
1606 ('sendall', s.sendall, True, []),
1607 ]
1608 recv_methods = [
1609 ('recv', s.recv, True, []),
1610 ('recvfrom', s.recvfrom, False, ["some.address"]),
1611 ('recv_into', _recv_into, True, []),
1612 ('recvfrom_into', _recvfrom_into, False, []),
1613 ]
1614 data_prefix = "PREFIX_"
1615
1616 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001617 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001618 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001619 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001620 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001621 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001622 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001623 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001624 "<<{outdata:r}>> ({nout:d}) received; "
1625 "expected <<{indata:r}>> ({nin:d})\n".format(
1626 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001627 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001628 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001629 )
1630 )
1631 except ValueError as e:
1632 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001633 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001634 "Failed to send with method <<{name:s}>>; "
1635 "expected to succeed.\n".format(name=meth_name)
1636 )
1637 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001638 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001639 "Method <<{name:s}>> failed with unexpected "
1640 "exception message: {exp:s}\n".format(
1641 name=meth_name, exp=e
1642 )
1643 )
1644
1645 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001646 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001647 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001648 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001649 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001650 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001651 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001652 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001653 "<<{outdata:r}>> ({nout:d}) received; "
1654 "expected <<{indata:r}>> ({nin:d})\n".format(
1655 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001656 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001657 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001658 )
1659 )
1660 except ValueError as e:
1661 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001662 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001663 "Failed to receive with method <<{name:s}>>; "
1664 "expected to succeed.\n".format(name=meth_name)
1665 )
1666 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001667 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001668 "Method <<{name:s}>> failed with unexpected "
1669 "exception message: {exp:s}\n".format(
1670 name=meth_name, exp=e
1671 )
1672 )
1673 # consume data
1674 s.read()
1675
Nick Coghlan513886a2011-08-28 00:00:27 +10001676 # Make sure sendmsg et al are disallowed to avoid
1677 # inadvertent disclosure of data and/or corruption
1678 # of the encrypted data stream
1679 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1680 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1681 self.assertRaises(NotImplementedError,
1682 s.recvmsg_into, bytearray(100))
1683
Antoine Pitrou480a1242010-04-28 21:37:09 +00001684 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001685 s.close()
1686 finally:
1687 server.stop()
1688 server.join()
1689
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001690 def test_handshake_timeout(self):
1691 # Issue #5103: SSL handshake must respect the socket timeout
1692 server = socket.socket(socket.AF_INET)
1693 host = "127.0.0.1"
1694 port = support.bind_port(server)
1695 started = threading.Event()
1696 finish = False
1697
1698 def serve():
1699 server.listen(5)
1700 started.set()
1701 conns = []
1702 while not finish:
1703 r, w, e = select.select([server], [], [], 0.1)
1704 if server in r:
1705 # Let the socket hang around rather than having
1706 # it closed by garbage collection.
1707 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001708 for sock in conns:
1709 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001710
1711 t = threading.Thread(target=serve)
1712 t.start()
1713 started.wait()
1714
1715 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001716 try:
1717 c = socket.socket(socket.AF_INET)
1718 c.settimeout(0.2)
1719 c.connect((host, port))
1720 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001721 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001722 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001723 finally:
1724 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001725 try:
1726 c = socket.socket(socket.AF_INET)
1727 c = ssl.wrap_socket(c)
1728 c.settimeout(0.2)
1729 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001730 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001731 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001732 finally:
1733 c.close()
1734 finally:
1735 finish = True
1736 t.join()
1737 server.close()
1738
Antoine Pitroud6494802011-07-21 01:11:30 +02001739 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1740 "'tls-unique' channel binding not available")
1741 def test_tls_unique_channel_binding(self):
1742 """Test tls-unique channel binding."""
1743 if support.verbose:
1744 sys.stdout.write("\n")
1745
1746 server = ThreadedEchoServer(CERTFILE,
1747 certreqs=ssl.CERT_NONE,
1748 ssl_version=ssl.PROTOCOL_TLSv1,
1749 cacerts=CERTFILE,
1750 chatty=True,
1751 connectionchatty=False)
1752 flag = threading.Event()
1753 server.start(flag)
1754 # wait for it to start
1755 flag.wait()
1756 # try to connect
1757 s = ssl.wrap_socket(socket.socket(),
1758 server_side=False,
1759 certfile=CERTFILE,
1760 ca_certs=CERTFILE,
1761 cert_reqs=ssl.CERT_NONE,
1762 ssl_version=ssl.PROTOCOL_TLSv1)
1763 s.connect((HOST, server.port))
1764 try:
1765 # get the data
1766 cb_data = s.get_channel_binding("tls-unique")
1767 if support.verbose:
1768 sys.stdout.write(" got channel binding data: {0!r}\n"
1769 .format(cb_data))
1770
1771 # check if it is sane
1772 self.assertIsNotNone(cb_data)
1773 self.assertEqual(len(cb_data), 12) # True for TLSv1
1774
1775 # and compare with the peers version
1776 s.write(b"CB tls-unique\n")
1777 peer_data_repr = s.read().strip()
1778 self.assertEqual(peer_data_repr,
1779 repr(cb_data).encode("us-ascii"))
1780 s.close()
1781
1782 # now, again
1783 s = ssl.wrap_socket(socket.socket(),
1784 server_side=False,
1785 certfile=CERTFILE,
1786 ca_certs=CERTFILE,
1787 cert_reqs=ssl.CERT_NONE,
1788 ssl_version=ssl.PROTOCOL_TLSv1)
1789 s.connect((HOST, server.port))
1790 new_cb_data = s.get_channel_binding("tls-unique")
1791 if support.verbose:
1792 sys.stdout.write(" got another channel binding data: {0!r}\n"
1793 .format(new_cb_data))
1794 # is it really unique
1795 self.assertNotEqual(cb_data, new_cb_data)
1796 self.assertIsNotNone(cb_data)
1797 self.assertEqual(len(cb_data), 12) # True for TLSv1
1798 s.write(b"CB tls-unique\n")
1799 peer_data_repr = s.read().strip()
1800 self.assertEqual(peer_data_repr,
1801 repr(new_cb_data).encode("us-ascii"))
1802 s.close()
1803 finally:
1804 server.stop()
1805 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001806
Thomas Woutersed03b412007-08-28 21:37:11 +00001807def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001808 if support.verbose:
1809 plats = {
1810 'Linux': platform.linux_distribution,
1811 'Mac': platform.mac_ver,
1812 'Windows': platform.win32_ver,
1813 }
1814 for name, func in plats.items():
1815 plat = func()
1816 if plat and plat[0]:
1817 plat = '%s %r' % (name, plat)
1818 break
1819 else:
1820 plat = repr(platform.platform())
1821 print("test_ssl: testing with %r %r" %
1822 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1823 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001824 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001825
Antoine Pitrou152efa22010-05-16 18:19:27 +00001826 for filename in [
1827 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1828 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1829 BADCERT, BADKEY, EMPTYCERT]:
1830 if not os.path.exists(filename):
1831 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001832
Antoine Pitrou152efa22010-05-16 18:19:27 +00001833 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001834
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001835 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001836 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001837
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001838 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001839 thread_info = support.threading_setup()
1840 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001841 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001842
Antoine Pitrou480a1242010-04-28 21:37:09 +00001843 try:
1844 support.run_unittest(*tests)
1845 finally:
1846 if _have_threads:
1847 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001848
1849if __name__ == "__main__":
1850 test_main()