blob: febebaf0777f910f06ae80083fa7ae11c6552f7d [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
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010051# Two keys and certs signed by the same CA (for SNI tests)
52SIGNED_CERTFILE = data_file("keycert3.pem")
53SIGNED_CERTFILE2 = data_file("keycert4.pem")
54SIGNING_CA = data_file("pycacert.pem")
55
Antoine Pitrou152efa22010-05-16 18:19:27 +000056SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
57
58EMPTYCERT = data_file("nullcert.pem")
59BADCERT = data_file("badcert.pem")
60WRONGCERT = data_file("XXXnonexisting.pem")
61BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020062NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000063
Antoine Pitrou0e576f12011-12-22 10:03:38 +010064DHFILE = data_file("dh512.pem")
65BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000066
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010067
Thomas Woutersed03b412007-08-28 21:37:11 +000068def handle_error(prefix):
69 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000070 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000071 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000072
Antoine Pitroub5218772010-05-21 09:56:06 +000073def can_clear_options():
74 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020075 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000076
77def no_sslv2_implies_sslv3_hello():
78 # 0.9.7h or higher
79 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
80
Thomas Woutersed03b412007-08-28 21:37:11 +000081
Antoine Pitrou23df4832010-08-04 17:14:06 +000082# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
83def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020084 if hasattr(ssl, 'PROTOCOL_SSLv2'):
85 @functools.wraps(func)
86 def f(*args, **kwargs):
87 try:
88 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
89 except ssl.SSLError:
90 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
91 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
92 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
93 return func(*args, **kwargs)
94 return f
95 else:
96 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000097
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010098needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
99
Antoine Pitrou23df4832010-08-04 17:14:06 +0000100
Antoine Pitrou152efa22010-05-16 18:19:27 +0000101class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000102
Antoine Pitrou480a1242010-04-28 21:37:09 +0000103 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200104 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 ssl.PROTOCOL_SSLv23
106 ssl.PROTOCOL_SSLv3
107 ssl.PROTOCOL_TLSv1
108 ssl.CERT_NONE
109 ssl.CERT_OPTIONAL
110 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100111 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100112 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100113 if ssl.HAS_ECDH:
114 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100115 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
116 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000117 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100118 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000119
Antoine Pitrou480a1242010-04-28 21:37:09 +0000120 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000121 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000122 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000123 sys.stdout.write("\n RAND_status is %d (%s)\n"
124 % (v, (v and "sufficient randomness") or
125 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200126
127 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
128 self.assertEqual(len(data), 16)
129 self.assertEqual(is_cryptographic, v == 1)
130 if v:
131 data = ssl.RAND_bytes(16)
132 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200133 else:
134 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200135
Jesus Ceac8754a12012-09-11 02:00:58 +0200136 self.assertRaises(TypeError, ssl.RAND_egd, 1)
137 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000139
Antoine Pitrou480a1242010-04-28 21:37:09 +0000140 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000141 # note that this uses an 'unofficial' function in _ssl.c,
142 # provided solely for this test, to exercise the certificate
143 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000144 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000145 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000146 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200147 self.assertEqual(p['issuer'],
148 ((('countryName', 'XY'),),
149 (('localityName', 'Castle Anthrax'),),
150 (('organizationName', 'Python Software Foundation'),),
151 (('commonName', 'localhost'),))
152 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100153 # Note the next three asserts will fail if the keys are regenerated
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200154 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
155 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
156 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
157 self.assertEqual(p['subject'],
158 ((('countryName', 'XY'),),
159 (('localityName', 'Castle Anthrax'),),
160 (('organizationName', 'Python Software Foundation'),),
161 (('commonName', 'localhost'),))
162 )
163 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
164 # Issue #13034: the subjectAltName in some certificates
165 # (notably projects.developer.nokia.com:443) wasn't parsed
166 p = ssl._ssl._test_decode_cert(NOKIACERT)
167 if support.verbose:
168 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
169 self.assertEqual(p['subjectAltName'],
170 (('DNS', 'projects.developer.nokia.com'),
171 ('DNS', 'projects.forum.nokia.com'))
172 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000173
Antoine Pitrou480a1242010-04-28 21:37:09 +0000174 def test_DER_to_PEM(self):
175 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
176 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000177 d1 = ssl.PEM_cert_to_DER_cert(pem)
178 p2 = ssl.DER_cert_to_PEM_cert(d1)
179 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000180 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000181 if not p2.startswith(ssl.PEM_HEADER + '\n'):
182 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
183 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
184 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000185
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000186 def test_openssl_version(self):
187 n = ssl.OPENSSL_VERSION_NUMBER
188 t = ssl.OPENSSL_VERSION_INFO
189 s = ssl.OPENSSL_VERSION
190 self.assertIsInstance(n, int)
191 self.assertIsInstance(t, tuple)
192 self.assertIsInstance(s, str)
193 # Some sanity checks follow
194 # >= 0.9
195 self.assertGreaterEqual(n, 0x900000)
196 # < 2.0
197 self.assertLess(n, 0x20000000)
198 major, minor, fix, patch, status = t
199 self.assertGreaterEqual(major, 0)
200 self.assertLess(major, 2)
201 self.assertGreaterEqual(minor, 0)
202 self.assertLess(minor, 256)
203 self.assertGreaterEqual(fix, 0)
204 self.assertLess(fix, 256)
205 self.assertGreaterEqual(patch, 0)
206 self.assertLessEqual(patch, 26)
207 self.assertGreaterEqual(status, 0)
208 self.assertLessEqual(status, 15)
209 # Version string as returned by OpenSSL, the format might change
210 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
211 (s, t))
212
Antoine Pitrou9d543662010-04-23 23:10:32 +0000213 @support.cpython_only
214 def test_refcycle(self):
215 # Issue #7943: an SSL object doesn't create reference cycles with
216 # itself.
217 s = socket.socket(socket.AF_INET)
218 ss = ssl.wrap_socket(s)
219 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100220 with support.check_warnings(("", ResourceWarning)):
221 del ss
222 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000223
Antoine Pitroua468adc2010-09-14 14:43:44 +0000224 def test_wrapped_unconnected(self):
225 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200226 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000227 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100228 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100229 self.assertRaises(OSError, ss.recv, 1)
230 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
231 self.assertRaises(OSError, ss.recvfrom, 1)
232 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
233 self.assertRaises(OSError, ss.send, b'x')
234 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000235
Antoine Pitrou40f08742010-04-24 22:04:40 +0000236 def test_timeout(self):
237 # Issue #8524: when creating an SSL socket, the timeout of the
238 # original socket should be retained.
239 for timeout in (None, 0.0, 5.0):
240 s = socket.socket(socket.AF_INET)
241 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100242 with ssl.wrap_socket(s) as ss:
243 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000244
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000245 def test_errors(self):
246 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000247 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000248 "certfile must be specified",
249 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000250 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000251 "certfile must be specified for server-side operations",
252 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000253 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000254 "certfile must be specified for server-side operations",
255 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100256 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
257 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
258 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200259 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000260 with socket.socket() as sock:
261 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000262 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200263 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000264 with socket.socket() as sock:
265 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000266 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200267 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000268 with socket.socket() as sock:
269 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000270 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000271
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000272 def test_match_hostname(self):
273 def ok(cert, hostname):
274 ssl.match_hostname(cert, hostname)
275 def fail(cert, hostname):
276 self.assertRaises(ssl.CertificateError,
277 ssl.match_hostname, cert, hostname)
278
279 cert = {'subject': ((('commonName', 'example.com'),),)}
280 ok(cert, 'example.com')
281 ok(cert, 'ExAmple.cOm')
282 fail(cert, 'www.example.com')
283 fail(cert, '.example.com')
284 fail(cert, 'example.org')
285 fail(cert, 'exampleXcom')
286
287 cert = {'subject': ((('commonName', '*.a.com'),),)}
288 ok(cert, 'foo.a.com')
289 fail(cert, 'bar.foo.a.com')
290 fail(cert, 'a.com')
291 fail(cert, 'Xa.com')
292 fail(cert, '.a.com')
293
294 cert = {'subject': ((('commonName', 'a.*.com'),),)}
295 ok(cert, 'a.foo.com')
296 fail(cert, 'a..com')
297 fail(cert, 'a.com')
298
299 cert = {'subject': ((('commonName', 'f*.com'),),)}
300 ok(cert, 'foo.com')
301 ok(cert, 'f.com')
302 fail(cert, 'bar.com')
303 fail(cert, 'foo.a.com')
304 fail(cert, 'bar.foo.com')
305
306 # Slightly fake real-world example
307 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
308 'subject': ((('commonName', 'linuxfrz.org'),),),
309 'subjectAltName': (('DNS', 'linuxfr.org'),
310 ('DNS', 'linuxfr.com'),
311 ('othername', '<unsupported>'))}
312 ok(cert, 'linuxfr.org')
313 ok(cert, 'linuxfr.com')
314 # Not a "DNS" entry
315 fail(cert, '<unsupported>')
316 # When there is a subjectAltName, commonName isn't used
317 fail(cert, 'linuxfrz.org')
318
319 # A pristine real-world example
320 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
321 'subject': ((('countryName', 'US'),),
322 (('stateOrProvinceName', 'California'),),
323 (('localityName', 'Mountain View'),),
324 (('organizationName', 'Google Inc'),),
325 (('commonName', 'mail.google.com'),))}
326 ok(cert, 'mail.google.com')
327 fail(cert, 'gmail.com')
328 # Only commonName is considered
329 fail(cert, 'California')
330
331 # Neither commonName nor subjectAltName
332 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
333 'subject': ((('countryName', 'US'),),
334 (('stateOrProvinceName', 'California'),),
335 (('localityName', 'Mountain View'),),
336 (('organizationName', 'Google Inc'),))}
337 fail(cert, 'mail.google.com')
338
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200339 # No DNS entry in subjectAltName but a commonName
340 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
341 'subject': ((('countryName', 'US'),),
342 (('stateOrProvinceName', 'California'),),
343 (('localityName', 'Mountain View'),),
344 (('commonName', 'mail.google.com'),)),
345 'subjectAltName': (('othername', 'blabla'), )}
346 ok(cert, 'mail.google.com')
347
348 # No DNS entry subjectAltName and no commonName
349 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
350 'subject': ((('countryName', 'US'),),
351 (('stateOrProvinceName', 'California'),),
352 (('localityName', 'Mountain View'),),
353 (('organizationName', 'Google Inc'),)),
354 'subjectAltName': (('othername', 'blabla'),)}
355 fail(cert, 'google.com')
356
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000357 # Empty cert / no cert
358 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
359 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
360
Antoine Pitroud5323212010-10-22 18:19:07 +0000361 def test_server_side(self):
362 # server_hostname doesn't work for server sockets
363 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000364 with socket.socket() as sock:
365 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
366 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000367
Antoine Pitroud6494802011-07-21 01:11:30 +0200368 def test_unknown_channel_binding(self):
369 # should raise ValueError for unknown type
370 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100371 with ssl.wrap_socket(s) as ss:
372 with self.assertRaises(ValueError):
373 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200374
375 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
376 "'tls-unique' channel binding not available")
377 def test_tls_unique_channel_binding(self):
378 # unconnected should return None for known type
379 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100380 with ssl.wrap_socket(s) as ss:
381 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200382 # the same for server-side
383 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100384 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
385 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200386
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600387 def test_dealloc_warn(self):
388 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
389 r = repr(ss)
390 with self.assertWarns(ResourceWarning) as cm:
391 ss = None
392 support.gc_collect()
393 self.assertIn(r, str(cm.warning.args[0]))
394
Antoine Pitrou152efa22010-05-16 18:19:27 +0000395class ContextTests(unittest.TestCase):
396
Antoine Pitrou23df4832010-08-04 17:14:06 +0000397 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000398 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200399 if hasattr(ssl, 'PROTOCOL_SSLv2'):
400 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000401 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
402 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
403 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
404 self.assertRaises(TypeError, ssl.SSLContext)
405 self.assertRaises(ValueError, ssl.SSLContext, -1)
406 self.assertRaises(ValueError, ssl.SSLContext, 42)
407
Antoine Pitrou23df4832010-08-04 17:14:06 +0000408 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000409 def test_protocol(self):
410 for proto in PROTOCOLS:
411 ctx = ssl.SSLContext(proto)
412 self.assertEqual(ctx.protocol, proto)
413
414 def test_ciphers(self):
415 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
416 ctx.set_ciphers("ALL")
417 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000418 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000419 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000420
Antoine Pitrou23df4832010-08-04 17:14:06 +0000421 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000422 def test_options(self):
423 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
424 # OP_ALL is the default value
425 self.assertEqual(ssl.OP_ALL, ctx.options)
426 ctx.options |= ssl.OP_NO_SSLv2
427 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
428 ctx.options)
429 ctx.options |= ssl.OP_NO_SSLv3
430 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
431 ctx.options)
432 if can_clear_options():
433 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
434 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
435 ctx.options)
436 ctx.options = 0
437 self.assertEqual(0, ctx.options)
438 else:
439 with self.assertRaises(ValueError):
440 ctx.options = 0
441
Antoine Pitrou152efa22010-05-16 18:19:27 +0000442 def test_verify(self):
443 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
444 # Default value
445 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
446 ctx.verify_mode = ssl.CERT_OPTIONAL
447 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
448 ctx.verify_mode = ssl.CERT_REQUIRED
449 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
450 ctx.verify_mode = ssl.CERT_NONE
451 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
452 with self.assertRaises(TypeError):
453 ctx.verify_mode = None
454 with self.assertRaises(ValueError):
455 ctx.verify_mode = 42
456
457 def test_load_cert_chain(self):
458 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
459 # Combined key and cert in a single file
460 ctx.load_cert_chain(CERTFILE)
461 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
462 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200463 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000464 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000465 self.assertEqual(cm.exception.errno, errno.ENOENT)
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(BADCERT)
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(EMPTYCERT)
470 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000471 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000472 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
473 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
474 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000475 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000476 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000477 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000478 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000479 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000480 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
481 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000482 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000483 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000484 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200485 # Password protected key and cert
486 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
487 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
488 ctx.load_cert_chain(CERTFILE_PROTECTED,
489 password=bytearray(KEY_PASSWORD.encode()))
490 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
491 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
492 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
493 bytearray(KEY_PASSWORD.encode()))
494 with self.assertRaisesRegex(TypeError, "should be a string"):
495 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
496 with self.assertRaises(ssl.SSLError):
497 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
498 with self.assertRaisesRegex(ValueError, "cannot be longer"):
499 # openssl has a fixed limit on the password buffer.
500 # PEM_BUFSIZE is generally set to 1kb.
501 # Return a string larger than this.
502 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
503 # Password callback
504 def getpass_unicode():
505 return KEY_PASSWORD
506 def getpass_bytes():
507 return KEY_PASSWORD.encode()
508 def getpass_bytearray():
509 return bytearray(KEY_PASSWORD.encode())
510 def getpass_badpass():
511 return "badpass"
512 def getpass_huge():
513 return b'a' * (1024 * 1024)
514 def getpass_bad_type():
515 return 9
516 def getpass_exception():
517 raise Exception('getpass error')
518 class GetPassCallable:
519 def __call__(self):
520 return KEY_PASSWORD
521 def getpass(self):
522 return KEY_PASSWORD
523 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
524 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
525 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
526 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
527 ctx.load_cert_chain(CERTFILE_PROTECTED,
528 password=GetPassCallable().getpass)
529 with self.assertRaises(ssl.SSLError):
530 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
531 with self.assertRaisesRegex(ValueError, "cannot be longer"):
532 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
533 with self.assertRaisesRegex(TypeError, "must return a string"):
534 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
535 with self.assertRaisesRegex(Exception, "getpass error"):
536 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
537 # Make sure the password function isn't called if it isn't needed
538 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000539
540 def test_load_verify_locations(self):
541 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
542 ctx.load_verify_locations(CERTFILE)
543 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
544 ctx.load_verify_locations(BYTES_CERTFILE)
545 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
546 self.assertRaises(TypeError, ctx.load_verify_locations)
547 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200548 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000549 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000550 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000551 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000552 ctx.load_verify_locations(BADCERT)
553 ctx.load_verify_locations(CERTFILE, CAPATH)
554 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
555
Victor Stinner80f75e62011-01-29 11:31:20 +0000556 # Issue #10989: crash if the second argument type is invalid
557 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
558
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100559 def test_load_dh_params(self):
560 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
561 ctx.load_dh_params(DHFILE)
562 if os.name != 'nt':
563 ctx.load_dh_params(BYTES_DHFILE)
564 self.assertRaises(TypeError, ctx.load_dh_params)
565 self.assertRaises(TypeError, ctx.load_dh_params, None)
566 with self.assertRaises(FileNotFoundError) as cm:
567 ctx.load_dh_params(WRONGCERT)
568 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200569 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100570 ctx.load_dh_params(CERTFILE)
571
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000572 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000573 def test_session_stats(self):
574 for proto in PROTOCOLS:
575 ctx = ssl.SSLContext(proto)
576 self.assertEqual(ctx.session_stats(), {
577 'number': 0,
578 'connect': 0,
579 'connect_good': 0,
580 'connect_renegotiate': 0,
581 'accept': 0,
582 'accept_good': 0,
583 'accept_renegotiate': 0,
584 'hits': 0,
585 'misses': 0,
586 'timeouts': 0,
587 'cache_full': 0,
588 })
589
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000590 def test_set_default_verify_paths(self):
591 # There's not much we can do to test that it acts as expected,
592 # so just check it doesn't crash or raise an exception.
593 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
594 ctx.set_default_verify_paths()
595
Antoine Pitrou501da612011-12-21 09:27:41 +0100596 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100597 def test_set_ecdh_curve(self):
598 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
599 ctx.set_ecdh_curve("prime256v1")
600 ctx.set_ecdh_curve(b"prime256v1")
601 self.assertRaises(TypeError, ctx.set_ecdh_curve)
602 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
603 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
604 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
605
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100606 @needs_sni
607 def test_sni_callback(self):
608 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
609
610 # set_servername_callback expects a callable, or None
611 self.assertRaises(TypeError, ctx.set_servername_callback)
612 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
613 self.assertRaises(TypeError, ctx.set_servername_callback, "")
614 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
615
616 def dummycallback(sock, servername, ctx):
617 pass
618 ctx.set_servername_callback(None)
619 ctx.set_servername_callback(dummycallback)
620
621 @needs_sni
622 def test_sni_callback_refcycle(self):
623 # Reference cycles through the servername callback are detected
624 # and cleared.
625 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
626 def dummycallback(sock, servername, ctx, cycle=ctx):
627 pass
628 ctx.set_servername_callback(dummycallback)
629 wr = weakref.ref(ctx)
630 del ctx, dummycallback
631 gc.collect()
632 self.assertIs(wr(), None)
633
Antoine Pitrou152efa22010-05-16 18:19:27 +0000634
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200635class SSLErrorTests(unittest.TestCase):
636
637 def test_str(self):
638 # The str() of a SSLError doesn't include the errno
639 e = ssl.SSLError(1, "foo")
640 self.assertEqual(str(e), "foo")
641 self.assertEqual(e.errno, 1)
642 # Same for a subclass
643 e = ssl.SSLZeroReturnError(1, "foo")
644 self.assertEqual(str(e), "foo")
645 self.assertEqual(e.errno, 1)
646
647 def test_lib_reason(self):
648 # Test the library and reason attributes
649 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
650 with self.assertRaises(ssl.SSLError) as cm:
651 ctx.load_dh_params(CERTFILE)
652 self.assertEqual(cm.exception.library, 'PEM')
653 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
654 s = str(cm.exception)
655 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
656
657 def test_subclass(self):
658 # Check that the appropriate SSLError subclass is raised
659 # (this only tests one of them)
660 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
661 with socket.socket() as s:
662 s.bind(("127.0.0.1", 0))
663 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100664 c = socket.socket()
665 c.connect(s.getsockname())
666 c.setblocking(False)
667 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200668 with self.assertRaises(ssl.SSLWantReadError) as cm:
669 c.do_handshake()
670 s = str(cm.exception)
671 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
672 # For compatibility
673 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
674
675
Bill Janssen6e027db2007-11-15 22:23:56 +0000676class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000677
Antoine Pitrou480a1242010-04-28 21:37:09 +0000678 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000679 with support.transient_internet("svn.python.org"):
680 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
681 cert_reqs=ssl.CERT_NONE)
682 try:
683 s.connect(("svn.python.org", 443))
684 self.assertEqual({}, s.getpeercert())
685 finally:
686 s.close()
687
688 # this should fail because we have no verification certs
689 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
690 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000691 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
692 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000693 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000694
Antoine Pitrou350c7222010-09-09 13:31:46 +0000695 # this should succeed because we specify the root cert
696 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
697 cert_reqs=ssl.CERT_REQUIRED,
698 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
699 try:
700 s.connect(("svn.python.org", 443))
701 self.assertTrue(s.getpeercert())
702 finally:
703 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000704
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000705 def test_connect_ex(self):
706 # Issue #11326: check connect_ex() implementation
707 with support.transient_internet("svn.python.org"):
708 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
709 cert_reqs=ssl.CERT_REQUIRED,
710 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
711 try:
712 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
713 self.assertTrue(s.getpeercert())
714 finally:
715 s.close()
716
717 def test_non_blocking_connect_ex(self):
718 # Issue #11326: non-blocking connect_ex() should allow handshake
719 # to proceed after the socket gets ready.
720 with support.transient_internet("svn.python.org"):
721 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
722 cert_reqs=ssl.CERT_REQUIRED,
723 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
724 do_handshake_on_connect=False)
725 try:
726 s.setblocking(False)
727 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000728 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
729 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000730 # Wait for connect to finish
731 select.select([], [s], [], 5.0)
732 # Non-blocking handshake
733 while True:
734 try:
735 s.do_handshake()
736 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200737 except ssl.SSLWantReadError:
738 select.select([s], [], [], 5.0)
739 except ssl.SSLWantWriteError:
740 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000741 # SSL established
742 self.assertTrue(s.getpeercert())
743 finally:
744 s.close()
745
Antoine Pitroub4410db2011-05-18 18:51:06 +0200746 def test_timeout_connect_ex(self):
747 # Issue #12065: on a timeout, connect_ex() should return the original
748 # errno (mimicking the behaviour of non-SSL sockets).
749 with support.transient_internet("svn.python.org"):
750 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
751 cert_reqs=ssl.CERT_REQUIRED,
752 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
753 do_handshake_on_connect=False)
754 try:
755 s.settimeout(0.0000001)
756 rc = s.connect_ex(('svn.python.org', 443))
757 if rc == 0:
758 self.skipTest("svn.python.org responded too quickly")
759 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
760 finally:
761 s.close()
762
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100763 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100764 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100765 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
766 cert_reqs=ssl.CERT_REQUIRED,
767 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
768 try:
769 self.assertEqual(errno.ECONNREFUSED,
770 s.connect_ex(("svn.python.org", 444)))
771 finally:
772 s.close()
773
Antoine Pitrou152efa22010-05-16 18:19:27 +0000774 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000775 with support.transient_internet("svn.python.org"):
776 # Same as test_connect, but with a separately created context
777 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
778 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
779 s.connect(("svn.python.org", 443))
780 try:
781 self.assertEqual({}, s.getpeercert())
782 finally:
783 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000784 # Same with a server hostname
785 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
786 server_hostname="svn.python.org")
787 if ssl.HAS_SNI:
788 s.connect(("svn.python.org", 443))
789 s.close()
790 else:
791 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000792 # This should fail because we have no verification certs
793 ctx.verify_mode = ssl.CERT_REQUIRED
794 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000795 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000796 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000797 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000798 # This should succeed because we specify the root cert
799 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
800 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
801 s.connect(("svn.python.org", 443))
802 try:
803 cert = s.getpeercert()
804 self.assertTrue(cert)
805 finally:
806 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000807
808 def test_connect_capath(self):
809 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000810 # NOTE: the subject hashing algorithm has been changed between
811 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
812 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000813 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000814 with support.transient_internet("svn.python.org"):
815 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
816 ctx.verify_mode = ssl.CERT_REQUIRED
817 ctx.load_verify_locations(capath=CAPATH)
818 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
819 s.connect(("svn.python.org", 443))
820 try:
821 cert = s.getpeercert()
822 self.assertTrue(cert)
823 finally:
824 s.close()
825 # Same with a bytes `capath` argument
826 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
827 ctx.verify_mode = ssl.CERT_REQUIRED
828 ctx.load_verify_locations(capath=BYTES_CAPATH)
829 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
830 s.connect(("svn.python.org", 443))
831 try:
832 cert = s.getpeercert()
833 self.assertTrue(cert)
834 finally:
835 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000836
Antoine Pitroue3220242010-04-24 11:13:53 +0000837 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
838 def test_makefile_close(self):
839 # Issue #5238: creating a file-like object with makefile() shouldn't
840 # delay closing the underlying "real socket" (here tested with its
841 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000842 with support.transient_internet("svn.python.org"):
843 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
844 ss.connect(("svn.python.org", 443))
845 fd = ss.fileno()
846 f = ss.makefile()
847 f.close()
848 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000849 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000850 # Closing the SSL socket should close the fd too
851 ss.close()
852 gc.collect()
853 with self.assertRaises(OSError) as e:
854 os.read(fd, 0)
855 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000856
Antoine Pitrou480a1242010-04-28 21:37:09 +0000857 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000858 with support.transient_internet("svn.python.org"):
859 s = socket.socket(socket.AF_INET)
860 s.connect(("svn.python.org", 443))
861 s.setblocking(False)
862 s = ssl.wrap_socket(s,
863 cert_reqs=ssl.CERT_NONE,
864 do_handshake_on_connect=False)
865 count = 0
866 while True:
867 try:
868 count += 1
869 s.do_handshake()
870 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200871 except ssl.SSLWantReadError:
872 select.select([s], [], [])
873 except ssl.SSLWantWriteError:
874 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000875 s.close()
876 if support.verbose:
877 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878
Antoine Pitrou480a1242010-04-28 21:37:09 +0000879 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200880 def _test_get_server_certificate(host, port, cert=None):
881 with support.transient_internet(host):
882 pem = ssl.get_server_certificate((host, port))
883 if not pem:
884 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200885
Antoine Pitrou15399c32011-04-28 19:23:55 +0200886 try:
887 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
888 except ssl.SSLError as x:
889 #should fail
890 if support.verbose:
891 sys.stdout.write("%s\n" % x)
892 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200893 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
894
Antoine Pitrou15399c32011-04-28 19:23:55 +0200895 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
896 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200897 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000898 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200899 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000900
Antoine Pitrou15399c32011-04-28 19:23:55 +0200901 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
902 if support.IPV6_ENABLED:
903 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000904
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000905 def test_ciphers(self):
906 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000907 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100908 with ssl.wrap_socket(socket.socket(socket.AF_INET),
909 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
910 s.connect(remote)
911 with ssl.wrap_socket(socket.socket(socket.AF_INET),
912 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
913 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000914 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000915 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000916 with socket.socket(socket.AF_INET) as sock:
917 s = ssl.wrap_socket(sock,
918 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
919 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000920
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000921 def test_algorithms(self):
922 # Issue #8484: all algorithms should be available when verifying a
923 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000924 # SHA256 was added in OpenSSL 0.9.8
925 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
926 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200927 # sha256.tbs-internet.com needs SNI to use the correct certificate
928 if not ssl.HAS_SNI:
929 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000930 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
931 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000932 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000933 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200934 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
935 ctx.verify_mode = ssl.CERT_REQUIRED
936 ctx.load_verify_locations(sha256_cert)
937 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
938 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000939 try:
940 s.connect(remote)
941 if support.verbose:
942 sys.stdout.write("\nCipher with %r is %r\n" %
943 (remote, s.cipher()))
944 sys.stdout.write("Certificate is:\n%s\n" %
945 pprint.pformat(s.getpeercert()))
946 finally:
947 s.close()
948
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949
950try:
951 import threading
952except ImportError:
953 _have_threads = False
954else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 _have_threads = True
956
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000957 from test.ssl_servers import make_https_server
958
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000959 class ThreadedEchoServer(threading.Thread):
960
961 class ConnectionHandler(threading.Thread):
962
963 """A mildly complicated class, because we want it to work both
964 with and without the SSL wrapper around the socket connection, so
965 that we can test the STARTTLS functionality."""
966
Bill Janssen6e027db2007-11-15 22:23:56 +0000967 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000968 self.server = server
969 self.running = False
970 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000971 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000972 self.sock.setblocking(1)
973 self.sslconn = None
974 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000975 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000976
Antoine Pitrou480a1242010-04-28 21:37:09 +0000977 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000979 self.sslconn = self.server.context.wrap_socket(
980 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100981 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100982 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000983 # XXX Various errors can have happened here, for example
984 # a mismatching protocol version, an invalid certificate,
985 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100986 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000987 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000988 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000989 self.running = False
990 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000991 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000992 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000993 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000994 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000996 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000997 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
998 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000999 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001000 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1001 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001002 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001004 sys.stdout.write(" server: selected protocol is now "
1005 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001006 return True
1007
1008 def read(self):
1009 if self.sslconn:
1010 return self.sslconn.read()
1011 else:
1012 return self.sock.recv(1024)
1013
1014 def write(self, bytes):
1015 if self.sslconn:
1016 return self.sslconn.write(bytes)
1017 else:
1018 return self.sock.send(bytes)
1019
1020 def close(self):
1021 if self.sslconn:
1022 self.sslconn.close()
1023 else:
1024 self.sock.close()
1025
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027 self.running = True
1028 if not self.server.starttls_server:
1029 if not self.wrap_conn():
1030 return
1031 while self.running:
1032 try:
1033 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001034 stripped = msg.strip()
1035 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001036 # eof, so quit this handler
1037 self.running = False
1038 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001039 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001040 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001041 sys.stdout.write(" server: client closed connection\n")
1042 self.close()
1043 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001044 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001045 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001046 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001047 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001048 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001049 if not self.wrap_conn():
1050 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001051 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001052 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001053 if support.verbose and self.server.connectionchatty:
1054 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001055 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001056 self.sock = self.sslconn.unwrap()
1057 self.sslconn = None
1058 if support.verbose and self.server.connectionchatty:
1059 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001060 elif stripped == b'CB tls-unique':
1061 if support.verbose and self.server.connectionchatty:
1062 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1063 data = self.sslconn.get_channel_binding("tls-unique")
1064 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001065 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001066 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001067 self.server.connectionchatty):
1068 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001069 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1070 % (msg, ctype, msg.lower(), ctype))
1071 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001072 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073 if self.server.chatty:
1074 handle_error("Test server failure:\n")
1075 self.close()
1076 self.running = False
1077 # normally, we'd just stop here, but for the test
1078 # harness, we want to stop the server
1079 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001080
Antoine Pitroub5218772010-05-21 09:56:06 +00001081 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001082 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001083 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001084 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001085 if context:
1086 self.context = context
1087 else:
1088 self.context = ssl.SSLContext(ssl_version
1089 if ssl_version is not None
1090 else ssl.PROTOCOL_TLSv1)
1091 self.context.verify_mode = (certreqs if certreqs is not None
1092 else ssl.CERT_NONE)
1093 if cacerts:
1094 self.context.load_verify_locations(cacerts)
1095 if certificate:
1096 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001097 if npn_protocols:
1098 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001099 if ciphers:
1100 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001101 self.chatty = chatty
1102 self.connectionchatty = connectionchatty
1103 self.starttls_server = starttls_server
1104 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001105 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001106 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001108 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001109 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001110 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001111 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001113 def __enter__(self):
1114 self.start(threading.Event())
1115 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001116 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001117
1118 def __exit__(self, *args):
1119 self.stop()
1120 self.join()
1121
Antoine Pitrou480a1242010-04-28 21:37:09 +00001122 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001123 self.flag = flag
1124 threading.Thread.start(self)
1125
Antoine Pitrou480a1242010-04-28 21:37:09 +00001126 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001127 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001128 self.sock.listen(5)
1129 self.active = True
1130 if self.flag:
1131 # signal an event
1132 self.flag.set()
1133 while self.active:
1134 try:
1135 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001136 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001137 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001138 + repr(connaddr) + '\n')
1139 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001141 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001142 except socket.timeout:
1143 pass
1144 except KeyboardInterrupt:
1145 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001146 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147
Antoine Pitrou480a1242010-04-28 21:37:09 +00001148 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001149 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150
Bill Janssen54cc54c2007-12-14 22:08:56 +00001151 class AsyncoreEchoServer(threading.Thread):
1152
1153 # this one's based on asyncore.dispatcher
1154
1155 class EchoServer (asyncore.dispatcher):
1156
1157 class ConnectionHandler (asyncore.dispatcher_with_send):
1158
1159 def __init__(self, conn, certfile):
1160 self.socket = ssl.wrap_socket(conn, server_side=True,
1161 certfile=certfile,
1162 do_handshake_on_connect=False)
1163 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001164 self._ssl_accepting = True
1165 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001166
1167 def readable(self):
1168 if isinstance(self.socket, ssl.SSLSocket):
1169 while self.socket.pending() > 0:
1170 self.handle_read_event()
1171 return True
1172
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001173 def _do_ssl_handshake(self):
1174 try:
1175 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001176 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1177 return
1178 except ssl.SSLEOFError:
1179 return self.handle_close()
1180 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001181 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001182 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001183 if err.args[0] == errno.ECONNABORTED:
1184 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001185 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001186 self._ssl_accepting = False
1187
1188 def handle_read(self):
1189 if self._ssl_accepting:
1190 self._do_ssl_handshake()
1191 else:
1192 data = self.recv(1024)
1193 if support.verbose:
1194 sys.stdout.write(" server: read %s from client\n" % repr(data))
1195 if not data:
1196 self.close()
1197 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001198 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001199
1200 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001201 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001202 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001203 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1204
1205 def handle_error(self):
1206 raise
1207
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001208 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001209 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001210 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1211 self.port = support.bind_port(sock, '')
1212 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001213 self.listen(5)
1214
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001215 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001216 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001217 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1218 self.ConnectionHandler(sock_obj, self.certfile)
1219
1220 def handle_error(self):
1221 raise
1222
Trent Nelson78520002008-04-10 20:54:35 +00001223 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001224 self.flag = None
1225 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001226 self.server = self.EchoServer(certfile)
1227 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001228 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001229 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001230
1231 def __str__(self):
1232 return "<%s %s>" % (self.__class__.__name__, self.server)
1233
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001234 def __enter__(self):
1235 self.start(threading.Event())
1236 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001237 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001238
1239 def __exit__(self, *args):
1240 if support.verbose:
1241 sys.stdout.write(" cleanup: stopping server.\n")
1242 self.stop()
1243 if support.verbose:
1244 sys.stdout.write(" cleanup: joining server thread.\n")
1245 self.join()
1246 if support.verbose:
1247 sys.stdout.write(" cleanup: successfully joined.\n")
1248
Bill Janssen54cc54c2007-12-14 22:08:56 +00001249 def start (self, flag=None):
1250 self.flag = flag
1251 threading.Thread.start(self)
1252
Antoine Pitrou480a1242010-04-28 21:37:09 +00001253 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001254 self.active = True
1255 if self.flag:
1256 self.flag.set()
1257 while self.active:
1258 try:
1259 asyncore.loop(1)
1260 except:
1261 pass
1262
Antoine Pitrou480a1242010-04-28 21:37:09 +00001263 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001264 self.active = False
1265 self.server.close()
1266
Antoine Pitrou480a1242010-04-28 21:37:09 +00001267 def bad_cert_test(certfile):
1268 """
1269 Launch a server with CERT_REQUIRED, and check that trying to
1270 connect to it with the given client certificate fails.
1271 """
Trent Nelson78520002008-04-10 20:54:35 +00001272 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001273 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001274 cacerts=CERTFILE, chatty=False,
1275 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001276 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001277 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001278 with socket.socket() as sock:
1279 s = ssl.wrap_socket(sock,
1280 certfile=certfile,
1281 ssl_version=ssl.PROTOCOL_TLSv1)
1282 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001283 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001284 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001285 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001286 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001287 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001288 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001289 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001290 if x.errno != errno.ENOENT:
1291 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001292 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001293 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001294 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001295 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001296
Antoine Pitroub5218772010-05-21 09:56:06 +00001297 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001298 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001299 """
1300 Launch a server, connect a client to it and try various reads
1301 and writes.
1302 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001303 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001304 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001305 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001306 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001307 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001308 with client_context.wrap_socket(socket.socket(),
1309 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001310 s.connect((HOST, server.port))
1311 for arg in [indata, bytearray(indata), memoryview(indata)]:
1312 if connectionchatty:
1313 if support.verbose:
1314 sys.stdout.write(
1315 " client: sending %r...\n" % indata)
1316 s.write(arg)
1317 outdata = s.read()
1318 if connectionchatty:
1319 if support.verbose:
1320 sys.stdout.write(" client: read %r\n" % outdata)
1321 if outdata != indata.lower():
1322 raise AssertionError(
1323 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1324 % (outdata[:20], len(outdata),
1325 indata[:20].lower(), len(indata)))
1326 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001327 if connectionchatty:
1328 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001329 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001330 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001331 'compression': s.compression(),
1332 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001333 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001334 'client_npn_protocol': s.selected_npn_protocol()
1335 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001336 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001337 stats['server_npn_protocols'] = server.selected_protocols
1338 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001339
Antoine Pitroub5218772010-05-21 09:56:06 +00001340 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1341 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001342 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001343 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001344 certtype = {
1345 ssl.CERT_NONE: "CERT_NONE",
1346 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1347 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1348 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001349 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001350 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001351 sys.stdout.write(formatstr %
1352 (ssl.get_protocol_name(client_protocol),
1353 ssl.get_protocol_name(server_protocol),
1354 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001355 client_context = ssl.SSLContext(client_protocol)
1356 client_context.options = ssl.OP_ALL | client_options
1357 server_context = ssl.SSLContext(server_protocol)
1358 server_context.options = ssl.OP_ALL | server_options
1359 for ctx in (client_context, server_context):
1360 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001361 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1362 # will send an SSLv3 hello (rather than SSLv2) starting from
1363 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001364 ctx.set_ciphers("ALL")
1365 ctx.load_cert_chain(CERTFILE)
1366 ctx.load_verify_locations(CERTFILE)
1367 try:
1368 server_params_test(client_context, server_context,
1369 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001370 # Protocol mismatch can result in either an SSLError, or a
1371 # "Connection reset by peer" error.
1372 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001373 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001374 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001375 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001377 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001378 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001379 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001380 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001381 "Client protocol %s succeeded with server protocol %s!"
1382 % (ssl.get_protocol_name(client_protocol),
1383 ssl.get_protocol_name(server_protocol)))
1384
1385
Bill Janssen6e027db2007-11-15 22:23:56 +00001386 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001387
Antoine Pitrou23df4832010-08-04 17:14:06 +00001388 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 def test_echo(self):
1390 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001391 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001392 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001393 for protocol in PROTOCOLS:
1394 context = ssl.SSLContext(protocol)
1395 context.load_cert_chain(CERTFILE)
1396 server_params_test(context, context,
1397 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001398
Antoine Pitrou480a1242010-04-28 21:37:09 +00001399 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001400 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001401 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001402 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1403 context.verify_mode = ssl.CERT_REQUIRED
1404 context.load_verify_locations(CERTFILE)
1405 context.load_cert_chain(CERTFILE)
1406 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001407 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001408 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001409 s.connect((HOST, server.port))
1410 cert = s.getpeercert()
1411 self.assertTrue(cert, "Can't get peer certificate.")
1412 cipher = s.cipher()
1413 if support.verbose:
1414 sys.stdout.write(pprint.pformat(cert) + '\n')
1415 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1416 if 'subject' not in cert:
1417 self.fail("No subject field in certificate: %s." %
1418 pprint.pformat(cert))
1419 if ((('organizationName', 'Python Software Foundation'),)
1420 not in cert['subject']):
1421 self.fail(
1422 "Missing or invalid 'organizationName' field in certificate subject; "
1423 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001424 self.assertIn('notBefore', cert)
1425 self.assertIn('notAfter', cert)
1426 before = ssl.cert_time_to_seconds(cert['notBefore'])
1427 after = ssl.cert_time_to_seconds(cert['notAfter'])
1428 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001429 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001430
Antoine Pitrou480a1242010-04-28 21:37:09 +00001431 def test_empty_cert(self):
1432 """Connecting with an empty cert file"""
1433 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1434 "nullcert.pem"))
1435 def test_malformed_cert(self):
1436 """Connecting with a badly formatted certificate (syntax error)"""
1437 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1438 "badcert.pem"))
1439 def test_nonexisting_cert(self):
1440 """Connecting with a non-existing cert file"""
1441 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1442 "wrongcert.pem"))
1443 def test_malformed_key(self):
1444 """Connecting with a badly formatted key (syntax error)"""
1445 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1446 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001447
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001449 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00001450 in the client when attempting handshake.
1451 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001452 listener_ready = threading.Event()
1453 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001454
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001455 s = socket.socket()
1456 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001457
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001458 # `listener` runs in a thread. It sits in an accept() until
1459 # the main thread connects. Then it rudely closes the socket,
1460 # and sets Event `listener_gone` to let the main thread know
1461 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001462 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001463 s.listen(5)
1464 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001465 newsock, addr = s.accept()
1466 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001467 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001468 listener_gone.set()
1469
1470 def connector():
1471 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001472 with socket.socket() as c:
1473 c.connect((HOST, port))
1474 listener_gone.wait()
1475 try:
1476 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001477 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001478 pass
1479 else:
1480 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001481
1482 t = threading.Thread(target=listener)
1483 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001484 try:
1485 connector()
1486 finally:
1487 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001488
Antoine Pitrou23df4832010-08-04 17:14:06 +00001489 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001490 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1491 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 def test_protocol_sslv2(self):
1493 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001494 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001495 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001496 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1497 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1498 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1499 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1500 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1501 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001502 # SSLv23 client with specific SSL options
1503 if no_sslv2_implies_sslv3_hello():
1504 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1505 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1506 client_options=ssl.OP_NO_SSLv2)
1507 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1508 client_options=ssl.OP_NO_SSLv3)
1509 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1510 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001511
Antoine Pitrou23df4832010-08-04 17:14:06 +00001512 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001513 def test_protocol_sslv23(self):
1514 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001515 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001516 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001517 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1518 try:
1519 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02001520 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02001521 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1522 if support.verbose:
1523 sys.stdout.write(
1524 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1525 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001526 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1527 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1528 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001529
Antoine Pitrou480a1242010-04-28 21:37:09 +00001530 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1531 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1532 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001533
Antoine Pitrou480a1242010-04-28 21:37:09 +00001534 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1535 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1536 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001537
Antoine Pitroub5218772010-05-21 09:56:06 +00001538 # Server with specific SSL options
1539 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1540 server_options=ssl.OP_NO_SSLv3)
1541 # Will choose TLSv1
1542 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1543 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1544 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1545 server_options=ssl.OP_NO_TLSv1)
1546
1547
Antoine Pitrou23df4832010-08-04 17:14:06 +00001548 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001549 def test_protocol_sslv3(self):
1550 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001551 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001552 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001553 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1554 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1555 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001556 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1557 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001558 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1559 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001560 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001561 if no_sslv2_implies_sslv3_hello():
1562 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1563 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1564 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001565
Antoine Pitrou23df4832010-08-04 17:14:06 +00001566 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 def test_protocol_tlsv1(self):
1568 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001569 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001570 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1572 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1573 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001574 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1575 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001576 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001577 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1578 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001579
Antoine Pitrou480a1242010-04-28 21:37:09 +00001580 def test_starttls(self):
1581 """Switching from clear text to encrypted and back again."""
1582 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 +00001583
Trent Nelson78520002008-04-10 20:54:35 +00001584 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001585 ssl_version=ssl.PROTOCOL_TLSv1,
1586 starttls_server=True,
1587 chatty=True,
1588 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001589 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001590 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001591 s = socket.socket()
1592 s.setblocking(1)
1593 s.connect((HOST, server.port))
1594 if support.verbose:
1595 sys.stdout.write("\n")
1596 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001597 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001598 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001599 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001600 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001601 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001602 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001603 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001604 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001605 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001606 msg = outdata.strip().lower()
1607 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1608 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001609 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001610 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001611 " client: read %r from server, starting TLS...\n"
1612 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001613 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1614 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001615 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1616 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001617 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001618 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001619 " client: read %r from server, ending TLS...\n"
1620 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001621 s = conn.unwrap()
1622 wrapped = False
1623 else:
1624 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001625 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001626 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001627 if support.verbose:
1628 sys.stdout.write(" client: closing connection.\n")
1629 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001630 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001631 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001632 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001633 if wrapped:
1634 conn.close()
1635 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001637
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 def test_socketserver(self):
1639 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001640 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001641 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001642 if support.verbose:
1643 sys.stdout.write('\n')
1644 with open(CERTFILE, 'rb') as f:
1645 d1 = f.read()
1646 d2 = ''
1647 # now fetch the same data from the HTTPS server
1648 url = 'https://%s:%d/%s' % (
1649 HOST, server.port, os.path.split(CERTFILE)[1])
1650 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001651 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001652 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001653 if dlen and (int(dlen) > 0):
1654 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001655 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001656 sys.stdout.write(
1657 " client: read %d bytes from remote server '%s'\n"
1658 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001659 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001660 f.close()
1661 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001662
Antoine Pitrou480a1242010-04-28 21:37:09 +00001663 def test_asyncore_server(self):
1664 """Check the example asyncore integration."""
1665 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001666
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001667 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001668 sys.stdout.write("\n")
1669
Antoine Pitrou480a1242010-04-28 21:37:09 +00001670 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001671 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001672 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001673 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001674 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001675 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001676 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001677 " client: sending %r...\n" % indata)
1678 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001679 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001680 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001681 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001682 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001683 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001684 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1685 % (outdata[:20], len(outdata),
1686 indata[:20].lower(), len(indata)))
1687 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001688 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001689 sys.stdout.write(" client: closing connection.\n")
1690 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001691 if support.verbose:
1692 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001693
Antoine Pitrou480a1242010-04-28 21:37:09 +00001694 def test_recv_send(self):
1695 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001696 if support.verbose:
1697 sys.stdout.write("\n")
1698
1699 server = ThreadedEchoServer(CERTFILE,
1700 certreqs=ssl.CERT_NONE,
1701 ssl_version=ssl.PROTOCOL_TLSv1,
1702 cacerts=CERTFILE,
1703 chatty=True,
1704 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001705 with server:
1706 s = ssl.wrap_socket(socket.socket(),
1707 server_side=False,
1708 certfile=CERTFILE,
1709 ca_certs=CERTFILE,
1710 cert_reqs=ssl.CERT_NONE,
1711 ssl_version=ssl.PROTOCOL_TLSv1)
1712 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001713 # helper methods for standardising recv* method signatures
1714 def _recv_into():
1715 b = bytearray(b"\0"*100)
1716 count = s.recv_into(b)
1717 return b[:count]
1718
1719 def _recvfrom_into():
1720 b = bytearray(b"\0"*100)
1721 count, addr = s.recvfrom_into(b)
1722 return b[:count]
1723
1724 # (name, method, whether to expect success, *args)
1725 send_methods = [
1726 ('send', s.send, True, []),
1727 ('sendto', s.sendto, False, ["some.address"]),
1728 ('sendall', s.sendall, True, []),
1729 ]
1730 recv_methods = [
1731 ('recv', s.recv, True, []),
1732 ('recvfrom', s.recvfrom, False, ["some.address"]),
1733 ('recv_into', _recv_into, True, []),
1734 ('recvfrom_into', _recvfrom_into, False, []),
1735 ]
1736 data_prefix = "PREFIX_"
1737
1738 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001739 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001740 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001741 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001742 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001743 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001744 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001745 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001746 "<<{outdata:r}>> ({nout:d}) received; "
1747 "expected <<{indata:r}>> ({nin:d})\n".format(
1748 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001749 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001750 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001751 )
1752 )
1753 except ValueError as e:
1754 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001755 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001756 "Failed to send with method <<{name:s}>>; "
1757 "expected to succeed.\n".format(name=meth_name)
1758 )
1759 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001760 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001761 "Method <<{name:s}>> failed with unexpected "
1762 "exception message: {exp:s}\n".format(
1763 name=meth_name, exp=e
1764 )
1765 )
1766
1767 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001768 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001769 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001770 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001771 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001772 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001773 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001774 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001775 "<<{outdata:r}>> ({nout:d}) received; "
1776 "expected <<{indata:r}>> ({nin:d})\n".format(
1777 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001778 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001779 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001780 )
1781 )
1782 except ValueError as e:
1783 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001784 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001785 "Failed to receive with method <<{name:s}>>; "
1786 "expected to succeed.\n".format(name=meth_name)
1787 )
1788 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001789 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001790 "Method <<{name:s}>> failed with unexpected "
1791 "exception message: {exp:s}\n".format(
1792 name=meth_name, exp=e
1793 )
1794 )
1795 # consume data
1796 s.read()
1797
Nick Coghlan513886a2011-08-28 00:00:27 +10001798 # Make sure sendmsg et al are disallowed to avoid
1799 # inadvertent disclosure of data and/or corruption
1800 # of the encrypted data stream
1801 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1802 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1803 self.assertRaises(NotImplementedError,
1804 s.recvmsg_into, bytearray(100))
1805
Antoine Pitrou480a1242010-04-28 21:37:09 +00001806 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001807 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001808
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001809 def test_handshake_timeout(self):
1810 # Issue #5103: SSL handshake must respect the socket timeout
1811 server = socket.socket(socket.AF_INET)
1812 host = "127.0.0.1"
1813 port = support.bind_port(server)
1814 started = threading.Event()
1815 finish = False
1816
1817 def serve():
1818 server.listen(5)
1819 started.set()
1820 conns = []
1821 while not finish:
1822 r, w, e = select.select([server], [], [], 0.1)
1823 if server in r:
1824 # Let the socket hang around rather than having
1825 # it closed by garbage collection.
1826 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001827 for sock in conns:
1828 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001829
1830 t = threading.Thread(target=serve)
1831 t.start()
1832 started.wait()
1833
1834 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001835 try:
1836 c = socket.socket(socket.AF_INET)
1837 c.settimeout(0.2)
1838 c.connect((host, port))
1839 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001840 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001841 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001842 finally:
1843 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001844 try:
1845 c = socket.socket(socket.AF_INET)
1846 c = ssl.wrap_socket(c)
1847 c.settimeout(0.2)
1848 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001849 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001850 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001851 finally:
1852 c.close()
1853 finally:
1854 finish = True
1855 t.join()
1856 server.close()
1857
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001858 def test_server_accept(self):
1859 # Issue #16357: accept() on a SSLSocket created through
1860 # SSLContext.wrap_socket().
1861 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1862 context.verify_mode = ssl.CERT_REQUIRED
1863 context.load_verify_locations(CERTFILE)
1864 context.load_cert_chain(CERTFILE)
1865 server = socket.socket(socket.AF_INET)
1866 host = "127.0.0.1"
1867 port = support.bind_port(server)
1868 server = context.wrap_socket(server, server_side=True)
1869
1870 evt = threading.Event()
1871 remote = None
1872 peer = None
1873 def serve():
1874 nonlocal remote, peer
1875 server.listen(5)
1876 # Block on the accept and wait on the connection to close.
1877 evt.set()
1878 remote, peer = server.accept()
1879 remote.recv(1)
1880
1881 t = threading.Thread(target=serve)
1882 t.start()
1883 # Client wait until server setup and perform a connect.
1884 evt.wait()
1885 client = context.wrap_socket(socket.socket())
1886 client.connect((host, port))
1887 client_addr = client.getsockname()
1888 client.close()
1889 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001890 remote.close()
1891 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001892 # Sanity checks.
1893 self.assertIsInstance(remote, ssl.SSLSocket)
1894 self.assertEqual(peer, client_addr)
1895
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001896 def test_default_ciphers(self):
1897 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1898 try:
1899 # Force a set of weak ciphers on our client context
1900 context.set_ciphers("DES")
1901 except ssl.SSLError:
1902 self.skipTest("no DES cipher available")
1903 with ThreadedEchoServer(CERTFILE,
1904 ssl_version=ssl.PROTOCOL_SSLv23,
1905 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001906 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001907 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001908 s.connect((HOST, server.port))
1909 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1910
Antoine Pitroud6494802011-07-21 01:11:30 +02001911 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1912 "'tls-unique' channel binding not available")
1913 def test_tls_unique_channel_binding(self):
1914 """Test tls-unique channel binding."""
1915 if support.verbose:
1916 sys.stdout.write("\n")
1917
1918 server = ThreadedEchoServer(CERTFILE,
1919 certreqs=ssl.CERT_NONE,
1920 ssl_version=ssl.PROTOCOL_TLSv1,
1921 cacerts=CERTFILE,
1922 chatty=True,
1923 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001924 with server:
1925 s = ssl.wrap_socket(socket.socket(),
1926 server_side=False,
1927 certfile=CERTFILE,
1928 ca_certs=CERTFILE,
1929 cert_reqs=ssl.CERT_NONE,
1930 ssl_version=ssl.PROTOCOL_TLSv1)
1931 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001932 # get the data
1933 cb_data = s.get_channel_binding("tls-unique")
1934 if support.verbose:
1935 sys.stdout.write(" got channel binding data: {0!r}\n"
1936 .format(cb_data))
1937
1938 # check if it is sane
1939 self.assertIsNotNone(cb_data)
1940 self.assertEqual(len(cb_data), 12) # True for TLSv1
1941
1942 # and compare with the peers version
1943 s.write(b"CB tls-unique\n")
1944 peer_data_repr = s.read().strip()
1945 self.assertEqual(peer_data_repr,
1946 repr(cb_data).encode("us-ascii"))
1947 s.close()
1948
1949 # now, again
1950 s = ssl.wrap_socket(socket.socket(),
1951 server_side=False,
1952 certfile=CERTFILE,
1953 ca_certs=CERTFILE,
1954 cert_reqs=ssl.CERT_NONE,
1955 ssl_version=ssl.PROTOCOL_TLSv1)
1956 s.connect((HOST, server.port))
1957 new_cb_data = s.get_channel_binding("tls-unique")
1958 if support.verbose:
1959 sys.stdout.write(" got another channel binding data: {0!r}\n"
1960 .format(new_cb_data))
1961 # is it really unique
1962 self.assertNotEqual(cb_data, new_cb_data)
1963 self.assertIsNotNone(cb_data)
1964 self.assertEqual(len(cb_data), 12) # True for TLSv1
1965 s.write(b"CB tls-unique\n")
1966 peer_data_repr = s.read().strip()
1967 self.assertEqual(peer_data_repr,
1968 repr(new_cb_data).encode("us-ascii"))
1969 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001970
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001971 def test_compression(self):
1972 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1973 context.load_cert_chain(CERTFILE)
1974 stats = server_params_test(context, context,
1975 chatty=True, connectionchatty=True)
1976 if support.verbose:
1977 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1978 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1979
1980 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1981 "ssl.OP_NO_COMPRESSION needed for this test")
1982 def test_compression_disabled(self):
1983 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1984 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001985 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001986 stats = server_params_test(context, context,
1987 chatty=True, connectionchatty=True)
1988 self.assertIs(stats['compression'], None)
1989
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001990 def test_dh_params(self):
1991 # Check we can get a connection with ephemeral Diffie-Hellman
1992 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1993 context.load_cert_chain(CERTFILE)
1994 context.load_dh_params(DHFILE)
1995 context.set_ciphers("kEDH")
1996 stats = server_params_test(context, context,
1997 chatty=True, connectionchatty=True)
1998 cipher = stats["cipher"][0]
1999 parts = cipher.split("-")
2000 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2001 self.fail("Non-DH cipher: " + cipher[0])
2002
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002003 def test_selected_npn_protocol(self):
2004 # selected_npn_protocol() is None unless NPN is used
2005 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2006 context.load_cert_chain(CERTFILE)
2007 stats = server_params_test(context, context,
2008 chatty=True, connectionchatty=True)
2009 self.assertIs(stats['client_npn_protocol'], None)
2010
2011 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2012 def test_npn_protocols(self):
2013 server_protocols = ['http/1.1', 'spdy/2']
2014 protocol_tests = [
2015 (['http/1.1', 'spdy/2'], 'http/1.1'),
2016 (['spdy/2', 'http/1.1'], 'http/1.1'),
2017 (['spdy/2', 'test'], 'spdy/2'),
2018 (['abc', 'def'], 'abc')
2019 ]
2020 for client_protocols, expected in protocol_tests:
2021 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2022 server_context.load_cert_chain(CERTFILE)
2023 server_context.set_npn_protocols(server_protocols)
2024 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2025 client_context.load_cert_chain(CERTFILE)
2026 client_context.set_npn_protocols(client_protocols)
2027 stats = server_params_test(client_context, server_context,
2028 chatty=True, connectionchatty=True)
2029
2030 msg = "failed trying %s (s) and %s (c).\n" \
2031 "was expecting %s, but got %%s from the %%s" \
2032 % (str(server_protocols), str(client_protocols),
2033 str(expected))
2034 client_result = stats['client_npn_protocol']
2035 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2036 server_result = stats['server_npn_protocols'][-1] \
2037 if len(stats['server_npn_protocols']) else 'nothing'
2038 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2039
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002040 def sni_contexts(self):
2041 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2042 server_context.load_cert_chain(SIGNED_CERTFILE)
2043 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2044 other_context.load_cert_chain(SIGNED_CERTFILE2)
2045 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2046 client_context.verify_mode = ssl.CERT_REQUIRED
2047 client_context.load_verify_locations(SIGNING_CA)
2048 return server_context, other_context, client_context
2049
2050 def check_common_name(self, stats, name):
2051 cert = stats['peercert']
2052 self.assertIn((('commonName', name),), cert['subject'])
2053
2054 @needs_sni
2055 def test_sni_callback(self):
2056 calls = []
2057 server_context, other_context, client_context = self.sni_contexts()
2058
2059 def servername_cb(ssl_sock, server_name, initial_context):
2060 calls.append((server_name, initial_context))
2061 ssl_sock.context = other_context
2062 server_context.set_servername_callback(servername_cb)
2063
2064 stats = server_params_test(client_context, server_context,
2065 chatty=True,
2066 sni_name='supermessage')
2067 # The hostname was fetched properly, and the certificate was
2068 # changed for the connection.
2069 self.assertEqual(calls, [("supermessage", server_context)])
2070 # CERTFILE4 was selected
2071 self.check_common_name(stats, 'fakehostname')
2072
2073 # Check disabling the callback
2074 calls = []
2075 server_context.set_servername_callback(None)
2076
2077 stats = server_params_test(client_context, server_context,
2078 chatty=True,
2079 sni_name='notfunny')
2080 # Certificate didn't change
2081 self.check_common_name(stats, 'localhost')
2082 self.assertEqual(calls, [])
2083
2084 @needs_sni
2085 def test_sni_callback_alert(self):
2086 # Returning a TLS alert is reflected to the connecting client
2087 server_context, other_context, client_context = self.sni_contexts()
2088
2089 def cb_returning_alert(ssl_sock, server_name, initial_context):
2090 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2091 server_context.set_servername_callback(cb_returning_alert)
2092
2093 with self.assertRaises(ssl.SSLError) as cm:
2094 stats = server_params_test(client_context, server_context,
2095 chatty=False,
2096 sni_name='supermessage')
2097 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2098
2099 @needs_sni
2100 def test_sni_callback_raising(self):
2101 # Raising fails the connection with a TLS handshake failure alert.
2102 server_context, other_context, client_context = self.sni_contexts()
2103
2104 def cb_raising(ssl_sock, server_name, initial_context):
2105 1/0
2106 server_context.set_servername_callback(cb_raising)
2107
2108 with self.assertRaises(ssl.SSLError) as cm, \
2109 support.captured_stderr() as stderr:
2110 stats = server_params_test(client_context, server_context,
2111 chatty=False,
2112 sni_name='supermessage')
2113 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2114 self.assertIn("ZeroDivisionError", stderr.getvalue())
2115
2116 @needs_sni
2117 def test_sni_callback_wrong_return_type(self):
2118 # Returning the wrong return type terminates the TLS connection
2119 # with an internal error alert.
2120 server_context, other_context, client_context = self.sni_contexts()
2121
2122 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2123 return "foo"
2124 server_context.set_servername_callback(cb_wrong_return_type)
2125
2126 with self.assertRaises(ssl.SSLError) as cm, \
2127 support.captured_stderr() as stderr:
2128 stats = server_params_test(client_context, server_context,
2129 chatty=False,
2130 sni_name='supermessage')
2131 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2132 self.assertIn("TypeError", stderr.getvalue())
2133
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002134
Thomas Woutersed03b412007-08-28 21:37:11 +00002135def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002136 if support.verbose:
2137 plats = {
2138 'Linux': platform.linux_distribution,
2139 'Mac': platform.mac_ver,
2140 'Windows': platform.win32_ver,
2141 }
2142 for name, func in plats.items():
2143 plat = func()
2144 if plat and plat[0]:
2145 plat = '%s %r' % (name, plat)
2146 break
2147 else:
2148 plat = repr(platform.platform())
2149 print("test_ssl: testing with %r %r" %
2150 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2151 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002152 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002153
Antoine Pitrou152efa22010-05-16 18:19:27 +00002154 for filename in [
2155 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2156 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002157 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002158 BADCERT, BADKEY, EMPTYCERT]:
2159 if not os.path.exists(filename):
2160 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002161
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002162 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002163
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002164 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002165 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002166
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002167 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002168 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002169 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002170 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002171
Antoine Pitrou480a1242010-04-28 21:37:09 +00002172 try:
2173 support.run_unittest(*tests)
2174 finally:
2175 if _have_threads:
2176 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002177
2178if __name__ == "__main__":
2179 test_main()