blob: 4d67fa1de4fcd92757b58b0e47a1636d75a62fa8 [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"):
693 pem = ssl.get_server_certificate(("svn.python.org", 443))
694 if not pem:
695 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000696
Antoine Pitrou350c7222010-09-09 13:31:46 +0000697 try:
698 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
699 except ssl.SSLError as x:
700 #should fail
701 if support.verbose:
702 sys.stdout.write("%s\n" % x)
703 else:
704 self.fail("Got server certificate %s for svn.python.org!" % pem)
705
706 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
707 if not pem:
708 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000709 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000710 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000711
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000712 def test_ciphers(self):
713 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000714 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000715 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000716 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000717 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000718 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
719 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
720 s.connect(remote)
721 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000722 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000723 with socket.socket(socket.AF_INET) as sock:
724 s = ssl.wrap_socket(sock,
725 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
726 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000727
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000728 def test_algorithms(self):
729 # Issue #8484: all algorithms should be available when verifying a
730 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000731 # SHA256 was added in OpenSSL 0.9.8
732 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
733 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200734 # sha256.tbs-internet.com needs SNI to use the correct certificate
735 if not ssl.HAS_SNI:
736 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000737 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
738 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000739 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000740 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200741 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
742 ctx.verify_mode = ssl.CERT_REQUIRED
743 ctx.load_verify_locations(sha256_cert)
744 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
745 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000746 try:
747 s.connect(remote)
748 if support.verbose:
749 sys.stdout.write("\nCipher with %r is %r\n" %
750 (remote, s.cipher()))
751 sys.stdout.write("Certificate is:\n%s\n" %
752 pprint.pformat(s.getpeercert()))
753 finally:
754 s.close()
755
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756
757try:
758 import threading
759except ImportError:
760 _have_threads = False
761else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000762 _have_threads = True
763
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000764 from test.ssl_servers import make_https_server
765
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000766 class ThreadedEchoServer(threading.Thread):
767
768 class ConnectionHandler(threading.Thread):
769
770 """A mildly complicated class, because we want it to work both
771 with and without the SSL wrapper around the socket connection, so
772 that we can test the STARTTLS functionality."""
773
Bill Janssen6e027db2007-11-15 22:23:56 +0000774 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000775 self.server = server
776 self.running = False
777 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000778 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000779 self.sock.setblocking(1)
780 self.sslconn = None
781 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000782 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783
Antoine Pitrou480a1242010-04-28 21:37:09 +0000784 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000785 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000786 self.sslconn = self.server.context.wrap_socket(
787 self.sock, server_side=True)
Nadeem Vawda7b39b9b2013-03-03 22:31:21 +0100788 except (ssl.SSLError, socket.error) as e:
789 # Treat ECONNRESET as though it were an SSLError - OpenSSL
790 # on Ubuntu abruptly closes the connection when asked to use
791 # an unsupported protocol.
792 if (not isinstance(e, ssl.SSLError) and
793 e.errno != errno.ECONNRESET):
794 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000795 # XXX Various errors can have happened here, for example
796 # a mismatching protocol version, an invalid certificate,
797 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100798 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000799 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000800 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000801 self.running = False
802 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000803 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000804 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000805 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000806 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000807 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000808 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000809 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
810 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000811 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000812 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
813 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000814 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000815 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
816 return True
817
818 def read(self):
819 if self.sslconn:
820 return self.sslconn.read()
821 else:
822 return self.sock.recv(1024)
823
824 def write(self, bytes):
825 if self.sslconn:
826 return self.sslconn.write(bytes)
827 else:
828 return self.sock.send(bytes)
829
830 def close(self):
831 if self.sslconn:
832 self.sslconn.close()
833 else:
834 self.sock.close()
835
Antoine Pitrou480a1242010-04-28 21:37:09 +0000836 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000837 self.running = True
838 if not self.server.starttls_server:
839 if not self.wrap_conn():
840 return
841 while self.running:
842 try:
843 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000844 stripped = msg.strip()
845 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 # eof, so quit this handler
847 self.running = False
848 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000849 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000850 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851 sys.stdout.write(" server: client closed connection\n")
852 self.close()
853 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000854 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000855 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000856 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000857 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000858 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000859 if not self.wrap_conn():
860 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000861 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000862 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000863 if support.verbose and self.server.connectionchatty:
864 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000865 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000866 self.sock = self.sslconn.unwrap()
867 self.sslconn = None
868 if support.verbose and self.server.connectionchatty:
869 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000871 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 self.server.connectionchatty):
873 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000874 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
875 % (msg, ctype, msg.lower(), ctype))
876 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000877 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878 if self.server.chatty:
879 handle_error("Test server failure:\n")
880 self.close()
881 self.running = False
882 # normally, we'd just stop here, but for the test
883 # harness, we want to stop the server
884 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000885
Antoine Pitroub5218772010-05-21 09:56:06 +0000886 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000887 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000888 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000889 ciphers=None, context=None):
890 if context:
891 self.context = context
892 else:
893 self.context = ssl.SSLContext(ssl_version
894 if ssl_version is not None
895 else ssl.PROTOCOL_TLSv1)
896 self.context.verify_mode = (certreqs if certreqs is not None
897 else ssl.CERT_NONE)
898 if cacerts:
899 self.context.load_verify_locations(cacerts)
900 if certificate:
901 self.context.load_cert_chain(certificate)
902 if ciphers:
903 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000904 self.chatty = chatty
905 self.connectionchatty = connectionchatty
906 self.starttls_server = starttls_server
907 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000908 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000910 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100911 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000913 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000914
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100915 def __enter__(self):
916 self.start(threading.Event())
917 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100918 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100919
920 def __exit__(self, *args):
921 self.stop()
922 self.join()
923
Antoine Pitrou480a1242010-04-28 21:37:09 +0000924 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 self.flag = flag
926 threading.Thread.start(self)
927
Antoine Pitrou480a1242010-04-28 21:37:09 +0000928 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000929 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 self.sock.listen(5)
931 self.active = True
932 if self.flag:
933 # signal an event
934 self.flag.set()
935 while self.active:
936 try:
937 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000938 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000939 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000940 + repr(connaddr) + '\n')
941 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000942 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +0100943 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000944 except socket.timeout:
945 pass
946 except KeyboardInterrupt:
947 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000948 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949
Antoine Pitrou480a1242010-04-28 21:37:09 +0000950 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000952
Bill Janssen54cc54c2007-12-14 22:08:56 +0000953 class AsyncoreEchoServer(threading.Thread):
954
955 # this one's based on asyncore.dispatcher
956
957 class EchoServer (asyncore.dispatcher):
958
959 class ConnectionHandler (asyncore.dispatcher_with_send):
960
961 def __init__(self, conn, certfile):
962 self.socket = ssl.wrap_socket(conn, server_side=True,
963 certfile=certfile,
964 do_handshake_on_connect=False)
965 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000966 self._ssl_accepting = True
967 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000968
969 def readable(self):
970 if isinstance(self.socket, ssl.SSLSocket):
971 while self.socket.pending() > 0:
972 self.handle_read_event()
973 return True
974
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000975 def _do_ssl_handshake(self):
976 try:
977 self.socket.do_handshake()
978 except ssl.SSLError as err:
979 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
980 ssl.SSL_ERROR_WANT_WRITE):
981 return
982 elif err.args[0] == ssl.SSL_ERROR_EOF:
983 return self.handle_close()
984 raise
985 except socket.error as err:
986 if err.args[0] == errno.ECONNABORTED:
987 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000988 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000989 self._ssl_accepting = False
990
991 def handle_read(self):
992 if self._ssl_accepting:
993 self._do_ssl_handshake()
994 else:
995 data = self.recv(1024)
996 if support.verbose:
997 sys.stdout.write(" server: read %s from client\n" % repr(data))
998 if not data:
999 self.close()
1000 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001002
1003 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001004 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001005 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001006 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1007
1008 def handle_error(self):
1009 raise
1010
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001011 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001012 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001013 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1014 self.port = support.bind_port(sock, '')
1015 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001016 self.listen(5)
1017
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001018 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001019 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001020 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1021 self.ConnectionHandler(sock_obj, self.certfile)
1022
1023 def handle_error(self):
1024 raise
1025
Trent Nelson78520002008-04-10 20:54:35 +00001026 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001027 self.flag = None
1028 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001029 self.server = self.EchoServer(certfile)
1030 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001031 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001032 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001033
1034 def __str__(self):
1035 return "<%s %s>" % (self.__class__.__name__, self.server)
1036
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001037 def __enter__(self):
1038 self.start(threading.Event())
1039 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001040 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001041
1042 def __exit__(self, *args):
1043 if support.verbose:
1044 sys.stdout.write(" cleanup: stopping server.\n")
1045 self.stop()
1046 if support.verbose:
1047 sys.stdout.write(" cleanup: joining server thread.\n")
1048 self.join()
1049 if support.verbose:
1050 sys.stdout.write(" cleanup: successfully joined.\n")
1051
Bill Janssen54cc54c2007-12-14 22:08:56 +00001052 def start (self, flag=None):
1053 self.flag = flag
1054 threading.Thread.start(self)
1055
Antoine Pitrou480a1242010-04-28 21:37:09 +00001056 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001057 self.active = True
1058 if self.flag:
1059 self.flag.set()
1060 while self.active:
1061 try:
1062 asyncore.loop(1)
1063 except:
1064 pass
1065
Antoine Pitrou480a1242010-04-28 21:37:09 +00001066 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001067 self.active = False
1068 self.server.close()
1069
Antoine Pitrou480a1242010-04-28 21:37:09 +00001070 def bad_cert_test(certfile):
1071 """
1072 Launch a server with CERT_REQUIRED, and check that trying to
1073 connect to it with the given client certificate fails.
1074 """
Trent Nelson78520002008-04-10 20:54:35 +00001075 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001076 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001077 cacerts=CERTFILE, chatty=False,
1078 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001079 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001080 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001081 with socket.socket() as sock:
1082 s = ssl.wrap_socket(sock,
1083 certfile=certfile,
1084 ssl_version=ssl.PROTOCOL_TLSv1)
1085 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001087 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001088 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001089 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001090 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001091 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001092 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001093 if x.errno != errno.ENOENT:
1094 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001095 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001096 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001097 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001098 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001099
Antoine Pitroub5218772010-05-21 09:56:06 +00001100 def server_params_test(client_context, server_context, indata=b"FOO\n",
1101 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001102 """
1103 Launch a server, connect a client to it and try various reads
1104 and writes.
1105 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001106 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001108 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001109 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001110 with client_context.wrap_socket(socket.socket()) as s:
1111 s.connect((HOST, server.port))
1112 for arg in [indata, bytearray(indata), memoryview(indata)]:
1113 if connectionchatty:
1114 if support.verbose:
1115 sys.stdout.write(
1116 " client: sending %r...\n" % indata)
1117 s.write(arg)
1118 outdata = s.read()
1119 if connectionchatty:
1120 if support.verbose:
1121 sys.stdout.write(" client: read %r\n" % outdata)
1122 if outdata != indata.lower():
1123 raise AssertionError(
1124 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1125 % (outdata[:20], len(outdata),
1126 indata[:20].lower(), len(indata)))
1127 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001128 if connectionchatty:
1129 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001130 sys.stdout.write(" client: closing connection.\n")
1131 s.close()
Thomas Woutersed03b412007-08-28 21:37:11 +00001132
Antoine Pitroub5218772010-05-21 09:56:06 +00001133 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1134 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001135 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001136 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001137 certtype = {
1138 ssl.CERT_NONE: "CERT_NONE",
1139 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1140 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1141 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001142 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001143 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144 sys.stdout.write(formatstr %
1145 (ssl.get_protocol_name(client_protocol),
1146 ssl.get_protocol_name(server_protocol),
1147 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001148 client_context = ssl.SSLContext(client_protocol)
1149 client_context.options = ssl.OP_ALL | client_options
1150 server_context = ssl.SSLContext(server_protocol)
1151 server_context.options = ssl.OP_ALL | server_options
1152 for ctx in (client_context, server_context):
1153 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001154 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1155 # will send an SSLv3 hello (rather than SSLv2) starting from
1156 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001157 ctx.set_ciphers("ALL")
1158 ctx.load_cert_chain(CERTFILE)
1159 ctx.load_verify_locations(CERTFILE)
1160 try:
1161 server_params_test(client_context, server_context,
1162 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001163 # Protocol mismatch can result in either an SSLError, or a
1164 # "Connection reset by peer" error.
1165 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001166 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001168 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001169 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001170 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001171 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001172 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001173 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 "Client protocol %s succeeded with server protocol %s!"
1175 % (ssl.get_protocol_name(client_protocol),
1176 ssl.get_protocol_name(server_protocol)))
1177
1178
Bill Janssen6e027db2007-11-15 22:23:56 +00001179 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001180
Antoine Pitrou23df4832010-08-04 17:14:06 +00001181 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 def test_echo(self):
1183 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001184 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001185 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001186 for protocol in PROTOCOLS:
1187 context = ssl.SSLContext(protocol)
1188 context.load_cert_chain(CERTFILE)
1189 server_params_test(context, context,
1190 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001191
Antoine Pitrou480a1242010-04-28 21:37:09 +00001192 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001193 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001194 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001195 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1196 context.verify_mode = ssl.CERT_REQUIRED
1197 context.load_verify_locations(CERTFILE)
1198 context.load_cert_chain(CERTFILE)
1199 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001200 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001201 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001202 s.connect((HOST, server.port))
1203 cert = s.getpeercert()
1204 self.assertTrue(cert, "Can't get peer certificate.")
1205 cipher = s.cipher()
1206 if support.verbose:
1207 sys.stdout.write(pprint.pformat(cert) + '\n')
1208 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1209 if 'subject' not in cert:
1210 self.fail("No subject field in certificate: %s." %
1211 pprint.pformat(cert))
1212 if ((('organizationName', 'Python Software Foundation'),)
1213 not in cert['subject']):
1214 self.fail(
1215 "Missing or invalid 'organizationName' field in certificate subject; "
1216 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001217 self.assertIn('notBefore', cert)
1218 self.assertIn('notAfter', cert)
1219 before = ssl.cert_time_to_seconds(cert['notBefore'])
1220 after = ssl.cert_time_to_seconds(cert['notAfter'])
1221 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001222 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001223
Antoine Pitrou480a1242010-04-28 21:37:09 +00001224 def test_empty_cert(self):
1225 """Connecting with an empty cert file"""
1226 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1227 "nullcert.pem"))
1228 def test_malformed_cert(self):
1229 """Connecting with a badly formatted certificate (syntax error)"""
1230 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1231 "badcert.pem"))
1232 def test_nonexisting_cert(self):
1233 """Connecting with a non-existing cert file"""
1234 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1235 "wrongcert.pem"))
1236 def test_malformed_key(self):
1237 """Connecting with a badly formatted key (syntax error)"""
1238 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1239 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001240
Antoine Pitrou480a1242010-04-28 21:37:09 +00001241 def test_rude_shutdown(self):
1242 """A brutal shutdown of an SSL server should raise an IOError
1243 in the client when attempting handshake.
1244 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001245 listener_ready = threading.Event()
1246 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001247
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001248 s = socket.socket()
1249 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001250
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001251 # `listener` runs in a thread. It sits in an accept() until
1252 # the main thread connects. Then it rudely closes the socket,
1253 # and sets Event `listener_gone` to let the main thread know
1254 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001255 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001256 s.listen(5)
1257 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001258 newsock, addr = s.accept()
1259 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001260 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001261 listener_gone.set()
1262
1263 def connector():
1264 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001265 with socket.socket() as c:
1266 c.connect((HOST, port))
1267 listener_gone.wait()
1268 try:
1269 ssl_sock = ssl.wrap_socket(c)
1270 except IOError:
1271 pass
1272 else:
1273 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001274
1275 t = threading.Thread(target=listener)
1276 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001277 try:
1278 connector()
1279 finally:
1280 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001281
Antoine Pitrou23df4832010-08-04 17:14:06 +00001282 @skip_if_broken_ubuntu_ssl
Victor Stinneree18b6f2011-05-10 00:38:00 +02001283 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001284 def test_protocol_sslv2(self):
1285 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001286 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001287 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001288 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1289 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1290 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1291 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1292 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1293 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001294 # SSLv23 client with specific SSL options
1295 if no_sslv2_implies_sslv3_hello():
1296 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1297 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1298 client_options=ssl.OP_NO_SSLv2)
1299 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1300 client_options=ssl.OP_NO_SSLv3)
1301 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1302 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001303
Antoine Pitrou23df4832010-08-04 17:14:06 +00001304 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001305 def test_protocol_sslv23(self):
1306 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001307 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001308 sys.stdout.write("\n")
Victor Stinneree18b6f2011-05-10 00:38:00 +02001309 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1310 try:
1311 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1312 except (ssl.SSLError, socket.error) as x:
1313 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1314 if support.verbose:
1315 sys.stdout.write(
1316 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1317 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001318 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1319 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1320 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001321
Antoine Pitrou480a1242010-04-28 21:37:09 +00001322 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1323 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1324 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001325
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1327 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1328 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001329
Antoine Pitroub5218772010-05-21 09:56:06 +00001330 # Server with specific SSL options
1331 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1332 server_options=ssl.OP_NO_SSLv3)
1333 # Will choose TLSv1
1334 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1335 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1336 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1337 server_options=ssl.OP_NO_TLSv1)
1338
1339
Antoine Pitrou23df4832010-08-04 17:14:06 +00001340 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 def test_protocol_sslv3(self):
1342 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001343 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001344 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001345 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1346 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1347 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001348 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1349 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001350 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1351 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001353 if no_sslv2_implies_sslv3_hello():
1354 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1355 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1356 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001357
Antoine Pitrou23df4832010-08-04 17:14:06 +00001358 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001359 def test_protocol_tlsv1(self):
1360 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001361 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001362 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001363 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1364 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1365 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001366 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1367 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001368 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001369 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1370 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001371
Antoine Pitrou480a1242010-04-28 21:37:09 +00001372 def test_starttls(self):
1373 """Switching from clear text to encrypted and back again."""
1374 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 +00001375
Trent Nelson78520002008-04-10 20:54:35 +00001376 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001377 ssl_version=ssl.PROTOCOL_TLSv1,
1378 starttls_server=True,
1379 chatty=True,
1380 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001381 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001382 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001383 s = socket.socket()
1384 s.setblocking(1)
1385 s.connect((HOST, server.port))
1386 if support.verbose:
1387 sys.stdout.write("\n")
1388 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001389 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001390 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001392 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001393 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001394 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001397 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001398 msg = outdata.strip().lower()
1399 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1400 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001401 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001402 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001403 " client: read %r from server, starting TLS...\n"
1404 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001405 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1406 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001407 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1408 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001409 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001410 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001411 " client: read %r from server, ending TLS...\n"
1412 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001413 s = conn.unwrap()
1414 wrapped = False
1415 else:
1416 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001417 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001419 if support.verbose:
1420 sys.stdout.write(" client: closing connection.\n")
1421 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001422 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001423 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001424 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001425 if wrapped:
1426 conn.close()
1427 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001428 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001429
Antoine Pitrou480a1242010-04-28 21:37:09 +00001430 def test_socketserver(self):
1431 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001432 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001433 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001434 if support.verbose:
1435 sys.stdout.write('\n')
1436 with open(CERTFILE, 'rb') as f:
1437 d1 = f.read()
1438 d2 = ''
1439 # now fetch the same data from the HTTPS server
1440 url = 'https://%s:%d/%s' % (
1441 HOST, server.port, os.path.split(CERTFILE)[1])
1442 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001443 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001444 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001445 if dlen and (int(dlen) > 0):
1446 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001447 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001448 sys.stdout.write(
1449 " client: read %d bytes from remote server '%s'\n"
1450 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001451 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001452 f.close()
1453 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001454
Antoine Pitrou480a1242010-04-28 21:37:09 +00001455 def test_asyncore_server(self):
1456 """Check the example asyncore integration."""
1457 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001458
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001459 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001460 sys.stdout.write("\n")
1461
Antoine Pitrou480a1242010-04-28 21:37:09 +00001462 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001463 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001464 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001465 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001466 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001467 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001468 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001469 " client: sending %r...\n" % indata)
1470 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001471 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001472 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001473 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001474 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001475 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001476 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1477 % (outdata[:20], len(outdata),
1478 indata[:20].lower(), len(indata)))
1479 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001480 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001481 sys.stdout.write(" client: closing connection.\n")
1482 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001483 if support.verbose:
1484 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001485
Antoine Pitrou480a1242010-04-28 21:37:09 +00001486 def test_recv_send(self):
1487 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001488 if support.verbose:
1489 sys.stdout.write("\n")
1490
1491 server = ThreadedEchoServer(CERTFILE,
1492 certreqs=ssl.CERT_NONE,
1493 ssl_version=ssl.PROTOCOL_TLSv1,
1494 cacerts=CERTFILE,
1495 chatty=True,
1496 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001497 with server:
1498 s = ssl.wrap_socket(socket.socket(),
1499 server_side=False,
1500 certfile=CERTFILE,
1501 ca_certs=CERTFILE,
1502 cert_reqs=ssl.CERT_NONE,
1503 ssl_version=ssl.PROTOCOL_TLSv1)
1504 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001505 # helper methods for standardising recv* method signatures
1506 def _recv_into():
1507 b = bytearray(b"\0"*100)
1508 count = s.recv_into(b)
1509 return b[:count]
1510
1511 def _recvfrom_into():
1512 b = bytearray(b"\0"*100)
1513 count, addr = s.recvfrom_into(b)
1514 return b[:count]
1515
1516 # (name, method, whether to expect success, *args)
1517 send_methods = [
1518 ('send', s.send, True, []),
1519 ('sendto', s.sendto, False, ["some.address"]),
1520 ('sendall', s.sendall, True, []),
1521 ]
1522 recv_methods = [
1523 ('recv', s.recv, True, []),
1524 ('recvfrom', s.recvfrom, False, ["some.address"]),
1525 ('recv_into', _recv_into, True, []),
1526 ('recvfrom_into', _recvfrom_into, False, []),
1527 ]
1528 data_prefix = "PREFIX_"
1529
1530 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001531 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001532 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001533 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001534 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001535 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001536 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001537 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001538 "<<{outdata:r}>> ({nout:d}) received; "
1539 "expected <<{indata:r}>> ({nin:d})\n".format(
1540 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001541 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001542 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001543 )
1544 )
1545 except ValueError as e:
1546 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001547 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001548 "Failed to send with method <<{name:s}>>; "
1549 "expected to succeed.\n".format(name=meth_name)
1550 )
1551 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001552 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001553 "Method <<{name:s}>> failed with unexpected "
1554 "exception message: {exp:s}\n".format(
1555 name=meth_name, exp=e
1556 )
1557 )
1558
1559 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001560 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001561 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001562 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001563 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001564 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001565 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001566 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 "<<{outdata:r}>> ({nout:d}) received; "
1568 "expected <<{indata:r}>> ({nin:d})\n".format(
1569 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001570 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001572 )
1573 )
1574 except ValueError as e:
1575 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001576 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001577 "Failed to receive with method <<{name:s}>>; "
1578 "expected to succeed.\n".format(name=meth_name)
1579 )
1580 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001581 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001582 "Method <<{name:s}>> failed with unexpected "
1583 "exception message: {exp:s}\n".format(
1584 name=meth_name, exp=e
1585 )
1586 )
1587 # consume data
1588 s.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001589 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001590 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001591
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001592 def test_handshake_timeout(self):
1593 # Issue #5103: SSL handshake must respect the socket timeout
1594 server = socket.socket(socket.AF_INET)
1595 host = "127.0.0.1"
1596 port = support.bind_port(server)
1597 started = threading.Event()
1598 finish = False
1599
1600 def serve():
1601 server.listen(5)
1602 started.set()
1603 conns = []
1604 while not finish:
1605 r, w, e = select.select([server], [], [], 0.1)
1606 if server in r:
1607 # Let the socket hang around rather than having
1608 # it closed by garbage collection.
1609 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001610 for sock in conns:
1611 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001612
1613 t = threading.Thread(target=serve)
1614 t.start()
1615 started.wait()
1616
1617 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001618 try:
1619 c = socket.socket(socket.AF_INET)
1620 c.settimeout(0.2)
1621 c.connect((host, port))
1622 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001623 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001624 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001625 finally:
1626 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001627 try:
1628 c = socket.socket(socket.AF_INET)
1629 c = ssl.wrap_socket(c)
1630 c.settimeout(0.2)
1631 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001632 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001633 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001634 finally:
1635 c.close()
1636 finally:
1637 finish = True
1638 t.join()
1639 server.close()
1640
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001641 def test_server_accept(self):
1642 # Issue #16357: accept() on a SSLSocket created through
1643 # SSLContext.wrap_socket().
1644 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1645 context.verify_mode = ssl.CERT_REQUIRED
1646 context.load_verify_locations(CERTFILE)
1647 context.load_cert_chain(CERTFILE)
1648 server = socket.socket(socket.AF_INET)
1649 host = "127.0.0.1"
1650 port = support.bind_port(server)
1651 server = context.wrap_socket(server, server_side=True)
1652
1653 evt = threading.Event()
1654 remote = None
1655 peer = None
1656 def serve():
1657 nonlocal remote, peer
1658 server.listen(5)
1659 # Block on the accept and wait on the connection to close.
1660 evt.set()
1661 remote, peer = server.accept()
1662 remote.recv(1)
1663
1664 t = threading.Thread(target=serve)
1665 t.start()
1666 # Client wait until server setup and perform a connect.
1667 evt.wait()
1668 client = context.wrap_socket(socket.socket())
1669 client.connect((host, port))
1670 client_addr = client.getsockname()
1671 client.close()
1672 t.join()
1673 # Sanity checks.
1674 self.assertIsInstance(remote, ssl.SSLSocket)
1675 self.assertEqual(peer, client_addr)
1676
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001677 def test_default_ciphers(self):
1678 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1679 try:
1680 # Force a set of weak ciphers on our client context
1681 context.set_ciphers("DES")
1682 except ssl.SSLError:
1683 self.skipTest("no DES cipher available")
1684 with ThreadedEchoServer(CERTFILE,
1685 ssl_version=ssl.PROTOCOL_SSLv23,
1686 chatty=False) as server:
1687 with socket.socket() as sock:
1688 s = context.wrap_socket(sock)
1689 with self.assertRaises((OSError, ssl.SSLError)):
1690 s.connect((HOST, server.port))
1691 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1692
Bill Janssen58afe4c2008-09-08 16:45:19 +00001693
Thomas Woutersed03b412007-08-28 21:37:11 +00001694def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001695 if support.verbose:
1696 plats = {
1697 'Linux': platform.linux_distribution,
1698 'Mac': platform.mac_ver,
1699 'Windows': platform.win32_ver,
1700 }
1701 for name, func in plats.items():
1702 plat = func()
1703 if plat and plat[0]:
1704 plat = '%s %r' % (name, plat)
1705 break
1706 else:
1707 plat = repr(platform.platform())
1708 print("test_ssl: testing with %r %r" %
1709 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1710 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001711 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001712
Antoine Pitrou152efa22010-05-16 18:19:27 +00001713 for filename in [
1714 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1715 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1716 BADCERT, BADKEY, EMPTYCERT]:
1717 if not os.path.exists(filename):
1718 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001719
Antoine Pitrou152efa22010-05-16 18:19:27 +00001720 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001721
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001722 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001723 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001724
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001725 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001726 thread_info = support.threading_setup()
1727 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001728 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001729
Antoine Pitrou480a1242010-04-28 21:37:09 +00001730 try:
1731 support.run_unittest(*tests)
1732 finally:
1733 if _have_threads:
1734 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001735
1736if __name__ == "__main__":
1737 test_main()