blob: ca74e7132e7a5c8466ea40232f0dafd03a431c5e [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
21# Optionally test SSL support, if we have it in the tested platform
22skip_expected = False
23try:
24 import ssl
25except ImportError:
26 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000027else:
28 PROTOCOLS = [
29 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
30 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
31 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000032
Benjamin Petersonee8712c2008-05-20 21:35:26 +000033HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000034
35data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
Antoine Pitrou81564092010-10-08 23:06:24 +000037# The custom key and certificate files used in test_ssl are generated
38# using Lib/test/make_ssl_certs.py.
39# Other certificates are simply fetched from the Internet servers they
40# are meant to authenticate.
41
Antoine Pitrou152efa22010-05-16 18:19:27 +000042CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000044ONLYCERT = data_file("ssl_cert.pem")
45ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_ONLYCERT = os.fsencode(ONLYCERT)
47BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000048CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000049BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
52
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
57
Thomas Woutersed03b412007-08-28 21:37:11 +000058
Thomas Woutersed03b412007-08-28 21:37:11 +000059def handle_error(prefix):
60 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000061 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000062 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000063
Antoine Pitroub5218772010-05-21 09:56:06 +000064def can_clear_options():
65 # 0.9.8m or higher
66 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
67
68def no_sslv2_implies_sslv3_hello():
69 # 0.9.7h or higher
70 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
71
Thomas Woutersed03b412007-08-28 21:37:11 +000072
Antoine Pitrou23df4832010-08-04 17:14:06 +000073# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
74def skip_if_broken_ubuntu_ssl(func):
75 @functools.wraps(func)
76 def f(*args, **kwargs):
77 try:
78 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
79 except ssl.SSLError:
80 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
81 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
82 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
83 return func(*args, **kwargs)
84 return f
85
86
Antoine Pitrou152efa22010-05-16 18:19:27 +000087class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000088
Antoine Pitrou480a1242010-04-28 21:37:09 +000089 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000090 ssl.PROTOCOL_SSLv2
91 ssl.PROTOCOL_SSLv23
92 ssl.PROTOCOL_SSLv3
93 ssl.PROTOCOL_TLSv1
94 ssl.CERT_NONE
95 ssl.CERT_OPTIONAL
96 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000097
Antoine Pitrou480a1242010-04-28 21:37:09 +000098 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000099 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000100 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 sys.stdout.write("\n RAND_status is %d (%s)\n"
102 % (v, (v and "sufficient randomness") or
103 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000104 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 ssl.RAND_egd(1)
106 except TypeError:
107 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000108 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000109 print("didn't raise TypeError")
110 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000111
Antoine Pitrou480a1242010-04-28 21:37:09 +0000112 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 # note that this uses an 'unofficial' function in _ssl.c,
114 # provided solely for this test, to exercise the certificate
115 # parsing code
116 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000117 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000118 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000119
Antoine Pitrou480a1242010-04-28 21:37:09 +0000120 def test_DER_to_PEM(self):
121 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
122 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000123 d1 = ssl.PEM_cert_to_DER_cert(pem)
124 p2 = ssl.DER_cert_to_PEM_cert(d1)
125 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000126 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000127 if not p2.startswith(ssl.PEM_HEADER + '\n'):
128 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
129 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
130 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000131
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000132 def test_openssl_version(self):
133 n = ssl.OPENSSL_VERSION_NUMBER
134 t = ssl.OPENSSL_VERSION_INFO
135 s = ssl.OPENSSL_VERSION
136 self.assertIsInstance(n, int)
137 self.assertIsInstance(t, tuple)
138 self.assertIsInstance(s, str)
139 # Some sanity checks follow
140 # >= 0.9
141 self.assertGreaterEqual(n, 0x900000)
142 # < 2.0
143 self.assertLess(n, 0x20000000)
144 major, minor, fix, patch, status = t
145 self.assertGreaterEqual(major, 0)
146 self.assertLess(major, 2)
147 self.assertGreaterEqual(minor, 0)
148 self.assertLess(minor, 256)
149 self.assertGreaterEqual(fix, 0)
150 self.assertLess(fix, 256)
151 self.assertGreaterEqual(patch, 0)
152 self.assertLessEqual(patch, 26)
153 self.assertGreaterEqual(status, 0)
154 self.assertLessEqual(status, 15)
155 # Version string as returned by OpenSSL, the format might change
156 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
157 (s, t))
158
Antoine Pitrou9d543662010-04-23 23:10:32 +0000159 @support.cpython_only
160 def test_refcycle(self):
161 # Issue #7943: an SSL object doesn't create reference cycles with
162 # itself.
163 s = socket.socket(socket.AF_INET)
164 ss = ssl.wrap_socket(s)
165 wr = weakref.ref(ss)
166 del ss
167 self.assertEqual(wr(), None)
168
Antoine Pitroua468adc2010-09-14 14:43:44 +0000169 def test_wrapped_unconnected(self):
170 # Methods on an unconnected SSLSocket propagate the original
171 # socket.error raise by the underlying socket object.
172 s = socket.socket(socket.AF_INET)
173 ss = ssl.wrap_socket(s)
174 self.assertRaises(socket.error, ss.recv, 1)
175 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
176 self.assertRaises(socket.error, ss.recvfrom, 1)
177 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
178 self.assertRaises(socket.error, ss.send, b'x')
179 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
180
Antoine Pitrou40f08742010-04-24 22:04:40 +0000181 def test_timeout(self):
182 # Issue #8524: when creating an SSL socket, the timeout of the
183 # original socket should be retained.
184 for timeout in (None, 0.0, 5.0):
185 s = socket.socket(socket.AF_INET)
186 s.settimeout(timeout)
187 ss = ssl.wrap_socket(s)
188 self.assertEqual(timeout, ss.gettimeout())
189
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000190 def test_errors(self):
191 sock = socket.socket()
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000192 self.assertRaisesRegexp(ValueError,
193 "certfile must be specified",
194 ssl.wrap_socket, sock, keyfile=CERTFILE)
195 self.assertRaisesRegexp(ValueError,
196 "certfile must be specified for server-side operations",
197 ssl.wrap_socket, sock, server_side=True)
198 self.assertRaisesRegexp(ValueError,
199 "certfile must be specified for server-side operations",
200 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000201 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
202 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
203 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000204 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000205 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000206 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000207 with self.assertRaises(IOError) as cm:
208 ssl.wrap_socket(socket.socket(), certfile=CERTFILE, keyfile=WRONGCERT)
209 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000210 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000211 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000212 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000213
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000214 def test_match_hostname(self):
215 def ok(cert, hostname):
216 ssl.match_hostname(cert, hostname)
217 def fail(cert, hostname):
218 self.assertRaises(ssl.CertificateError,
219 ssl.match_hostname, cert, hostname)
220
221 cert = {'subject': ((('commonName', 'example.com'),),)}
222 ok(cert, 'example.com')
223 ok(cert, 'ExAmple.cOm')
224 fail(cert, 'www.example.com')
225 fail(cert, '.example.com')
226 fail(cert, 'example.org')
227 fail(cert, 'exampleXcom')
228
229 cert = {'subject': ((('commonName', '*.a.com'),),)}
230 ok(cert, 'foo.a.com')
231 fail(cert, 'bar.foo.a.com')
232 fail(cert, 'a.com')
233 fail(cert, 'Xa.com')
234 fail(cert, '.a.com')
235
236 cert = {'subject': ((('commonName', 'a.*.com'),),)}
237 ok(cert, 'a.foo.com')
238 fail(cert, 'a..com')
239 fail(cert, 'a.com')
240
241 cert = {'subject': ((('commonName', 'f*.com'),),)}
242 ok(cert, 'foo.com')
243 ok(cert, 'f.com')
244 fail(cert, 'bar.com')
245 fail(cert, 'foo.a.com')
246 fail(cert, 'bar.foo.com')
247
248 # Slightly fake real-world example
249 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
250 'subject': ((('commonName', 'linuxfrz.org'),),),
251 'subjectAltName': (('DNS', 'linuxfr.org'),
252 ('DNS', 'linuxfr.com'),
253 ('othername', '<unsupported>'))}
254 ok(cert, 'linuxfr.org')
255 ok(cert, 'linuxfr.com')
256 # Not a "DNS" entry
257 fail(cert, '<unsupported>')
258 # When there is a subjectAltName, commonName isn't used
259 fail(cert, 'linuxfrz.org')
260
261 # A pristine real-world example
262 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
263 'subject': ((('countryName', 'US'),),
264 (('stateOrProvinceName', 'California'),),
265 (('localityName', 'Mountain View'),),
266 (('organizationName', 'Google Inc'),),
267 (('commonName', 'mail.google.com'),))}
268 ok(cert, 'mail.google.com')
269 fail(cert, 'gmail.com')
270 # Only commonName is considered
271 fail(cert, 'California')
272
273 # Neither commonName nor subjectAltName
274 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
275 'subject': ((('countryName', 'US'),),
276 (('stateOrProvinceName', 'California'),),
277 (('localityName', 'Mountain View'),),
278 (('organizationName', 'Google Inc'),))}
279 fail(cert, 'mail.google.com')
280
281 # Empty cert / no cert
282 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
283 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
284
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000285
Antoine Pitrou152efa22010-05-16 18:19:27 +0000286class ContextTests(unittest.TestCase):
287
Antoine Pitrou23df4832010-08-04 17:14:06 +0000288 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000289 def test_constructor(self):
290 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
291 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
292 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
293 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
294 self.assertRaises(TypeError, ssl.SSLContext)
295 self.assertRaises(ValueError, ssl.SSLContext, -1)
296 self.assertRaises(ValueError, ssl.SSLContext, 42)
297
Antoine Pitrou23df4832010-08-04 17:14:06 +0000298 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000299 def test_protocol(self):
300 for proto in PROTOCOLS:
301 ctx = ssl.SSLContext(proto)
302 self.assertEqual(ctx.protocol, proto)
303
304 def test_ciphers(self):
305 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
306 ctx.set_ciphers("ALL")
307 ctx.set_ciphers("DEFAULT")
308 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000309 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000310
Antoine Pitrou23df4832010-08-04 17:14:06 +0000311 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000312 def test_options(self):
313 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
314 # OP_ALL is the default value
315 self.assertEqual(ssl.OP_ALL, ctx.options)
316 ctx.options |= ssl.OP_NO_SSLv2
317 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
318 ctx.options)
319 ctx.options |= ssl.OP_NO_SSLv3
320 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
321 ctx.options)
322 if can_clear_options():
323 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
324 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
325 ctx.options)
326 ctx.options = 0
327 self.assertEqual(0, ctx.options)
328 else:
329 with self.assertRaises(ValueError):
330 ctx.options = 0
331
Antoine Pitrou152efa22010-05-16 18:19:27 +0000332 def test_verify(self):
333 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
334 # Default value
335 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
336 ctx.verify_mode = ssl.CERT_OPTIONAL
337 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
338 ctx.verify_mode = ssl.CERT_REQUIRED
339 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
340 ctx.verify_mode = ssl.CERT_NONE
341 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
342 with self.assertRaises(TypeError):
343 ctx.verify_mode = None
344 with self.assertRaises(ValueError):
345 ctx.verify_mode = 42
346
347 def test_load_cert_chain(self):
348 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
349 # Combined key and cert in a single file
350 ctx.load_cert_chain(CERTFILE)
351 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
352 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000353 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000354 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000355 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000356 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
357 ctx.load_cert_chain(BADCERT)
358 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
359 ctx.load_cert_chain(EMPTYCERT)
360 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000361 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000362 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
363 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
364 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
365 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
366 ctx.load_cert_chain(ONLYCERT)
367 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
368 ctx.load_cert_chain(ONLYKEY)
369 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
370 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
371 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000372 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000373 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000374 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000375
376 def test_load_verify_locations(self):
377 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
378 ctx.load_verify_locations(CERTFILE)
379 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
380 ctx.load_verify_locations(BYTES_CERTFILE)
381 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
382 self.assertRaises(TypeError, ctx.load_verify_locations)
383 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000384 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000385 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000386 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000387 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
388 ctx.load_verify_locations(BADCERT)
389 ctx.load_verify_locations(CERTFILE, CAPATH)
390 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
391
Antoine Pitroub0182c82010-10-12 20:09:02 +0000392 def test_session_stats(self):
393 for proto in PROTOCOLS:
394 ctx = ssl.SSLContext(proto)
395 self.assertEqual(ctx.session_stats(), {
396 'number': 0,
397 'connect': 0,
398 'connect_good': 0,
399 'connect_renegotiate': 0,
400 'accept': 0,
401 'accept_good': 0,
402 'accept_renegotiate': 0,
403 'hits': 0,
404 'misses': 0,
405 'timeouts': 0,
406 'cache_full': 0,
407 })
408
Antoine Pitrou152efa22010-05-16 18:19:27 +0000409
Bill Janssen6e027db2007-11-15 22:23:56 +0000410class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000411
Antoine Pitrou480a1242010-04-28 21:37:09 +0000412 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000413 with support.transient_internet("svn.python.org"):
414 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
415 cert_reqs=ssl.CERT_NONE)
416 try:
417 s.connect(("svn.python.org", 443))
418 self.assertEqual({}, s.getpeercert())
419 finally:
420 s.close()
421
422 # this should fail because we have no verification certs
423 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
424 cert_reqs=ssl.CERT_REQUIRED)
425 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
426 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000427 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000428
Antoine Pitrou350c7222010-09-09 13:31:46 +0000429 # this should succeed because we specify the root cert
430 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
431 cert_reqs=ssl.CERT_REQUIRED,
432 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
433 try:
434 s.connect(("svn.python.org", 443))
435 self.assertTrue(s.getpeercert())
436 finally:
437 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000438
439 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000440 with support.transient_internet("svn.python.org"):
441 # Same as test_connect, but with a separately created context
442 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
443 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
444 s.connect(("svn.python.org", 443))
445 try:
446 self.assertEqual({}, s.getpeercert())
447 finally:
448 s.close()
449 # This should fail because we have no verification certs
450 ctx.verify_mode = ssl.CERT_REQUIRED
451 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
452 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
453 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000454 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000455 # This should succeed because we specify the root cert
456 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
457 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
458 s.connect(("svn.python.org", 443))
459 try:
460 cert = s.getpeercert()
461 self.assertTrue(cert)
462 finally:
463 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000464
465 def test_connect_capath(self):
466 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000467 # NOTE: the subject hashing algorithm has been changed between
468 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
469 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000470 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000471 with support.transient_internet("svn.python.org"):
472 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
473 ctx.verify_mode = ssl.CERT_REQUIRED
474 ctx.load_verify_locations(capath=CAPATH)
475 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
476 s.connect(("svn.python.org", 443))
477 try:
478 cert = s.getpeercert()
479 self.assertTrue(cert)
480 finally:
481 s.close()
482 # Same with a bytes `capath` argument
483 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
484 ctx.verify_mode = ssl.CERT_REQUIRED
485 ctx.load_verify_locations(capath=BYTES_CAPATH)
486 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
487 s.connect(("svn.python.org", 443))
488 try:
489 cert = s.getpeercert()
490 self.assertTrue(cert)
491 finally:
492 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493
Antoine Pitroue3220242010-04-24 11:13:53 +0000494 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
495 def test_makefile_close(self):
496 # Issue #5238: creating a file-like object with makefile() shouldn't
497 # delay closing the underlying "real socket" (here tested with its
498 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000499 with support.transient_internet("svn.python.org"):
500 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
501 ss.connect(("svn.python.org", 443))
502 fd = ss.fileno()
503 f = ss.makefile()
504 f.close()
505 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000506 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000507 # Closing the SSL socket should close the fd too
508 ss.close()
509 gc.collect()
510 with self.assertRaises(OSError) as e:
511 os.read(fd, 0)
512 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000513
Antoine Pitrou480a1242010-04-28 21:37:09 +0000514 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000515 with support.transient_internet("svn.python.org"):
516 s = socket.socket(socket.AF_INET)
517 s.connect(("svn.python.org", 443))
518 s.setblocking(False)
519 s = ssl.wrap_socket(s,
520 cert_reqs=ssl.CERT_NONE,
521 do_handshake_on_connect=False)
522 count = 0
523 while True:
524 try:
525 count += 1
526 s.do_handshake()
527 break
528 except ssl.SSLError as err:
529 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
530 select.select([s], [], [])
531 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
532 select.select([], [s], [])
533 else:
534 raise
535 s.close()
536 if support.verbose:
537 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000538
Antoine Pitrou480a1242010-04-28 21:37:09 +0000539 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000540 with support.transient_internet("svn.python.org"):
541 pem = ssl.get_server_certificate(("svn.python.org", 443))
542 if not pem:
543 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000544
Antoine Pitrou350c7222010-09-09 13:31:46 +0000545 try:
546 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
547 except ssl.SSLError as x:
548 #should fail
549 if support.verbose:
550 sys.stdout.write("%s\n" % x)
551 else:
552 self.fail("Got server certificate %s for svn.python.org!" % pem)
553
554 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
555 if not pem:
556 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000557 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000558 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000559
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000560 def test_ciphers(self):
561 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000562 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000563 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000564 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000565 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000566 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
567 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
568 s.connect(remote)
569 # Error checking can happen at instantiation or when connecting
570 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
571 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
572 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
573 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000574
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000575 def test_algorithms(self):
576 # Issue #8484: all algorithms should be available when verifying a
577 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000578 # SHA256 was added in OpenSSL 0.9.8
579 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
580 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000581 # NOTE: https://sha256.tbs-internet.com is another possible test host
582 remote = ("sha2.hboeck.de", 443)
583 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000584 with support.transient_internet("sha2.hboeck.de"):
585 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
586 cert_reqs=ssl.CERT_REQUIRED,
587 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000588 try:
589 s.connect(remote)
590 if support.verbose:
591 sys.stdout.write("\nCipher with %r is %r\n" %
592 (remote, s.cipher()))
593 sys.stdout.write("Certificate is:\n%s\n" %
594 pprint.pformat(s.getpeercert()))
595 finally:
596 s.close()
597
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000598
599try:
600 import threading
601except ImportError:
602 _have_threads = False
603else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000604 _have_threads = True
605
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000606 from test.ssl_servers import make_https_server
607
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000608 class ThreadedEchoServer(threading.Thread):
609
610 class ConnectionHandler(threading.Thread):
611
612 """A mildly complicated class, because we want it to work both
613 with and without the SSL wrapper around the socket connection, so
614 that we can test the STARTTLS functionality."""
615
Bill Janssen6e027db2007-11-15 22:23:56 +0000616 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000617 self.server = server
618 self.running = False
619 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000620 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000621 self.sock.setblocking(1)
622 self.sslconn = None
623 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000624 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000625
Antoine Pitrou480a1242010-04-28 21:37:09 +0000626 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000628 self.sslconn = self.server.context.wrap_socket(
629 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000630 except ssl.SSLError:
631 # XXX Various errors can have happened here, for example
632 # a mismatching protocol version, an invalid certificate,
633 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000635 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000636 self.running = False
637 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000638 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000640 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000641 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000642 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000643 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000644 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
645 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000646 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000647 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
648 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000649 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
651 return True
652
653 def read(self):
654 if self.sslconn:
655 return self.sslconn.read()
656 else:
657 return self.sock.recv(1024)
658
659 def write(self, bytes):
660 if self.sslconn:
661 return self.sslconn.write(bytes)
662 else:
663 return self.sock.send(bytes)
664
665 def close(self):
666 if self.sslconn:
667 self.sslconn.close()
668 else:
669 self.sock.close()
670
Antoine Pitrou480a1242010-04-28 21:37:09 +0000671 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000672 self.running = True
673 if not self.server.starttls_server:
674 if not self.wrap_conn():
675 return
676 while self.running:
677 try:
678 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000679 stripped = msg.strip()
680 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000681 # eof, so quit this handler
682 self.running = False
683 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000684 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000685 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000686 sys.stdout.write(" server: client closed connection\n")
687 self.close()
688 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000689 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000690 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000691 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000692 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000693 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000694 if not self.wrap_conn():
695 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000696 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000697 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000698 if support.verbose and self.server.connectionchatty:
699 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000700 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000701 self.sock = self.sslconn.unwrap()
702 self.sslconn = None
703 if support.verbose and self.server.connectionchatty:
704 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000706 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000707 self.server.connectionchatty):
708 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000709 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
710 % (msg, ctype, msg.lower(), ctype))
711 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000712 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000713 if self.server.chatty:
714 handle_error("Test server failure:\n")
715 self.close()
716 self.running = False
717 # normally, we'd just stop here, but for the test
718 # harness, we want to stop the server
719 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000720
Antoine Pitroub5218772010-05-21 09:56:06 +0000721 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000722 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000723 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000724 ciphers=None, context=None):
725 if context:
726 self.context = context
727 else:
728 self.context = ssl.SSLContext(ssl_version
729 if ssl_version is not None
730 else ssl.PROTOCOL_TLSv1)
731 self.context.verify_mode = (certreqs if certreqs is not None
732 else ssl.CERT_NONE)
733 if cacerts:
734 self.context.load_verify_locations(cacerts)
735 if certificate:
736 self.context.load_cert_chain(certificate)
737 if ciphers:
738 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 self.chatty = chatty
740 self.connectionchatty = connectionchatty
741 self.starttls_server = starttls_server
742 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000743 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000744 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000745 self.active = False
746 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000747 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000748
Antoine Pitrou480a1242010-04-28 21:37:09 +0000749 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750 self.flag = flag
751 threading.Thread.start(self)
752
Antoine Pitrou480a1242010-04-28 21:37:09 +0000753 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000754 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000755 self.sock.listen(5)
756 self.active = True
757 if self.flag:
758 # signal an event
759 self.flag.set()
760 while self.active:
761 try:
762 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000763 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000764 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000765 + repr(connaddr) + '\n')
766 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000767 handler.start()
768 except socket.timeout:
769 pass
770 except KeyboardInterrupt:
771 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000772 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000773
Antoine Pitrou480a1242010-04-28 21:37:09 +0000774 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000775 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000776
Bill Janssen54cc54c2007-12-14 22:08:56 +0000777 class AsyncoreEchoServer(threading.Thread):
778
779 # this one's based on asyncore.dispatcher
780
781 class EchoServer (asyncore.dispatcher):
782
783 class ConnectionHandler (asyncore.dispatcher_with_send):
784
785 def __init__(self, conn, certfile):
786 self.socket = ssl.wrap_socket(conn, server_side=True,
787 certfile=certfile,
788 do_handshake_on_connect=False)
789 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000790 self._ssl_accepting = True
791 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000792
793 def readable(self):
794 if isinstance(self.socket, ssl.SSLSocket):
795 while self.socket.pending() > 0:
796 self.handle_read_event()
797 return True
798
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000799 def _do_ssl_handshake(self):
800 try:
801 self.socket.do_handshake()
802 except ssl.SSLError as err:
803 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
804 ssl.SSL_ERROR_WANT_WRITE):
805 return
806 elif err.args[0] == ssl.SSL_ERROR_EOF:
807 return self.handle_close()
808 raise
809 except socket.error as err:
810 if err.args[0] == errno.ECONNABORTED:
811 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000812 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000813 self._ssl_accepting = False
814
815 def handle_read(self):
816 if self._ssl_accepting:
817 self._do_ssl_handshake()
818 else:
819 data = self.recv(1024)
820 if support.verbose:
821 sys.stdout.write(" server: read %s from client\n" % repr(data))
822 if not data:
823 self.close()
824 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000825 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000826
827 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000828 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000829 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000830 sys.stdout.write(" server: closed connection %s\n" % self.socket)
831
832 def handle_error(self):
833 raise
834
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000835 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000836 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000837 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
838 self.port = support.bind_port(sock, '')
839 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000840 self.listen(5)
841
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000842 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000843 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000844 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
845 self.ConnectionHandler(sock_obj, self.certfile)
846
847 def handle_error(self):
848 raise
849
Trent Nelson78520002008-04-10 20:54:35 +0000850 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000851 self.flag = None
852 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000853 self.server = self.EchoServer(certfile)
854 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000855 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000856 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000857
858 def __str__(self):
859 return "<%s %s>" % (self.__class__.__name__, self.server)
860
861 def start (self, flag=None):
862 self.flag = flag
863 threading.Thread.start(self)
864
Antoine Pitrou480a1242010-04-28 21:37:09 +0000865 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000866 self.active = True
867 if self.flag:
868 self.flag.set()
869 while self.active:
870 try:
871 asyncore.loop(1)
872 except:
873 pass
874
Antoine Pitrou480a1242010-04-28 21:37:09 +0000875 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000876 self.active = False
877 self.server.close()
878
Antoine Pitrou480a1242010-04-28 21:37:09 +0000879 def bad_cert_test(certfile):
880 """
881 Launch a server with CERT_REQUIRED, and check that trying to
882 connect to it with the given client certificate fails.
883 """
Trent Nelson78520002008-04-10 20:54:35 +0000884 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000885 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000886 cacerts=CERTFILE, chatty=False,
887 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000888 flag = threading.Event()
889 server.start(flag)
890 # wait for it to start
891 flag.wait()
892 # try to connect
893 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000894 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 s = ssl.wrap_socket(socket.socket(),
896 certfile=certfile,
897 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000898 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000899 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000900 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000901 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000902 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000903 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000904 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000905 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000906 if x.errno != errno.ENOENT:
907 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000908 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000909 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000910 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000911 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 finally:
913 server.stop()
914 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000915
Antoine Pitroub5218772010-05-21 09:56:06 +0000916 def server_params_test(client_context, server_context, indata=b"FOO\n",
917 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000918 """
919 Launch a server, connect a client to it and try various reads
920 and writes.
921 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000922 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000924 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 flag = threading.Event()
926 server.start(flag)
927 # wait for it to start
928 flag.wait()
929 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000931 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000932 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000933 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000934 if connectionchatty:
935 if support.verbose:
936 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000937 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000938 s.write(arg)
939 outdata = s.read()
940 if connectionchatty:
941 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000942 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000943 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000944 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000945 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
946 % (outdata[:20], len(outdata),
947 indata[:20].lower(), len(indata)))
948 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000949 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000950 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000951 sys.stdout.write(" client: closing connection.\n")
952 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953 finally:
954 server.stop()
955 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000956
Antoine Pitroub5218772010-05-21 09:56:06 +0000957 def try_protocol_combo(server_protocol, client_protocol, expect_success,
958 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000959 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000961 certtype = {
962 ssl.CERT_NONE: "CERT_NONE",
963 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
964 ssl.CERT_REQUIRED: "CERT_REQUIRED",
965 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000966 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000967 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000968 sys.stdout.write(formatstr %
969 (ssl.get_protocol_name(client_protocol),
970 ssl.get_protocol_name(server_protocol),
971 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000972 client_context = ssl.SSLContext(client_protocol)
973 client_context.options = ssl.OP_ALL | client_options
974 server_context = ssl.SSLContext(server_protocol)
975 server_context.options = ssl.OP_ALL | server_options
976 for ctx in (client_context, server_context):
977 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000978 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
979 # will send an SSLv3 hello (rather than SSLv2) starting from
980 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000981 ctx.set_ciphers("ALL")
982 ctx.load_cert_chain(CERTFILE)
983 ctx.load_verify_locations(CERTFILE)
984 try:
985 server_params_test(client_context, server_context,
986 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000987 # Protocol mismatch can result in either an SSLError, or a
988 # "Connection reset by peer" error.
989 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000990 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000992 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000993 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000994 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000996 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000997 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 "Client protocol %s succeeded with server protocol %s!"
999 % (ssl.get_protocol_name(client_protocol),
1000 ssl.get_protocol_name(server_protocol)))
1001
1002
Bill Janssen6e027db2007-11-15 22:23:56 +00001003 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004
Antoine Pitrou23df4832010-08-04 17:14:06 +00001005 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001006 def test_echo(self):
1007 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001008 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001009 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001010 for protocol in PROTOCOLS:
1011 context = ssl.SSLContext(protocol)
1012 context.load_cert_chain(CERTFILE)
1013 server_params_test(context, context,
1014 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001015
Antoine Pitrou480a1242010-04-28 21:37:09 +00001016 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001017 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001018 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001019 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1020 context.verify_mode = ssl.CERT_REQUIRED
1021 context.load_verify_locations(CERTFILE)
1022 context.load_cert_chain(CERTFILE)
1023 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001024 flag = threading.Event()
1025 server.start(flag)
1026 # wait for it to start
1027 flag.wait()
1028 # try to connect
1029 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001030 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001031 s.connect((HOST, server.port))
1032 cert = s.getpeercert()
1033 self.assertTrue(cert, "Can't get peer certificate.")
1034 cipher = s.cipher()
1035 if support.verbose:
1036 sys.stdout.write(pprint.pformat(cert) + '\n')
1037 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1038 if 'subject' not in cert:
1039 self.fail("No subject field in certificate: %s." %
1040 pprint.pformat(cert))
1041 if ((('organizationName', 'Python Software Foundation'),)
1042 not in cert['subject']):
1043 self.fail(
1044 "Missing or invalid 'organizationName' field in certificate subject; "
1045 "should be 'Python Software Foundation'.")
1046 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001047 finally:
1048 server.stop()
1049 server.join()
1050
Antoine Pitrou480a1242010-04-28 21:37:09 +00001051 def test_empty_cert(self):
1052 """Connecting with an empty cert file"""
1053 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1054 "nullcert.pem"))
1055 def test_malformed_cert(self):
1056 """Connecting with a badly formatted certificate (syntax error)"""
1057 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1058 "badcert.pem"))
1059 def test_nonexisting_cert(self):
1060 """Connecting with a non-existing cert file"""
1061 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1062 "wrongcert.pem"))
1063 def test_malformed_key(self):
1064 """Connecting with a badly formatted key (syntax error)"""
1065 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1066 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001067
Antoine Pitrou480a1242010-04-28 21:37:09 +00001068 def test_rude_shutdown(self):
1069 """A brutal shutdown of an SSL server should raise an IOError
1070 in the client when attempting handshake.
1071 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001072 listener_ready = threading.Event()
1073 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001074
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001075 s = socket.socket()
1076 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001077
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001078 # `listener` runs in a thread. It sits in an accept() until
1079 # the main thread connects. Then it rudely closes the socket,
1080 # and sets Event `listener_gone` to let the main thread know
1081 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001082 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001083 s.listen(5)
1084 listener_ready.set()
1085 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001086 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001087 listener_gone.set()
1088
1089 def connector():
1090 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001091 c = socket.socket()
1092 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001093 listener_gone.wait()
1094 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001095 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001096 except IOError:
1097 pass
1098 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001099 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001100
1101 t = threading.Thread(target=listener)
1102 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001103 try:
1104 connector()
1105 finally:
1106 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001107
Antoine Pitrou23df4832010-08-04 17:14:06 +00001108 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001109 def test_protocol_sslv2(self):
1110 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001111 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001113 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1114 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1115 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1116 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1117 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1118 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001119 # SSLv23 client with specific SSL options
1120 if no_sslv2_implies_sslv3_hello():
1121 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1122 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1123 client_options=ssl.OP_NO_SSLv2)
1124 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1125 client_options=ssl.OP_NO_SSLv3)
1126 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1127 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001128
Antoine Pitrou23df4832010-08-04 17:14:06 +00001129 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001130 def test_protocol_sslv23(self):
1131 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001132 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001133 sys.stdout.write("\n")
1134 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001135 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001136 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001137 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001138 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001139 sys.stdout.write(
1140 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1141 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001142 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1143 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1144 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001145
Antoine Pitrou480a1242010-04-28 21:37:09 +00001146 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1147 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1148 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001149
Antoine Pitrou480a1242010-04-28 21:37:09 +00001150 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1151 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1152 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001153
Antoine Pitroub5218772010-05-21 09:56:06 +00001154 # Server with specific SSL options
1155 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1156 server_options=ssl.OP_NO_SSLv3)
1157 # Will choose TLSv1
1158 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1159 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1160 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1161 server_options=ssl.OP_NO_TLSv1)
1162
1163
Antoine Pitrou23df4832010-08-04 17:14:06 +00001164 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001165 def test_protocol_sslv3(self):
1166 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001167 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001168 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001169 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1170 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1171 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1172 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1173 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1174 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001175 if no_sslv2_implies_sslv3_hello():
1176 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1177 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1178 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179
Antoine Pitrou23df4832010-08-04 17:14:06 +00001180 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001181 def test_protocol_tlsv1(self):
1182 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001183 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001184 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001185 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1186 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1187 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1188 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1189 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1190 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001191
Antoine Pitrou480a1242010-04-28 21:37:09 +00001192 def test_starttls(self):
1193 """Switching from clear text to encrypted and back again."""
1194 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 +00001195
Trent Nelson78520002008-04-10 20:54:35 +00001196 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001197 ssl_version=ssl.PROTOCOL_TLSv1,
1198 starttls_server=True,
1199 chatty=True,
1200 connectionchatty=True)
1201 flag = threading.Event()
1202 server.start(flag)
1203 # wait for it to start
1204 flag.wait()
1205 # try to connect
1206 wrapped = False
1207 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001208 s = socket.socket()
1209 s.setblocking(1)
1210 s.connect((HOST, server.port))
1211 if support.verbose:
1212 sys.stdout.write("\n")
1213 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001214 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001215 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001217 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001218 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001219 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001220 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001221 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001222 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001223 msg = outdata.strip().lower()
1224 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1225 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001226 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001227 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001228 " client: read %r from server, starting TLS...\n"
1229 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001230 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1231 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001232 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1233 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001234 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001235 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001236 " client: read %r from server, ending TLS...\n"
1237 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001238 s = conn.unwrap()
1239 wrapped = False
1240 else:
1241 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001242 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001243 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001244 if support.verbose:
1245 sys.stdout.write(" client: closing connection.\n")
1246 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001247 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001248 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001250 if wrapped:
1251 conn.close()
1252 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001253 s.close()
1254 finally:
1255 server.stop()
1256 server.join()
1257
Antoine Pitrou480a1242010-04-28 21:37:09 +00001258 def test_socketserver(self):
1259 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001260 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001261 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001262 if support.verbose:
1263 sys.stdout.write('\n')
1264 with open(CERTFILE, 'rb') as f:
1265 d1 = f.read()
1266 d2 = ''
1267 # now fetch the same data from the HTTPS server
1268 url = 'https://%s:%d/%s' % (
1269 HOST, server.port, os.path.split(CERTFILE)[1])
1270 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001271 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001272 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001273 if dlen and (int(dlen) > 0):
1274 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001275 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001276 sys.stdout.write(
1277 " client: read %d bytes from remote server '%s'\n"
1278 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001279 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001280 f.close()
1281 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001282
Antoine Pitrou480a1242010-04-28 21:37:09 +00001283 def test_asyncore_server(self):
1284 """Check the example asyncore integration."""
1285 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001286
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001287 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001288 sys.stdout.write("\n")
1289
Antoine Pitrou480a1242010-04-28 21:37:09 +00001290 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001291 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001292 flag = threading.Event()
1293 server.start(flag)
1294 # wait for it to start
1295 flag.wait()
1296 # try to connect
1297 try:
1298 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001299 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001300 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001301 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001302 " client: sending %r...\n" % indata)
1303 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001304 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001305 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001306 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001307 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001308 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001309 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1310 % (outdata[:20], len(outdata),
1311 indata[:20].lower(), len(indata)))
1312 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001313 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001314 sys.stdout.write(" client: closing connection.\n")
1315 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001316 if support.verbose:
1317 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001318 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001319 if support.verbose:
1320 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001321 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001322 if support.verbose:
1323 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001324 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001325 if support.verbose:
1326 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001327
Antoine Pitrou480a1242010-04-28 21:37:09 +00001328 def test_recv_send(self):
1329 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001330 if support.verbose:
1331 sys.stdout.write("\n")
1332
1333 server = ThreadedEchoServer(CERTFILE,
1334 certreqs=ssl.CERT_NONE,
1335 ssl_version=ssl.PROTOCOL_TLSv1,
1336 cacerts=CERTFILE,
1337 chatty=True,
1338 connectionchatty=False)
1339 flag = threading.Event()
1340 server.start(flag)
1341 # wait for it to start
1342 flag.wait()
1343 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001344 s = ssl.wrap_socket(socket.socket(),
1345 server_side=False,
1346 certfile=CERTFILE,
1347 ca_certs=CERTFILE,
1348 cert_reqs=ssl.CERT_NONE,
1349 ssl_version=ssl.PROTOCOL_TLSv1)
1350 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001351 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001352 # helper methods for standardising recv* method signatures
1353 def _recv_into():
1354 b = bytearray(b"\0"*100)
1355 count = s.recv_into(b)
1356 return b[:count]
1357
1358 def _recvfrom_into():
1359 b = bytearray(b"\0"*100)
1360 count, addr = s.recvfrom_into(b)
1361 return b[:count]
1362
1363 # (name, method, whether to expect success, *args)
1364 send_methods = [
1365 ('send', s.send, True, []),
1366 ('sendto', s.sendto, False, ["some.address"]),
1367 ('sendall', s.sendall, True, []),
1368 ]
1369 recv_methods = [
1370 ('recv', s.recv, True, []),
1371 ('recvfrom', s.recvfrom, False, ["some.address"]),
1372 ('recv_into', _recv_into, True, []),
1373 ('recvfrom_into', _recvfrom_into, False, []),
1374 ]
1375 data_prefix = "PREFIX_"
1376
1377 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001378 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001379 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001381 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001382 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001383 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001384 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001385 "<<{outdata:r}>> ({nout:d}) received; "
1386 "expected <<{indata:r}>> ({nin:d})\n".format(
1387 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001388 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001390 )
1391 )
1392 except ValueError as e:
1393 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001394 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001395 "Failed to send with method <<{name:s}>>; "
1396 "expected to succeed.\n".format(name=meth_name)
1397 )
1398 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001399 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001400 "Method <<{name:s}>> failed with unexpected "
1401 "exception message: {exp:s}\n".format(
1402 name=meth_name, exp=e
1403 )
1404 )
1405
1406 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001407 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001408 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001409 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001410 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001411 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001412 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001413 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001414 "<<{outdata:r}>> ({nout:d}) received; "
1415 "expected <<{indata:r}>> ({nin:d})\n".format(
1416 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001417 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001419 )
1420 )
1421 except ValueError as e:
1422 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001423 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001424 "Failed to receive with method <<{name:s}>>; "
1425 "expected to succeed.\n".format(name=meth_name)
1426 )
1427 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001428 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001429 "Method <<{name:s}>> failed with unexpected "
1430 "exception message: {exp:s}\n".format(
1431 name=meth_name, exp=e
1432 )
1433 )
1434 # consume data
1435 s.read()
1436
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001438 s.close()
1439 finally:
1440 server.stop()
1441 server.join()
1442
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001443 def test_handshake_timeout(self):
1444 # Issue #5103: SSL handshake must respect the socket timeout
1445 server = socket.socket(socket.AF_INET)
1446 host = "127.0.0.1"
1447 port = support.bind_port(server)
1448 started = threading.Event()
1449 finish = False
1450
1451 def serve():
1452 server.listen(5)
1453 started.set()
1454 conns = []
1455 while not finish:
1456 r, w, e = select.select([server], [], [], 0.1)
1457 if server in r:
1458 # Let the socket hang around rather than having
1459 # it closed by garbage collection.
1460 conns.append(server.accept()[0])
1461
1462 t = threading.Thread(target=serve)
1463 t.start()
1464 started.wait()
1465
1466 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001467 try:
1468 c = socket.socket(socket.AF_INET)
1469 c.settimeout(0.2)
1470 c.connect((host, port))
1471 # Will attempt handshake and time out
1472 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1473 ssl.wrap_socket, c)
1474 finally:
1475 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001476 try:
1477 c = socket.socket(socket.AF_INET)
1478 c = ssl.wrap_socket(c)
1479 c.settimeout(0.2)
1480 # Will attempt handshake and time out
1481 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1482 c.connect, (host, port))
1483 finally:
1484 c.close()
1485 finally:
1486 finish = True
1487 t.join()
1488 server.close()
1489
Bill Janssen58afe4c2008-09-08 16:45:19 +00001490
Thomas Woutersed03b412007-08-28 21:37:11 +00001491def test_main(verbose=False):
1492 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001493 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001494
Antoine Pitrou15cee622010-08-04 16:45:21 +00001495 if support.verbose:
1496 plats = {
1497 'Linux': platform.linux_distribution,
1498 'Mac': platform.mac_ver,
1499 'Windows': platform.win32_ver,
1500 }
1501 for name, func in plats.items():
1502 plat = func()
1503 if plat and plat[0]:
1504 plat = '%s %r' % (name, plat)
1505 break
1506 else:
1507 plat = repr(platform.platform())
1508 print("test_ssl: testing with %r %r" %
1509 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1510 print(" under %s" % plat)
1511
Antoine Pitrou152efa22010-05-16 18:19:27 +00001512 for filename in [
1513 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1514 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1515 BADCERT, BADKEY, EMPTYCERT]:
1516 if not os.path.exists(filename):
1517 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001518
Antoine Pitrou152efa22010-05-16 18:19:27 +00001519 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001520
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001521 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001522 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001523
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001524 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001525 thread_info = support.threading_setup()
1526 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001527 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001528
Antoine Pitrou480a1242010-04-28 21:37:09 +00001529 try:
1530 support.run_unittest(*tests)
1531 finally:
1532 if _have_threads:
1533 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001534
1535if __name__ == "__main__":
1536 test_main()