blob: 5c8df8bad86472551f9098ab13451319d9586520 [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 Stinner17ca3232011-05-10 00:48:41 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner17ca3232011-05-10 00:48:41 +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 Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020054NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056
Thomas Woutersed03b412007-08-28 21:37:11 +000057def handle_error(prefix):
58 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000059 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000060 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000061
Antoine Pitroub5218772010-05-21 09:56:06 +000062def can_clear_options():
63 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020064 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000065
66def no_sslv2_implies_sslv3_hello():
67 # 0.9.7h or higher
68 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
69
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitrou23df4832010-08-04 17:14:06 +000071# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
72def skip_if_broken_ubuntu_ssl(func):
Victor Stinner17ca3232011-05-10 00:48:41 +020073 if hasattr(ssl, 'PROTOCOL_SSLv2'):
74 @functools.wraps(func)
75 def f(*args, **kwargs):
76 try:
77 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
78 except ssl.SSLError:
79 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
80 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
81 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
82 return func(*args, **kwargs)
83 return f
84 else:
85 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000086
87
Antoine Pitrou152efa22010-05-16 18:19:27 +000088class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000089
Antoine Pitrou480a1242010-04-28 21:37:09 +000090 def test_constants(self):
Victor Stinneree18b6f2011-05-10 00:38:00 +020091 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000092 ssl.PROTOCOL_SSLv23
93 ssl.PROTOCOL_SSLv3
94 ssl.PROTOCOL_TLSv1
95 ssl.CERT_NONE
96 ssl.CERT_OPTIONAL
97 ssl.CERT_REQUIRED
Antoine Pitroud5323212010-10-22 18:19:07 +000098 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +000099
Antoine Pitrou480a1242010-04-28 21:37:09 +0000100 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000102 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000103 sys.stdout.write("\n RAND_status is %d (%s)\n"
104 % (v, (v and "sufficient randomness") or
105 "insufficient randomness"))
Jesus Ceac8754a12012-09-11 02:00:58 +0200106 self.assertRaises(TypeError, ssl.RAND_egd, 1)
107 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000108 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000109
Antoine Pitrou480a1242010-04-28 21:37:09 +0000110 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000111 # note that this uses an 'unofficial' function in _ssl.c,
112 # provided solely for this test, to exercise the certificate
113 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000114 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000115 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000116 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200117 self.assertEqual(p['issuer'],
118 ((('countryName', 'XY'),),
119 (('localityName', 'Castle Anthrax'),),
120 (('organizationName', 'Python Software Foundation'),),
121 (('commonName', 'localhost'),))
122 )
123 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
124 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
125 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
126 self.assertEqual(p['subject'],
127 ((('countryName', 'XY'),),
128 (('localityName', 'Castle Anthrax'),),
129 (('organizationName', 'Python Software Foundation'),),
130 (('commonName', 'localhost'),))
131 )
132 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
133 # Issue #13034: the subjectAltName in some certificates
134 # (notably projects.developer.nokia.com:443) wasn't parsed
135 p = ssl._ssl._test_decode_cert(NOKIACERT)
136 if support.verbose:
137 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
138 self.assertEqual(p['subjectAltName'],
139 (('DNS', 'projects.developer.nokia.com'),
140 ('DNS', 'projects.forum.nokia.com'))
141 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000142
Antoine Pitrou480a1242010-04-28 21:37:09 +0000143 def test_DER_to_PEM(self):
144 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
145 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000146 d1 = ssl.PEM_cert_to_DER_cert(pem)
147 p2 = ssl.DER_cert_to_PEM_cert(d1)
148 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000149 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000150 if not p2.startswith(ssl.PEM_HEADER + '\n'):
151 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
152 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
153 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000154
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000155 def test_openssl_version(self):
156 n = ssl.OPENSSL_VERSION_NUMBER
157 t = ssl.OPENSSL_VERSION_INFO
158 s = ssl.OPENSSL_VERSION
159 self.assertIsInstance(n, int)
160 self.assertIsInstance(t, tuple)
161 self.assertIsInstance(s, str)
162 # Some sanity checks follow
163 # >= 0.9
164 self.assertGreaterEqual(n, 0x900000)
165 # < 2.0
166 self.assertLess(n, 0x20000000)
167 major, minor, fix, patch, status = t
168 self.assertGreaterEqual(major, 0)
169 self.assertLess(major, 2)
170 self.assertGreaterEqual(minor, 0)
171 self.assertLess(minor, 256)
172 self.assertGreaterEqual(fix, 0)
173 self.assertLess(fix, 256)
174 self.assertGreaterEqual(patch, 0)
175 self.assertLessEqual(patch, 26)
176 self.assertGreaterEqual(status, 0)
177 self.assertLessEqual(status, 15)
178 # Version string as returned by OpenSSL, the format might change
179 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
180 (s, t))
181
Antoine Pitrou9d543662010-04-23 23:10:32 +0000182 @support.cpython_only
183 def test_refcycle(self):
184 # Issue #7943: an SSL object doesn't create reference cycles with
185 # itself.
186 s = socket.socket(socket.AF_INET)
187 ss = ssl.wrap_socket(s)
188 wr = weakref.ref(ss)
189 del ss
190 self.assertEqual(wr(), None)
191
Antoine Pitroua468adc2010-09-14 14:43:44 +0000192 def test_wrapped_unconnected(self):
193 # Methods on an unconnected SSLSocket propagate the original
194 # socket.error raise by the underlying socket object.
195 s = socket.socket(socket.AF_INET)
196 ss = ssl.wrap_socket(s)
197 self.assertRaises(socket.error, ss.recv, 1)
198 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
199 self.assertRaises(socket.error, ss.recvfrom, 1)
200 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
201 self.assertRaises(socket.error, ss.send, b'x')
202 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
203
Antoine Pitrou40f08742010-04-24 22:04:40 +0000204 def test_timeout(self):
205 # Issue #8524: when creating an SSL socket, the timeout of the
206 # original socket should be retained.
207 for timeout in (None, 0.0, 5.0):
208 s = socket.socket(socket.AF_INET)
209 s.settimeout(timeout)
210 ss = ssl.wrap_socket(s)
211 self.assertEqual(timeout, ss.gettimeout())
212
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000213 def test_errors(self):
214 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000215 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000216 "certfile must be specified",
217 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000218 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000219 "certfile must be specified for server-side operations",
220 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000221 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000222 "certfile must be specified for server-side operations",
223 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000224 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000225 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000226 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000227 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000228 with socket.socket() as sock:
229 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000230 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000231 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000232 with socket.socket() as sock:
233 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000234 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000235 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000236 with socket.socket() as sock:
237 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000238 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000239
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000240 def test_match_hostname(self):
241 def ok(cert, hostname):
242 ssl.match_hostname(cert, hostname)
243 def fail(cert, hostname):
244 self.assertRaises(ssl.CertificateError,
245 ssl.match_hostname, cert, hostname)
246
247 cert = {'subject': ((('commonName', 'example.com'),),)}
248 ok(cert, 'example.com')
249 ok(cert, 'ExAmple.cOm')
250 fail(cert, 'www.example.com')
251 fail(cert, '.example.com')
252 fail(cert, 'example.org')
253 fail(cert, 'exampleXcom')
254
255 cert = {'subject': ((('commonName', '*.a.com'),),)}
256 ok(cert, 'foo.a.com')
257 fail(cert, 'bar.foo.a.com')
258 fail(cert, 'a.com')
259 fail(cert, 'Xa.com')
260 fail(cert, '.a.com')
261
262 cert = {'subject': ((('commonName', 'a.*.com'),),)}
263 ok(cert, 'a.foo.com')
264 fail(cert, 'a..com')
265 fail(cert, 'a.com')
266
267 cert = {'subject': ((('commonName', 'f*.com'),),)}
268 ok(cert, 'foo.com')
269 ok(cert, 'f.com')
270 fail(cert, 'bar.com')
271 fail(cert, 'foo.a.com')
272 fail(cert, 'bar.foo.com')
273
274 # Slightly fake real-world example
275 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
276 'subject': ((('commonName', 'linuxfrz.org'),),),
277 'subjectAltName': (('DNS', 'linuxfr.org'),
278 ('DNS', 'linuxfr.com'),
279 ('othername', '<unsupported>'))}
280 ok(cert, 'linuxfr.org')
281 ok(cert, 'linuxfr.com')
282 # Not a "DNS" entry
283 fail(cert, '<unsupported>')
284 # When there is a subjectAltName, commonName isn't used
285 fail(cert, 'linuxfrz.org')
286
287 # A pristine real-world example
288 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
289 'subject': ((('countryName', 'US'),),
290 (('stateOrProvinceName', 'California'),),
291 (('localityName', 'Mountain View'),),
292 (('organizationName', 'Google Inc'),),
293 (('commonName', 'mail.google.com'),))}
294 ok(cert, 'mail.google.com')
295 fail(cert, 'gmail.com')
296 # Only commonName is considered
297 fail(cert, 'California')
298
299 # Neither commonName nor subjectAltName
300 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
301 'subject': ((('countryName', 'US'),),
302 (('stateOrProvinceName', 'California'),),
303 (('localityName', 'Mountain View'),),
304 (('organizationName', 'Google Inc'),))}
305 fail(cert, 'mail.google.com')
306
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200307 # No DNS entry in subjectAltName but a commonName
308 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
309 'subject': ((('countryName', 'US'),),
310 (('stateOrProvinceName', 'California'),),
311 (('localityName', 'Mountain View'),),
312 (('commonName', 'mail.google.com'),)),
313 'subjectAltName': (('othername', 'blabla'), )}
314 ok(cert, 'mail.google.com')
315
316 # No DNS entry subjectAltName and no commonName
317 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
318 'subject': ((('countryName', 'US'),),
319 (('stateOrProvinceName', 'California'),),
320 (('localityName', 'Mountain View'),),
321 (('organizationName', 'Google Inc'),)),
322 'subjectAltName': (('othername', 'blabla'),)}
323 fail(cert, 'google.com')
324
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000325 # Empty cert / no cert
326 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
327 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
328
Antoine Pitrou86d53ca2013-05-18 17:56:42 +0200329 # Issue #17980: avoid denials of service by refusing more than one
330 # wildcard per fragment.
331 cert = {'subject': ((('commonName', 'a*b.com'),),)}
332 ok(cert, 'axxb.com')
333 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
334 ok(cert, 'axxb.com')
335 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
336 with self.assertRaises(ssl.CertificateError) as cm:
337 ssl.match_hostname(cert, 'axxbxxc.com')
338 self.assertIn("too many wildcards", str(cm.exception))
339
Antoine Pitroud5323212010-10-22 18:19:07 +0000340 def test_server_side(self):
341 # server_hostname doesn't work for server sockets
342 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000343 with socket.socket() as sock:
344 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
345 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000346
Antoine Pitrou152efa22010-05-16 18:19:27 +0000347class ContextTests(unittest.TestCase):
348
Antoine Pitrou23df4832010-08-04 17:14:06 +0000349 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000350 def test_constructor(self):
Victor Stinner17ca3232011-05-10 00:48:41 +0200351 if hasattr(ssl, 'PROTOCOL_SSLv2'):
352 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000353 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
354 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
355 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
356 self.assertRaises(TypeError, ssl.SSLContext)
357 self.assertRaises(ValueError, ssl.SSLContext, -1)
358 self.assertRaises(ValueError, ssl.SSLContext, 42)
359
Antoine Pitrou23df4832010-08-04 17:14:06 +0000360 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000361 def test_protocol(self):
362 for proto in PROTOCOLS:
363 ctx = ssl.SSLContext(proto)
364 self.assertEqual(ctx.protocol, proto)
365
366 def test_ciphers(self):
367 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
368 ctx.set_ciphers("ALL")
369 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000370 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000371 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000372
Antoine Pitrou23df4832010-08-04 17:14:06 +0000373 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000374 def test_options(self):
375 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
376 # OP_ALL is the default value
377 self.assertEqual(ssl.OP_ALL, ctx.options)
378 ctx.options |= ssl.OP_NO_SSLv2
379 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
380 ctx.options)
381 ctx.options |= ssl.OP_NO_SSLv3
382 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
383 ctx.options)
384 if can_clear_options():
385 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
386 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
387 ctx.options)
388 ctx.options = 0
389 self.assertEqual(0, ctx.options)
390 else:
391 with self.assertRaises(ValueError):
392 ctx.options = 0
393
Antoine Pitrou152efa22010-05-16 18:19:27 +0000394 def test_verify(self):
395 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
396 # Default value
397 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
398 ctx.verify_mode = ssl.CERT_OPTIONAL
399 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
400 ctx.verify_mode = ssl.CERT_REQUIRED
401 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
402 ctx.verify_mode = ssl.CERT_NONE
403 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
404 with self.assertRaises(TypeError):
405 ctx.verify_mode = None
406 with self.assertRaises(ValueError):
407 ctx.verify_mode = 42
408
409 def test_load_cert_chain(self):
410 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
411 # Combined key and cert in a single file
412 ctx.load_cert_chain(CERTFILE)
413 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
414 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000415 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000416 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000417 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000418 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000419 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000420 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000421 ctx.load_cert_chain(EMPTYCERT)
422 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000423 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000424 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
425 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
426 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000427 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000428 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000429 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000430 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000431 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000432 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
433 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000434 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000435 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000436 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000437
438 def test_load_verify_locations(self):
439 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
440 ctx.load_verify_locations(CERTFILE)
441 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
442 ctx.load_verify_locations(BYTES_CERTFILE)
443 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
444 self.assertRaises(TypeError, ctx.load_verify_locations)
445 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000446 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000447 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000448 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000449 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000450 ctx.load_verify_locations(BADCERT)
451 ctx.load_verify_locations(CERTFILE, CAPATH)
452 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
453
Victor Stinner80f75e62011-01-29 11:31:20 +0000454 # Issue #10989: crash if the second argument type is invalid
455 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
456
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000457 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000458 def test_session_stats(self):
459 for proto in PROTOCOLS:
460 ctx = ssl.SSLContext(proto)
461 self.assertEqual(ctx.session_stats(), {
462 'number': 0,
463 'connect': 0,
464 'connect_good': 0,
465 'connect_renegotiate': 0,
466 'accept': 0,
467 'accept_good': 0,
468 'accept_renegotiate': 0,
469 'hits': 0,
470 'misses': 0,
471 'timeouts': 0,
472 'cache_full': 0,
473 })
474
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000475 def test_set_default_verify_paths(self):
476 # There's not much we can do to test that it acts as expected,
477 # so just check it doesn't crash or raise an exception.
478 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
479 ctx.set_default_verify_paths()
480
Antoine Pitrou152efa22010-05-16 18:19:27 +0000481
Bill Janssen6e027db2007-11-15 22:23:56 +0000482class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000483
Antoine Pitrou480a1242010-04-28 21:37:09 +0000484 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000485 with support.transient_internet("svn.python.org"):
486 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
487 cert_reqs=ssl.CERT_NONE)
488 try:
489 s.connect(("svn.python.org", 443))
490 self.assertEqual({}, s.getpeercert())
491 finally:
492 s.close()
493
494 # this should fail because we have no verification certs
495 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
496 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000497 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
498 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000499 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000500
Antoine Pitrou350c7222010-09-09 13:31:46 +0000501 # this should succeed because we specify the root cert
502 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
503 cert_reqs=ssl.CERT_REQUIRED,
504 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
505 try:
506 s.connect(("svn.python.org", 443))
507 self.assertTrue(s.getpeercert())
508 finally:
509 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000510
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000511 def test_connect_ex(self):
512 # Issue #11326: check connect_ex() implementation
513 with support.transient_internet("svn.python.org"):
514 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
515 cert_reqs=ssl.CERT_REQUIRED,
516 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
517 try:
518 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
519 self.assertTrue(s.getpeercert())
520 finally:
521 s.close()
522
523 def test_non_blocking_connect_ex(self):
524 # Issue #11326: non-blocking connect_ex() should allow handshake
525 # to proceed after the socket gets ready.
526 with support.transient_internet("svn.python.org"):
527 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
528 cert_reqs=ssl.CERT_REQUIRED,
529 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
530 do_handshake_on_connect=False)
531 try:
532 s.setblocking(False)
533 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitroud1c98452011-02-27 15:45:16 +0000534 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
535 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000536 # Wait for connect to finish
537 select.select([], [s], [], 5.0)
538 # Non-blocking handshake
539 while True:
540 try:
541 s.do_handshake()
542 break
543 except ssl.SSLError as err:
544 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
545 select.select([s], [], [], 5.0)
546 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
547 select.select([], [s], [], 5.0)
548 else:
549 raise
550 # SSL established
551 self.assertTrue(s.getpeercert())
552 finally:
553 s.close()
554
Antoine Pitroub4410db2011-05-18 18:51:06 +0200555 def test_timeout_connect_ex(self):
556 # Issue #12065: on a timeout, connect_ex() should return the original
557 # errno (mimicking the behaviour of non-SSL sockets).
558 with support.transient_internet("svn.python.org"):
559 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
560 cert_reqs=ssl.CERT_REQUIRED,
561 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
562 do_handshake_on_connect=False)
563 try:
564 s.settimeout(0.0000001)
565 rc = s.connect_ex(('svn.python.org', 443))
566 if rc == 0:
567 self.skipTest("svn.python.org responded too quickly")
568 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
569 finally:
570 s.close()
571
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100572 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100573 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100574 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
575 cert_reqs=ssl.CERT_REQUIRED,
576 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
577 try:
578 self.assertEqual(errno.ECONNREFUSED,
579 s.connect_ex(("svn.python.org", 444)))
580 finally:
581 s.close()
582
Antoine Pitrou152efa22010-05-16 18:19:27 +0000583 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000584 with support.transient_internet("svn.python.org"):
585 # Same as test_connect, but with a separately created context
586 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
587 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
588 s.connect(("svn.python.org", 443))
589 try:
590 self.assertEqual({}, s.getpeercert())
591 finally:
592 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000593 # Same with a server hostname
594 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
595 server_hostname="svn.python.org")
596 if ssl.HAS_SNI:
597 s.connect(("svn.python.org", 443))
598 s.close()
599 else:
600 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000601 # This should fail because we have no verification certs
602 ctx.verify_mode = ssl.CERT_REQUIRED
603 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000604 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000605 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000606 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000607 # This should succeed because we specify the root cert
608 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
609 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
610 s.connect(("svn.python.org", 443))
611 try:
612 cert = s.getpeercert()
613 self.assertTrue(cert)
614 finally:
615 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000616
617 def test_connect_capath(self):
618 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000619 # NOTE: the subject hashing algorithm has been changed between
620 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
621 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000622 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000623 with support.transient_internet("svn.python.org"):
624 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
625 ctx.verify_mode = ssl.CERT_REQUIRED
626 ctx.load_verify_locations(capath=CAPATH)
627 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
628 s.connect(("svn.python.org", 443))
629 try:
630 cert = s.getpeercert()
631 self.assertTrue(cert)
632 finally:
633 s.close()
634 # Same with a bytes `capath` argument
635 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
636 ctx.verify_mode = ssl.CERT_REQUIRED
637 ctx.load_verify_locations(capath=BYTES_CAPATH)
638 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
639 s.connect(("svn.python.org", 443))
640 try:
641 cert = s.getpeercert()
642 self.assertTrue(cert)
643 finally:
644 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645
Antoine Pitroue3220242010-04-24 11:13:53 +0000646 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
647 def test_makefile_close(self):
648 # Issue #5238: creating a file-like object with makefile() shouldn't
649 # delay closing the underlying "real socket" (here tested with its
650 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000651 with support.transient_internet("svn.python.org"):
652 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
653 ss.connect(("svn.python.org", 443))
654 fd = ss.fileno()
655 f = ss.makefile()
656 f.close()
657 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000658 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000659 # Closing the SSL socket should close the fd too
660 ss.close()
661 gc.collect()
662 with self.assertRaises(OSError) as e:
663 os.read(fd, 0)
664 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000665
Antoine Pitrou480a1242010-04-28 21:37:09 +0000666 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000667 with support.transient_internet("svn.python.org"):
668 s = socket.socket(socket.AF_INET)
669 s.connect(("svn.python.org", 443))
670 s.setblocking(False)
671 s = ssl.wrap_socket(s,
672 cert_reqs=ssl.CERT_NONE,
673 do_handshake_on_connect=False)
674 count = 0
675 while True:
676 try:
677 count += 1
678 s.do_handshake()
679 break
680 except ssl.SSLError as err:
681 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
682 select.select([s], [], [])
683 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
684 select.select([], [s], [])
685 else:
686 raise
687 s.close()
688 if support.verbose:
689 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000690
Antoine Pitrou480a1242010-04-28 21:37:09 +0000691 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000692 with support.transient_internet("svn.python.org"):
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500693 pem = ssl.get_server_certificate(("svn.python.org", 443),
694 ssl.PROTOCOL_SSLv23)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000695 if not pem:
696 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000697
Antoine Pitrou350c7222010-09-09 13:31:46 +0000698 try:
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500699 pem = ssl.get_server_certificate(("svn.python.org", 443),
700 ssl.PROTOCOL_SSLv23,
701 ca_certs=CERTFILE)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000702 except ssl.SSLError as x:
703 #should fail
704 if support.verbose:
705 sys.stdout.write("%s\n" % x)
706 else:
707 self.fail("Got server certificate %s for svn.python.org!" % pem)
708
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500709 pem = ssl.get_server_certificate(("svn.python.org", 443),
710 ssl.PROTOCOL_SSLv23,
711 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000712 if not pem:
713 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000714 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000715 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000716
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000717 def test_ciphers(self):
718 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000719 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000720 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000721 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000722 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000723 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
724 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
725 s.connect(remote)
726 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000727 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000728 with socket.socket(socket.AF_INET) as sock:
729 s = ssl.wrap_socket(sock,
730 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
731 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000732
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000733 def test_algorithms(self):
734 # Issue #8484: all algorithms should be available when verifying a
735 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000736 # SHA256 was added in OpenSSL 0.9.8
737 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
738 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200739 # sha256.tbs-internet.com needs SNI to use the correct certificate
740 if not ssl.HAS_SNI:
741 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000742 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
743 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000744 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000745 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200746 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
747 ctx.verify_mode = ssl.CERT_REQUIRED
748 ctx.load_verify_locations(sha256_cert)
749 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
750 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000751 try:
752 s.connect(remote)
753 if support.verbose:
754 sys.stdout.write("\nCipher with %r is %r\n" %
755 (remote, s.cipher()))
756 sys.stdout.write("Certificate is:\n%s\n" %
757 pprint.pformat(s.getpeercert()))
758 finally:
759 s.close()
760
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000761
762try:
763 import threading
764except ImportError:
765 _have_threads = False
766else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000767 _have_threads = True
768
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000769 from test.ssl_servers import make_https_server
770
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000771 class ThreadedEchoServer(threading.Thread):
772
773 class ConnectionHandler(threading.Thread):
774
775 """A mildly complicated class, because we want it to work both
776 with and without the SSL wrapper around the socket connection, so
777 that we can test the STARTTLS functionality."""
778
Bill Janssen6e027db2007-11-15 22:23:56 +0000779 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000780 self.server = server
781 self.running = False
782 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000783 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000784 self.sock.setblocking(1)
785 self.sslconn = None
786 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000787 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000788
Antoine Pitrou480a1242010-04-28 21:37:09 +0000789 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000790 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000791 self.sslconn = self.server.context.wrap_socket(
792 self.sock, server_side=True)
Nadeem Vawda7b39b9b2013-03-03 22:31:21 +0100793 except (ssl.SSLError, socket.error) as e:
794 # Treat ECONNRESET as though it were an SSLError - OpenSSL
795 # on Ubuntu abruptly closes the connection when asked to use
796 # an unsupported protocol.
797 if (not isinstance(e, ssl.SSLError) and
798 e.errno != errno.ECONNRESET):
799 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000800 # XXX Various errors can have happened here, for example
801 # a mismatching protocol version, an invalid certificate,
802 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100803 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000804 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000805 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000806 self.running = False
807 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000808 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000809 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000810 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000811 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000812 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000813 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000814 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
815 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000816 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000817 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
818 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000819 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000820 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
821 return True
822
823 def read(self):
824 if self.sslconn:
825 return self.sslconn.read()
826 else:
827 return self.sock.recv(1024)
828
829 def write(self, bytes):
830 if self.sslconn:
831 return self.sslconn.write(bytes)
832 else:
833 return self.sock.send(bytes)
834
835 def close(self):
836 if self.sslconn:
837 self.sslconn.close()
838 else:
839 self.sock.close()
840
Antoine Pitrou480a1242010-04-28 21:37:09 +0000841 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842 self.running = True
843 if not self.server.starttls_server:
844 if not self.wrap_conn():
845 return
846 while self.running:
847 try:
848 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000849 stripped = msg.strip()
850 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851 # eof, so quit this handler
852 self.running = False
853 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000854 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000855 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856 sys.stdout.write(" server: client closed connection\n")
857 self.close()
858 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000859 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000860 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000861 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000863 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000864 if not self.wrap_conn():
865 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000866 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000867 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000868 if support.verbose and self.server.connectionchatty:
869 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000870 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000871 self.sock = self.sslconn.unwrap()
872 self.sslconn = None
873 if support.verbose and self.server.connectionchatty:
874 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000875 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000876 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000877 self.server.connectionchatty):
878 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000879 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
880 % (msg, ctype, msg.lower(), ctype))
881 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000882 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000883 if self.server.chatty:
884 handle_error("Test server failure:\n")
885 self.close()
886 self.running = False
887 # normally, we'd just stop here, but for the test
888 # harness, we want to stop the server
889 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000890
Antoine Pitroub5218772010-05-21 09:56:06 +0000891 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000892 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000893 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000894 ciphers=None, context=None):
895 if context:
896 self.context = context
897 else:
898 self.context = ssl.SSLContext(ssl_version
899 if ssl_version is not None
900 else ssl.PROTOCOL_TLSv1)
901 self.context.verify_mode = (certreqs if certreqs is not None
902 else ssl.CERT_NONE)
903 if cacerts:
904 self.context.load_verify_locations(cacerts)
905 if certificate:
906 self.context.load_cert_chain(certificate)
907 if ciphers:
908 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 self.chatty = chatty
910 self.connectionchatty = connectionchatty
911 self.starttls_server = starttls_server
912 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000913 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000914 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100916 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000917 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000918 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100920 def __enter__(self):
921 self.start(threading.Event())
922 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100923 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100924
925 def __exit__(self, *args):
926 self.stop()
927 self.join()
928
Antoine Pitrou480a1242010-04-28 21:37:09 +0000929 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 self.flag = flag
931 threading.Thread.start(self)
932
Antoine Pitrou480a1242010-04-28 21:37:09 +0000933 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000934 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 self.sock.listen(5)
936 self.active = True
937 if self.flag:
938 # signal an event
939 self.flag.set()
940 while self.active:
941 try:
942 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000943 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000944 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000945 + repr(connaddr) + '\n')
946 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +0100948 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 except socket.timeout:
950 pass
951 except KeyboardInterrupt:
952 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000953 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000954
Antoine Pitrou480a1242010-04-28 21:37:09 +0000955 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000956 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000957
Bill Janssen54cc54c2007-12-14 22:08:56 +0000958 class AsyncoreEchoServer(threading.Thread):
959
960 # this one's based on asyncore.dispatcher
961
962 class EchoServer (asyncore.dispatcher):
963
964 class ConnectionHandler (asyncore.dispatcher_with_send):
965
966 def __init__(self, conn, certfile):
967 self.socket = ssl.wrap_socket(conn, server_side=True,
968 certfile=certfile,
969 do_handshake_on_connect=False)
970 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000971 self._ssl_accepting = True
972 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000973
974 def readable(self):
975 if isinstance(self.socket, ssl.SSLSocket):
976 while self.socket.pending() > 0:
977 self.handle_read_event()
978 return True
979
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000980 def _do_ssl_handshake(self):
981 try:
982 self.socket.do_handshake()
983 except ssl.SSLError as err:
984 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
985 ssl.SSL_ERROR_WANT_WRITE):
986 return
987 elif err.args[0] == ssl.SSL_ERROR_EOF:
988 return self.handle_close()
989 raise
990 except socket.error as err:
991 if err.args[0] == errno.ECONNABORTED:
992 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000993 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000994 self._ssl_accepting = False
995
996 def handle_read(self):
997 if self._ssl_accepting:
998 self._do_ssl_handshake()
999 else:
1000 data = self.recv(1024)
1001 if support.verbose:
1002 sys.stdout.write(" server: read %s from client\n" % repr(data))
1003 if not data:
1004 self.close()
1005 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001006 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001007
1008 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001009 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001010 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001011 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1012
1013 def handle_error(self):
1014 raise
1015
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001016 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001017 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001018 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1019 self.port = support.bind_port(sock, '')
1020 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001021 self.listen(5)
1022
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001023 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001024 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001025 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1026 self.ConnectionHandler(sock_obj, self.certfile)
1027
1028 def handle_error(self):
1029 raise
1030
Trent Nelson78520002008-04-10 20:54:35 +00001031 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001032 self.flag = None
1033 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001034 self.server = self.EchoServer(certfile)
1035 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001036 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001037 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001038
1039 def __str__(self):
1040 return "<%s %s>" % (self.__class__.__name__, self.server)
1041
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001042 def __enter__(self):
1043 self.start(threading.Event())
1044 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001045 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001046
1047 def __exit__(self, *args):
1048 if support.verbose:
1049 sys.stdout.write(" cleanup: stopping server.\n")
1050 self.stop()
1051 if support.verbose:
1052 sys.stdout.write(" cleanup: joining server thread.\n")
1053 self.join()
1054 if support.verbose:
1055 sys.stdout.write(" cleanup: successfully joined.\n")
1056
Bill Janssen54cc54c2007-12-14 22:08:56 +00001057 def start (self, flag=None):
1058 self.flag = flag
1059 threading.Thread.start(self)
1060
Antoine Pitrou480a1242010-04-28 21:37:09 +00001061 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001062 self.active = True
1063 if self.flag:
1064 self.flag.set()
1065 while self.active:
1066 try:
1067 asyncore.loop(1)
1068 except:
1069 pass
1070
Antoine Pitrou480a1242010-04-28 21:37:09 +00001071 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001072 self.active = False
1073 self.server.close()
1074
Antoine Pitrou480a1242010-04-28 21:37:09 +00001075 def bad_cert_test(certfile):
1076 """
1077 Launch a server with CERT_REQUIRED, and check that trying to
1078 connect to it with the given client certificate fails.
1079 """
Trent Nelson78520002008-04-10 20:54:35 +00001080 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001081 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001082 cacerts=CERTFILE, chatty=False,
1083 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001084 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001085 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001086 with socket.socket() as sock:
1087 s = ssl.wrap_socket(sock,
1088 certfile=certfile,
1089 ssl_version=ssl.PROTOCOL_TLSv1)
1090 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001091 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001092 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001093 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001094 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001095 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001096 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001097 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001098 if x.errno != errno.ENOENT:
1099 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001100 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001101 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001102 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001103 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001104
Antoine Pitroub5218772010-05-21 09:56:06 +00001105 def server_params_test(client_context, server_context, indata=b"FOO\n",
1106 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001107 """
1108 Launch a server, connect a client to it and try various reads
1109 and writes.
1110 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001111 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001113 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001114 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001115 with client_context.wrap_socket(socket.socket()) as s:
1116 s.connect((HOST, server.port))
1117 for arg in [indata, bytearray(indata), memoryview(indata)]:
1118 if connectionchatty:
1119 if support.verbose:
1120 sys.stdout.write(
1121 " client: sending %r...\n" % indata)
1122 s.write(arg)
1123 outdata = s.read()
1124 if connectionchatty:
1125 if support.verbose:
1126 sys.stdout.write(" client: read %r\n" % outdata)
1127 if outdata != indata.lower():
1128 raise AssertionError(
1129 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1130 % (outdata[:20], len(outdata),
1131 indata[:20].lower(), len(indata)))
1132 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001133 if connectionchatty:
1134 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001135 sys.stdout.write(" client: closing connection.\n")
1136 s.close()
Thomas Woutersed03b412007-08-28 21:37:11 +00001137
Antoine Pitroub5218772010-05-21 09:56:06 +00001138 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1139 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001140 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001141 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001142 certtype = {
1143 ssl.CERT_NONE: "CERT_NONE",
1144 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1145 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1146 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001147 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001148 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001149 sys.stdout.write(formatstr %
1150 (ssl.get_protocol_name(client_protocol),
1151 ssl.get_protocol_name(server_protocol),
1152 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001153 client_context = ssl.SSLContext(client_protocol)
1154 client_context.options = ssl.OP_ALL | client_options
1155 server_context = ssl.SSLContext(server_protocol)
1156 server_context.options = ssl.OP_ALL | server_options
1157 for ctx in (client_context, server_context):
1158 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001159 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1160 # will send an SSLv3 hello (rather than SSLv2) starting from
1161 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001162 ctx.set_ciphers("ALL")
1163 ctx.load_cert_chain(CERTFILE)
1164 ctx.load_verify_locations(CERTFILE)
1165 try:
1166 server_params_test(client_context, server_context,
1167 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001168 # Protocol mismatch can result in either an SSLError, or a
1169 # "Connection reset by peer" error.
1170 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001171 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001172 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001173 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001175 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001176 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001177 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001178 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 "Client protocol %s succeeded with server protocol %s!"
1180 % (ssl.get_protocol_name(client_protocol),
1181 ssl.get_protocol_name(server_protocol)))
1182
1183
Bill Janssen6e027db2007-11-15 22:23:56 +00001184 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001185
Antoine Pitrou23df4832010-08-04 17:14:06 +00001186 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001187 def test_echo(self):
1188 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001189 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001190 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001191 for protocol in PROTOCOLS:
1192 context = ssl.SSLContext(protocol)
1193 context.load_cert_chain(CERTFILE)
1194 server_params_test(context, context,
1195 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001196
Antoine Pitrou480a1242010-04-28 21:37:09 +00001197 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001198 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001199 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001200 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1201 context.verify_mode = ssl.CERT_REQUIRED
1202 context.load_verify_locations(CERTFILE)
1203 context.load_cert_chain(CERTFILE)
1204 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001205 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001206 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001207 s.connect((HOST, server.port))
1208 cert = s.getpeercert()
1209 self.assertTrue(cert, "Can't get peer certificate.")
1210 cipher = s.cipher()
1211 if support.verbose:
1212 sys.stdout.write(pprint.pformat(cert) + '\n')
1213 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1214 if 'subject' not in cert:
1215 self.fail("No subject field in certificate: %s." %
1216 pprint.pformat(cert))
1217 if ((('organizationName', 'Python Software Foundation'),)
1218 not in cert['subject']):
1219 self.fail(
1220 "Missing or invalid 'organizationName' field in certificate subject; "
1221 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001222 self.assertIn('notBefore', cert)
1223 self.assertIn('notAfter', cert)
1224 before = ssl.cert_time_to_seconds(cert['notBefore'])
1225 after = ssl.cert_time_to_seconds(cert['notAfter'])
1226 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001227 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001228
Antoine Pitrou480a1242010-04-28 21:37:09 +00001229 def test_empty_cert(self):
1230 """Connecting with an empty cert file"""
1231 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1232 "nullcert.pem"))
1233 def test_malformed_cert(self):
1234 """Connecting with a badly formatted certificate (syntax error)"""
1235 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1236 "badcert.pem"))
1237 def test_nonexisting_cert(self):
1238 """Connecting with a non-existing cert file"""
1239 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1240 "wrongcert.pem"))
1241 def test_malformed_key(self):
1242 """Connecting with a badly formatted key (syntax error)"""
1243 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1244 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001245
Antoine Pitrou480a1242010-04-28 21:37:09 +00001246 def test_rude_shutdown(self):
1247 """A brutal shutdown of an SSL server should raise an IOError
1248 in the client when attempting handshake.
1249 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001250 listener_ready = threading.Event()
1251 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001252
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001253 s = socket.socket()
1254 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001255
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001256 # `listener` runs in a thread. It sits in an accept() until
1257 # the main thread connects. Then it rudely closes the socket,
1258 # and sets Event `listener_gone` to let the main thread know
1259 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001260 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001261 s.listen(5)
1262 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001263 newsock, addr = s.accept()
1264 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001265 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001266 listener_gone.set()
1267
1268 def connector():
1269 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001270 with socket.socket() as c:
1271 c.connect((HOST, port))
1272 listener_gone.wait()
1273 try:
1274 ssl_sock = ssl.wrap_socket(c)
1275 except IOError:
1276 pass
1277 else:
1278 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001279
1280 t = threading.Thread(target=listener)
1281 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001282 try:
1283 connector()
1284 finally:
1285 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001286
Antoine Pitrou23df4832010-08-04 17:14:06 +00001287 @skip_if_broken_ubuntu_ssl
Victor Stinneree18b6f2011-05-10 00:38:00 +02001288 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001289 def test_protocol_sslv2(self):
1290 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001291 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001292 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001293 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1294 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1295 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1296 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1297 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1298 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001299 # SSLv23 client with specific SSL options
1300 if no_sslv2_implies_sslv3_hello():
1301 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1302 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1303 client_options=ssl.OP_NO_SSLv2)
1304 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1305 client_options=ssl.OP_NO_SSLv3)
1306 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1307 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001308
Antoine Pitrou23df4832010-08-04 17:14:06 +00001309 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001310 def test_protocol_sslv23(self):
1311 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001312 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001313 sys.stdout.write("\n")
Victor Stinneree18b6f2011-05-10 00:38:00 +02001314 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1315 try:
1316 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1317 except (ssl.SSLError, socket.error) as x:
1318 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1319 if support.verbose:
1320 sys.stdout.write(
1321 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1322 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001323 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1324 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1325 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001326
Antoine Pitrou480a1242010-04-28 21:37:09 +00001327 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1328 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1329 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001330
Antoine Pitrou480a1242010-04-28 21:37:09 +00001331 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1332 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1333 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001334
Antoine Pitroub5218772010-05-21 09:56:06 +00001335 # Server with specific SSL options
1336 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1337 server_options=ssl.OP_NO_SSLv3)
1338 # Will choose TLSv1
1339 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1340 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1341 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1342 server_options=ssl.OP_NO_TLSv1)
1343
1344
Antoine Pitrou23df4832010-08-04 17:14:06 +00001345 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001346 def test_protocol_sslv3(self):
1347 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001348 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001349 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001350 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1351 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1352 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001353 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1354 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001355 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1356 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001358 if no_sslv2_implies_sslv3_hello():
1359 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1360 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1361 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001362
Antoine Pitrou23df4832010-08-04 17:14:06 +00001363 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001364 def test_protocol_tlsv1(self):
1365 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001366 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001367 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001368 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1369 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1370 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001371 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1372 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001373 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001374 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1375 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001376
Antoine Pitrou480a1242010-04-28 21:37:09 +00001377 def test_starttls(self):
1378 """Switching from clear text to encrypted and back again."""
1379 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 +00001380
Trent Nelson78520002008-04-10 20:54:35 +00001381 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001382 ssl_version=ssl.PROTOCOL_TLSv1,
1383 starttls_server=True,
1384 chatty=True,
1385 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001386 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001387 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001388 s = socket.socket()
1389 s.setblocking(1)
1390 s.connect((HOST, server.port))
1391 if support.verbose:
1392 sys.stdout.write("\n")
1393 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001394 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001395 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001397 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001398 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001399 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001400 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001401 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001402 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001403 msg = outdata.strip().lower()
1404 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1405 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001406 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001407 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001408 " client: read %r from server, starting TLS...\n"
1409 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001410 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1411 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001412 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1413 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001414 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001415 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001416 " client: read %r from server, ending TLS...\n"
1417 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001418 s = conn.unwrap()
1419 wrapped = False
1420 else:
1421 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001422 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001423 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001424 if support.verbose:
1425 sys.stdout.write(" client: closing connection.\n")
1426 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001427 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001428 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001429 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001430 if wrapped:
1431 conn.close()
1432 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001433 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 def test_socketserver(self):
1436 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001437 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001438 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001439 if support.verbose:
1440 sys.stdout.write('\n')
1441 with open(CERTFILE, 'rb') as f:
1442 d1 = f.read()
1443 d2 = ''
1444 # now fetch the same data from the HTTPS server
1445 url = 'https://%s:%d/%s' % (
1446 HOST, server.port, os.path.split(CERTFILE)[1])
1447 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001448 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001449 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001450 if dlen and (int(dlen) > 0):
1451 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001452 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001453 sys.stdout.write(
1454 " client: read %d bytes from remote server '%s'\n"
1455 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001456 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001457 f.close()
1458 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001459
Antoine Pitrou480a1242010-04-28 21:37:09 +00001460 def test_asyncore_server(self):
1461 """Check the example asyncore integration."""
1462 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001463
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001464 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001465 sys.stdout.write("\n")
1466
Antoine Pitrou480a1242010-04-28 21:37:09 +00001467 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001468 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001469 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001470 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001471 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001472 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001473 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001474 " client: sending %r...\n" % indata)
1475 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001476 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001477 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001478 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001479 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001480 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001481 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1482 % (outdata[:20], len(outdata),
1483 indata[:20].lower(), len(indata)))
1484 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001485 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001486 sys.stdout.write(" client: closing connection.\n")
1487 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001488 if support.verbose:
1489 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001490
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 def test_recv_send(self):
1492 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001493 if support.verbose:
1494 sys.stdout.write("\n")
1495
1496 server = ThreadedEchoServer(CERTFILE,
1497 certreqs=ssl.CERT_NONE,
1498 ssl_version=ssl.PROTOCOL_TLSv1,
1499 cacerts=CERTFILE,
1500 chatty=True,
1501 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001502 with server:
1503 s = ssl.wrap_socket(socket.socket(),
1504 server_side=False,
1505 certfile=CERTFILE,
1506 ca_certs=CERTFILE,
1507 cert_reqs=ssl.CERT_NONE,
1508 ssl_version=ssl.PROTOCOL_TLSv1)
1509 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001510 # helper methods for standardising recv* method signatures
1511 def _recv_into():
1512 b = bytearray(b"\0"*100)
1513 count = s.recv_into(b)
1514 return b[:count]
1515
1516 def _recvfrom_into():
1517 b = bytearray(b"\0"*100)
1518 count, addr = s.recvfrom_into(b)
1519 return b[:count]
1520
1521 # (name, method, whether to expect success, *args)
1522 send_methods = [
1523 ('send', s.send, True, []),
1524 ('sendto', s.sendto, False, ["some.address"]),
1525 ('sendall', s.sendall, True, []),
1526 ]
1527 recv_methods = [
1528 ('recv', s.recv, True, []),
1529 ('recvfrom', s.recvfrom, False, ["some.address"]),
1530 ('recv_into', _recv_into, True, []),
1531 ('recvfrom_into', _recvfrom_into, False, []),
1532 ]
1533 data_prefix = "PREFIX_"
1534
1535 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001536 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001537 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001538 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001539 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001540 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001541 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001542 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001543 "<<{outdata:r}>> ({nout:d}) received; "
1544 "expected <<{indata:r}>> ({nin:d})\n".format(
1545 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001546 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001547 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001548 )
1549 )
1550 except ValueError as e:
1551 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001552 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001553 "Failed to send with method <<{name:s}>>; "
1554 "expected to succeed.\n".format(name=meth_name)
1555 )
1556 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001557 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001558 "Method <<{name:s}>> failed with unexpected "
1559 "exception message: {exp:s}\n".format(
1560 name=meth_name, exp=e
1561 )
1562 )
1563
1564 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001565 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001566 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001568 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001569 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001570 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001571 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001572 "<<{outdata:r}>> ({nout:d}) received; "
1573 "expected <<{indata:r}>> ({nin:d})\n".format(
1574 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001575 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001576 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001577 )
1578 )
1579 except ValueError as e:
1580 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001581 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001582 "Failed to receive with method <<{name:s}>>; "
1583 "expected to succeed.\n".format(name=meth_name)
1584 )
1585 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001586 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001587 "Method <<{name:s}>> failed with unexpected "
1588 "exception message: {exp:s}\n".format(
1589 name=meth_name, exp=e
1590 )
1591 )
1592 # consume data
1593 s.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001594 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001595 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001596
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001597 def test_handshake_timeout(self):
1598 # Issue #5103: SSL handshake must respect the socket timeout
1599 server = socket.socket(socket.AF_INET)
1600 host = "127.0.0.1"
1601 port = support.bind_port(server)
1602 started = threading.Event()
1603 finish = False
1604
1605 def serve():
1606 server.listen(5)
1607 started.set()
1608 conns = []
1609 while not finish:
1610 r, w, e = select.select([server], [], [], 0.1)
1611 if server in r:
1612 # Let the socket hang around rather than having
1613 # it closed by garbage collection.
1614 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001615 for sock in conns:
1616 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001617
1618 t = threading.Thread(target=serve)
1619 t.start()
1620 started.wait()
1621
1622 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001623 try:
1624 c = socket.socket(socket.AF_INET)
1625 c.settimeout(0.2)
1626 c.connect((host, port))
1627 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001628 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001629 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001630 finally:
1631 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001632 try:
1633 c = socket.socket(socket.AF_INET)
1634 c = ssl.wrap_socket(c)
1635 c.settimeout(0.2)
1636 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001637 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001638 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001639 finally:
1640 c.close()
1641 finally:
1642 finish = True
1643 t.join()
1644 server.close()
1645
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001646 def test_server_accept(self):
1647 # Issue #16357: accept() on a SSLSocket created through
1648 # SSLContext.wrap_socket().
1649 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1650 context.verify_mode = ssl.CERT_REQUIRED
1651 context.load_verify_locations(CERTFILE)
1652 context.load_cert_chain(CERTFILE)
1653 server = socket.socket(socket.AF_INET)
1654 host = "127.0.0.1"
1655 port = support.bind_port(server)
1656 server = context.wrap_socket(server, server_side=True)
1657
1658 evt = threading.Event()
1659 remote = None
1660 peer = None
1661 def serve():
1662 nonlocal remote, peer
1663 server.listen(5)
1664 # Block on the accept and wait on the connection to close.
1665 evt.set()
1666 remote, peer = server.accept()
1667 remote.recv(1)
1668
1669 t = threading.Thread(target=serve)
1670 t.start()
1671 # Client wait until server setup and perform a connect.
1672 evt.wait()
1673 client = context.wrap_socket(socket.socket())
1674 client.connect((host, port))
1675 client_addr = client.getsockname()
1676 client.close()
1677 t.join()
1678 # Sanity checks.
1679 self.assertIsInstance(remote, ssl.SSLSocket)
1680 self.assertEqual(peer, client_addr)
1681
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001682 def test_default_ciphers(self):
1683 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1684 try:
1685 # Force a set of weak ciphers on our client context
1686 context.set_ciphers("DES")
1687 except ssl.SSLError:
1688 self.skipTest("no DES cipher available")
1689 with ThreadedEchoServer(CERTFILE,
1690 ssl_version=ssl.PROTOCOL_SSLv23,
1691 chatty=False) as server:
1692 with socket.socket() as sock:
1693 s = context.wrap_socket(sock)
1694 with self.assertRaises((OSError, ssl.SSLError)):
1695 s.connect((HOST, server.port))
1696 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1697
Bill Janssen58afe4c2008-09-08 16:45:19 +00001698
Thomas Woutersed03b412007-08-28 21:37:11 +00001699def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001700 if support.verbose:
1701 plats = {
1702 'Linux': platform.linux_distribution,
1703 'Mac': platform.mac_ver,
1704 'Windows': platform.win32_ver,
1705 }
1706 for name, func in plats.items():
1707 plat = func()
1708 if plat and plat[0]:
1709 plat = '%s %r' % (name, plat)
1710 break
1711 else:
1712 plat = repr(platform.platform())
1713 print("test_ssl: testing with %r %r" %
1714 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1715 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001716 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001717
Antoine Pitrou152efa22010-05-16 18:19:27 +00001718 for filename in [
1719 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1720 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1721 BADCERT, BADKEY, EMPTYCERT]:
1722 if not os.path.exists(filename):
1723 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001724
Antoine Pitrou152efa22010-05-16 18:19:27 +00001725 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001726
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001727 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001728 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001729
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001730 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001731 thread_info = support.threading_setup()
1732 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001733 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001734
Antoine Pitrou480a1242010-04-28 21:37:09 +00001735 try:
1736 support.run_unittest(*tests)
1737 finally:
1738 if _have_threads:
1739 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001740
1741if __name__ == "__main__":
1742 test_main()