blob: 4bf7ad88fd58fef2bd3411e4942e129d46a8cad3 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
23PROTOCOLS = [
Victor Stinner3de49192011-05-09 00:42:58 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner3de49192011-05-09 00:42:58 +020027if hasattr(ssl, 'PROTOCOL_SSLv2'):
28 PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
Thomas Woutersed03b412007-08-28 21:37:11 +000029
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Antoine Pitrou81564092010-10-08 23:06:24 +000034# The custom key and certificate files used in test_ssl are generated
35# using Lib/test/make_ssl_certs.py.
36# Other certificates are simply fetched from the Internet servers they
37# are meant to authenticate.
38
Antoine Pitrou152efa22010-05-16 18:19:27 +000039CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020045CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
46ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
47KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000048CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000049BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
52
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020057NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000058
Antoine Pitrou0e576f12011-12-22 10:03:38 +010059DHFILE = data_file("dh512.pem")
60BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000061
Thomas Woutersed03b412007-08-28 21:37:11 +000062def handle_error(prefix):
63 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000064 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000065 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000066
Antoine Pitroub5218772010-05-21 09:56:06 +000067def can_clear_options():
68 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020069 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000070
71def no_sslv2_implies_sslv3_hello():
72 # 0.9.7h or higher
73 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
74
Thomas Woutersed03b412007-08-28 21:37:11 +000075
Antoine Pitrou23df4832010-08-04 17:14:06 +000076# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
77def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020078 if hasattr(ssl, 'PROTOCOL_SSLv2'):
79 @functools.wraps(func)
80 def f(*args, **kwargs):
81 try:
82 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
83 except ssl.SSLError:
84 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
85 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
86 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
87 return func(*args, **kwargs)
88 return f
89 else:
90 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000091
92
Antoine Pitrou152efa22010-05-16 18:19:27 +000093class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020096 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 ssl.PROTOCOL_SSLv23
98 ssl.PROTOCOL_SSLv3
99 ssl.PROTOCOL_TLSv1
100 ssl.CERT_NONE
101 ssl.CERT_OPTIONAL
102 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100103 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100104 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100105 if ssl.HAS_ECDH:
106 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100107 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
108 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000109 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100110 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000111
Antoine Pitrou480a1242010-04-28 21:37:09 +0000112 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n RAND_status is %d (%s)\n"
116 % (v, (v and "sufficient randomness") or
117 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200118
119 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
120 self.assertEqual(len(data), 16)
121 self.assertEqual(is_cryptographic, v == 1)
122 if v:
123 data = ssl.RAND_bytes(16)
124 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200125 else:
126 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200127
Jesus Ceac8754a12012-09-11 02:00:58 +0200128 self.assertRaises(TypeError, ssl.RAND_egd, 1)
129 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000130 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000131
Antoine Pitrou480a1242010-04-28 21:37:09 +0000132 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000133 # note that this uses an 'unofficial' function in _ssl.c,
134 # provided solely for this test, to exercise the certificate
135 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000136 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000137 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200139 self.assertEqual(p['issuer'],
140 ((('countryName', 'XY'),),
141 (('localityName', 'Castle Anthrax'),),
142 (('organizationName', 'Python Software Foundation'),),
143 (('commonName', 'localhost'),))
144 )
145 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
146 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
147 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
148 self.assertEqual(p['subject'],
149 ((('countryName', 'XY'),),
150 (('localityName', 'Castle Anthrax'),),
151 (('organizationName', 'Python Software Foundation'),),
152 (('commonName', 'localhost'),))
153 )
154 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
155 # Issue #13034: the subjectAltName in some certificates
156 # (notably projects.developer.nokia.com:443) wasn't parsed
157 p = ssl._ssl._test_decode_cert(NOKIACERT)
158 if support.verbose:
159 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
160 self.assertEqual(p['subjectAltName'],
161 (('DNS', 'projects.developer.nokia.com'),
162 ('DNS', 'projects.forum.nokia.com'))
163 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000164
Antoine Pitrou480a1242010-04-28 21:37:09 +0000165 def test_DER_to_PEM(self):
166 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
167 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000168 d1 = ssl.PEM_cert_to_DER_cert(pem)
169 p2 = ssl.DER_cert_to_PEM_cert(d1)
170 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000171 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000172 if not p2.startswith(ssl.PEM_HEADER + '\n'):
173 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
174 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
175 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000176
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000177 def test_openssl_version(self):
178 n = ssl.OPENSSL_VERSION_NUMBER
179 t = ssl.OPENSSL_VERSION_INFO
180 s = ssl.OPENSSL_VERSION
181 self.assertIsInstance(n, int)
182 self.assertIsInstance(t, tuple)
183 self.assertIsInstance(s, str)
184 # Some sanity checks follow
185 # >= 0.9
186 self.assertGreaterEqual(n, 0x900000)
187 # < 2.0
188 self.assertLess(n, 0x20000000)
189 major, minor, fix, patch, status = t
190 self.assertGreaterEqual(major, 0)
191 self.assertLess(major, 2)
192 self.assertGreaterEqual(minor, 0)
193 self.assertLess(minor, 256)
194 self.assertGreaterEqual(fix, 0)
195 self.assertLess(fix, 256)
196 self.assertGreaterEqual(patch, 0)
197 self.assertLessEqual(patch, 26)
198 self.assertGreaterEqual(status, 0)
199 self.assertLessEqual(status, 15)
200 # Version string as returned by OpenSSL, the format might change
201 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
202 (s, t))
203
Antoine Pitrou9d543662010-04-23 23:10:32 +0000204 @support.cpython_only
205 def test_refcycle(self):
206 # Issue #7943: an SSL object doesn't create reference cycles with
207 # itself.
208 s = socket.socket(socket.AF_INET)
209 ss = ssl.wrap_socket(s)
210 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100211 with support.check_warnings(("", ResourceWarning)):
212 del ss
213 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000214
Antoine Pitroua468adc2010-09-14 14:43:44 +0000215 def test_wrapped_unconnected(self):
216 # Methods on an unconnected SSLSocket propagate the original
217 # socket.error raise by the underlying socket object.
218 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100219 with ssl.wrap_socket(s) as ss:
220 self.assertRaises(socket.error, ss.recv, 1)
221 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
222 self.assertRaises(socket.error, ss.recvfrom, 1)
223 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
224 self.assertRaises(socket.error, ss.send, b'x')
225 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000226
Antoine Pitrou40f08742010-04-24 22:04:40 +0000227 def test_timeout(self):
228 # Issue #8524: when creating an SSL socket, the timeout of the
229 # original socket should be retained.
230 for timeout in (None, 0.0, 5.0):
231 s = socket.socket(socket.AF_INET)
232 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100233 with ssl.wrap_socket(s) as ss:
234 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000235
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000236 def test_errors(self):
237 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000238 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000239 "certfile must be specified",
240 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000241 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000242 "certfile must be specified for server-side operations",
243 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000244 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000245 "certfile must be specified for server-side operations",
246 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100247 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
248 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
249 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +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=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000253 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +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=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000257 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000258 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000259 with socket.socket() as sock:
260 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000261 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000262
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000263 def test_match_hostname(self):
264 def ok(cert, hostname):
265 ssl.match_hostname(cert, hostname)
266 def fail(cert, hostname):
267 self.assertRaises(ssl.CertificateError,
268 ssl.match_hostname, cert, hostname)
269
270 cert = {'subject': ((('commonName', 'example.com'),),)}
271 ok(cert, 'example.com')
272 ok(cert, 'ExAmple.cOm')
273 fail(cert, 'www.example.com')
274 fail(cert, '.example.com')
275 fail(cert, 'example.org')
276 fail(cert, 'exampleXcom')
277
278 cert = {'subject': ((('commonName', '*.a.com'),),)}
279 ok(cert, 'foo.a.com')
280 fail(cert, 'bar.foo.a.com')
281 fail(cert, 'a.com')
282 fail(cert, 'Xa.com')
283 fail(cert, '.a.com')
284
285 cert = {'subject': ((('commonName', 'a.*.com'),),)}
286 ok(cert, 'a.foo.com')
287 fail(cert, 'a..com')
288 fail(cert, 'a.com')
289
290 cert = {'subject': ((('commonName', 'f*.com'),),)}
291 ok(cert, 'foo.com')
292 ok(cert, 'f.com')
293 fail(cert, 'bar.com')
294 fail(cert, 'foo.a.com')
295 fail(cert, 'bar.foo.com')
296
297 # Slightly fake real-world example
298 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
299 'subject': ((('commonName', 'linuxfrz.org'),),),
300 'subjectAltName': (('DNS', 'linuxfr.org'),
301 ('DNS', 'linuxfr.com'),
302 ('othername', '<unsupported>'))}
303 ok(cert, 'linuxfr.org')
304 ok(cert, 'linuxfr.com')
305 # Not a "DNS" entry
306 fail(cert, '<unsupported>')
307 # When there is a subjectAltName, commonName isn't used
308 fail(cert, 'linuxfrz.org')
309
310 # A pristine real-world example
311 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
312 'subject': ((('countryName', 'US'),),
313 (('stateOrProvinceName', 'California'),),
314 (('localityName', 'Mountain View'),),
315 (('organizationName', 'Google Inc'),),
316 (('commonName', 'mail.google.com'),))}
317 ok(cert, 'mail.google.com')
318 fail(cert, 'gmail.com')
319 # Only commonName is considered
320 fail(cert, 'California')
321
322 # Neither commonName nor subjectAltName
323 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
324 'subject': ((('countryName', 'US'),),
325 (('stateOrProvinceName', 'California'),),
326 (('localityName', 'Mountain View'),),
327 (('organizationName', 'Google Inc'),))}
328 fail(cert, 'mail.google.com')
329
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200330 # No DNS entry in subjectAltName but a commonName
331 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
332 'subject': ((('countryName', 'US'),),
333 (('stateOrProvinceName', 'California'),),
334 (('localityName', 'Mountain View'),),
335 (('commonName', 'mail.google.com'),)),
336 'subjectAltName': (('othername', 'blabla'), )}
337 ok(cert, 'mail.google.com')
338
339 # No DNS entry subjectAltName and no commonName
340 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
341 'subject': ((('countryName', 'US'),),
342 (('stateOrProvinceName', 'California'),),
343 (('localityName', 'Mountain View'),),
344 (('organizationName', 'Google Inc'),)),
345 'subjectAltName': (('othername', 'blabla'),)}
346 fail(cert, 'google.com')
347
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000348 # Empty cert / no cert
349 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
350 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
351
Antoine Pitroud5323212010-10-22 18:19:07 +0000352 def test_server_side(self):
353 # server_hostname doesn't work for server sockets
354 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000355 with socket.socket() as sock:
356 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
357 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000358
Antoine Pitroud6494802011-07-21 01:11:30 +0200359 def test_unknown_channel_binding(self):
360 # should raise ValueError for unknown type
361 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100362 with ssl.wrap_socket(s) as ss:
363 with self.assertRaises(ValueError):
364 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200365
366 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
367 "'tls-unique' channel binding not available")
368 def test_tls_unique_channel_binding(self):
369 # unconnected should return None for known type
370 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100371 with ssl.wrap_socket(s) as ss:
372 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200373 # the same for server-side
374 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100375 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
376 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200377
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600378 def test_dealloc_warn(self):
379 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
380 r = repr(ss)
381 with self.assertWarns(ResourceWarning) as cm:
382 ss = None
383 support.gc_collect()
384 self.assertIn(r, str(cm.warning.args[0]))
385
Antoine Pitrou152efa22010-05-16 18:19:27 +0000386class ContextTests(unittest.TestCase):
387
Antoine Pitrou23df4832010-08-04 17:14:06 +0000388 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000389 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200390 if hasattr(ssl, 'PROTOCOL_SSLv2'):
391 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000392 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
393 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
394 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
395 self.assertRaises(TypeError, ssl.SSLContext)
396 self.assertRaises(ValueError, ssl.SSLContext, -1)
397 self.assertRaises(ValueError, ssl.SSLContext, 42)
398
Antoine Pitrou23df4832010-08-04 17:14:06 +0000399 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000400 def test_protocol(self):
401 for proto in PROTOCOLS:
402 ctx = ssl.SSLContext(proto)
403 self.assertEqual(ctx.protocol, proto)
404
405 def test_ciphers(self):
406 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
407 ctx.set_ciphers("ALL")
408 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000409 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000410 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000411
Antoine Pitrou23df4832010-08-04 17:14:06 +0000412 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000413 def test_options(self):
414 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
415 # OP_ALL is the default value
416 self.assertEqual(ssl.OP_ALL, ctx.options)
417 ctx.options |= ssl.OP_NO_SSLv2
418 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
419 ctx.options)
420 ctx.options |= ssl.OP_NO_SSLv3
421 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
422 ctx.options)
423 if can_clear_options():
424 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
425 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
426 ctx.options)
427 ctx.options = 0
428 self.assertEqual(0, ctx.options)
429 else:
430 with self.assertRaises(ValueError):
431 ctx.options = 0
432
Antoine Pitrou152efa22010-05-16 18:19:27 +0000433 def test_verify(self):
434 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
435 # Default value
436 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
437 ctx.verify_mode = ssl.CERT_OPTIONAL
438 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
439 ctx.verify_mode = ssl.CERT_REQUIRED
440 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
441 ctx.verify_mode = ssl.CERT_NONE
442 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
443 with self.assertRaises(TypeError):
444 ctx.verify_mode = None
445 with self.assertRaises(ValueError):
446 ctx.verify_mode = 42
447
448 def test_load_cert_chain(self):
449 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
450 # Combined key and cert in a single file
451 ctx.load_cert_chain(CERTFILE)
452 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
453 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000454 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000455 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000456 self.assertEqual(cm.exception.errno, errno.ENOENT)
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(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000459 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000460 ctx.load_cert_chain(EMPTYCERT)
461 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000462 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000463 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
464 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
465 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000466 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000467 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000468 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000469 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000470 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000471 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
472 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000473 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000474 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000475 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200476 # Password protected key and cert
477 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
478 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
479 ctx.load_cert_chain(CERTFILE_PROTECTED,
480 password=bytearray(KEY_PASSWORD.encode()))
481 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
482 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
483 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
484 bytearray(KEY_PASSWORD.encode()))
485 with self.assertRaisesRegex(TypeError, "should be a string"):
486 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
487 with self.assertRaises(ssl.SSLError):
488 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
489 with self.assertRaisesRegex(ValueError, "cannot be longer"):
490 # openssl has a fixed limit on the password buffer.
491 # PEM_BUFSIZE is generally set to 1kb.
492 # Return a string larger than this.
493 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
494 # Password callback
495 def getpass_unicode():
496 return KEY_PASSWORD
497 def getpass_bytes():
498 return KEY_PASSWORD.encode()
499 def getpass_bytearray():
500 return bytearray(KEY_PASSWORD.encode())
501 def getpass_badpass():
502 return "badpass"
503 def getpass_huge():
504 return b'a' * (1024 * 1024)
505 def getpass_bad_type():
506 return 9
507 def getpass_exception():
508 raise Exception('getpass error')
509 class GetPassCallable:
510 def __call__(self):
511 return KEY_PASSWORD
512 def getpass(self):
513 return KEY_PASSWORD
514 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
515 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
516 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
517 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
518 ctx.load_cert_chain(CERTFILE_PROTECTED,
519 password=GetPassCallable().getpass)
520 with self.assertRaises(ssl.SSLError):
521 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
522 with self.assertRaisesRegex(ValueError, "cannot be longer"):
523 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
524 with self.assertRaisesRegex(TypeError, "must return a string"):
525 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
526 with self.assertRaisesRegex(Exception, "getpass error"):
527 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
528 # Make sure the password function isn't called if it isn't needed
529 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000530
531 def test_load_verify_locations(self):
532 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
533 ctx.load_verify_locations(CERTFILE)
534 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
535 ctx.load_verify_locations(BYTES_CERTFILE)
536 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
537 self.assertRaises(TypeError, ctx.load_verify_locations)
538 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000539 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000540 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000541 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000542 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000543 ctx.load_verify_locations(BADCERT)
544 ctx.load_verify_locations(CERTFILE, CAPATH)
545 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
546
Victor Stinner80f75e62011-01-29 11:31:20 +0000547 # Issue #10989: crash if the second argument type is invalid
548 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
549
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100550 def test_load_dh_params(self):
551 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
552 ctx.load_dh_params(DHFILE)
553 if os.name != 'nt':
554 ctx.load_dh_params(BYTES_DHFILE)
555 self.assertRaises(TypeError, ctx.load_dh_params)
556 self.assertRaises(TypeError, ctx.load_dh_params, None)
557 with self.assertRaises(FileNotFoundError) as cm:
558 ctx.load_dh_params(WRONGCERT)
559 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200560 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100561 ctx.load_dh_params(CERTFILE)
562
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000563 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000564 def test_session_stats(self):
565 for proto in PROTOCOLS:
566 ctx = ssl.SSLContext(proto)
567 self.assertEqual(ctx.session_stats(), {
568 'number': 0,
569 'connect': 0,
570 'connect_good': 0,
571 'connect_renegotiate': 0,
572 'accept': 0,
573 'accept_good': 0,
574 'accept_renegotiate': 0,
575 'hits': 0,
576 'misses': 0,
577 'timeouts': 0,
578 'cache_full': 0,
579 })
580
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000581 def test_set_default_verify_paths(self):
582 # There's not much we can do to test that it acts as expected,
583 # so just check it doesn't crash or raise an exception.
584 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
585 ctx.set_default_verify_paths()
586
Antoine Pitrou501da612011-12-21 09:27:41 +0100587 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100588 def test_set_ecdh_curve(self):
589 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
590 ctx.set_ecdh_curve("prime256v1")
591 ctx.set_ecdh_curve(b"prime256v1")
592 self.assertRaises(TypeError, ctx.set_ecdh_curve)
593 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
594 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
595 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
596
Antoine Pitrou152efa22010-05-16 18:19:27 +0000597
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200598class SSLErrorTests(unittest.TestCase):
599
600 def test_str(self):
601 # The str() of a SSLError doesn't include the errno
602 e = ssl.SSLError(1, "foo")
603 self.assertEqual(str(e), "foo")
604 self.assertEqual(e.errno, 1)
605 # Same for a subclass
606 e = ssl.SSLZeroReturnError(1, "foo")
607 self.assertEqual(str(e), "foo")
608 self.assertEqual(e.errno, 1)
609
610 def test_lib_reason(self):
611 # Test the library and reason attributes
612 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
613 with self.assertRaises(ssl.SSLError) as cm:
614 ctx.load_dh_params(CERTFILE)
615 self.assertEqual(cm.exception.library, 'PEM')
616 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
617 s = str(cm.exception)
618 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
619
620 def test_subclass(self):
621 # Check that the appropriate SSLError subclass is raised
622 # (this only tests one of them)
623 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
624 with socket.socket() as s:
625 s.bind(("127.0.0.1", 0))
626 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100627 c = socket.socket()
628 c.connect(s.getsockname())
629 c.setblocking(False)
630 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200631 with self.assertRaises(ssl.SSLWantReadError) as cm:
632 c.do_handshake()
633 s = str(cm.exception)
634 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
635 # For compatibility
636 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
637
638
Bill Janssen6e027db2007-11-15 22:23:56 +0000639class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000640
Antoine Pitrou480a1242010-04-28 21:37:09 +0000641 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000642 with support.transient_internet("svn.python.org"):
643 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
644 cert_reqs=ssl.CERT_NONE)
645 try:
646 s.connect(("svn.python.org", 443))
647 self.assertEqual({}, s.getpeercert())
648 finally:
649 s.close()
650
651 # this should fail because we have no verification certs
652 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
653 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000654 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
655 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000656 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657
Antoine Pitrou350c7222010-09-09 13:31:46 +0000658 # this should succeed because we specify the root cert
659 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
660 cert_reqs=ssl.CERT_REQUIRED,
661 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
662 try:
663 s.connect(("svn.python.org", 443))
664 self.assertTrue(s.getpeercert())
665 finally:
666 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000667
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000668 def test_connect_ex(self):
669 # Issue #11326: check connect_ex() implementation
670 with support.transient_internet("svn.python.org"):
671 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
672 cert_reqs=ssl.CERT_REQUIRED,
673 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
674 try:
675 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
676 self.assertTrue(s.getpeercert())
677 finally:
678 s.close()
679
680 def test_non_blocking_connect_ex(self):
681 # Issue #11326: non-blocking connect_ex() should allow handshake
682 # to proceed after the socket gets ready.
683 with support.transient_internet("svn.python.org"):
684 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
685 cert_reqs=ssl.CERT_REQUIRED,
686 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
687 do_handshake_on_connect=False)
688 try:
689 s.setblocking(False)
690 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000691 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
692 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000693 # Wait for connect to finish
694 select.select([], [s], [], 5.0)
695 # Non-blocking handshake
696 while True:
697 try:
698 s.do_handshake()
699 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200700 except ssl.SSLWantReadError:
701 select.select([s], [], [], 5.0)
702 except ssl.SSLWantWriteError:
703 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000704 # SSL established
705 self.assertTrue(s.getpeercert())
706 finally:
707 s.close()
708
Antoine Pitroub4410db2011-05-18 18:51:06 +0200709 def test_timeout_connect_ex(self):
710 # Issue #12065: on a timeout, connect_ex() should return the original
711 # errno (mimicking the behaviour of non-SSL sockets).
712 with support.transient_internet("svn.python.org"):
713 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
714 cert_reqs=ssl.CERT_REQUIRED,
715 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
716 do_handshake_on_connect=False)
717 try:
718 s.settimeout(0.0000001)
719 rc = s.connect_ex(('svn.python.org', 443))
720 if rc == 0:
721 self.skipTest("svn.python.org responded too quickly")
722 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
723 finally:
724 s.close()
725
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100726 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100727 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100728 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
729 cert_reqs=ssl.CERT_REQUIRED,
730 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
731 try:
732 self.assertEqual(errno.ECONNREFUSED,
733 s.connect_ex(("svn.python.org", 444)))
734 finally:
735 s.close()
736
Antoine Pitrou152efa22010-05-16 18:19:27 +0000737 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000738 with support.transient_internet("svn.python.org"):
739 # Same as test_connect, but with a separately created context
740 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
741 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
742 s.connect(("svn.python.org", 443))
743 try:
744 self.assertEqual({}, s.getpeercert())
745 finally:
746 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000747 # Same with a server hostname
748 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
749 server_hostname="svn.python.org")
750 if ssl.HAS_SNI:
751 s.connect(("svn.python.org", 443))
752 s.close()
753 else:
754 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000755 # This should fail because we have no verification certs
756 ctx.verify_mode = ssl.CERT_REQUIRED
757 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000758 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000759 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000760 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000761 # This should succeed because we specify the root cert
762 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
763 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
764 s.connect(("svn.python.org", 443))
765 try:
766 cert = s.getpeercert()
767 self.assertTrue(cert)
768 finally:
769 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000770
771 def test_connect_capath(self):
772 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000773 # NOTE: the subject hashing algorithm has been changed between
774 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
775 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000776 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000777 with support.transient_internet("svn.python.org"):
778 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
779 ctx.verify_mode = ssl.CERT_REQUIRED
780 ctx.load_verify_locations(capath=CAPATH)
781 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
782 s.connect(("svn.python.org", 443))
783 try:
784 cert = s.getpeercert()
785 self.assertTrue(cert)
786 finally:
787 s.close()
788 # Same with a bytes `capath` argument
789 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
790 ctx.verify_mode = ssl.CERT_REQUIRED
791 ctx.load_verify_locations(capath=BYTES_CAPATH)
792 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
793 s.connect(("svn.python.org", 443))
794 try:
795 cert = s.getpeercert()
796 self.assertTrue(cert)
797 finally:
798 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000799
Antoine Pitroue3220242010-04-24 11:13:53 +0000800 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
801 def test_makefile_close(self):
802 # Issue #5238: creating a file-like object with makefile() shouldn't
803 # delay closing the underlying "real socket" (here tested with its
804 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000805 with support.transient_internet("svn.python.org"):
806 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
807 ss.connect(("svn.python.org", 443))
808 fd = ss.fileno()
809 f = ss.makefile()
810 f.close()
811 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000812 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000813 # Closing the SSL socket should close the fd too
814 ss.close()
815 gc.collect()
816 with self.assertRaises(OSError) as e:
817 os.read(fd, 0)
818 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000819
Antoine Pitrou480a1242010-04-28 21:37:09 +0000820 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000821 with support.transient_internet("svn.python.org"):
822 s = socket.socket(socket.AF_INET)
823 s.connect(("svn.python.org", 443))
824 s.setblocking(False)
825 s = ssl.wrap_socket(s,
826 cert_reqs=ssl.CERT_NONE,
827 do_handshake_on_connect=False)
828 count = 0
829 while True:
830 try:
831 count += 1
832 s.do_handshake()
833 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200834 except ssl.SSLWantReadError:
835 select.select([s], [], [])
836 except ssl.SSLWantWriteError:
837 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000838 s.close()
839 if support.verbose:
840 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000841
Antoine Pitrou480a1242010-04-28 21:37:09 +0000842 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200843 def _test_get_server_certificate(host, port, cert=None):
844 with support.transient_internet(host):
845 pem = ssl.get_server_certificate((host, port))
846 if not pem:
847 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200848
Antoine Pitrou15399c32011-04-28 19:23:55 +0200849 try:
850 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
851 except ssl.SSLError as x:
852 #should fail
853 if support.verbose:
854 sys.stdout.write("%s\n" % x)
855 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200856 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
857
Antoine Pitrou15399c32011-04-28 19:23:55 +0200858 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
859 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200860 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000861 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200862 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000863
Antoine Pitrou15399c32011-04-28 19:23:55 +0200864 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
865 if support.IPV6_ENABLED:
866 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000867
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000868 def test_ciphers(self):
869 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000870 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100871 with ssl.wrap_socket(socket.socket(socket.AF_INET),
872 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
873 s.connect(remote)
874 with ssl.wrap_socket(socket.socket(socket.AF_INET),
875 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
876 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000877 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000878 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000879 with socket.socket(socket.AF_INET) as sock:
880 s = ssl.wrap_socket(sock,
881 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
882 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000883
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000884 def test_algorithms(self):
885 # Issue #8484: all algorithms should be available when verifying a
886 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000887 # SHA256 was added in OpenSSL 0.9.8
888 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
889 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200890 # sha256.tbs-internet.com needs SNI to use the correct certificate
891 if not ssl.HAS_SNI:
892 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000893 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
894 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000895 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000896 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200897 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
898 ctx.verify_mode = ssl.CERT_REQUIRED
899 ctx.load_verify_locations(sha256_cert)
900 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
901 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000902 try:
903 s.connect(remote)
904 if support.verbose:
905 sys.stdout.write("\nCipher with %r is %r\n" %
906 (remote, s.cipher()))
907 sys.stdout.write("Certificate is:\n%s\n" %
908 pprint.pformat(s.getpeercert()))
909 finally:
910 s.close()
911
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912
913try:
914 import threading
915except ImportError:
916 _have_threads = False
917else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918 _have_threads = True
919
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000920 from test.ssl_servers import make_https_server
921
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 class ThreadedEchoServer(threading.Thread):
923
924 class ConnectionHandler(threading.Thread):
925
926 """A mildly complicated class, because we want it to work both
927 with and without the SSL wrapper around the socket connection, so
928 that we can test the STARTTLS functionality."""
929
Bill Janssen6e027db2007-11-15 22:23:56 +0000930 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000931 self.server = server
932 self.running = False
933 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000934 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 self.sock.setblocking(1)
936 self.sslconn = None
937 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000938 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000939
Antoine Pitrou480a1242010-04-28 21:37:09 +0000940 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000942 self.sslconn = self.server.context.wrap_socket(
943 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100944 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100945 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000946 # XXX Various errors can have happened here, for example
947 # a mismatching protocol version, an invalid certificate,
948 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100949 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000950 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000951 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000952 self.running = False
953 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000954 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000956 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000957 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000958 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000959 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
961 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000962 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
964 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000965 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000966 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100967 sys.stdout.write(" server: selected protocol is now "
968 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000969 return True
970
971 def read(self):
972 if self.sslconn:
973 return self.sslconn.read()
974 else:
975 return self.sock.recv(1024)
976
977 def write(self, bytes):
978 if self.sslconn:
979 return self.sslconn.write(bytes)
980 else:
981 return self.sock.send(bytes)
982
983 def close(self):
984 if self.sslconn:
985 self.sslconn.close()
986 else:
987 self.sock.close()
988
Antoine Pitrou480a1242010-04-28 21:37:09 +0000989 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 self.running = True
991 if not self.server.starttls_server:
992 if not self.wrap_conn():
993 return
994 while self.running:
995 try:
996 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000997 stripped = msg.strip()
998 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000999 # eof, so quit this handler
1000 self.running = False
1001 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001002 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001003 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004 sys.stdout.write(" server: client closed connection\n")
1005 self.close()
1006 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001007 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001008 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001009 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001010 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001011 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001012 if not self.wrap_conn():
1013 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001014 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001015 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001016 if support.verbose and self.server.connectionchatty:
1017 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001018 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001019 self.sock = self.sslconn.unwrap()
1020 self.sslconn = None
1021 if support.verbose and self.server.connectionchatty:
1022 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001023 elif stripped == b'CB tls-unique':
1024 if support.verbose and self.server.connectionchatty:
1025 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1026 data = self.sslconn.get_channel_binding("tls-unique")
1027 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001028 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001029 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001030 self.server.connectionchatty):
1031 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001032 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1033 % (msg, ctype, msg.lower(), ctype))
1034 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001035 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001036 if self.server.chatty:
1037 handle_error("Test server failure:\n")
1038 self.close()
1039 self.running = False
1040 # normally, we'd just stop here, but for the test
1041 # harness, we want to stop the server
1042 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001043
Antoine Pitroub5218772010-05-21 09:56:06 +00001044 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001045 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001046 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001047 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001048 if context:
1049 self.context = context
1050 else:
1051 self.context = ssl.SSLContext(ssl_version
1052 if ssl_version is not None
1053 else ssl.PROTOCOL_TLSv1)
1054 self.context.verify_mode = (certreqs if certreqs is not None
1055 else ssl.CERT_NONE)
1056 if cacerts:
1057 self.context.load_verify_locations(cacerts)
1058 if certificate:
1059 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001060 if npn_protocols:
1061 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001062 if ciphers:
1063 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001064 self.chatty = chatty
1065 self.connectionchatty = connectionchatty
1066 self.starttls_server = starttls_server
1067 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001068 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001069 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001070 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001071 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001072 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001074 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001075
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001076 def __enter__(self):
1077 self.start(threading.Event())
1078 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001079 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001080
1081 def __exit__(self, *args):
1082 self.stop()
1083 self.join()
1084
Antoine Pitrou480a1242010-04-28 21:37:09 +00001085 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086 self.flag = flag
1087 threading.Thread.start(self)
1088
Antoine Pitrou480a1242010-04-28 21:37:09 +00001089 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001090 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001091 self.sock.listen(5)
1092 self.active = True
1093 if self.flag:
1094 # signal an event
1095 self.flag.set()
1096 while self.active:
1097 try:
1098 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001099 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001100 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001101 + repr(connaddr) + '\n')
1102 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001103 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001104 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001105 except socket.timeout:
1106 pass
1107 except KeyboardInterrupt:
1108 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001109 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001110
Antoine Pitrou480a1242010-04-28 21:37:09 +00001111 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001113
Bill Janssen54cc54c2007-12-14 22:08:56 +00001114 class AsyncoreEchoServer(threading.Thread):
1115
1116 # this one's based on asyncore.dispatcher
1117
1118 class EchoServer (asyncore.dispatcher):
1119
1120 class ConnectionHandler (asyncore.dispatcher_with_send):
1121
1122 def __init__(self, conn, certfile):
1123 self.socket = ssl.wrap_socket(conn, server_side=True,
1124 certfile=certfile,
1125 do_handshake_on_connect=False)
1126 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001127 self._ssl_accepting = True
1128 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001129
1130 def readable(self):
1131 if isinstance(self.socket, ssl.SSLSocket):
1132 while self.socket.pending() > 0:
1133 self.handle_read_event()
1134 return True
1135
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001136 def _do_ssl_handshake(self):
1137 try:
1138 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001139 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1140 return
1141 except ssl.SSLEOFError:
1142 return self.handle_close()
1143 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001144 raise
1145 except socket.error as err:
1146 if err.args[0] == errno.ECONNABORTED:
1147 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001148 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001149 self._ssl_accepting = False
1150
1151 def handle_read(self):
1152 if self._ssl_accepting:
1153 self._do_ssl_handshake()
1154 else:
1155 data = self.recv(1024)
1156 if support.verbose:
1157 sys.stdout.write(" server: read %s from client\n" % repr(data))
1158 if not data:
1159 self.close()
1160 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001161 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001162
1163 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001164 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001165 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001166 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1167
1168 def handle_error(self):
1169 raise
1170
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001171 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001172 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001173 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1174 self.port = support.bind_port(sock, '')
1175 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001176 self.listen(5)
1177
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001178 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001179 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001180 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1181 self.ConnectionHandler(sock_obj, self.certfile)
1182
1183 def handle_error(self):
1184 raise
1185
Trent Nelson78520002008-04-10 20:54:35 +00001186 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001187 self.flag = None
1188 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001189 self.server = self.EchoServer(certfile)
1190 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001191 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001192 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001193
1194 def __str__(self):
1195 return "<%s %s>" % (self.__class__.__name__, self.server)
1196
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001197 def __enter__(self):
1198 self.start(threading.Event())
1199 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001200 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001201
1202 def __exit__(self, *args):
1203 if support.verbose:
1204 sys.stdout.write(" cleanup: stopping server.\n")
1205 self.stop()
1206 if support.verbose:
1207 sys.stdout.write(" cleanup: joining server thread.\n")
1208 self.join()
1209 if support.verbose:
1210 sys.stdout.write(" cleanup: successfully joined.\n")
1211
Bill Janssen54cc54c2007-12-14 22:08:56 +00001212 def start (self, flag=None):
1213 self.flag = flag
1214 threading.Thread.start(self)
1215
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001217 self.active = True
1218 if self.flag:
1219 self.flag.set()
1220 while self.active:
1221 try:
1222 asyncore.loop(1)
1223 except:
1224 pass
1225
Antoine Pitrou480a1242010-04-28 21:37:09 +00001226 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001227 self.active = False
1228 self.server.close()
1229
Antoine Pitrou480a1242010-04-28 21:37:09 +00001230 def bad_cert_test(certfile):
1231 """
1232 Launch a server with CERT_REQUIRED, and check that trying to
1233 connect to it with the given client certificate fails.
1234 """
Trent Nelson78520002008-04-10 20:54:35 +00001235 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001236 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001237 cacerts=CERTFILE, chatty=False,
1238 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001239 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001240 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001241 with socket.socket() as sock:
1242 s = ssl.wrap_socket(sock,
1243 certfile=certfile,
1244 ssl_version=ssl.PROTOCOL_TLSv1)
1245 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001246 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001247 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001248 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001249 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001250 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001251 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001252 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001253 if x.errno != errno.ENOENT:
1254 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001255 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001256 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001257 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001258 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001259
Antoine Pitroub5218772010-05-21 09:56:06 +00001260 def server_params_test(client_context, server_context, indata=b"FOO\n",
1261 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001262 """
1263 Launch a server, connect a client to it and try various reads
1264 and writes.
1265 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001266 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001267 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001268 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001269 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001270 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001271 with client_context.wrap_socket(socket.socket()) as s:
1272 s.connect((HOST, server.port))
1273 for arg in [indata, bytearray(indata), memoryview(indata)]:
1274 if connectionchatty:
1275 if support.verbose:
1276 sys.stdout.write(
1277 " client: sending %r...\n" % indata)
1278 s.write(arg)
1279 outdata = s.read()
1280 if connectionchatty:
1281 if support.verbose:
1282 sys.stdout.write(" client: read %r\n" % outdata)
1283 if outdata != indata.lower():
1284 raise AssertionError(
1285 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1286 % (outdata[:20], len(outdata),
1287 indata[:20].lower(), len(indata)))
1288 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001289 if connectionchatty:
1290 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001291 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001292 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001293 'compression': s.compression(),
1294 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001295 'client_npn_protocol': s.selected_npn_protocol()
1296 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001297 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001298 stats['server_npn_protocols'] = server.selected_protocols
1299 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001300
Antoine Pitroub5218772010-05-21 09:56:06 +00001301 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1302 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001303 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001304 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001305 certtype = {
1306 ssl.CERT_NONE: "CERT_NONE",
1307 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1308 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1309 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001310 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001311 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001312 sys.stdout.write(formatstr %
1313 (ssl.get_protocol_name(client_protocol),
1314 ssl.get_protocol_name(server_protocol),
1315 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001316 client_context = ssl.SSLContext(client_protocol)
1317 client_context.options = ssl.OP_ALL | client_options
1318 server_context = ssl.SSLContext(server_protocol)
1319 server_context.options = ssl.OP_ALL | server_options
1320 for ctx in (client_context, server_context):
1321 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001322 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1323 # will send an SSLv3 hello (rather than SSLv2) starting from
1324 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001325 ctx.set_ciphers("ALL")
1326 ctx.load_cert_chain(CERTFILE)
1327 ctx.load_verify_locations(CERTFILE)
1328 try:
1329 server_params_test(client_context, server_context,
1330 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001331 # Protocol mismatch can result in either an SSLError, or a
1332 # "Connection reset by peer" error.
1333 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001334 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001335 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001336 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001337 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001338 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001339 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001340 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001341 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001342 "Client protocol %s succeeded with server protocol %s!"
1343 % (ssl.get_protocol_name(client_protocol),
1344 ssl.get_protocol_name(server_protocol)))
1345
1346
Bill Janssen6e027db2007-11-15 22:23:56 +00001347 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001348
Antoine Pitrou23df4832010-08-04 17:14:06 +00001349 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001350 def test_echo(self):
1351 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001352 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001353 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001354 for protocol in PROTOCOLS:
1355 context = ssl.SSLContext(protocol)
1356 context.load_cert_chain(CERTFILE)
1357 server_params_test(context, context,
1358 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001359
Antoine Pitrou480a1242010-04-28 21:37:09 +00001360 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001361 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001362 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001363 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1364 context.verify_mode = ssl.CERT_REQUIRED
1365 context.load_verify_locations(CERTFILE)
1366 context.load_cert_chain(CERTFILE)
1367 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001368 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001369 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001370 s.connect((HOST, server.port))
1371 cert = s.getpeercert()
1372 self.assertTrue(cert, "Can't get peer certificate.")
1373 cipher = s.cipher()
1374 if support.verbose:
1375 sys.stdout.write(pprint.pformat(cert) + '\n')
1376 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1377 if 'subject' not in cert:
1378 self.fail("No subject field in certificate: %s." %
1379 pprint.pformat(cert))
1380 if ((('organizationName', 'Python Software Foundation'),)
1381 not in cert['subject']):
1382 self.fail(
1383 "Missing or invalid 'organizationName' field in certificate subject; "
1384 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001385 self.assertIn('notBefore', cert)
1386 self.assertIn('notAfter', cert)
1387 before = ssl.cert_time_to_seconds(cert['notBefore'])
1388 after = ssl.cert_time_to_seconds(cert['notAfter'])
1389 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001390 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001391
Antoine Pitrou480a1242010-04-28 21:37:09 +00001392 def test_empty_cert(self):
1393 """Connecting with an empty cert file"""
1394 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1395 "nullcert.pem"))
1396 def test_malformed_cert(self):
1397 """Connecting with a badly formatted certificate (syntax error)"""
1398 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1399 "badcert.pem"))
1400 def test_nonexisting_cert(self):
1401 """Connecting with a non-existing cert file"""
1402 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1403 "wrongcert.pem"))
1404 def test_malformed_key(self):
1405 """Connecting with a badly formatted key (syntax error)"""
1406 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1407 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001408
Antoine Pitrou480a1242010-04-28 21:37:09 +00001409 def test_rude_shutdown(self):
1410 """A brutal shutdown of an SSL server should raise an IOError
1411 in the client when attempting handshake.
1412 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001413 listener_ready = threading.Event()
1414 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001415
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001416 s = socket.socket()
1417 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001418
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001419 # `listener` runs in a thread. It sits in an accept() until
1420 # the main thread connects. Then it rudely closes the socket,
1421 # and sets Event `listener_gone` to let the main thread know
1422 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001423 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001424 s.listen(5)
1425 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001426 newsock, addr = s.accept()
1427 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001428 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001429 listener_gone.set()
1430
1431 def connector():
1432 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001433 with socket.socket() as c:
1434 c.connect((HOST, port))
1435 listener_gone.wait()
1436 try:
1437 ssl_sock = ssl.wrap_socket(c)
1438 except IOError:
1439 pass
1440 else:
1441 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001442
1443 t = threading.Thread(target=listener)
1444 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001445 try:
1446 connector()
1447 finally:
1448 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001449
Antoine Pitrou23df4832010-08-04 17:14:06 +00001450 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001451 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1452 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001453 def test_protocol_sslv2(self):
1454 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001455 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001456 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001457 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1458 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1459 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1460 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1461 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1462 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001463 # SSLv23 client with specific SSL options
1464 if no_sslv2_implies_sslv3_hello():
1465 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1466 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1467 client_options=ssl.OP_NO_SSLv2)
1468 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1469 client_options=ssl.OP_NO_SSLv3)
1470 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1471 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001472
Antoine Pitrou23df4832010-08-04 17:14:06 +00001473 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001474 def test_protocol_sslv23(self):
1475 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001476 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001477 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001478 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1479 try:
1480 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1481 except (ssl.SSLError, socket.error) as x:
1482 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1483 if support.verbose:
1484 sys.stdout.write(
1485 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1486 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001487 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1488 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1489 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001490
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1492 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1493 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001494
Antoine Pitrou480a1242010-04-28 21:37:09 +00001495 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1496 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1497 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001498
Antoine Pitroub5218772010-05-21 09:56:06 +00001499 # Server with specific SSL options
1500 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1501 server_options=ssl.OP_NO_SSLv3)
1502 # Will choose TLSv1
1503 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1504 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1505 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1506 server_options=ssl.OP_NO_TLSv1)
1507
1508
Antoine Pitrou23df4832010-08-04 17:14:06 +00001509 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001510 def test_protocol_sslv3(self):
1511 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001512 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001513 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001514 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1515 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1516 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001517 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1518 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001519 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1520 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001521 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001522 if no_sslv2_implies_sslv3_hello():
1523 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1524 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1525 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001526
Antoine Pitrou23df4832010-08-04 17:14:06 +00001527 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001528 def test_protocol_tlsv1(self):
1529 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001530 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001531 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001532 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1533 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1534 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001535 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1536 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001537 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001538 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1539 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001540
Antoine Pitrou480a1242010-04-28 21:37:09 +00001541 def test_starttls(self):
1542 """Switching from clear text to encrypted and back again."""
1543 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 +00001544
Trent Nelson78520002008-04-10 20:54:35 +00001545 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001546 ssl_version=ssl.PROTOCOL_TLSv1,
1547 starttls_server=True,
1548 chatty=True,
1549 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001550 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001551 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001552 s = socket.socket()
1553 s.setblocking(1)
1554 s.connect((HOST, server.port))
1555 if support.verbose:
1556 sys.stdout.write("\n")
1557 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001558 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001559 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001560 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001561 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001562 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001563 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001564 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001565 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001566 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 msg = outdata.strip().lower()
1568 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1569 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001570 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001571 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001572 " client: read %r from server, starting TLS...\n"
1573 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001574 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1575 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001576 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1577 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001578 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001579 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001580 " client: read %r from server, ending TLS...\n"
1581 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001582 s = conn.unwrap()
1583 wrapped = False
1584 else:
1585 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001586 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001587 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001588 if support.verbose:
1589 sys.stdout.write(" client: closing connection.\n")
1590 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001591 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001592 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001593 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001594 if wrapped:
1595 conn.close()
1596 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001597 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001598
Antoine Pitrou480a1242010-04-28 21:37:09 +00001599 def test_socketserver(self):
1600 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001601 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001602 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001603 if support.verbose:
1604 sys.stdout.write('\n')
1605 with open(CERTFILE, 'rb') as f:
1606 d1 = f.read()
1607 d2 = ''
1608 # now fetch the same data from the HTTPS server
1609 url = 'https://%s:%d/%s' % (
1610 HOST, server.port, os.path.split(CERTFILE)[1])
1611 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001612 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001613 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001614 if dlen and (int(dlen) > 0):
1615 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001616 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001617 sys.stdout.write(
1618 " client: read %d bytes from remote server '%s'\n"
1619 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001620 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001621 f.close()
1622 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001623
Antoine Pitrou480a1242010-04-28 21:37:09 +00001624 def test_asyncore_server(self):
1625 """Check the example asyncore integration."""
1626 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001627
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001628 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001629 sys.stdout.write("\n")
1630
Antoine Pitrou480a1242010-04-28 21:37:09 +00001631 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001632 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001633 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001634 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001635 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001636 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001637 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 " client: sending %r...\n" % indata)
1639 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001640 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001641 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001642 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001643 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001644 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001645 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1646 % (outdata[:20], len(outdata),
1647 indata[:20].lower(), len(indata)))
1648 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001649 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001650 sys.stdout.write(" client: closing connection.\n")
1651 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001652 if support.verbose:
1653 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001654
Antoine Pitrou480a1242010-04-28 21:37:09 +00001655 def test_recv_send(self):
1656 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001657 if support.verbose:
1658 sys.stdout.write("\n")
1659
1660 server = ThreadedEchoServer(CERTFILE,
1661 certreqs=ssl.CERT_NONE,
1662 ssl_version=ssl.PROTOCOL_TLSv1,
1663 cacerts=CERTFILE,
1664 chatty=True,
1665 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001666 with server:
1667 s = ssl.wrap_socket(socket.socket(),
1668 server_side=False,
1669 certfile=CERTFILE,
1670 ca_certs=CERTFILE,
1671 cert_reqs=ssl.CERT_NONE,
1672 ssl_version=ssl.PROTOCOL_TLSv1)
1673 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001674 # helper methods for standardising recv* method signatures
1675 def _recv_into():
1676 b = bytearray(b"\0"*100)
1677 count = s.recv_into(b)
1678 return b[:count]
1679
1680 def _recvfrom_into():
1681 b = bytearray(b"\0"*100)
1682 count, addr = s.recvfrom_into(b)
1683 return b[:count]
1684
1685 # (name, method, whether to expect success, *args)
1686 send_methods = [
1687 ('send', s.send, True, []),
1688 ('sendto', s.sendto, False, ["some.address"]),
1689 ('sendall', s.sendall, True, []),
1690 ]
1691 recv_methods = [
1692 ('recv', s.recv, True, []),
1693 ('recvfrom', s.recvfrom, False, ["some.address"]),
1694 ('recv_into', _recv_into, True, []),
1695 ('recvfrom_into', _recvfrom_into, False, []),
1696 ]
1697 data_prefix = "PREFIX_"
1698
1699 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001700 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001701 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001702 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001703 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001704 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001705 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001706 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001707 "<<{outdata:r}>> ({nout:d}) received; "
1708 "expected <<{indata:r}>> ({nin:d})\n".format(
1709 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001710 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001711 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001712 )
1713 )
1714 except ValueError as e:
1715 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001716 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001717 "Failed to send with method <<{name:s}>>; "
1718 "expected to succeed.\n".format(name=meth_name)
1719 )
1720 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001721 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001722 "Method <<{name:s}>> failed with unexpected "
1723 "exception message: {exp:s}\n".format(
1724 name=meth_name, exp=e
1725 )
1726 )
1727
1728 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001729 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001730 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001731 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001732 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001733 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001734 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001735 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001736 "<<{outdata:r}>> ({nout:d}) received; "
1737 "expected <<{indata:r}>> ({nin:d})\n".format(
1738 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001739 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001740 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001741 )
1742 )
1743 except ValueError as e:
1744 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001745 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001746 "Failed to receive with method <<{name:s}>>; "
1747 "expected to succeed.\n".format(name=meth_name)
1748 )
1749 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001750 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001751 "Method <<{name:s}>> failed with unexpected "
1752 "exception message: {exp:s}\n".format(
1753 name=meth_name, exp=e
1754 )
1755 )
1756 # consume data
1757 s.read()
1758
Nick Coghlan513886a2011-08-28 00:00:27 +10001759 # Make sure sendmsg et al are disallowed to avoid
1760 # inadvertent disclosure of data and/or corruption
1761 # of the encrypted data stream
1762 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1763 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1764 self.assertRaises(NotImplementedError,
1765 s.recvmsg_into, bytearray(100))
1766
Antoine Pitrou480a1242010-04-28 21:37:09 +00001767 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001768 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001769
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001770 def test_handshake_timeout(self):
1771 # Issue #5103: SSL handshake must respect the socket timeout
1772 server = socket.socket(socket.AF_INET)
1773 host = "127.0.0.1"
1774 port = support.bind_port(server)
1775 started = threading.Event()
1776 finish = False
1777
1778 def serve():
1779 server.listen(5)
1780 started.set()
1781 conns = []
1782 while not finish:
1783 r, w, e = select.select([server], [], [], 0.1)
1784 if server in r:
1785 # Let the socket hang around rather than having
1786 # it closed by garbage collection.
1787 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001788 for sock in conns:
1789 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001790
1791 t = threading.Thread(target=serve)
1792 t.start()
1793 started.wait()
1794
1795 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001796 try:
1797 c = socket.socket(socket.AF_INET)
1798 c.settimeout(0.2)
1799 c.connect((host, port))
1800 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001801 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001802 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001803 finally:
1804 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001805 try:
1806 c = socket.socket(socket.AF_INET)
1807 c = ssl.wrap_socket(c)
1808 c.settimeout(0.2)
1809 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001810 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001811 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001812 finally:
1813 c.close()
1814 finally:
1815 finish = True
1816 t.join()
1817 server.close()
1818
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001819 def test_server_accept(self):
1820 # Issue #16357: accept() on a SSLSocket created through
1821 # SSLContext.wrap_socket().
1822 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1823 context.verify_mode = ssl.CERT_REQUIRED
1824 context.load_verify_locations(CERTFILE)
1825 context.load_cert_chain(CERTFILE)
1826 server = socket.socket(socket.AF_INET)
1827 host = "127.0.0.1"
1828 port = support.bind_port(server)
1829 server = context.wrap_socket(server, server_side=True)
1830
1831 evt = threading.Event()
1832 remote = None
1833 peer = None
1834 def serve():
1835 nonlocal remote, peer
1836 server.listen(5)
1837 # Block on the accept and wait on the connection to close.
1838 evt.set()
1839 remote, peer = server.accept()
1840 remote.recv(1)
1841
1842 t = threading.Thread(target=serve)
1843 t.start()
1844 # Client wait until server setup and perform a connect.
1845 evt.wait()
1846 client = context.wrap_socket(socket.socket())
1847 client.connect((host, port))
1848 client_addr = client.getsockname()
1849 client.close()
1850 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001851 remote.close()
1852 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001853 # Sanity checks.
1854 self.assertIsInstance(remote, ssl.SSLSocket)
1855 self.assertEqual(peer, client_addr)
1856
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001857 def test_default_ciphers(self):
1858 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1859 try:
1860 # Force a set of weak ciphers on our client context
1861 context.set_ciphers("DES")
1862 except ssl.SSLError:
1863 self.skipTest("no DES cipher available")
1864 with ThreadedEchoServer(CERTFILE,
1865 ssl_version=ssl.PROTOCOL_SSLv23,
1866 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001867 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001868 with self.assertRaises((OSError, ssl.SSLError)):
1869 s.connect((HOST, server.port))
1870 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1871
Antoine Pitroud6494802011-07-21 01:11:30 +02001872 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1873 "'tls-unique' channel binding not available")
1874 def test_tls_unique_channel_binding(self):
1875 """Test tls-unique channel binding."""
1876 if support.verbose:
1877 sys.stdout.write("\n")
1878
1879 server = ThreadedEchoServer(CERTFILE,
1880 certreqs=ssl.CERT_NONE,
1881 ssl_version=ssl.PROTOCOL_TLSv1,
1882 cacerts=CERTFILE,
1883 chatty=True,
1884 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001885 with server:
1886 s = ssl.wrap_socket(socket.socket(),
1887 server_side=False,
1888 certfile=CERTFILE,
1889 ca_certs=CERTFILE,
1890 cert_reqs=ssl.CERT_NONE,
1891 ssl_version=ssl.PROTOCOL_TLSv1)
1892 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001893 # get the data
1894 cb_data = s.get_channel_binding("tls-unique")
1895 if support.verbose:
1896 sys.stdout.write(" got channel binding data: {0!r}\n"
1897 .format(cb_data))
1898
1899 # check if it is sane
1900 self.assertIsNotNone(cb_data)
1901 self.assertEqual(len(cb_data), 12) # True for TLSv1
1902
1903 # and compare with the peers version
1904 s.write(b"CB tls-unique\n")
1905 peer_data_repr = s.read().strip()
1906 self.assertEqual(peer_data_repr,
1907 repr(cb_data).encode("us-ascii"))
1908 s.close()
1909
1910 # now, again
1911 s = ssl.wrap_socket(socket.socket(),
1912 server_side=False,
1913 certfile=CERTFILE,
1914 ca_certs=CERTFILE,
1915 cert_reqs=ssl.CERT_NONE,
1916 ssl_version=ssl.PROTOCOL_TLSv1)
1917 s.connect((HOST, server.port))
1918 new_cb_data = s.get_channel_binding("tls-unique")
1919 if support.verbose:
1920 sys.stdout.write(" got another channel binding data: {0!r}\n"
1921 .format(new_cb_data))
1922 # is it really unique
1923 self.assertNotEqual(cb_data, new_cb_data)
1924 self.assertIsNotNone(cb_data)
1925 self.assertEqual(len(cb_data), 12) # True for TLSv1
1926 s.write(b"CB tls-unique\n")
1927 peer_data_repr = s.read().strip()
1928 self.assertEqual(peer_data_repr,
1929 repr(new_cb_data).encode("us-ascii"))
1930 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001931
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001932 def test_compression(self):
1933 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1934 context.load_cert_chain(CERTFILE)
1935 stats = server_params_test(context, context,
1936 chatty=True, connectionchatty=True)
1937 if support.verbose:
1938 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1939 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1940
1941 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1942 "ssl.OP_NO_COMPRESSION needed for this test")
1943 def test_compression_disabled(self):
1944 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1945 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001946 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001947 stats = server_params_test(context, context,
1948 chatty=True, connectionchatty=True)
1949 self.assertIs(stats['compression'], None)
1950
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001951 def test_dh_params(self):
1952 # Check we can get a connection with ephemeral Diffie-Hellman
1953 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1954 context.load_cert_chain(CERTFILE)
1955 context.load_dh_params(DHFILE)
1956 context.set_ciphers("kEDH")
1957 stats = server_params_test(context, context,
1958 chatty=True, connectionchatty=True)
1959 cipher = stats["cipher"][0]
1960 parts = cipher.split("-")
1961 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1962 self.fail("Non-DH cipher: " + cipher[0])
1963
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001964 def test_selected_npn_protocol(self):
1965 # selected_npn_protocol() is None unless NPN is used
1966 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1967 context.load_cert_chain(CERTFILE)
1968 stats = server_params_test(context, context,
1969 chatty=True, connectionchatty=True)
1970 self.assertIs(stats['client_npn_protocol'], None)
1971
1972 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1973 def test_npn_protocols(self):
1974 server_protocols = ['http/1.1', 'spdy/2']
1975 protocol_tests = [
1976 (['http/1.1', 'spdy/2'], 'http/1.1'),
1977 (['spdy/2', 'http/1.1'], 'http/1.1'),
1978 (['spdy/2', 'test'], 'spdy/2'),
1979 (['abc', 'def'], 'abc')
1980 ]
1981 for client_protocols, expected in protocol_tests:
1982 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1983 server_context.load_cert_chain(CERTFILE)
1984 server_context.set_npn_protocols(server_protocols)
1985 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1986 client_context.load_cert_chain(CERTFILE)
1987 client_context.set_npn_protocols(client_protocols)
1988 stats = server_params_test(client_context, server_context,
1989 chatty=True, connectionchatty=True)
1990
1991 msg = "failed trying %s (s) and %s (c).\n" \
1992 "was expecting %s, but got %%s from the %%s" \
1993 % (str(server_protocols), str(client_protocols),
1994 str(expected))
1995 client_result = stats['client_npn_protocol']
1996 self.assertEqual(client_result, expected, msg % (client_result, "client"))
1997 server_result = stats['server_npn_protocols'][-1] \
1998 if len(stats['server_npn_protocols']) else 'nothing'
1999 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2000
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002001
Thomas Woutersed03b412007-08-28 21:37:11 +00002002def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002003 if support.verbose:
2004 plats = {
2005 'Linux': platform.linux_distribution,
2006 'Mac': platform.mac_ver,
2007 'Windows': platform.win32_ver,
2008 }
2009 for name, func in plats.items():
2010 plat = func()
2011 if plat and plat[0]:
2012 plat = '%s %r' % (name, plat)
2013 break
2014 else:
2015 plat = repr(platform.platform())
2016 print("test_ssl: testing with %r %r" %
2017 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2018 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002019 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002020
Antoine Pitrou152efa22010-05-16 18:19:27 +00002021 for filename in [
2022 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2023 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2024 BADCERT, BADKEY, EMPTYCERT]:
2025 if not os.path.exists(filename):
2026 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002027
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002028 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002029
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002030 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002031 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002032
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002033 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002034 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002035 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002036 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002037
Antoine Pitrou480a1242010-04-28 21:37:09 +00002038 try:
2039 support.run_unittest(*tests)
2040 finally:
2041 if _have_threads:
2042 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002043
2044if __name__ == "__main__":
2045 test_main()