blob: b11723c5381d6e94ac66730394539b2efe78c366 [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 = [
24 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
25 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Thomas Woutersed03b412007-08-28 21:37:11 +000027
Benjamin Petersonee8712c2008-05-20 21:35:26 +000028HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000029
30data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
Antoine Pitrou81564092010-10-08 23:06:24 +000032# The custom key and certificate files used in test_ssl are generated
33# using Lib/test/make_ssl_certs.py.
34# Other certificates are simply fetched from the Internet servers they
35# are meant to authenticate.
36
Antoine Pitrou152efa22010-05-16 18:19:27 +000037CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000038BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000039ONLYCERT = data_file("ssl_cert.pem")
40ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000041BYTES_ONLYCERT = os.fsencode(ONLYCERT)
42BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000043CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000044BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045
46SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
47
48EMPTYCERT = data_file("nullcert.pem")
49BADCERT = data_file("badcert.pem")
50WRONGCERT = data_file("XXXnonexisting.pem")
51BADKEY = data_file("badkey.pem")
52
Thomas Woutersed03b412007-08-28 21:37:11 +000053
Thomas Woutersed03b412007-08-28 21:37:11 +000054def handle_error(prefix):
55 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000056 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000057 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000058
Antoine Pitroub5218772010-05-21 09:56:06 +000059def can_clear_options():
60 # 0.9.8m or higher
61 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
62
63def no_sslv2_implies_sslv3_hello():
64 # 0.9.7h or higher
65 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
66
Thomas Woutersed03b412007-08-28 21:37:11 +000067
Antoine Pitrou23df4832010-08-04 17:14:06 +000068# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
69def skip_if_broken_ubuntu_ssl(func):
70 @functools.wraps(func)
71 def f(*args, **kwargs):
72 try:
73 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
74 except ssl.SSLError:
75 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
76 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
77 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
78 return func(*args, **kwargs)
79 return f
80
81
Antoine Pitrou152efa22010-05-16 18:19:27 +000082class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000083
Antoine Pitrou480a1242010-04-28 21:37:09 +000084 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000085 ssl.PROTOCOL_SSLv2
86 ssl.PROTOCOL_SSLv23
87 ssl.PROTOCOL_SSLv3
88 ssl.PROTOCOL_TLSv1
89 ssl.CERT_NONE
90 ssl.CERT_OPTIONAL
91 ssl.CERT_REQUIRED
Antoine Pitroud5323212010-10-22 18:19:07 +000092 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Antoine Pitrou480a1242010-04-28 21:37:09 +000094 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000095 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000096 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 sys.stdout.write("\n RAND_status is %d (%s)\n"
98 % (v, (v and "sufficient randomness") or
99 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000100 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 ssl.RAND_egd(1)
102 except TypeError:
103 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000104 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 print("didn't raise TypeError")
106 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000107
Antoine Pitrou480a1242010-04-28 21:37:09 +0000108 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000109 # note that this uses an 'unofficial' function in _ssl.c,
110 # provided solely for this test, to exercise the certificate
111 # parsing code
112 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000113 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000115
Antoine Pitrou480a1242010-04-28 21:37:09 +0000116 def test_DER_to_PEM(self):
117 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
118 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000119 d1 = ssl.PEM_cert_to_DER_cert(pem)
120 p2 = ssl.DER_cert_to_PEM_cert(d1)
121 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000122 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000123 if not p2.startswith(ssl.PEM_HEADER + '\n'):
124 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
125 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
126 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000128 def test_openssl_version(self):
129 n = ssl.OPENSSL_VERSION_NUMBER
130 t = ssl.OPENSSL_VERSION_INFO
131 s = ssl.OPENSSL_VERSION
132 self.assertIsInstance(n, int)
133 self.assertIsInstance(t, tuple)
134 self.assertIsInstance(s, str)
135 # Some sanity checks follow
136 # >= 0.9
137 self.assertGreaterEqual(n, 0x900000)
138 # < 2.0
139 self.assertLess(n, 0x20000000)
140 major, minor, fix, patch, status = t
141 self.assertGreaterEqual(major, 0)
142 self.assertLess(major, 2)
143 self.assertGreaterEqual(minor, 0)
144 self.assertLess(minor, 256)
145 self.assertGreaterEqual(fix, 0)
146 self.assertLess(fix, 256)
147 self.assertGreaterEqual(patch, 0)
148 self.assertLessEqual(patch, 26)
149 self.assertGreaterEqual(status, 0)
150 self.assertLessEqual(status, 15)
151 # Version string as returned by OpenSSL, the format might change
152 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
153 (s, t))
154
Antoine Pitrou9d543662010-04-23 23:10:32 +0000155 @support.cpython_only
156 def test_refcycle(self):
157 # Issue #7943: an SSL object doesn't create reference cycles with
158 # itself.
159 s = socket.socket(socket.AF_INET)
160 ss = ssl.wrap_socket(s)
161 wr = weakref.ref(ss)
162 del ss
163 self.assertEqual(wr(), None)
164
Antoine Pitroua468adc2010-09-14 14:43:44 +0000165 def test_wrapped_unconnected(self):
166 # Methods on an unconnected SSLSocket propagate the original
167 # socket.error raise by the underlying socket object.
168 s = socket.socket(socket.AF_INET)
169 ss = ssl.wrap_socket(s)
170 self.assertRaises(socket.error, ss.recv, 1)
171 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
172 self.assertRaises(socket.error, ss.recvfrom, 1)
173 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
174 self.assertRaises(socket.error, ss.send, b'x')
175 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
176
Antoine Pitrou40f08742010-04-24 22:04:40 +0000177 def test_timeout(self):
178 # Issue #8524: when creating an SSL socket, the timeout of the
179 # original socket should be retained.
180 for timeout in (None, 0.0, 5.0):
181 s = socket.socket(socket.AF_INET)
182 s.settimeout(timeout)
183 ss = ssl.wrap_socket(s)
184 self.assertEqual(timeout, ss.gettimeout())
185
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000186 def test_errors(self):
187 sock = socket.socket()
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000188 self.assertRaisesRegexp(ValueError,
189 "certfile must be specified",
190 ssl.wrap_socket, sock, keyfile=CERTFILE)
191 self.assertRaisesRegexp(ValueError,
192 "certfile must be specified for server-side operations",
193 ssl.wrap_socket, sock, server_side=True)
194 self.assertRaisesRegexp(ValueError,
195 "certfile must be specified for server-side operations",
196 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000197 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
198 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
199 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000200 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000201 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000202 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000203 with self.assertRaises(IOError) as cm:
204 ssl.wrap_socket(socket.socket(), certfile=CERTFILE, keyfile=WRONGCERT)
205 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000206 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000207 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000208 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000209
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000210 def test_match_hostname(self):
211 def ok(cert, hostname):
212 ssl.match_hostname(cert, hostname)
213 def fail(cert, hostname):
214 self.assertRaises(ssl.CertificateError,
215 ssl.match_hostname, cert, hostname)
216
217 cert = {'subject': ((('commonName', 'example.com'),),)}
218 ok(cert, 'example.com')
219 ok(cert, 'ExAmple.cOm')
220 fail(cert, 'www.example.com')
221 fail(cert, '.example.com')
222 fail(cert, 'example.org')
223 fail(cert, 'exampleXcom')
224
225 cert = {'subject': ((('commonName', '*.a.com'),),)}
226 ok(cert, 'foo.a.com')
227 fail(cert, 'bar.foo.a.com')
228 fail(cert, 'a.com')
229 fail(cert, 'Xa.com')
230 fail(cert, '.a.com')
231
232 cert = {'subject': ((('commonName', 'a.*.com'),),)}
233 ok(cert, 'a.foo.com')
234 fail(cert, 'a..com')
235 fail(cert, 'a.com')
236
237 cert = {'subject': ((('commonName', 'f*.com'),),)}
238 ok(cert, 'foo.com')
239 ok(cert, 'f.com')
240 fail(cert, 'bar.com')
241 fail(cert, 'foo.a.com')
242 fail(cert, 'bar.foo.com')
243
244 # Slightly fake real-world example
245 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
246 'subject': ((('commonName', 'linuxfrz.org'),),),
247 'subjectAltName': (('DNS', 'linuxfr.org'),
248 ('DNS', 'linuxfr.com'),
249 ('othername', '<unsupported>'))}
250 ok(cert, 'linuxfr.org')
251 ok(cert, 'linuxfr.com')
252 # Not a "DNS" entry
253 fail(cert, '<unsupported>')
254 # When there is a subjectAltName, commonName isn't used
255 fail(cert, 'linuxfrz.org')
256
257 # A pristine real-world example
258 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
259 'subject': ((('countryName', 'US'),),
260 (('stateOrProvinceName', 'California'),),
261 (('localityName', 'Mountain View'),),
262 (('organizationName', 'Google Inc'),),
263 (('commonName', 'mail.google.com'),))}
264 ok(cert, 'mail.google.com')
265 fail(cert, 'gmail.com')
266 # Only commonName is considered
267 fail(cert, 'California')
268
269 # Neither commonName nor subjectAltName
270 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
271 'subject': ((('countryName', 'US'),),
272 (('stateOrProvinceName', 'California'),),
273 (('localityName', 'Mountain View'),),
274 (('organizationName', 'Google Inc'),))}
275 fail(cert, 'mail.google.com')
276
277 # Empty cert / no cert
278 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
279 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
280
Antoine Pitroud5323212010-10-22 18:19:07 +0000281 def test_server_side(self):
282 # server_hostname doesn't work for server sockets
283 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
284 sock = socket.socket()
285 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
286 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000287
Antoine Pitrou152efa22010-05-16 18:19:27 +0000288class ContextTests(unittest.TestCase):
289
Antoine Pitrou23df4832010-08-04 17:14:06 +0000290 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000291 def test_constructor(self):
292 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
293 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
294 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
295 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
296 self.assertRaises(TypeError, ssl.SSLContext)
297 self.assertRaises(ValueError, ssl.SSLContext, -1)
298 self.assertRaises(ValueError, ssl.SSLContext, 42)
299
Antoine Pitrou23df4832010-08-04 17:14:06 +0000300 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000301 def test_protocol(self):
302 for proto in PROTOCOLS:
303 ctx = ssl.SSLContext(proto)
304 self.assertEqual(ctx.protocol, proto)
305
306 def test_ciphers(self):
307 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
308 ctx.set_ciphers("ALL")
309 ctx.set_ciphers("DEFAULT")
310 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000311 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000312
Antoine Pitrou23df4832010-08-04 17:14:06 +0000313 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000314 def test_options(self):
315 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
316 # OP_ALL is the default value
317 self.assertEqual(ssl.OP_ALL, ctx.options)
318 ctx.options |= ssl.OP_NO_SSLv2
319 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
320 ctx.options)
321 ctx.options |= ssl.OP_NO_SSLv3
322 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
323 ctx.options)
324 if can_clear_options():
325 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
326 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
327 ctx.options)
328 ctx.options = 0
329 self.assertEqual(0, ctx.options)
330 else:
331 with self.assertRaises(ValueError):
332 ctx.options = 0
333
Antoine Pitrou152efa22010-05-16 18:19:27 +0000334 def test_verify(self):
335 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
336 # Default value
337 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
338 ctx.verify_mode = ssl.CERT_OPTIONAL
339 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
340 ctx.verify_mode = ssl.CERT_REQUIRED
341 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
342 ctx.verify_mode = ssl.CERT_NONE
343 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
344 with self.assertRaises(TypeError):
345 ctx.verify_mode = None
346 with self.assertRaises(ValueError):
347 ctx.verify_mode = 42
348
349 def test_load_cert_chain(self):
350 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
351 # Combined key and cert in a single file
352 ctx.load_cert_chain(CERTFILE)
353 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
354 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000355 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000356 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000357 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000358 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
359 ctx.load_cert_chain(BADCERT)
360 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
361 ctx.load_cert_chain(EMPTYCERT)
362 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000363 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000364 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
365 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
366 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
367 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
368 ctx.load_cert_chain(ONLYCERT)
369 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
370 ctx.load_cert_chain(ONLYKEY)
371 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
372 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
373 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000374 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000375 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000376 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000377
378 def test_load_verify_locations(self):
379 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
380 ctx.load_verify_locations(CERTFILE)
381 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
382 ctx.load_verify_locations(BYTES_CERTFILE)
383 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
384 self.assertRaises(TypeError, ctx.load_verify_locations)
385 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000386 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000387 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000388 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000389 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
390 ctx.load_verify_locations(BADCERT)
391 ctx.load_verify_locations(CERTFILE, CAPATH)
392 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
393
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000394 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000395 def test_session_stats(self):
396 for proto in PROTOCOLS:
397 ctx = ssl.SSLContext(proto)
398 self.assertEqual(ctx.session_stats(), {
399 'number': 0,
400 'connect': 0,
401 'connect_good': 0,
402 'connect_renegotiate': 0,
403 'accept': 0,
404 'accept_good': 0,
405 'accept_renegotiate': 0,
406 'hits': 0,
407 'misses': 0,
408 'timeouts': 0,
409 'cache_full': 0,
410 })
411
Antoine Pitrou152efa22010-05-16 18:19:27 +0000412
Bill Janssen6e027db2007-11-15 22:23:56 +0000413class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000414
Antoine Pitrou480a1242010-04-28 21:37:09 +0000415 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000416 with support.transient_internet("svn.python.org"):
417 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
418 cert_reqs=ssl.CERT_NONE)
419 try:
420 s.connect(("svn.python.org", 443))
421 self.assertEqual({}, s.getpeercert())
422 finally:
423 s.close()
424
425 # this should fail because we have no verification certs
426 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
427 cert_reqs=ssl.CERT_REQUIRED)
428 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
429 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000430 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000431
Antoine Pitrou350c7222010-09-09 13:31:46 +0000432 # this should succeed because we specify the root cert
433 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
434 cert_reqs=ssl.CERT_REQUIRED,
435 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
436 try:
437 s.connect(("svn.python.org", 443))
438 self.assertTrue(s.getpeercert())
439 finally:
440 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000441
442 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000443 with support.transient_internet("svn.python.org"):
444 # Same as test_connect, but with a separately created context
445 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
446 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
447 s.connect(("svn.python.org", 443))
448 try:
449 self.assertEqual({}, s.getpeercert())
450 finally:
451 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000452 # Same with a server hostname
453 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
454 server_hostname="svn.python.org")
455 if ssl.HAS_SNI:
456 s.connect(("svn.python.org", 443))
457 s.close()
458 else:
459 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000460 # This should fail because we have no verification certs
461 ctx.verify_mode = ssl.CERT_REQUIRED
462 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
463 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
464 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000465 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000466 # This should succeed because we specify the root cert
467 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
468 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
469 s.connect(("svn.python.org", 443))
470 try:
471 cert = s.getpeercert()
472 self.assertTrue(cert)
473 finally:
474 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000475
476 def test_connect_capath(self):
477 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000478 # NOTE: the subject hashing algorithm has been changed between
479 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
480 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000481 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000482 with support.transient_internet("svn.python.org"):
483 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
484 ctx.verify_mode = ssl.CERT_REQUIRED
485 ctx.load_verify_locations(capath=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()
493 # Same with a bytes `capath` argument
494 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
495 ctx.verify_mode = ssl.CERT_REQUIRED
496 ctx.load_verify_locations(capath=BYTES_CAPATH)
497 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
498 s.connect(("svn.python.org", 443))
499 try:
500 cert = s.getpeercert()
501 self.assertTrue(cert)
502 finally:
503 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000504
Antoine Pitroue3220242010-04-24 11:13:53 +0000505 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
506 def test_makefile_close(self):
507 # Issue #5238: creating a file-like object with makefile() shouldn't
508 # delay closing the underlying "real socket" (here tested with its
509 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000510 with support.transient_internet("svn.python.org"):
511 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
512 ss.connect(("svn.python.org", 443))
513 fd = ss.fileno()
514 f = ss.makefile()
515 f.close()
516 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000517 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000518 # Closing the SSL socket should close the fd too
519 ss.close()
520 gc.collect()
521 with self.assertRaises(OSError) as e:
522 os.read(fd, 0)
523 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000524
Antoine Pitrou480a1242010-04-28 21:37:09 +0000525 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000526 with support.transient_internet("svn.python.org"):
527 s = socket.socket(socket.AF_INET)
528 s.connect(("svn.python.org", 443))
529 s.setblocking(False)
530 s = ssl.wrap_socket(s,
531 cert_reqs=ssl.CERT_NONE,
532 do_handshake_on_connect=False)
533 count = 0
534 while True:
535 try:
536 count += 1
537 s.do_handshake()
538 break
539 except ssl.SSLError as err:
540 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
541 select.select([s], [], [])
542 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
543 select.select([], [s], [])
544 else:
545 raise
546 s.close()
547 if support.verbose:
548 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000549
Antoine Pitrou480a1242010-04-28 21:37:09 +0000550 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000551 with support.transient_internet("svn.python.org"):
552 pem = ssl.get_server_certificate(("svn.python.org", 443))
553 if not pem:
554 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000555
Antoine Pitrou350c7222010-09-09 13:31:46 +0000556 try:
557 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
558 except ssl.SSLError as x:
559 #should fail
560 if support.verbose:
561 sys.stdout.write("%s\n" % x)
562 else:
563 self.fail("Got server certificate %s for svn.python.org!" % pem)
564
565 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
566 if not pem:
567 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000568 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000569 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000570
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000571 def test_ciphers(self):
572 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000573 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000574 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000575 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000576 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000577 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
578 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
579 s.connect(remote)
580 # Error checking can happen at instantiation or when connecting
581 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
582 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
583 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
584 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000585
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000586 def test_algorithms(self):
587 # Issue #8484: all algorithms should be available when verifying a
588 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000589 # SHA256 was added in OpenSSL 0.9.8
590 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
591 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000592 # NOTE: https://sha256.tbs-internet.com is another possible test host
593 remote = ("sha2.hboeck.de", 443)
594 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000595 with support.transient_internet("sha2.hboeck.de"):
596 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
597 cert_reqs=ssl.CERT_REQUIRED,
598 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000599 try:
600 s.connect(remote)
601 if support.verbose:
602 sys.stdout.write("\nCipher with %r is %r\n" %
603 (remote, s.cipher()))
604 sys.stdout.write("Certificate is:\n%s\n" %
605 pprint.pformat(s.getpeercert()))
606 finally:
607 s.close()
608
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000609
610try:
611 import threading
612except ImportError:
613 _have_threads = False
614else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000615 _have_threads = True
616
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000617 from test.ssl_servers import make_https_server
618
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000619 class ThreadedEchoServer(threading.Thread):
620
621 class ConnectionHandler(threading.Thread):
622
623 """A mildly complicated class, because we want it to work both
624 with and without the SSL wrapper around the socket connection, so
625 that we can test the STARTTLS functionality."""
626
Bill Janssen6e027db2007-11-15 22:23:56 +0000627 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000628 self.server = server
629 self.running = False
630 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000631 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000632 self.sock.setblocking(1)
633 self.sslconn = None
634 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000635 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000636
Antoine Pitrou480a1242010-04-28 21:37:09 +0000637 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000638 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000639 self.sslconn = self.server.context.wrap_socket(
640 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000641 except ssl.SSLError:
642 # XXX Various errors can have happened here, for example
643 # a mismatching protocol version, an invalid certificate,
644 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000645 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000646 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000647 self.running = False
648 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000649 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000651 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000652 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000653 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000654 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000655 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
656 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000657 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000658 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
659 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000660 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000661 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
662 return True
663
664 def read(self):
665 if self.sslconn:
666 return self.sslconn.read()
667 else:
668 return self.sock.recv(1024)
669
670 def write(self, bytes):
671 if self.sslconn:
672 return self.sslconn.write(bytes)
673 else:
674 return self.sock.send(bytes)
675
676 def close(self):
677 if self.sslconn:
678 self.sslconn.close()
679 else:
680 self.sock.close()
681
Antoine Pitrou480a1242010-04-28 21:37:09 +0000682 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000683 self.running = True
684 if not self.server.starttls_server:
685 if not self.wrap_conn():
686 return
687 while self.running:
688 try:
689 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000690 stripped = msg.strip()
691 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000692 # eof, so quit this handler
693 self.running = False
694 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000695 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000696 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000697 sys.stdout.write(" server: client closed connection\n")
698 self.close()
699 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000700 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000701 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000702 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000703 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000704 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 if not self.wrap_conn():
706 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000707 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000708 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000709 if support.verbose and self.server.connectionchatty:
710 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000711 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000712 self.sock = self.sslconn.unwrap()
713 self.sslconn = None
714 if support.verbose and self.server.connectionchatty:
715 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000716 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000717 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000718 self.server.connectionchatty):
719 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000720 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
721 % (msg, ctype, msg.lower(), ctype))
722 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000723 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000724 if self.server.chatty:
725 handle_error("Test server failure:\n")
726 self.close()
727 self.running = False
728 # normally, we'd just stop here, but for the test
729 # harness, we want to stop the server
730 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000731
Antoine Pitroub5218772010-05-21 09:56:06 +0000732 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000733 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000734 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000735 ciphers=None, context=None):
736 if context:
737 self.context = context
738 else:
739 self.context = ssl.SSLContext(ssl_version
740 if ssl_version is not None
741 else ssl.PROTOCOL_TLSv1)
742 self.context.verify_mode = (certreqs if certreqs is not None
743 else ssl.CERT_NONE)
744 if cacerts:
745 self.context.load_verify_locations(cacerts)
746 if certificate:
747 self.context.load_cert_chain(certificate)
748 if ciphers:
749 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750 self.chatty = chatty
751 self.connectionchatty = connectionchatty
752 self.starttls_server = starttls_server
753 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000754 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000755 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756 self.active = False
757 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000758 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000759
Antoine Pitrou480a1242010-04-28 21:37:09 +0000760 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000761 self.flag = flag
762 threading.Thread.start(self)
763
Antoine Pitrou480a1242010-04-28 21:37:09 +0000764 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000765 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000766 self.sock.listen(5)
767 self.active = True
768 if self.flag:
769 # signal an event
770 self.flag.set()
771 while self.active:
772 try:
773 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000774 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000775 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000776 + repr(connaddr) + '\n')
777 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000778 handler.start()
779 except socket.timeout:
780 pass
781 except KeyboardInterrupt:
782 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000783 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000784
Antoine Pitrou480a1242010-04-28 21:37:09 +0000785 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000786 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787
Bill Janssen54cc54c2007-12-14 22:08:56 +0000788 class AsyncoreEchoServer(threading.Thread):
789
790 # this one's based on asyncore.dispatcher
791
792 class EchoServer (asyncore.dispatcher):
793
794 class ConnectionHandler (asyncore.dispatcher_with_send):
795
796 def __init__(self, conn, certfile):
797 self.socket = ssl.wrap_socket(conn, server_side=True,
798 certfile=certfile,
799 do_handshake_on_connect=False)
800 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000801 self._ssl_accepting = True
802 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000803
804 def readable(self):
805 if isinstance(self.socket, ssl.SSLSocket):
806 while self.socket.pending() > 0:
807 self.handle_read_event()
808 return True
809
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000810 def _do_ssl_handshake(self):
811 try:
812 self.socket.do_handshake()
813 except ssl.SSLError as err:
814 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
815 ssl.SSL_ERROR_WANT_WRITE):
816 return
817 elif err.args[0] == ssl.SSL_ERROR_EOF:
818 return self.handle_close()
819 raise
820 except socket.error as err:
821 if err.args[0] == errno.ECONNABORTED:
822 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000823 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000824 self._ssl_accepting = False
825
826 def handle_read(self):
827 if self._ssl_accepting:
828 self._do_ssl_handshake()
829 else:
830 data = self.recv(1024)
831 if support.verbose:
832 sys.stdout.write(" server: read %s from client\n" % repr(data))
833 if not data:
834 self.close()
835 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000836 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000837
838 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000839 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000840 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000841 sys.stdout.write(" server: closed connection %s\n" % self.socket)
842
843 def handle_error(self):
844 raise
845
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000846 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000847 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000848 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
849 self.port = support.bind_port(sock, '')
850 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000851 self.listen(5)
852
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000853 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000854 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000855 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
856 self.ConnectionHandler(sock_obj, self.certfile)
857
858 def handle_error(self):
859 raise
860
Trent Nelson78520002008-04-10 20:54:35 +0000861 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000862 self.flag = None
863 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000864 self.server = self.EchoServer(certfile)
865 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000866 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000867 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000868
869 def __str__(self):
870 return "<%s %s>" % (self.__class__.__name__, self.server)
871
872 def start (self, flag=None):
873 self.flag = flag
874 threading.Thread.start(self)
875
Antoine Pitrou480a1242010-04-28 21:37:09 +0000876 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000877 self.active = True
878 if self.flag:
879 self.flag.set()
880 while self.active:
881 try:
882 asyncore.loop(1)
883 except:
884 pass
885
Antoine Pitrou480a1242010-04-28 21:37:09 +0000886 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000887 self.active = False
888 self.server.close()
889
Antoine Pitrou480a1242010-04-28 21:37:09 +0000890 def bad_cert_test(certfile):
891 """
892 Launch a server with CERT_REQUIRED, and check that trying to
893 connect to it with the given client certificate fails.
894 """
Trent Nelson78520002008-04-10 20:54:35 +0000895 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000897 cacerts=CERTFILE, chatty=False,
898 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000899 flag = threading.Event()
900 server.start(flag)
901 # wait for it to start
902 flag.wait()
903 # try to connect
904 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000905 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000906 s = ssl.wrap_socket(socket.socket(),
907 certfile=certfile,
908 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000909 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000910 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000911 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000912 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000913 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000914 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000915 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000916 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000917 if x.errno != errno.ENOENT:
918 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000919 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000920 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000922 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923 finally:
924 server.stop()
925 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000926
Antoine Pitroub5218772010-05-21 09:56:06 +0000927 def server_params_test(client_context, server_context, indata=b"FOO\n",
928 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000929 """
930 Launch a server, connect a client to it and try various reads
931 and writes.
932 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000933 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000934 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000935 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000936 flag = threading.Event()
937 server.start(flag)
938 # wait for it to start
939 flag.wait()
940 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000942 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000943 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000944 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000945 if connectionchatty:
946 if support.verbose:
947 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000948 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000949 s.write(arg)
950 outdata = s.read()
951 if connectionchatty:
952 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000953 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000954 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000955 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000956 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
957 % (outdata[:20], len(outdata),
958 indata[:20].lower(), len(indata)))
959 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000960 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000961 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000962 sys.stdout.write(" client: closing connection.\n")
963 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000964 finally:
965 server.stop()
966 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000967
Antoine Pitroub5218772010-05-21 09:56:06 +0000968 def try_protocol_combo(server_protocol, client_protocol, expect_success,
969 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000970 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000971 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000972 certtype = {
973 ssl.CERT_NONE: "CERT_NONE",
974 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
975 ssl.CERT_REQUIRED: "CERT_REQUIRED",
976 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000977 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000978 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979 sys.stdout.write(formatstr %
980 (ssl.get_protocol_name(client_protocol),
981 ssl.get_protocol_name(server_protocol),
982 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000983 client_context = ssl.SSLContext(client_protocol)
984 client_context.options = ssl.OP_ALL | client_options
985 server_context = ssl.SSLContext(server_protocol)
986 server_context.options = ssl.OP_ALL | server_options
987 for ctx in (client_context, server_context):
988 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000989 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
990 # will send an SSLv3 hello (rather than SSLv2) starting from
991 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000992 ctx.set_ciphers("ALL")
993 ctx.load_cert_chain(CERTFILE)
994 ctx.load_verify_locations(CERTFILE)
995 try:
996 server_params_test(client_context, server_context,
997 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000998 # Protocol mismatch can result in either an SSLError, or a
999 # "Connection reset by peer" error.
1000 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001003 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001004 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001005 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001006 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001007 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001008 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001009 "Client protocol %s succeeded with server protocol %s!"
1010 % (ssl.get_protocol_name(client_protocol),
1011 ssl.get_protocol_name(server_protocol)))
1012
1013
Bill Janssen6e027db2007-11-15 22:23:56 +00001014 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001015
Antoine Pitrou23df4832010-08-04 17:14:06 +00001016 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001017 def test_echo(self):
1018 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001019 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001020 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001021 for protocol in PROTOCOLS:
1022 context = ssl.SSLContext(protocol)
1023 context.load_cert_chain(CERTFILE)
1024 server_params_test(context, context,
1025 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001026
Antoine Pitrou480a1242010-04-28 21:37:09 +00001027 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001028 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001029 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001030 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1031 context.verify_mode = ssl.CERT_REQUIRED
1032 context.load_verify_locations(CERTFILE)
1033 context.load_cert_chain(CERTFILE)
1034 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001035 flag = threading.Event()
1036 server.start(flag)
1037 # wait for it to start
1038 flag.wait()
1039 # try to connect
1040 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001041 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001042 s.connect((HOST, server.port))
1043 cert = s.getpeercert()
1044 self.assertTrue(cert, "Can't get peer certificate.")
1045 cipher = s.cipher()
1046 if support.verbose:
1047 sys.stdout.write(pprint.pformat(cert) + '\n')
1048 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1049 if 'subject' not in cert:
1050 self.fail("No subject field in certificate: %s." %
1051 pprint.pformat(cert))
1052 if ((('organizationName', 'Python Software Foundation'),)
1053 not in cert['subject']):
1054 self.fail(
1055 "Missing or invalid 'organizationName' field in certificate subject; "
1056 "should be 'Python Software Foundation'.")
1057 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001058 finally:
1059 server.stop()
1060 server.join()
1061
Antoine Pitrou480a1242010-04-28 21:37:09 +00001062 def test_empty_cert(self):
1063 """Connecting with an empty cert file"""
1064 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1065 "nullcert.pem"))
1066 def test_malformed_cert(self):
1067 """Connecting with a badly formatted certificate (syntax error)"""
1068 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1069 "badcert.pem"))
1070 def test_nonexisting_cert(self):
1071 """Connecting with a non-existing cert file"""
1072 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1073 "wrongcert.pem"))
1074 def test_malformed_key(self):
1075 """Connecting with a badly formatted key (syntax error)"""
1076 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1077 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001078
Antoine Pitrou480a1242010-04-28 21:37:09 +00001079 def test_rude_shutdown(self):
1080 """A brutal shutdown of an SSL server should raise an IOError
1081 in the client when attempting handshake.
1082 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001083 listener_ready = threading.Event()
1084 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001085
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001086 s = socket.socket()
1087 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001088
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001089 # `listener` runs in a thread. It sits in an accept() until
1090 # the main thread connects. Then it rudely closes the socket,
1091 # and sets Event `listener_gone` to let the main thread know
1092 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001093 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001094 s.listen(5)
1095 listener_ready.set()
1096 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001097 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001098 listener_gone.set()
1099
1100 def connector():
1101 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001102 c = socket.socket()
1103 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001104 listener_gone.wait()
1105 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001106 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001107 except IOError:
1108 pass
1109 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001110 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001111
1112 t = threading.Thread(target=listener)
1113 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001114 try:
1115 connector()
1116 finally:
1117 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001118
Antoine Pitrou23df4832010-08-04 17:14:06 +00001119 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001120 def test_protocol_sslv2(self):
1121 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001122 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001123 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001124 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1125 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1126 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1127 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1128 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1129 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001130 # SSLv23 client with specific SSL options
1131 if no_sslv2_implies_sslv3_hello():
1132 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1133 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1134 client_options=ssl.OP_NO_SSLv2)
1135 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1136 client_options=ssl.OP_NO_SSLv3)
1137 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1138 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001139
Antoine Pitrou23df4832010-08-04 17:14:06 +00001140 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 def test_protocol_sslv23(self):
1142 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001143 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144 sys.stdout.write("\n")
1145 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001146 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001147 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001149 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 sys.stdout.write(
1151 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1152 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001153 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1154 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1155 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156
Antoine Pitrou480a1242010-04-28 21:37:09 +00001157 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1158 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1159 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001160
Antoine Pitrou480a1242010-04-28 21:37:09 +00001161 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1162 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1163 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001164
Antoine Pitroub5218772010-05-21 09:56:06 +00001165 # Server with specific SSL options
1166 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1167 server_options=ssl.OP_NO_SSLv3)
1168 # Will choose TLSv1
1169 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1170 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1171 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1172 server_options=ssl.OP_NO_TLSv1)
1173
1174
Antoine Pitrou23df4832010-08-04 17:14:06 +00001175 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001176 def test_protocol_sslv3(self):
1177 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001178 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1181 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1182 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1183 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1184 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1185 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001186 if no_sslv2_implies_sslv3_hello():
1187 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1188 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1189 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001190
Antoine Pitrou23df4832010-08-04 17:14:06 +00001191 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001192 def test_protocol_tlsv1(self):
1193 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001194 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001195 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001196 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1197 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1198 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1199 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1200 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1201 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001202
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 def test_starttls(self):
1204 """Switching from clear text to encrypted and back again."""
1205 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 +00001206
Trent Nelson78520002008-04-10 20:54:35 +00001207 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001208 ssl_version=ssl.PROTOCOL_TLSv1,
1209 starttls_server=True,
1210 chatty=True,
1211 connectionchatty=True)
1212 flag = threading.Event()
1213 server.start(flag)
1214 # wait for it to start
1215 flag.wait()
1216 # try to connect
1217 wrapped = False
1218 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001219 s = socket.socket()
1220 s.setblocking(1)
1221 s.connect((HOST, server.port))
1222 if support.verbose:
1223 sys.stdout.write("\n")
1224 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001225 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001226 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001227 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001228 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001229 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001230 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001232 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001233 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001234 msg = outdata.strip().lower()
1235 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1236 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001237 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001238 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001239 " client: read %r from server, starting TLS...\n"
1240 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001241 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1242 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001243 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1244 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001245 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001246 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001247 " client: read %r from server, ending TLS...\n"
1248 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001249 s = conn.unwrap()
1250 wrapped = False
1251 else:
1252 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001253 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001254 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001255 if support.verbose:
1256 sys.stdout.write(" client: closing connection.\n")
1257 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001258 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001259 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001260 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001261 if wrapped:
1262 conn.close()
1263 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001264 s.close()
1265 finally:
1266 server.stop()
1267 server.join()
1268
Antoine Pitrou480a1242010-04-28 21:37:09 +00001269 def test_socketserver(self):
1270 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001271 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001272 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001273 if support.verbose:
1274 sys.stdout.write('\n')
1275 with open(CERTFILE, 'rb') as f:
1276 d1 = f.read()
1277 d2 = ''
1278 # now fetch the same data from the HTTPS server
1279 url = 'https://%s:%d/%s' % (
1280 HOST, server.port, os.path.split(CERTFILE)[1])
1281 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001282 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001283 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001284 if dlen and (int(dlen) > 0):
1285 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001286 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001287 sys.stdout.write(
1288 " client: read %d bytes from remote server '%s'\n"
1289 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001290 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001291 f.close()
1292 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001293
Antoine Pitrou480a1242010-04-28 21:37:09 +00001294 def test_asyncore_server(self):
1295 """Check the example asyncore integration."""
1296 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001297
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001298 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001299 sys.stdout.write("\n")
1300
Antoine Pitrou480a1242010-04-28 21:37:09 +00001301 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001302 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001303 flag = threading.Event()
1304 server.start(flag)
1305 # wait for it to start
1306 flag.wait()
1307 # try to connect
1308 try:
1309 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001310 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001311 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001312 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001313 " client: sending %r...\n" % indata)
1314 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001315 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001316 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001317 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001318 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001319 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001320 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1321 % (outdata[:20], len(outdata),
1322 indata[:20].lower(), len(indata)))
1323 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001324 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001325 sys.stdout.write(" client: closing connection.\n")
1326 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001327 if support.verbose:
1328 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001329 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001330 if support.verbose:
1331 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001332 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001333 if support.verbose:
1334 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001335 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001336 if support.verbose:
1337 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001338
Antoine Pitrou480a1242010-04-28 21:37:09 +00001339 def test_recv_send(self):
1340 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001341 if support.verbose:
1342 sys.stdout.write("\n")
1343
1344 server = ThreadedEchoServer(CERTFILE,
1345 certreqs=ssl.CERT_NONE,
1346 ssl_version=ssl.PROTOCOL_TLSv1,
1347 cacerts=CERTFILE,
1348 chatty=True,
1349 connectionchatty=False)
1350 flag = threading.Event()
1351 server.start(flag)
1352 # wait for it to start
1353 flag.wait()
1354 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001355 s = ssl.wrap_socket(socket.socket(),
1356 server_side=False,
1357 certfile=CERTFILE,
1358 ca_certs=CERTFILE,
1359 cert_reqs=ssl.CERT_NONE,
1360 ssl_version=ssl.PROTOCOL_TLSv1)
1361 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001362 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001363 # helper methods for standardising recv* method signatures
1364 def _recv_into():
1365 b = bytearray(b"\0"*100)
1366 count = s.recv_into(b)
1367 return b[:count]
1368
1369 def _recvfrom_into():
1370 b = bytearray(b"\0"*100)
1371 count, addr = s.recvfrom_into(b)
1372 return b[:count]
1373
1374 # (name, method, whether to expect success, *args)
1375 send_methods = [
1376 ('send', s.send, True, []),
1377 ('sendto', s.sendto, False, ["some.address"]),
1378 ('sendall', s.sendall, True, []),
1379 ]
1380 recv_methods = [
1381 ('recv', s.recv, True, []),
1382 ('recvfrom', s.recvfrom, False, ["some.address"]),
1383 ('recv_into', _recv_into, True, []),
1384 ('recvfrom_into', _recvfrom_into, False, []),
1385 ]
1386 data_prefix = "PREFIX_"
1387
1388 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001390 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001392 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001393 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001394 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001395 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 "<<{outdata:r}>> ({nout:d}) received; "
1397 "expected <<{indata:r}>> ({nin:d})\n".format(
1398 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001399 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001401 )
1402 )
1403 except ValueError as e:
1404 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001405 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001406 "Failed to send with method <<{name:s}>>; "
1407 "expected to succeed.\n".format(name=meth_name)
1408 )
1409 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001410 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001411 "Method <<{name:s}>> failed with unexpected "
1412 "exception message: {exp:s}\n".format(
1413 name=meth_name, exp=e
1414 )
1415 )
1416
1417 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001419 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001420 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001421 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001422 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001423 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001424 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001425 "<<{outdata:r}>> ({nout:d}) received; "
1426 "expected <<{indata:r}>> ({nin:d})\n".format(
1427 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001428 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001429 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001430 )
1431 )
1432 except ValueError as e:
1433 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001434 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001435 "Failed to receive with method <<{name:s}>>; "
1436 "expected to succeed.\n".format(name=meth_name)
1437 )
1438 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001439 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001440 "Method <<{name:s}>> failed with unexpected "
1441 "exception message: {exp:s}\n".format(
1442 name=meth_name, exp=e
1443 )
1444 )
1445 # consume data
1446 s.read()
1447
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001449 s.close()
1450 finally:
1451 server.stop()
1452 server.join()
1453
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001454 def test_handshake_timeout(self):
1455 # Issue #5103: SSL handshake must respect the socket timeout
1456 server = socket.socket(socket.AF_INET)
1457 host = "127.0.0.1"
1458 port = support.bind_port(server)
1459 started = threading.Event()
1460 finish = False
1461
1462 def serve():
1463 server.listen(5)
1464 started.set()
1465 conns = []
1466 while not finish:
1467 r, w, e = select.select([server], [], [], 0.1)
1468 if server in r:
1469 # Let the socket hang around rather than having
1470 # it closed by garbage collection.
1471 conns.append(server.accept()[0])
1472
1473 t = threading.Thread(target=serve)
1474 t.start()
1475 started.wait()
1476
1477 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001478 try:
1479 c = socket.socket(socket.AF_INET)
1480 c.settimeout(0.2)
1481 c.connect((host, port))
1482 # Will attempt handshake and time out
1483 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1484 ssl.wrap_socket, c)
1485 finally:
1486 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001487 try:
1488 c = socket.socket(socket.AF_INET)
1489 c = ssl.wrap_socket(c)
1490 c.settimeout(0.2)
1491 # Will attempt handshake and time out
1492 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1493 c.connect, (host, port))
1494 finally:
1495 c.close()
1496 finally:
1497 finish = True
1498 t.join()
1499 server.close()
1500
Bill Janssen58afe4c2008-09-08 16:45:19 +00001501
Thomas Woutersed03b412007-08-28 21:37:11 +00001502def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001503 if support.verbose:
1504 plats = {
1505 'Linux': platform.linux_distribution,
1506 'Mac': platform.mac_ver,
1507 'Windows': platform.win32_ver,
1508 }
1509 for name, func in plats.items():
1510 plat = func()
1511 if plat and plat[0]:
1512 plat = '%s %r' % (name, plat)
1513 break
1514 else:
1515 plat = repr(platform.platform())
1516 print("test_ssl: testing with %r %r" %
1517 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1518 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001519 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001520
Antoine Pitrou152efa22010-05-16 18:19:27 +00001521 for filename in [
1522 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1523 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1524 BADCERT, BADKEY, EMPTYCERT]:
1525 if not os.path.exists(filename):
1526 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001527
Antoine Pitrou152efa22010-05-16 18:19:27 +00001528 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001529
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001530 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001531 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001532
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001533 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001534 thread_info = support.threading_setup()
1535 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001536 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001537
Antoine Pitrou480a1242010-04-28 21:37:09 +00001538 try:
1539 support.run_unittest(*tests)
1540 finally:
1541 if _have_threads:
1542 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001543
1544if __name__ == "__main__":
1545 test_main()