blob: fdd2cf79e8b83d7af8c037e2422b388f0cd33c70 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
23PROTOCOLS = [
Victor Stinner3de49192011-05-09 00:42:58 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner3de49192011-05-09 00:42:58 +020027if hasattr(ssl, 'PROTOCOL_SSLv2'):
28 PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
Thomas Woutersed03b412007-08-28 21:37:11 +000029
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Antoine Pitrou81564092010-10-08 23:06:24 +000034# The custom key and certificate files used in test_ssl are generated
35# using Lib/test/make_ssl_certs.py.
36# Other certificates are simply fetched from the Internet servers they
37# are meant to authenticate.
38
Antoine Pitrou152efa22010-05-16 18:19:27 +000039CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020045CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
46ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
47KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000048CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000049BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
52
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020057NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020058NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000059
Antoine Pitrou0e576f12011-12-22 10:03:38 +010060DHFILE = data_file("dh512.pem")
61BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000062
Thomas Woutersed03b412007-08-28 21:37:11 +000063def handle_error(prefix):
64 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000065 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000066 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000067
Antoine Pitroub5218772010-05-21 09:56:06 +000068def can_clear_options():
69 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020070 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000071
72def no_sslv2_implies_sslv3_hello():
73 # 0.9.7h or higher
74 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
75
Thomas Woutersed03b412007-08-28 21:37:11 +000076
Antoine Pitrou23df4832010-08-04 17:14:06 +000077# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
78def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020079 if hasattr(ssl, 'PROTOCOL_SSLv2'):
80 @functools.wraps(func)
81 def f(*args, **kwargs):
82 try:
83 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
84 except ssl.SSLError:
85 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
86 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
87 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
88 return func(*args, **kwargs)
89 return f
90 else:
91 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000092
93
Antoine Pitrou152efa22010-05-16 18:19:27 +000094class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000095
Antoine Pitrou480a1242010-04-28 21:37:09 +000096 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020097 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 ssl.PROTOCOL_SSLv23
99 ssl.PROTOCOL_SSLv3
100 ssl.PROTOCOL_TLSv1
101 ssl.CERT_NONE
102 ssl.CERT_OPTIONAL
103 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100104 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100105 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100106 if ssl.HAS_ECDH:
107 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100108 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
109 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000110 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100111 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000112
Antoine Pitrou480a1242010-04-28 21:37:09 +0000113 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000115 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000116 sys.stdout.write("\n RAND_status is %d (%s)\n"
117 % (v, (v and "sufficient randomness") or
118 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200119
120 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
121 self.assertEqual(len(data), 16)
122 self.assertEqual(is_cryptographic, v == 1)
123 if v:
124 data = ssl.RAND_bytes(16)
125 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200126 else:
127 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200128
Jesus Ceac8754a12012-09-11 02:00:58 +0200129 self.assertRaises(TypeError, ssl.RAND_egd, 1)
130 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000131 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000132
Christian Heimesf77b4b22013-08-21 13:26:05 +0200133 @unittest.skipUnless(os.name == 'posix', 'requires posix')
134 def test_random_fork(self):
135 status = ssl.RAND_status()
136 if not status:
137 self.fail("OpenSSL's PRNG has insufficient randomness")
138
139 rfd, wfd = os.pipe()
140 pid = os.fork()
141 if pid == 0:
142 try:
143 os.close(rfd)
144 child_random = ssl.RAND_pseudo_bytes(16)[0]
145 self.assertEqual(len(child_random), 16)
146 os.write(wfd, child_random)
147 os.close(wfd)
148 except BaseException:
149 os._exit(1)
150 else:
151 os._exit(0)
152 else:
153 os.close(wfd)
154 self.addCleanup(os.close, rfd)
155 _, status = os.waitpid(pid, 0)
156 self.assertEqual(status, 0)
157
158 child_random = os.read(rfd, 16)
159 self.assertEqual(len(child_random), 16)
160 parent_random = ssl.RAND_pseudo_bytes(16)[0]
161 self.assertEqual(len(parent_random), 16)
162
163 self.assertNotEqual(child_random, parent_random)
164
Antoine Pitrou480a1242010-04-28 21:37:09 +0000165 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000166 # note that this uses an 'unofficial' function in _ssl.c,
167 # provided solely for this test, to exercise the certificate
168 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000169 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000170 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000171 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200172 self.assertEqual(p['issuer'],
173 ((('countryName', 'XY'),),
174 (('localityName', 'Castle Anthrax'),),
175 (('organizationName', 'Python Software Foundation'),),
176 (('commonName', 'localhost'),))
177 )
178 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
179 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
180 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
181 self.assertEqual(p['subject'],
182 ((('countryName', 'XY'),),
183 (('localityName', 'Castle Anthrax'),),
184 (('organizationName', 'Python Software Foundation'),),
185 (('commonName', 'localhost'),))
186 )
187 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
188 # Issue #13034: the subjectAltName in some certificates
189 # (notably projects.developer.nokia.com:443) wasn't parsed
190 p = ssl._ssl._test_decode_cert(NOKIACERT)
191 if support.verbose:
192 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
193 self.assertEqual(p['subjectAltName'],
194 (('DNS', 'projects.developer.nokia.com'),
195 ('DNS', 'projects.forum.nokia.com'))
196 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000197
Christian Heimes824f7f32013-08-17 00:54:47 +0200198 def test_parse_cert_CVE_2013_4238(self):
199 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
200 if support.verbose:
201 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
202 subject = ((('countryName', 'US'),),
203 (('stateOrProvinceName', 'Oregon'),),
204 (('localityName', 'Beaverton'),),
205 (('organizationName', 'Python Software Foundation'),),
206 (('organizationalUnitName', 'Python Core Development'),),
207 (('commonName', 'null.python.org\x00example.org'),),
208 (('emailAddress', 'python-dev@python.org'),))
209 self.assertEqual(p['subject'], subject)
210 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200211 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
212 san = (('DNS', 'altnull.python.org\x00example.com'),
213 ('email', 'null@python.org\x00user@example.org'),
214 ('URI', 'http://null.python.org\x00http://example.org'),
215 ('IP Address', '192.0.2.1'),
216 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
217 else:
218 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
219 san = (('DNS', 'altnull.python.org\x00example.com'),
220 ('email', 'null@python.org\x00user@example.org'),
221 ('URI', 'http://null.python.org\x00http://example.org'),
222 ('IP Address', '192.0.2.1'),
223 ('IP Address', '<invalid>'))
224
225 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200226
Antoine Pitrou480a1242010-04-28 21:37:09 +0000227 def test_DER_to_PEM(self):
228 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
229 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000230 d1 = ssl.PEM_cert_to_DER_cert(pem)
231 p2 = ssl.DER_cert_to_PEM_cert(d1)
232 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000233 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000234 if not p2.startswith(ssl.PEM_HEADER + '\n'):
235 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
236 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
237 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000238
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000239 def test_openssl_version(self):
240 n = ssl.OPENSSL_VERSION_NUMBER
241 t = ssl.OPENSSL_VERSION_INFO
242 s = ssl.OPENSSL_VERSION
243 self.assertIsInstance(n, int)
244 self.assertIsInstance(t, tuple)
245 self.assertIsInstance(s, str)
246 # Some sanity checks follow
247 # >= 0.9
248 self.assertGreaterEqual(n, 0x900000)
249 # < 2.0
250 self.assertLess(n, 0x20000000)
251 major, minor, fix, patch, status = t
252 self.assertGreaterEqual(major, 0)
253 self.assertLess(major, 2)
254 self.assertGreaterEqual(minor, 0)
255 self.assertLess(minor, 256)
256 self.assertGreaterEqual(fix, 0)
257 self.assertLess(fix, 256)
258 self.assertGreaterEqual(patch, 0)
259 self.assertLessEqual(patch, 26)
260 self.assertGreaterEqual(status, 0)
261 self.assertLessEqual(status, 15)
262 # Version string as returned by OpenSSL, the format might change
263 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
264 (s, t))
265
Antoine Pitrou9d543662010-04-23 23:10:32 +0000266 @support.cpython_only
267 def test_refcycle(self):
268 # Issue #7943: an SSL object doesn't create reference cycles with
269 # itself.
270 s = socket.socket(socket.AF_INET)
271 ss = ssl.wrap_socket(s)
272 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100273 with support.check_warnings(("", ResourceWarning)):
274 del ss
275 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000276
Antoine Pitroua468adc2010-09-14 14:43:44 +0000277 def test_wrapped_unconnected(self):
278 # Methods on an unconnected SSLSocket propagate the original
279 # socket.error raise by the underlying socket object.
280 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100281 with ssl.wrap_socket(s) as ss:
282 self.assertRaises(socket.error, ss.recv, 1)
283 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
284 self.assertRaises(socket.error, ss.recvfrom, 1)
285 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
286 self.assertRaises(socket.error, ss.send, b'x')
287 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000288
Antoine Pitrou40f08742010-04-24 22:04:40 +0000289 def test_timeout(self):
290 # Issue #8524: when creating an SSL socket, the timeout of the
291 # original socket should be retained.
292 for timeout in (None, 0.0, 5.0):
293 s = socket.socket(socket.AF_INET)
294 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100295 with ssl.wrap_socket(s) as ss:
296 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000297
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000298 def test_errors(self):
299 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000300 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000301 "certfile must be specified",
302 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000303 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000304 "certfile must be specified for server-side operations",
305 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000306 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000307 "certfile must be specified for server-side operations",
308 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100309 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
310 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
311 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000312 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000313 with socket.socket() as sock:
314 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000315 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000316 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000317 with socket.socket() as sock:
318 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000319 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000320 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000321 with socket.socket() as sock:
322 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000323 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000324
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000325 def test_match_hostname(self):
326 def ok(cert, hostname):
327 ssl.match_hostname(cert, hostname)
328 def fail(cert, hostname):
329 self.assertRaises(ssl.CertificateError,
330 ssl.match_hostname, cert, hostname)
331
332 cert = {'subject': ((('commonName', 'example.com'),),)}
333 ok(cert, 'example.com')
334 ok(cert, 'ExAmple.cOm')
335 fail(cert, 'www.example.com')
336 fail(cert, '.example.com')
337 fail(cert, 'example.org')
338 fail(cert, 'exampleXcom')
339
340 cert = {'subject': ((('commonName', '*.a.com'),),)}
341 ok(cert, 'foo.a.com')
342 fail(cert, 'bar.foo.a.com')
343 fail(cert, 'a.com')
344 fail(cert, 'Xa.com')
345 fail(cert, '.a.com')
346
347 cert = {'subject': ((('commonName', 'a.*.com'),),)}
348 ok(cert, 'a.foo.com')
349 fail(cert, 'a..com')
350 fail(cert, 'a.com')
351
352 cert = {'subject': ((('commonName', 'f*.com'),),)}
353 ok(cert, 'foo.com')
354 ok(cert, 'f.com')
355 fail(cert, 'bar.com')
356 fail(cert, 'foo.a.com')
357 fail(cert, 'bar.foo.com')
358
Christian Heimes824f7f32013-08-17 00:54:47 +0200359 # NULL bytes are bad, CVE-2013-4073
360 cert = {'subject': ((('commonName',
361 'null.python.org\x00example.org'),),)}
362 ok(cert, 'null.python.org\x00example.org') # or raise an error?
363 fail(cert, 'example.org')
364 fail(cert, 'null.python.org')
365
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000366 # Slightly fake real-world example
367 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
368 'subject': ((('commonName', 'linuxfrz.org'),),),
369 'subjectAltName': (('DNS', 'linuxfr.org'),
370 ('DNS', 'linuxfr.com'),
371 ('othername', '<unsupported>'))}
372 ok(cert, 'linuxfr.org')
373 ok(cert, 'linuxfr.com')
374 # Not a "DNS" entry
375 fail(cert, '<unsupported>')
376 # When there is a subjectAltName, commonName isn't used
377 fail(cert, 'linuxfrz.org')
378
379 # A pristine real-world example
380 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
381 'subject': ((('countryName', 'US'),),
382 (('stateOrProvinceName', 'California'),),
383 (('localityName', 'Mountain View'),),
384 (('organizationName', 'Google Inc'),),
385 (('commonName', 'mail.google.com'),))}
386 ok(cert, 'mail.google.com')
387 fail(cert, 'gmail.com')
388 # Only commonName is considered
389 fail(cert, 'California')
390
391 # Neither commonName nor subjectAltName
392 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
393 'subject': ((('countryName', 'US'),),
394 (('stateOrProvinceName', 'California'),),
395 (('localityName', 'Mountain View'),),
396 (('organizationName', 'Google Inc'),))}
397 fail(cert, 'mail.google.com')
398
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200399 # No DNS entry in subjectAltName but a commonName
400 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
401 'subject': ((('countryName', 'US'),),
402 (('stateOrProvinceName', 'California'),),
403 (('localityName', 'Mountain View'),),
404 (('commonName', 'mail.google.com'),)),
405 'subjectAltName': (('othername', 'blabla'), )}
406 ok(cert, 'mail.google.com')
407
408 # No DNS entry subjectAltName and no commonName
409 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
410 'subject': ((('countryName', 'US'),),
411 (('stateOrProvinceName', 'California'),),
412 (('localityName', 'Mountain View'),),
413 (('organizationName', 'Google Inc'),)),
414 'subjectAltName': (('othername', 'blabla'),)}
415 fail(cert, 'google.com')
416
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000417 # Empty cert / no cert
418 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
419 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
420
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200421 # Issue #17980: avoid denials of service by refusing more than one
422 # wildcard per fragment.
423 cert = {'subject': ((('commonName', 'a*b.com'),),)}
424 ok(cert, 'axxb.com')
425 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
426 ok(cert, 'axxb.com')
427 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
428 with self.assertRaises(ssl.CertificateError) as cm:
429 ssl.match_hostname(cert, 'axxbxxc.com')
430 self.assertIn("too many wildcards", str(cm.exception))
431
Antoine Pitroud5323212010-10-22 18:19:07 +0000432 def test_server_side(self):
433 # server_hostname doesn't work for server sockets
434 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000435 with socket.socket() as sock:
436 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
437 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000438
Antoine Pitroud6494802011-07-21 01:11:30 +0200439 def test_unknown_channel_binding(self):
440 # should raise ValueError for unknown type
441 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100442 with ssl.wrap_socket(s) as ss:
443 with self.assertRaises(ValueError):
444 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200445
446 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
447 "'tls-unique' channel binding not available")
448 def test_tls_unique_channel_binding(self):
449 # unconnected should return None for known type
450 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100451 with ssl.wrap_socket(s) as ss:
452 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200453 # the same for server-side
454 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100455 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
456 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200457
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600458 def test_dealloc_warn(self):
459 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
460 r = repr(ss)
461 with self.assertWarns(ResourceWarning) as cm:
462 ss = None
463 support.gc_collect()
464 self.assertIn(r, str(cm.warning.args[0]))
465
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466class ContextTests(unittest.TestCase):
467
Antoine Pitrou23df4832010-08-04 17:14:06 +0000468 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000469 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200470 if hasattr(ssl, 'PROTOCOL_SSLv2'):
471 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000472 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
473 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
474 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
475 self.assertRaises(TypeError, ssl.SSLContext)
476 self.assertRaises(ValueError, ssl.SSLContext, -1)
477 self.assertRaises(ValueError, ssl.SSLContext, 42)
478
Antoine Pitrou23df4832010-08-04 17:14:06 +0000479 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000480 def test_protocol(self):
481 for proto in PROTOCOLS:
482 ctx = ssl.SSLContext(proto)
483 self.assertEqual(ctx.protocol, proto)
484
485 def test_ciphers(self):
486 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
487 ctx.set_ciphers("ALL")
488 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000489 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000490 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000491
Antoine Pitrou23df4832010-08-04 17:14:06 +0000492 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000493 def test_options(self):
494 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
495 # OP_ALL is the default value
496 self.assertEqual(ssl.OP_ALL, ctx.options)
497 ctx.options |= ssl.OP_NO_SSLv2
498 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
499 ctx.options)
500 ctx.options |= ssl.OP_NO_SSLv3
501 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
502 ctx.options)
503 if can_clear_options():
504 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
505 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
506 ctx.options)
507 ctx.options = 0
508 self.assertEqual(0, ctx.options)
509 else:
510 with self.assertRaises(ValueError):
511 ctx.options = 0
512
Antoine Pitrou152efa22010-05-16 18:19:27 +0000513 def test_verify(self):
514 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
515 # Default value
516 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
517 ctx.verify_mode = ssl.CERT_OPTIONAL
518 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
519 ctx.verify_mode = ssl.CERT_REQUIRED
520 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
521 ctx.verify_mode = ssl.CERT_NONE
522 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
523 with self.assertRaises(TypeError):
524 ctx.verify_mode = None
525 with self.assertRaises(ValueError):
526 ctx.verify_mode = 42
527
528 def test_load_cert_chain(self):
529 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
530 # Combined key and cert in a single file
531 ctx.load_cert_chain(CERTFILE)
532 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
533 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000534 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000535 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000536 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000537 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000538 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000539 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000540 ctx.load_cert_chain(EMPTYCERT)
541 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000542 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000543 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
544 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
545 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000546 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000547 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000548 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000549 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000550 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000551 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
552 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000553 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000554 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000555 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200556 # Password protected key and cert
557 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
558 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
559 ctx.load_cert_chain(CERTFILE_PROTECTED,
560 password=bytearray(KEY_PASSWORD.encode()))
561 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
562 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
563 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
564 bytearray(KEY_PASSWORD.encode()))
565 with self.assertRaisesRegex(TypeError, "should be a string"):
566 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
567 with self.assertRaises(ssl.SSLError):
568 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
569 with self.assertRaisesRegex(ValueError, "cannot be longer"):
570 # openssl has a fixed limit on the password buffer.
571 # PEM_BUFSIZE is generally set to 1kb.
572 # Return a string larger than this.
573 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
574 # Password callback
575 def getpass_unicode():
576 return KEY_PASSWORD
577 def getpass_bytes():
578 return KEY_PASSWORD.encode()
579 def getpass_bytearray():
580 return bytearray(KEY_PASSWORD.encode())
581 def getpass_badpass():
582 return "badpass"
583 def getpass_huge():
584 return b'a' * (1024 * 1024)
585 def getpass_bad_type():
586 return 9
587 def getpass_exception():
588 raise Exception('getpass error')
589 class GetPassCallable:
590 def __call__(self):
591 return KEY_PASSWORD
592 def getpass(self):
593 return KEY_PASSWORD
594 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
595 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
596 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
597 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
598 ctx.load_cert_chain(CERTFILE_PROTECTED,
599 password=GetPassCallable().getpass)
600 with self.assertRaises(ssl.SSLError):
601 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
602 with self.assertRaisesRegex(ValueError, "cannot be longer"):
603 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
604 with self.assertRaisesRegex(TypeError, "must return a string"):
605 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
606 with self.assertRaisesRegex(Exception, "getpass error"):
607 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
608 # Make sure the password function isn't called if it isn't needed
609 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000610
611 def test_load_verify_locations(self):
612 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
613 ctx.load_verify_locations(CERTFILE)
614 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
615 ctx.load_verify_locations(BYTES_CERTFILE)
616 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
617 self.assertRaises(TypeError, ctx.load_verify_locations)
618 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000619 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000620 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000621 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000622 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000623 ctx.load_verify_locations(BADCERT)
624 ctx.load_verify_locations(CERTFILE, CAPATH)
625 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
626
Victor Stinner80f75e62011-01-29 11:31:20 +0000627 # Issue #10989: crash if the second argument type is invalid
628 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
629
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100630 def test_load_dh_params(self):
631 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
632 ctx.load_dh_params(DHFILE)
633 if os.name != 'nt':
634 ctx.load_dh_params(BYTES_DHFILE)
635 self.assertRaises(TypeError, ctx.load_dh_params)
636 self.assertRaises(TypeError, ctx.load_dh_params, None)
637 with self.assertRaises(FileNotFoundError) as cm:
638 ctx.load_dh_params(WRONGCERT)
639 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200640 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100641 ctx.load_dh_params(CERTFILE)
642
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000643 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000644 def test_session_stats(self):
645 for proto in PROTOCOLS:
646 ctx = ssl.SSLContext(proto)
647 self.assertEqual(ctx.session_stats(), {
648 'number': 0,
649 'connect': 0,
650 'connect_good': 0,
651 'connect_renegotiate': 0,
652 'accept': 0,
653 'accept_good': 0,
654 'accept_renegotiate': 0,
655 'hits': 0,
656 'misses': 0,
657 'timeouts': 0,
658 'cache_full': 0,
659 })
660
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000661 def test_set_default_verify_paths(self):
662 # There's not much we can do to test that it acts as expected,
663 # so just check it doesn't crash or raise an exception.
664 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
665 ctx.set_default_verify_paths()
666
Antoine Pitrou501da612011-12-21 09:27:41 +0100667 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100668 def test_set_ecdh_curve(self):
669 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
670 ctx.set_ecdh_curve("prime256v1")
671 ctx.set_ecdh_curve(b"prime256v1")
672 self.assertRaises(TypeError, ctx.set_ecdh_curve)
673 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
674 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
675 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
676
Antoine Pitrou152efa22010-05-16 18:19:27 +0000677
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200678class SSLErrorTests(unittest.TestCase):
679
680 def test_str(self):
681 # The str() of a SSLError doesn't include the errno
682 e = ssl.SSLError(1, "foo")
683 self.assertEqual(str(e), "foo")
684 self.assertEqual(e.errno, 1)
685 # Same for a subclass
686 e = ssl.SSLZeroReturnError(1, "foo")
687 self.assertEqual(str(e), "foo")
688 self.assertEqual(e.errno, 1)
689
690 def test_lib_reason(self):
691 # Test the library and reason attributes
692 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
693 with self.assertRaises(ssl.SSLError) as cm:
694 ctx.load_dh_params(CERTFILE)
695 self.assertEqual(cm.exception.library, 'PEM')
696 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
697 s = str(cm.exception)
698 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
699
700 def test_subclass(self):
701 # Check that the appropriate SSLError subclass is raised
702 # (this only tests one of them)
703 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
704 with socket.socket() as s:
705 s.bind(("127.0.0.1", 0))
706 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100707 c = socket.socket()
708 c.connect(s.getsockname())
709 c.setblocking(False)
710 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200711 with self.assertRaises(ssl.SSLWantReadError) as cm:
712 c.do_handshake()
713 s = str(cm.exception)
714 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
715 # For compatibility
716 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
717
718
Bill Janssen6e027db2007-11-15 22:23:56 +0000719class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000720
Antoine Pitrou480a1242010-04-28 21:37:09 +0000721 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000722 with support.transient_internet("svn.python.org"):
723 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
724 cert_reqs=ssl.CERT_NONE)
725 try:
726 s.connect(("svn.python.org", 443))
727 self.assertEqual({}, s.getpeercert())
728 finally:
729 s.close()
730
731 # this should fail because we have no verification certs
732 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
733 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000734 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
735 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000736 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000737
Antoine Pitrou350c7222010-09-09 13:31:46 +0000738 # this should succeed because we specify the root cert
739 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
740 cert_reqs=ssl.CERT_REQUIRED,
741 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
742 try:
743 s.connect(("svn.python.org", 443))
744 self.assertTrue(s.getpeercert())
745 finally:
746 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000747
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000748 def test_connect_ex(self):
749 # Issue #11326: check connect_ex() implementation
750 with support.transient_internet("svn.python.org"):
751 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
752 cert_reqs=ssl.CERT_REQUIRED,
753 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
754 try:
755 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
756 self.assertTrue(s.getpeercert())
757 finally:
758 s.close()
759
760 def test_non_blocking_connect_ex(self):
761 # Issue #11326: non-blocking connect_ex() should allow handshake
762 # to proceed after the socket gets ready.
763 with support.transient_internet("svn.python.org"):
764 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
765 cert_reqs=ssl.CERT_REQUIRED,
766 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
767 do_handshake_on_connect=False)
768 try:
769 s.setblocking(False)
770 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000771 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
772 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000773 # Wait for connect to finish
774 select.select([], [s], [], 5.0)
775 # Non-blocking handshake
776 while True:
777 try:
778 s.do_handshake()
779 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200780 except ssl.SSLWantReadError:
781 select.select([s], [], [], 5.0)
782 except ssl.SSLWantWriteError:
783 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000784 # SSL established
785 self.assertTrue(s.getpeercert())
786 finally:
787 s.close()
788
Antoine Pitroub4410db2011-05-18 18:51:06 +0200789 def test_timeout_connect_ex(self):
790 # Issue #12065: on a timeout, connect_ex() should return the original
791 # errno (mimicking the behaviour of non-SSL sockets).
792 with support.transient_internet("svn.python.org"):
793 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
794 cert_reqs=ssl.CERT_REQUIRED,
795 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
796 do_handshake_on_connect=False)
797 try:
798 s.settimeout(0.0000001)
799 rc = s.connect_ex(('svn.python.org', 443))
800 if rc == 0:
801 self.skipTest("svn.python.org responded too quickly")
802 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
803 finally:
804 s.close()
805
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100806 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100807 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100808 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
809 cert_reqs=ssl.CERT_REQUIRED,
810 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
811 try:
812 self.assertEqual(errno.ECONNREFUSED,
813 s.connect_ex(("svn.python.org", 444)))
814 finally:
815 s.close()
816
Antoine Pitrou152efa22010-05-16 18:19:27 +0000817 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000818 with support.transient_internet("svn.python.org"):
819 # Same as test_connect, but with a separately created context
820 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
821 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
822 s.connect(("svn.python.org", 443))
823 try:
824 self.assertEqual({}, s.getpeercert())
825 finally:
826 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000827 # Same with a server hostname
828 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
829 server_hostname="svn.python.org")
830 if ssl.HAS_SNI:
831 s.connect(("svn.python.org", 443))
832 s.close()
833 else:
834 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000835 # This should fail because we have no verification certs
836 ctx.verify_mode = ssl.CERT_REQUIRED
837 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000838 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000839 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000840 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000841 # This should succeed because we specify the root cert
842 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
843 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
844 s.connect(("svn.python.org", 443))
845 try:
846 cert = s.getpeercert()
847 self.assertTrue(cert)
848 finally:
849 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000850
851 def test_connect_capath(self):
852 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000853 # NOTE: the subject hashing algorithm has been changed between
854 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
855 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000856 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000857 with support.transient_internet("svn.python.org"):
858 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
859 ctx.verify_mode = ssl.CERT_REQUIRED
860 ctx.load_verify_locations(capath=CAPATH)
861 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
862 s.connect(("svn.python.org", 443))
863 try:
864 cert = s.getpeercert()
865 self.assertTrue(cert)
866 finally:
867 s.close()
868 # Same with a bytes `capath` argument
869 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
870 ctx.verify_mode = ssl.CERT_REQUIRED
871 ctx.load_verify_locations(capath=BYTES_CAPATH)
872 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
873 s.connect(("svn.python.org", 443))
874 try:
875 cert = s.getpeercert()
876 self.assertTrue(cert)
877 finally:
878 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879
Antoine Pitroue3220242010-04-24 11:13:53 +0000880 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
881 def test_makefile_close(self):
882 # Issue #5238: creating a file-like object with makefile() shouldn't
883 # delay closing the underlying "real socket" (here tested with its
884 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000885 with support.transient_internet("svn.python.org"):
886 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
887 ss.connect(("svn.python.org", 443))
888 fd = ss.fileno()
889 f = ss.makefile()
890 f.close()
891 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000892 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000893 # Closing the SSL socket should close the fd too
894 ss.close()
895 gc.collect()
896 with self.assertRaises(OSError) as e:
897 os.read(fd, 0)
898 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000899
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000901 with support.transient_internet("svn.python.org"):
902 s = socket.socket(socket.AF_INET)
903 s.connect(("svn.python.org", 443))
904 s.setblocking(False)
905 s = ssl.wrap_socket(s,
906 cert_reqs=ssl.CERT_NONE,
907 do_handshake_on_connect=False)
908 count = 0
909 while True:
910 try:
911 count += 1
912 s.do_handshake()
913 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200914 except ssl.SSLWantReadError:
915 select.select([s], [], [])
916 except ssl.SSLWantWriteError:
917 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000918 s.close()
919 if support.verbose:
920 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921
Antoine Pitrou480a1242010-04-28 21:37:09 +0000922 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200923 def _test_get_server_certificate(host, port, cert=None):
924 with support.transient_internet(host):
925 pem = ssl.get_server_certificate((host, port))
926 if not pem:
927 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200928
Antoine Pitrou15399c32011-04-28 19:23:55 +0200929 try:
930 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
931 except ssl.SSLError as x:
932 #should fail
933 if support.verbose:
934 sys.stdout.write("%s\n" % x)
935 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200936 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
937
Antoine Pitrou15399c32011-04-28 19:23:55 +0200938 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
939 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200940 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000941 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200942 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000943
Antoine Pitrou15399c32011-04-28 19:23:55 +0200944 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
945 if support.IPV6_ENABLED:
946 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000947
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000948 def test_ciphers(self):
949 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000950 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100951 with ssl.wrap_socket(socket.socket(socket.AF_INET),
952 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
953 s.connect(remote)
954 with ssl.wrap_socket(socket.socket(socket.AF_INET),
955 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
956 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000957 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000958 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000959 with socket.socket(socket.AF_INET) as sock:
960 s = ssl.wrap_socket(sock,
961 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
962 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000963
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000964 def test_algorithms(self):
965 # Issue #8484: all algorithms should be available when verifying a
966 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000967 # SHA256 was added in OpenSSL 0.9.8
968 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
969 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200970 # sha256.tbs-internet.com needs SNI to use the correct certificate
971 if not ssl.HAS_SNI:
972 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000973 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
974 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000975 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000976 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200977 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
978 ctx.verify_mode = ssl.CERT_REQUIRED
979 ctx.load_verify_locations(sha256_cert)
980 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
981 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000982 try:
983 s.connect(remote)
984 if support.verbose:
985 sys.stdout.write("\nCipher with %r is %r\n" %
986 (remote, s.cipher()))
987 sys.stdout.write("Certificate is:\n%s\n" %
988 pprint.pformat(s.getpeercert()))
989 finally:
990 s.close()
991
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000992
993try:
994 import threading
995except ImportError:
996 _have_threads = False
997else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 _have_threads = True
999
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001000 from test.ssl_servers import make_https_server
1001
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002 class ThreadedEchoServer(threading.Thread):
1003
1004 class ConnectionHandler(threading.Thread):
1005
1006 """A mildly complicated class, because we want it to work both
1007 with and without the SSL wrapper around the socket connection, so
1008 that we can test the STARTTLS functionality."""
1009
Bill Janssen6e027db2007-11-15 22:23:56 +00001010 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001011 self.server = server
1012 self.running = False
1013 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001014 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001015 self.sock.setblocking(1)
1016 self.sslconn = None
1017 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001018 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001019
Antoine Pitrou480a1242010-04-28 21:37:09 +00001020 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001021 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001022 self.sslconn = self.server.context.wrap_socket(
1023 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001024 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001025 except (ssl.SSLError, ConnectionResetError) as e:
1026 # We treat ConnectionResetError as though it were an
1027 # SSLError - OpenSSL on Ubuntu abruptly closes the
1028 # connection when asked to use an unsupported protocol.
1029 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001030 # XXX Various errors can have happened here, for example
1031 # a mismatching protocol version, an invalid certificate,
1032 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001033 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001035 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001036 self.running = False
1037 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001038 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001039 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001040 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001041 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001042 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001043 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001044 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1045 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001046 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001047 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1048 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001049 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001050 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001051 sys.stdout.write(" server: selected protocol is now "
1052 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001053 return True
1054
1055 def read(self):
1056 if self.sslconn:
1057 return self.sslconn.read()
1058 else:
1059 return self.sock.recv(1024)
1060
1061 def write(self, bytes):
1062 if self.sslconn:
1063 return self.sslconn.write(bytes)
1064 else:
1065 return self.sock.send(bytes)
1066
1067 def close(self):
1068 if self.sslconn:
1069 self.sslconn.close()
1070 else:
1071 self.sock.close()
1072
Antoine Pitrou480a1242010-04-28 21:37:09 +00001073 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001074 self.running = True
1075 if not self.server.starttls_server:
1076 if not self.wrap_conn():
1077 return
1078 while self.running:
1079 try:
1080 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001081 stripped = msg.strip()
1082 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001083 # eof, so quit this handler
1084 self.running = False
1085 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001086 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001087 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001088 sys.stdout.write(" server: client closed connection\n")
1089 self.close()
1090 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001091 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001092 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001093 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001094 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001095 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001096 if not self.wrap_conn():
1097 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001098 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001099 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001100 if support.verbose and self.server.connectionchatty:
1101 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001102 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001103 self.sock = self.sslconn.unwrap()
1104 self.sslconn = None
1105 if support.verbose and self.server.connectionchatty:
1106 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001107 elif stripped == b'CB tls-unique':
1108 if support.verbose and self.server.connectionchatty:
1109 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1110 data = self.sslconn.get_channel_binding("tls-unique")
1111 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001113 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001114 self.server.connectionchatty):
1115 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001116 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1117 % (msg, ctype, msg.lower(), ctype))
1118 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001119 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001120 if self.server.chatty:
1121 handle_error("Test server failure:\n")
1122 self.close()
1123 self.running = False
1124 # normally, we'd just stop here, but for the test
1125 # harness, we want to stop the server
1126 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127
Antoine Pitroub5218772010-05-21 09:56:06 +00001128 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001129 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001130 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001131 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001132 if context:
1133 self.context = context
1134 else:
1135 self.context = ssl.SSLContext(ssl_version
1136 if ssl_version is not None
1137 else ssl.PROTOCOL_TLSv1)
1138 self.context.verify_mode = (certreqs if certreqs is not None
1139 else ssl.CERT_NONE)
1140 if cacerts:
1141 self.context.load_verify_locations(cacerts)
1142 if certificate:
1143 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001144 if npn_protocols:
1145 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001146 if ciphers:
1147 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148 self.chatty = chatty
1149 self.connectionchatty = connectionchatty
1150 self.starttls_server = starttls_server
1151 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001152 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001153 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001154 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001155 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001156 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001157 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001158 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001159
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001160 def __enter__(self):
1161 self.start(threading.Event())
1162 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001163 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001164
1165 def __exit__(self, *args):
1166 self.stop()
1167 self.join()
1168
Antoine Pitrou480a1242010-04-28 21:37:09 +00001169 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001170 self.flag = flag
1171 threading.Thread.start(self)
1172
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001174 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001175 self.sock.listen(5)
1176 self.active = True
1177 if self.flag:
1178 # signal an event
1179 self.flag.set()
1180 while self.active:
1181 try:
1182 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001183 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001184 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001185 + repr(connaddr) + '\n')
1186 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001187 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001188 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001189 except socket.timeout:
1190 pass
1191 except KeyboardInterrupt:
1192 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001193 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001194
Antoine Pitrou480a1242010-04-28 21:37:09 +00001195 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001196 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001197
Bill Janssen54cc54c2007-12-14 22:08:56 +00001198 class AsyncoreEchoServer(threading.Thread):
1199
1200 # this one's based on asyncore.dispatcher
1201
1202 class EchoServer (asyncore.dispatcher):
1203
1204 class ConnectionHandler (asyncore.dispatcher_with_send):
1205
1206 def __init__(self, conn, certfile):
1207 self.socket = ssl.wrap_socket(conn, server_side=True,
1208 certfile=certfile,
1209 do_handshake_on_connect=False)
1210 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001211 self._ssl_accepting = True
1212 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001213
1214 def readable(self):
1215 if isinstance(self.socket, ssl.SSLSocket):
1216 while self.socket.pending() > 0:
1217 self.handle_read_event()
1218 return True
1219
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001220 def _do_ssl_handshake(self):
1221 try:
1222 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001223 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1224 return
1225 except ssl.SSLEOFError:
1226 return self.handle_close()
1227 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001228 raise
1229 except socket.error as err:
1230 if err.args[0] == errno.ECONNABORTED:
1231 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001232 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001233 self._ssl_accepting = False
1234
1235 def handle_read(self):
1236 if self._ssl_accepting:
1237 self._do_ssl_handshake()
1238 else:
1239 data = self.recv(1024)
1240 if support.verbose:
1241 sys.stdout.write(" server: read %s from client\n" % repr(data))
1242 if not data:
1243 self.close()
1244 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001245 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001246
1247 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001248 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001249 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001250 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1251
1252 def handle_error(self):
1253 raise
1254
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001255 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001256 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001257 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1258 self.port = support.bind_port(sock, '')
1259 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001260 self.listen(5)
1261
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001262 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001263 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001264 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1265 self.ConnectionHandler(sock_obj, self.certfile)
1266
1267 def handle_error(self):
1268 raise
1269
Trent Nelson78520002008-04-10 20:54:35 +00001270 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001271 self.flag = None
1272 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001273 self.server = self.EchoServer(certfile)
1274 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001275 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001276 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001277
1278 def __str__(self):
1279 return "<%s %s>" % (self.__class__.__name__, self.server)
1280
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001281 def __enter__(self):
1282 self.start(threading.Event())
1283 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001284 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001285
1286 def __exit__(self, *args):
1287 if support.verbose:
1288 sys.stdout.write(" cleanup: stopping server.\n")
1289 self.stop()
1290 if support.verbose:
1291 sys.stdout.write(" cleanup: joining server thread.\n")
1292 self.join()
1293 if support.verbose:
1294 sys.stdout.write(" cleanup: successfully joined.\n")
1295
Bill Janssen54cc54c2007-12-14 22:08:56 +00001296 def start (self, flag=None):
1297 self.flag = flag
1298 threading.Thread.start(self)
1299
Antoine Pitrou480a1242010-04-28 21:37:09 +00001300 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001301 self.active = True
1302 if self.flag:
1303 self.flag.set()
1304 while self.active:
1305 try:
1306 asyncore.loop(1)
1307 except:
1308 pass
1309
Antoine Pitrou480a1242010-04-28 21:37:09 +00001310 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001311 self.active = False
1312 self.server.close()
1313
Antoine Pitrou480a1242010-04-28 21:37:09 +00001314 def bad_cert_test(certfile):
1315 """
1316 Launch a server with CERT_REQUIRED, and check that trying to
1317 connect to it with the given client certificate fails.
1318 """
Trent Nelson78520002008-04-10 20:54:35 +00001319 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001320 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001321 cacerts=CERTFILE, chatty=False,
1322 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001323 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001324 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001325 with socket.socket() as sock:
1326 s = ssl.wrap_socket(sock,
1327 certfile=certfile,
1328 ssl_version=ssl.PROTOCOL_TLSv1)
1329 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001330 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001331 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001332 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001333 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001334 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001335 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001336 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001337 if x.errno != errno.ENOENT:
1338 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001339 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001340 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001341 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001342 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001343
Antoine Pitroub5218772010-05-21 09:56:06 +00001344 def server_params_test(client_context, server_context, indata=b"FOO\n",
1345 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001346 """
1347 Launch a server, connect a client to it and try various reads
1348 and writes.
1349 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001350 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001351 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001352 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001353 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001354 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001355 with client_context.wrap_socket(socket.socket()) as s:
1356 s.connect((HOST, server.port))
1357 for arg in [indata, bytearray(indata), memoryview(indata)]:
1358 if connectionchatty:
1359 if support.verbose:
1360 sys.stdout.write(
1361 " client: sending %r...\n" % indata)
1362 s.write(arg)
1363 outdata = s.read()
1364 if connectionchatty:
1365 if support.verbose:
1366 sys.stdout.write(" client: read %r\n" % outdata)
1367 if outdata != indata.lower():
1368 raise AssertionError(
1369 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1370 % (outdata[:20], len(outdata),
1371 indata[:20].lower(), len(indata)))
1372 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001373 if connectionchatty:
1374 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001375 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001376 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001377 'compression': s.compression(),
1378 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001379 'client_npn_protocol': s.selected_npn_protocol()
1380 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001381 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001382 stats['server_npn_protocols'] = server.selected_protocols
1383 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001384
Antoine Pitroub5218772010-05-21 09:56:06 +00001385 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1386 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001387 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001388 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 certtype = {
1390 ssl.CERT_NONE: "CERT_NONE",
1391 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1392 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1393 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001394 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001396 sys.stdout.write(formatstr %
1397 (ssl.get_protocol_name(client_protocol),
1398 ssl.get_protocol_name(server_protocol),
1399 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001400 client_context = ssl.SSLContext(client_protocol)
1401 client_context.options = ssl.OP_ALL | client_options
1402 server_context = ssl.SSLContext(server_protocol)
1403 server_context.options = ssl.OP_ALL | server_options
1404 for ctx in (client_context, server_context):
1405 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001406 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1407 # will send an SSLv3 hello (rather than SSLv2) starting from
1408 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001409 ctx.set_ciphers("ALL")
1410 ctx.load_cert_chain(CERTFILE)
1411 ctx.load_verify_locations(CERTFILE)
1412 try:
1413 server_params_test(client_context, server_context,
1414 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001415 # Protocol mismatch can result in either an SSLError, or a
1416 # "Connection reset by peer" error.
1417 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001419 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001420 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001421 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001422 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001423 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001424 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001425 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001426 "Client protocol %s succeeded with server protocol %s!"
1427 % (ssl.get_protocol_name(client_protocol),
1428 ssl.get_protocol_name(server_protocol)))
1429
1430
Bill Janssen6e027db2007-11-15 22:23:56 +00001431 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001432
Antoine Pitrou23df4832010-08-04 17:14:06 +00001433 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001434 def test_echo(self):
1435 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001436 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001437 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001438 for protocol in PROTOCOLS:
1439 context = ssl.SSLContext(protocol)
1440 context.load_cert_chain(CERTFILE)
1441 server_params_test(context, context,
1442 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001443
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001445 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001446 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001447 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1448 context.verify_mode = ssl.CERT_REQUIRED
1449 context.load_verify_locations(CERTFILE)
1450 context.load_cert_chain(CERTFILE)
1451 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001452 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001453 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001454 s.connect((HOST, server.port))
1455 cert = s.getpeercert()
1456 self.assertTrue(cert, "Can't get peer certificate.")
1457 cipher = s.cipher()
1458 if support.verbose:
1459 sys.stdout.write(pprint.pformat(cert) + '\n')
1460 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1461 if 'subject' not in cert:
1462 self.fail("No subject field in certificate: %s." %
1463 pprint.pformat(cert))
1464 if ((('organizationName', 'Python Software Foundation'),)
1465 not in cert['subject']):
1466 self.fail(
1467 "Missing or invalid 'organizationName' field in certificate subject; "
1468 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001469 self.assertIn('notBefore', cert)
1470 self.assertIn('notAfter', cert)
1471 before = ssl.cert_time_to_seconds(cert['notBefore'])
1472 after = ssl.cert_time_to_seconds(cert['notAfter'])
1473 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001474 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001475
Antoine Pitrou480a1242010-04-28 21:37:09 +00001476 def test_empty_cert(self):
1477 """Connecting with an empty cert file"""
1478 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1479 "nullcert.pem"))
1480 def test_malformed_cert(self):
1481 """Connecting with a badly formatted certificate (syntax error)"""
1482 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1483 "badcert.pem"))
1484 def test_nonexisting_cert(self):
1485 """Connecting with a non-existing cert file"""
1486 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1487 "wrongcert.pem"))
1488 def test_malformed_key(self):
1489 """Connecting with a badly formatted key (syntax error)"""
1490 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1491 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001492
Antoine Pitrou480a1242010-04-28 21:37:09 +00001493 def test_rude_shutdown(self):
1494 """A brutal shutdown of an SSL server should raise an IOError
1495 in the client when attempting handshake.
1496 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001497 listener_ready = threading.Event()
1498 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001499
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001500 s = socket.socket()
1501 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001502
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001503 # `listener` runs in a thread. It sits in an accept() until
1504 # the main thread connects. Then it rudely closes the socket,
1505 # and sets Event `listener_gone` to let the main thread know
1506 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001507 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001508 s.listen(5)
1509 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001510 newsock, addr = s.accept()
1511 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001512 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001513 listener_gone.set()
1514
1515 def connector():
1516 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001517 with socket.socket() as c:
1518 c.connect((HOST, port))
1519 listener_gone.wait()
1520 try:
1521 ssl_sock = ssl.wrap_socket(c)
1522 except IOError:
1523 pass
1524 else:
1525 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001526
1527 t = threading.Thread(target=listener)
1528 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001529 try:
1530 connector()
1531 finally:
1532 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001533
Antoine Pitrou23df4832010-08-04 17:14:06 +00001534 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001535 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1536 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001537 def test_protocol_sslv2(self):
1538 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001539 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001540 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001541 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1542 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1543 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1544 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1545 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1546 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001547 # SSLv23 client with specific SSL options
1548 if no_sslv2_implies_sslv3_hello():
1549 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1550 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1551 client_options=ssl.OP_NO_SSLv2)
1552 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1553 client_options=ssl.OP_NO_SSLv3)
1554 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1555 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001556
Antoine Pitrou23df4832010-08-04 17:14:06 +00001557 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001558 def test_protocol_sslv23(self):
1559 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001560 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001561 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001562 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1563 try:
1564 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1565 except (ssl.SSLError, socket.error) as x:
1566 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1567 if support.verbose:
1568 sys.stdout.write(
1569 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1570 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1572 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1573 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001574
Antoine Pitrou480a1242010-04-28 21:37:09 +00001575 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1576 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1577 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001578
Antoine Pitrou480a1242010-04-28 21:37:09 +00001579 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1580 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1581 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001582
Antoine Pitroub5218772010-05-21 09:56:06 +00001583 # Server with specific SSL options
1584 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1585 server_options=ssl.OP_NO_SSLv3)
1586 # Will choose TLSv1
1587 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1588 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1589 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1590 server_options=ssl.OP_NO_TLSv1)
1591
1592
Antoine Pitrou23df4832010-08-04 17:14:06 +00001593 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001594 def test_protocol_sslv3(self):
1595 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001596 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001597 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001598 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1599 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1600 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001601 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1602 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001603 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1604 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001605 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001606 if no_sslv2_implies_sslv3_hello():
1607 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1608 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1609 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001610
Antoine Pitrou23df4832010-08-04 17:14:06 +00001611 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001612 def test_protocol_tlsv1(self):
1613 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001614 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001615 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001616 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1617 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1618 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001619 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1620 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001621 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001622 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1623 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001624
Antoine Pitrou480a1242010-04-28 21:37:09 +00001625 def test_starttls(self):
1626 """Switching from clear text to encrypted and back again."""
1627 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 +00001628
Trent Nelson78520002008-04-10 20:54:35 +00001629 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001630 ssl_version=ssl.PROTOCOL_TLSv1,
1631 starttls_server=True,
1632 chatty=True,
1633 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001634 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001635 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001636 s = socket.socket()
1637 s.setblocking(1)
1638 s.connect((HOST, server.port))
1639 if support.verbose:
1640 sys.stdout.write("\n")
1641 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001642 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001643 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001644 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001645 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001646 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001647 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001648 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001649 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001650 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001651 msg = outdata.strip().lower()
1652 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1653 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001654 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001655 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001656 " client: read %r from server, starting TLS...\n"
1657 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001658 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1659 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001660 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1661 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001662 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001663 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001664 " client: read %r from server, ending TLS...\n"
1665 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001666 s = conn.unwrap()
1667 wrapped = False
1668 else:
1669 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001670 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001671 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001672 if support.verbose:
1673 sys.stdout.write(" client: closing connection.\n")
1674 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001675 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001676 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001677 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001678 if wrapped:
1679 conn.close()
1680 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001681 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001682
Antoine Pitrou480a1242010-04-28 21:37:09 +00001683 def test_socketserver(self):
1684 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001685 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001686 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001687 if support.verbose:
1688 sys.stdout.write('\n')
1689 with open(CERTFILE, 'rb') as f:
1690 d1 = f.read()
1691 d2 = ''
1692 # now fetch the same data from the HTTPS server
1693 url = 'https://%s:%d/%s' % (
1694 HOST, server.port, os.path.split(CERTFILE)[1])
1695 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001696 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001697 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001698 if dlen and (int(dlen) > 0):
1699 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001700 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001701 sys.stdout.write(
1702 " client: read %d bytes from remote server '%s'\n"
1703 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001704 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001705 f.close()
1706 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001707
Antoine Pitrou480a1242010-04-28 21:37:09 +00001708 def test_asyncore_server(self):
1709 """Check the example asyncore integration."""
1710 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001711
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001712 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001713 sys.stdout.write("\n")
1714
Antoine Pitrou480a1242010-04-28 21:37:09 +00001715 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001716 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001717 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001718 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001719 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001720 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001721 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001722 " client: sending %r...\n" % indata)
1723 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001724 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001725 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001726 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001727 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001728 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001729 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1730 % (outdata[:20], len(outdata),
1731 indata[:20].lower(), len(indata)))
1732 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001733 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001734 sys.stdout.write(" client: closing connection.\n")
1735 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001736 if support.verbose:
1737 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001738
Antoine Pitrou480a1242010-04-28 21:37:09 +00001739 def test_recv_send(self):
1740 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001741 if support.verbose:
1742 sys.stdout.write("\n")
1743
1744 server = ThreadedEchoServer(CERTFILE,
1745 certreqs=ssl.CERT_NONE,
1746 ssl_version=ssl.PROTOCOL_TLSv1,
1747 cacerts=CERTFILE,
1748 chatty=True,
1749 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001750 with server:
1751 s = ssl.wrap_socket(socket.socket(),
1752 server_side=False,
1753 certfile=CERTFILE,
1754 ca_certs=CERTFILE,
1755 cert_reqs=ssl.CERT_NONE,
1756 ssl_version=ssl.PROTOCOL_TLSv1)
1757 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001758 # helper methods for standardising recv* method signatures
1759 def _recv_into():
1760 b = bytearray(b"\0"*100)
1761 count = s.recv_into(b)
1762 return b[:count]
1763
1764 def _recvfrom_into():
1765 b = bytearray(b"\0"*100)
1766 count, addr = s.recvfrom_into(b)
1767 return b[:count]
1768
1769 # (name, method, whether to expect success, *args)
1770 send_methods = [
1771 ('send', s.send, True, []),
1772 ('sendto', s.sendto, False, ["some.address"]),
1773 ('sendall', s.sendall, True, []),
1774 ]
1775 recv_methods = [
1776 ('recv', s.recv, True, []),
1777 ('recvfrom', s.recvfrom, False, ["some.address"]),
1778 ('recv_into', _recv_into, True, []),
1779 ('recvfrom_into', _recvfrom_into, False, []),
1780 ]
1781 data_prefix = "PREFIX_"
1782
1783 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001784 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001785 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001786 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001787 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001788 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001789 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001790 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001791 "<<{outdata:r}>> ({nout:d}) received; "
1792 "expected <<{indata:r}>> ({nin:d})\n".format(
1793 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001794 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001795 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001796 )
1797 )
1798 except ValueError as e:
1799 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001800 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001801 "Failed to send with method <<{name:s}>>; "
1802 "expected to succeed.\n".format(name=meth_name)
1803 )
1804 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001805 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001806 "Method <<{name:s}>> failed with unexpected "
1807 "exception message: {exp:s}\n".format(
1808 name=meth_name, exp=e
1809 )
1810 )
1811
1812 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001813 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001814 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001815 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001816 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001817 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001818 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001819 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001820 "<<{outdata:r}>> ({nout:d}) received; "
1821 "expected <<{indata:r}>> ({nin:d})\n".format(
1822 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001823 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001824 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001825 )
1826 )
1827 except ValueError as e:
1828 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001829 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001830 "Failed to receive with method <<{name:s}>>; "
1831 "expected to succeed.\n".format(name=meth_name)
1832 )
1833 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001834 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001835 "Method <<{name:s}>> failed with unexpected "
1836 "exception message: {exp:s}\n".format(
1837 name=meth_name, exp=e
1838 )
1839 )
1840 # consume data
1841 s.read()
1842
Nick Coghlan513886a2011-08-28 00:00:27 +10001843 # Make sure sendmsg et al are disallowed to avoid
1844 # inadvertent disclosure of data and/or corruption
1845 # of the encrypted data stream
1846 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1847 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1848 self.assertRaises(NotImplementedError,
1849 s.recvmsg_into, bytearray(100))
1850
Antoine Pitrou480a1242010-04-28 21:37:09 +00001851 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001852 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001853
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001854 def test_handshake_timeout(self):
1855 # Issue #5103: SSL handshake must respect the socket timeout
1856 server = socket.socket(socket.AF_INET)
1857 host = "127.0.0.1"
1858 port = support.bind_port(server)
1859 started = threading.Event()
1860 finish = False
1861
1862 def serve():
1863 server.listen(5)
1864 started.set()
1865 conns = []
1866 while not finish:
1867 r, w, e = select.select([server], [], [], 0.1)
1868 if server in r:
1869 # Let the socket hang around rather than having
1870 # it closed by garbage collection.
1871 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001872 for sock in conns:
1873 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001874
1875 t = threading.Thread(target=serve)
1876 t.start()
1877 started.wait()
1878
1879 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001880 try:
1881 c = socket.socket(socket.AF_INET)
1882 c.settimeout(0.2)
1883 c.connect((host, port))
1884 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001885 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001886 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001887 finally:
1888 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001889 try:
1890 c = socket.socket(socket.AF_INET)
1891 c = ssl.wrap_socket(c)
1892 c.settimeout(0.2)
1893 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001894 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001895 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001896 finally:
1897 c.close()
1898 finally:
1899 finish = True
1900 t.join()
1901 server.close()
1902
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001903 def test_server_accept(self):
1904 # Issue #16357: accept() on a SSLSocket created through
1905 # SSLContext.wrap_socket().
1906 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1907 context.verify_mode = ssl.CERT_REQUIRED
1908 context.load_verify_locations(CERTFILE)
1909 context.load_cert_chain(CERTFILE)
1910 server = socket.socket(socket.AF_INET)
1911 host = "127.0.0.1"
1912 port = support.bind_port(server)
1913 server = context.wrap_socket(server, server_side=True)
1914
1915 evt = threading.Event()
1916 remote = None
1917 peer = None
1918 def serve():
1919 nonlocal remote, peer
1920 server.listen(5)
1921 # Block on the accept and wait on the connection to close.
1922 evt.set()
1923 remote, peer = server.accept()
1924 remote.recv(1)
1925
1926 t = threading.Thread(target=serve)
1927 t.start()
1928 # Client wait until server setup and perform a connect.
1929 evt.wait()
1930 client = context.wrap_socket(socket.socket())
1931 client.connect((host, port))
1932 client_addr = client.getsockname()
1933 client.close()
1934 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001935 remote.close()
1936 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001937 # Sanity checks.
1938 self.assertIsInstance(remote, ssl.SSLSocket)
1939 self.assertEqual(peer, client_addr)
1940
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001941 def test_default_ciphers(self):
1942 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1943 try:
1944 # Force a set of weak ciphers on our client context
1945 context.set_ciphers("DES")
1946 except ssl.SSLError:
1947 self.skipTest("no DES cipher available")
1948 with ThreadedEchoServer(CERTFILE,
1949 ssl_version=ssl.PROTOCOL_SSLv23,
1950 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001951 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001952 with self.assertRaises((OSError, ssl.SSLError)):
1953 s.connect((HOST, server.port))
1954 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1955
Antoine Pitroud6494802011-07-21 01:11:30 +02001956 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1957 "'tls-unique' channel binding not available")
1958 def test_tls_unique_channel_binding(self):
1959 """Test tls-unique channel binding."""
1960 if support.verbose:
1961 sys.stdout.write("\n")
1962
1963 server = ThreadedEchoServer(CERTFILE,
1964 certreqs=ssl.CERT_NONE,
1965 ssl_version=ssl.PROTOCOL_TLSv1,
1966 cacerts=CERTFILE,
1967 chatty=True,
1968 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001969 with server:
1970 s = ssl.wrap_socket(socket.socket(),
1971 server_side=False,
1972 certfile=CERTFILE,
1973 ca_certs=CERTFILE,
1974 cert_reqs=ssl.CERT_NONE,
1975 ssl_version=ssl.PROTOCOL_TLSv1)
1976 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001977 # get the data
1978 cb_data = s.get_channel_binding("tls-unique")
1979 if support.verbose:
1980 sys.stdout.write(" got channel binding data: {0!r}\n"
1981 .format(cb_data))
1982
1983 # check if it is sane
1984 self.assertIsNotNone(cb_data)
1985 self.assertEqual(len(cb_data), 12) # True for TLSv1
1986
1987 # and compare with the peers version
1988 s.write(b"CB tls-unique\n")
1989 peer_data_repr = s.read().strip()
1990 self.assertEqual(peer_data_repr,
1991 repr(cb_data).encode("us-ascii"))
1992 s.close()
1993
1994 # now, again
1995 s = ssl.wrap_socket(socket.socket(),
1996 server_side=False,
1997 certfile=CERTFILE,
1998 ca_certs=CERTFILE,
1999 cert_reqs=ssl.CERT_NONE,
2000 ssl_version=ssl.PROTOCOL_TLSv1)
2001 s.connect((HOST, server.port))
2002 new_cb_data = s.get_channel_binding("tls-unique")
2003 if support.verbose:
2004 sys.stdout.write(" got another channel binding data: {0!r}\n"
2005 .format(new_cb_data))
2006 # is it really unique
2007 self.assertNotEqual(cb_data, new_cb_data)
2008 self.assertIsNotNone(cb_data)
2009 self.assertEqual(len(cb_data), 12) # True for TLSv1
2010 s.write(b"CB tls-unique\n")
2011 peer_data_repr = s.read().strip()
2012 self.assertEqual(peer_data_repr,
2013 repr(new_cb_data).encode("us-ascii"))
2014 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002015
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002016 def test_compression(self):
2017 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2018 context.load_cert_chain(CERTFILE)
2019 stats = server_params_test(context, context,
2020 chatty=True, connectionchatty=True)
2021 if support.verbose:
2022 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2023 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2024
2025 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2026 "ssl.OP_NO_COMPRESSION needed for this test")
2027 def test_compression_disabled(self):
2028 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2029 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002030 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002031 stats = server_params_test(context, context,
2032 chatty=True, connectionchatty=True)
2033 self.assertIs(stats['compression'], None)
2034
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002035 def test_dh_params(self):
2036 # Check we can get a connection with ephemeral Diffie-Hellman
2037 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2038 context.load_cert_chain(CERTFILE)
2039 context.load_dh_params(DHFILE)
2040 context.set_ciphers("kEDH")
2041 stats = server_params_test(context, context,
2042 chatty=True, connectionchatty=True)
2043 cipher = stats["cipher"][0]
2044 parts = cipher.split("-")
2045 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2046 self.fail("Non-DH cipher: " + cipher[0])
2047
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002048 def test_selected_npn_protocol(self):
2049 # selected_npn_protocol() is None unless NPN is used
2050 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2051 context.load_cert_chain(CERTFILE)
2052 stats = server_params_test(context, context,
2053 chatty=True, connectionchatty=True)
2054 self.assertIs(stats['client_npn_protocol'], None)
2055
2056 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2057 def test_npn_protocols(self):
2058 server_protocols = ['http/1.1', 'spdy/2']
2059 protocol_tests = [
2060 (['http/1.1', 'spdy/2'], 'http/1.1'),
2061 (['spdy/2', 'http/1.1'], 'http/1.1'),
2062 (['spdy/2', 'test'], 'spdy/2'),
2063 (['abc', 'def'], 'abc')
2064 ]
2065 for client_protocols, expected in protocol_tests:
2066 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2067 server_context.load_cert_chain(CERTFILE)
2068 server_context.set_npn_protocols(server_protocols)
2069 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2070 client_context.load_cert_chain(CERTFILE)
2071 client_context.set_npn_protocols(client_protocols)
2072 stats = server_params_test(client_context, server_context,
2073 chatty=True, connectionchatty=True)
2074
2075 msg = "failed trying %s (s) and %s (c).\n" \
2076 "was expecting %s, but got %%s from the %%s" \
2077 % (str(server_protocols), str(client_protocols),
2078 str(expected))
2079 client_result = stats['client_npn_protocol']
2080 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2081 server_result = stats['server_npn_protocols'][-1] \
2082 if len(stats['server_npn_protocols']) else 'nothing'
2083 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2084
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002085
Thomas Woutersed03b412007-08-28 21:37:11 +00002086def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002087 if support.verbose:
2088 plats = {
2089 'Linux': platform.linux_distribution,
2090 'Mac': platform.mac_ver,
2091 'Windows': platform.win32_ver,
2092 }
2093 for name, func in plats.items():
2094 plat = func()
2095 if plat and plat[0]:
2096 plat = '%s %r' % (name, plat)
2097 break
2098 else:
2099 plat = repr(platform.platform())
2100 print("test_ssl: testing with %r %r" %
2101 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2102 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002103 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002104
Antoine Pitrou152efa22010-05-16 18:19:27 +00002105 for filename in [
2106 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2107 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2108 BADCERT, BADKEY, EMPTYCERT]:
2109 if not os.path.exists(filename):
2110 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002111
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002112 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002113
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002114 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002115 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002116
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002117 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002118 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002119 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002120 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002121
Antoine Pitrou480a1242010-04-28 21:37:09 +00002122 try:
2123 support.run_unittest(*tests)
2124 finally:
2125 if _have_threads:
2126 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002127
2128if __name__ == "__main__":
2129 test_main()