blob: 3347e9e6f3b5cfc4833d99b6b199d646bf36f5f7 [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
Antoine Pitroufb046912010-11-09 20:21:19 +0000112 p = ssl._ssl._test_decode_cert(CERTFILE)
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()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000188 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000189 "certfile must be specified",
190 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000191 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000192 "certfile must be specified for server-side operations",
193 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000194 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000195 "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)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000198 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000199 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000200 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000201 with socket.socket() as sock:
202 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000203 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000204 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000205 with socket.socket() as sock:
206 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000207 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000208 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000209 with socket.socket() as sock:
210 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000211 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000212
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000213 def test_match_hostname(self):
214 def ok(cert, hostname):
215 ssl.match_hostname(cert, hostname)
216 def fail(cert, hostname):
217 self.assertRaises(ssl.CertificateError,
218 ssl.match_hostname, cert, hostname)
219
220 cert = {'subject': ((('commonName', 'example.com'),),)}
221 ok(cert, 'example.com')
222 ok(cert, 'ExAmple.cOm')
223 fail(cert, 'www.example.com')
224 fail(cert, '.example.com')
225 fail(cert, 'example.org')
226 fail(cert, 'exampleXcom')
227
228 cert = {'subject': ((('commonName', '*.a.com'),),)}
229 ok(cert, 'foo.a.com')
230 fail(cert, 'bar.foo.a.com')
231 fail(cert, 'a.com')
232 fail(cert, 'Xa.com')
233 fail(cert, '.a.com')
234
235 cert = {'subject': ((('commonName', 'a.*.com'),),)}
236 ok(cert, 'a.foo.com')
237 fail(cert, 'a..com')
238 fail(cert, 'a.com')
239
240 cert = {'subject': ((('commonName', 'f*.com'),),)}
241 ok(cert, 'foo.com')
242 ok(cert, 'f.com')
243 fail(cert, 'bar.com')
244 fail(cert, 'foo.a.com')
245 fail(cert, 'bar.foo.com')
246
247 # Slightly fake real-world example
248 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
249 'subject': ((('commonName', 'linuxfrz.org'),),),
250 'subjectAltName': (('DNS', 'linuxfr.org'),
251 ('DNS', 'linuxfr.com'),
252 ('othername', '<unsupported>'))}
253 ok(cert, 'linuxfr.org')
254 ok(cert, 'linuxfr.com')
255 # Not a "DNS" entry
256 fail(cert, '<unsupported>')
257 # When there is a subjectAltName, commonName isn't used
258 fail(cert, 'linuxfrz.org')
259
260 # A pristine real-world example
261 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
262 'subject': ((('countryName', 'US'),),
263 (('stateOrProvinceName', 'California'),),
264 (('localityName', 'Mountain View'),),
265 (('organizationName', 'Google Inc'),),
266 (('commonName', 'mail.google.com'),))}
267 ok(cert, 'mail.google.com')
268 fail(cert, 'gmail.com')
269 # Only commonName is considered
270 fail(cert, 'California')
271
272 # Neither commonName nor subjectAltName
273 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
274 'subject': ((('countryName', 'US'),),
275 (('stateOrProvinceName', 'California'),),
276 (('localityName', 'Mountain View'),),
277 (('organizationName', 'Google Inc'),))}
278 fail(cert, 'mail.google.com')
279
280 # Empty cert / no cert
281 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
282 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
283
Antoine Pitroud5323212010-10-22 18:19:07 +0000284 def test_server_side(self):
285 # server_hostname doesn't work for server sockets
286 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000287 with socket.socket() as sock:
288 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
289 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000290
Antoine Pitrou152efa22010-05-16 18:19:27 +0000291class ContextTests(unittest.TestCase):
292
Antoine Pitrou23df4832010-08-04 17:14:06 +0000293 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000294 def test_constructor(self):
295 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
296 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
297 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
298 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
299 self.assertRaises(TypeError, ssl.SSLContext)
300 self.assertRaises(ValueError, ssl.SSLContext, -1)
301 self.assertRaises(ValueError, ssl.SSLContext, 42)
302
Antoine Pitrou23df4832010-08-04 17:14:06 +0000303 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000304 def test_protocol(self):
305 for proto in PROTOCOLS:
306 ctx = ssl.SSLContext(proto)
307 self.assertEqual(ctx.protocol, proto)
308
309 def test_ciphers(self):
310 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
311 ctx.set_ciphers("ALL")
312 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000313 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000314 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000315
Antoine Pitrou23df4832010-08-04 17:14:06 +0000316 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000317 def test_options(self):
318 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
319 # OP_ALL is the default value
320 self.assertEqual(ssl.OP_ALL, ctx.options)
321 ctx.options |= ssl.OP_NO_SSLv2
322 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
323 ctx.options)
324 ctx.options |= ssl.OP_NO_SSLv3
325 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
326 ctx.options)
327 if can_clear_options():
328 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
329 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
330 ctx.options)
331 ctx.options = 0
332 self.assertEqual(0, ctx.options)
333 else:
334 with self.assertRaises(ValueError):
335 ctx.options = 0
336
Antoine Pitrou152efa22010-05-16 18:19:27 +0000337 def test_verify(self):
338 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
339 # Default value
340 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
341 ctx.verify_mode = ssl.CERT_OPTIONAL
342 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
343 ctx.verify_mode = ssl.CERT_REQUIRED
344 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
345 ctx.verify_mode = ssl.CERT_NONE
346 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
347 with self.assertRaises(TypeError):
348 ctx.verify_mode = None
349 with self.assertRaises(ValueError):
350 ctx.verify_mode = 42
351
352 def test_load_cert_chain(self):
353 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
354 # Combined key and cert in a single file
355 ctx.load_cert_chain(CERTFILE)
356 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
357 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000358 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000359 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000360 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000361 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000362 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000363 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000364 ctx.load_cert_chain(EMPTYCERT)
365 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000366 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000367 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
368 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
369 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000370 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000371 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000372 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000373 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000374 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000375 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
376 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000377 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000378 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000379 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000380
381 def test_load_verify_locations(self):
382 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
383 ctx.load_verify_locations(CERTFILE)
384 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
385 ctx.load_verify_locations(BYTES_CERTFILE)
386 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
387 self.assertRaises(TypeError, ctx.load_verify_locations)
388 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000389 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000390 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000391 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000392 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000393 ctx.load_verify_locations(BADCERT)
394 ctx.load_verify_locations(CERTFILE, CAPATH)
395 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
396
Victor Stinner80f75e62011-01-29 11:31:20 +0000397 # Issue #10989: crash if the second argument type is invalid
398 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
399
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000400 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000401 def test_session_stats(self):
402 for proto in PROTOCOLS:
403 ctx = ssl.SSLContext(proto)
404 self.assertEqual(ctx.session_stats(), {
405 'number': 0,
406 'connect': 0,
407 'connect_good': 0,
408 'connect_renegotiate': 0,
409 'accept': 0,
410 'accept_good': 0,
411 'accept_renegotiate': 0,
412 'hits': 0,
413 'misses': 0,
414 'timeouts': 0,
415 'cache_full': 0,
416 })
417
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000418 def test_set_default_verify_paths(self):
419 # There's not much we can do to test that it acts as expected,
420 # so just check it doesn't crash or raise an exception.
421 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
422 ctx.set_default_verify_paths()
423
Antoine Pitrou152efa22010-05-16 18:19:27 +0000424
Bill Janssen6e027db2007-11-15 22:23:56 +0000425class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000426
Antoine Pitrou480a1242010-04-28 21:37:09 +0000427 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000428 with support.transient_internet("svn.python.org"):
429 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
430 cert_reqs=ssl.CERT_NONE)
431 try:
432 s.connect(("svn.python.org", 443))
433 self.assertEqual({}, s.getpeercert())
434 finally:
435 s.close()
436
437 # this should fail because we have no verification certs
438 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
439 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000440 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
441 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000442 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000443
Antoine Pitrou350c7222010-09-09 13:31:46 +0000444 # this should succeed because we specify the root cert
445 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
446 cert_reqs=ssl.CERT_REQUIRED,
447 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
448 try:
449 s.connect(("svn.python.org", 443))
450 self.assertTrue(s.getpeercert())
451 finally:
452 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000453
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000454 def test_connect_ex(self):
455 # Issue #11326: check connect_ex() implementation
456 with support.transient_internet("svn.python.org"):
457 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
458 cert_reqs=ssl.CERT_REQUIRED,
459 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
460 try:
461 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
462 self.assertTrue(s.getpeercert())
463 finally:
464 s.close()
465
466 def test_non_blocking_connect_ex(self):
467 # Issue #11326: non-blocking connect_ex() should allow handshake
468 # to proceed after the socket gets ready.
469 with support.transient_internet("svn.python.org"):
470 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
471 cert_reqs=ssl.CERT_REQUIRED,
472 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
473 do_handshake_on_connect=False)
474 try:
475 s.setblocking(False)
476 rc = s.connect_ex(('svn.python.org', 443))
477 self.assertIn(rc, (0, errno.EINPROGRESS))
478 # Wait for connect to finish
479 select.select([], [s], [], 5.0)
480 # Non-blocking handshake
481 while True:
482 try:
483 s.do_handshake()
484 break
485 except ssl.SSLError as err:
486 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
487 select.select([s], [], [], 5.0)
488 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
489 select.select([], [s], [], 5.0)
490 else:
491 raise
492 # SSL established
493 self.assertTrue(s.getpeercert())
494 finally:
495 s.close()
496
Antoine Pitrou152efa22010-05-16 18:19:27 +0000497 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000498 with support.transient_internet("svn.python.org"):
499 # Same as test_connect, but with a separately created context
500 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
501 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
502 s.connect(("svn.python.org", 443))
503 try:
504 self.assertEqual({}, s.getpeercert())
505 finally:
506 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000507 # Same with a server hostname
508 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
509 server_hostname="svn.python.org")
510 if ssl.HAS_SNI:
511 s.connect(("svn.python.org", 443))
512 s.close()
513 else:
514 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000515 # This should fail because we have no verification certs
516 ctx.verify_mode = ssl.CERT_REQUIRED
517 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000518 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000519 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000520 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000521 # This should succeed because we specify the root cert
522 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
523 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
524 s.connect(("svn.python.org", 443))
525 try:
526 cert = s.getpeercert()
527 self.assertTrue(cert)
528 finally:
529 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000530
531 def test_connect_capath(self):
532 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000533 # NOTE: the subject hashing algorithm has been changed between
534 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
535 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000536 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000537 with support.transient_internet("svn.python.org"):
538 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
539 ctx.verify_mode = ssl.CERT_REQUIRED
540 ctx.load_verify_locations(capath=CAPATH)
541 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
542 s.connect(("svn.python.org", 443))
543 try:
544 cert = s.getpeercert()
545 self.assertTrue(cert)
546 finally:
547 s.close()
548 # Same with a bytes `capath` argument
549 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
550 ctx.verify_mode = ssl.CERT_REQUIRED
551 ctx.load_verify_locations(capath=BYTES_CAPATH)
552 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
553 s.connect(("svn.python.org", 443))
554 try:
555 cert = s.getpeercert()
556 self.assertTrue(cert)
557 finally:
558 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000559
Antoine Pitroue3220242010-04-24 11:13:53 +0000560 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
561 def test_makefile_close(self):
562 # Issue #5238: creating a file-like object with makefile() shouldn't
563 # delay closing the underlying "real socket" (here tested with its
564 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000565 with support.transient_internet("svn.python.org"):
566 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
567 ss.connect(("svn.python.org", 443))
568 fd = ss.fileno()
569 f = ss.makefile()
570 f.close()
571 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000572 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000573 # Closing the SSL socket should close the fd too
574 ss.close()
575 gc.collect()
576 with self.assertRaises(OSError) as e:
577 os.read(fd, 0)
578 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000579
Antoine Pitrou480a1242010-04-28 21:37:09 +0000580 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000581 with support.transient_internet("svn.python.org"):
582 s = socket.socket(socket.AF_INET)
583 s.connect(("svn.python.org", 443))
584 s.setblocking(False)
585 s = ssl.wrap_socket(s,
586 cert_reqs=ssl.CERT_NONE,
587 do_handshake_on_connect=False)
588 count = 0
589 while True:
590 try:
591 count += 1
592 s.do_handshake()
593 break
594 except ssl.SSLError as err:
595 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
596 select.select([s], [], [])
597 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
598 select.select([], [s], [])
599 else:
600 raise
601 s.close()
602 if support.verbose:
603 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000604
Antoine Pitrou480a1242010-04-28 21:37:09 +0000605 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000606 with support.transient_internet("svn.python.org"):
607 pem = ssl.get_server_certificate(("svn.python.org", 443))
608 if not pem:
609 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000610
Antoine Pitrou350c7222010-09-09 13:31:46 +0000611 try:
612 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
613 except ssl.SSLError as x:
614 #should fail
615 if support.verbose:
616 sys.stdout.write("%s\n" % x)
617 else:
618 self.fail("Got server certificate %s for svn.python.org!" % pem)
619
620 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
621 if not pem:
622 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000623 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000624 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000625
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000626 def test_ciphers(self):
627 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000628 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000629 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000630 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000631 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000632 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
633 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
634 s.connect(remote)
635 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000636 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000637 with socket.socket(socket.AF_INET) as sock:
638 s = ssl.wrap_socket(sock,
639 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
640 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000641
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000642 def test_algorithms(self):
643 # Issue #8484: all algorithms should be available when verifying a
644 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000645 # SHA256 was added in OpenSSL 0.9.8
646 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
647 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000648 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
649 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000650 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000651 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000652 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
653 cert_reqs=ssl.CERT_REQUIRED,
654 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000655 try:
656 s.connect(remote)
657 if support.verbose:
658 sys.stdout.write("\nCipher with %r is %r\n" %
659 (remote, s.cipher()))
660 sys.stdout.write("Certificate is:\n%s\n" %
661 pprint.pformat(s.getpeercert()))
662 finally:
663 s.close()
664
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665
666try:
667 import threading
668except ImportError:
669 _have_threads = False
670else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000671 _have_threads = True
672
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000673 from test.ssl_servers import make_https_server
674
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000675 class ThreadedEchoServer(threading.Thread):
676
677 class ConnectionHandler(threading.Thread):
678
679 """A mildly complicated class, because we want it to work both
680 with and without the SSL wrapper around the socket connection, so
681 that we can test the STARTTLS functionality."""
682
Bill Janssen6e027db2007-11-15 22:23:56 +0000683 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000684 self.server = server
685 self.running = False
686 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000687 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000688 self.sock.setblocking(1)
689 self.sslconn = None
690 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000691 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000692
Antoine Pitrou480a1242010-04-28 21:37:09 +0000693 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000694 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000695 self.sslconn = self.server.context.wrap_socket(
696 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000697 except ssl.SSLError:
698 # XXX Various errors can have happened here, for example
699 # a mismatching protocol version, an invalid certificate,
700 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000701 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000702 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000703 self.running = False
704 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000705 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000706 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000707 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000708 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000709 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000710 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000711 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
712 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000713 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000714 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
715 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000716 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000717 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
718 return True
719
720 def read(self):
721 if self.sslconn:
722 return self.sslconn.read()
723 else:
724 return self.sock.recv(1024)
725
726 def write(self, bytes):
727 if self.sslconn:
728 return self.sslconn.write(bytes)
729 else:
730 return self.sock.send(bytes)
731
732 def close(self):
733 if self.sslconn:
734 self.sslconn.close()
735 else:
736 self.sock.close()
737
Antoine Pitrou480a1242010-04-28 21:37:09 +0000738 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 self.running = True
740 if not self.server.starttls_server:
741 if not self.wrap_conn():
742 return
743 while self.running:
744 try:
745 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000746 stripped = msg.strip()
747 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000748 # eof, so quit this handler
749 self.running = False
750 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000751 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000752 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000753 sys.stdout.write(" server: client closed connection\n")
754 self.close()
755 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000756 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000757 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000758 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000759 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000760 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000761 if not self.wrap_conn():
762 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000763 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000764 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000765 if support.verbose and self.server.connectionchatty:
766 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000767 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000768 self.sock = self.sslconn.unwrap()
769 self.sslconn = None
770 if support.verbose and self.server.connectionchatty:
771 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000772 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000773 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000774 self.server.connectionchatty):
775 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000776 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
777 % (msg, ctype, msg.lower(), ctype))
778 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000779 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000780 if self.server.chatty:
781 handle_error("Test server failure:\n")
782 self.close()
783 self.running = False
784 # normally, we'd just stop here, but for the test
785 # harness, we want to stop the server
786 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787
Antoine Pitroub5218772010-05-21 09:56:06 +0000788 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000789 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000790 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000791 ciphers=None, context=None):
792 if context:
793 self.context = context
794 else:
795 self.context = ssl.SSLContext(ssl_version
796 if ssl_version is not None
797 else ssl.PROTOCOL_TLSv1)
798 self.context.verify_mode = (certreqs if certreqs is not None
799 else ssl.CERT_NONE)
800 if cacerts:
801 self.context.load_verify_locations(cacerts)
802 if certificate:
803 self.context.load_cert_chain(certificate)
804 if ciphers:
805 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000806 self.chatty = chatty
807 self.connectionchatty = connectionchatty
808 self.starttls_server = starttls_server
809 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000810 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000811 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000812 self.active = False
813 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000814 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000815
Antoine Pitrou480a1242010-04-28 21:37:09 +0000816 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000817 self.flag = flag
818 threading.Thread.start(self)
819
Antoine Pitrou480a1242010-04-28 21:37:09 +0000820 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000821 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000822 self.sock.listen(5)
823 self.active = True
824 if self.flag:
825 # signal an event
826 self.flag.set()
827 while self.active:
828 try:
829 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000830 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000831 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000832 + repr(connaddr) + '\n')
833 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000834 handler.start()
835 except socket.timeout:
836 pass
837 except KeyboardInterrupt:
838 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000839 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000840
Antoine Pitrou480a1242010-04-28 21:37:09 +0000841 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000843
Bill Janssen54cc54c2007-12-14 22:08:56 +0000844 class AsyncoreEchoServer(threading.Thread):
845
846 # this one's based on asyncore.dispatcher
847
848 class EchoServer (asyncore.dispatcher):
849
850 class ConnectionHandler (asyncore.dispatcher_with_send):
851
852 def __init__(self, conn, certfile):
853 self.socket = ssl.wrap_socket(conn, server_side=True,
854 certfile=certfile,
855 do_handshake_on_connect=False)
856 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000857 self._ssl_accepting = True
858 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000859
860 def readable(self):
861 if isinstance(self.socket, ssl.SSLSocket):
862 while self.socket.pending() > 0:
863 self.handle_read_event()
864 return True
865
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000866 def _do_ssl_handshake(self):
867 try:
868 self.socket.do_handshake()
869 except ssl.SSLError as err:
870 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
871 ssl.SSL_ERROR_WANT_WRITE):
872 return
873 elif err.args[0] == ssl.SSL_ERROR_EOF:
874 return self.handle_close()
875 raise
876 except socket.error as err:
877 if err.args[0] == errno.ECONNABORTED:
878 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000879 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000880 self._ssl_accepting = False
881
882 def handle_read(self):
883 if self._ssl_accepting:
884 self._do_ssl_handshake()
885 else:
886 data = self.recv(1024)
887 if support.verbose:
888 sys.stdout.write(" server: read %s from client\n" % repr(data))
889 if not data:
890 self.close()
891 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000892 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000893
894 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000895 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000896 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000897 sys.stdout.write(" server: closed connection %s\n" % self.socket)
898
899 def handle_error(self):
900 raise
901
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000902 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000903 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000904 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
905 self.port = support.bind_port(sock, '')
906 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000907 self.listen(5)
908
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000909 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000910 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000911 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
912 self.ConnectionHandler(sock_obj, self.certfile)
913
914 def handle_error(self):
915 raise
916
Trent Nelson78520002008-04-10 20:54:35 +0000917 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000918 self.flag = None
919 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000920 self.server = self.EchoServer(certfile)
921 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000922 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000923 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000924
925 def __str__(self):
926 return "<%s %s>" % (self.__class__.__name__, self.server)
927
928 def start (self, flag=None):
929 self.flag = flag
930 threading.Thread.start(self)
931
Antoine Pitrou480a1242010-04-28 21:37:09 +0000932 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000933 self.active = True
934 if self.flag:
935 self.flag.set()
936 while self.active:
937 try:
938 asyncore.loop(1)
939 except:
940 pass
941
Antoine Pitrou480a1242010-04-28 21:37:09 +0000942 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000943 self.active = False
944 self.server.close()
945
Antoine Pitrou480a1242010-04-28 21:37:09 +0000946 def bad_cert_test(certfile):
947 """
948 Launch a server with CERT_REQUIRED, and check that trying to
949 connect to it with the given client certificate fails.
950 """
Trent Nelson78520002008-04-10 20:54:35 +0000951 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000952 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000953 cacerts=CERTFILE, chatty=False,
954 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 flag = threading.Event()
956 server.start(flag)
957 # wait for it to start
958 flag.wait()
959 # try to connect
960 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000961 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000962 with socket.socket() as sock:
963 s = ssl.wrap_socket(sock,
964 certfile=certfile,
965 ssl_version=ssl.PROTOCOL_TLSv1)
966 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000967 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000968 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000969 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000970 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000971 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +0000972 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000973 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000974 if x.errno != errno.ENOENT:
975 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000976 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000977 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000979 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980 finally:
981 server.stop()
982 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000983
Antoine Pitroub5218772010-05-21 09:56:06 +0000984 def server_params_test(client_context, server_context, indata=b"FOO\n",
985 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000986 """
987 Launch a server, connect a client to it and try various reads
988 and writes.
989 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000990 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000992 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000993 flag = threading.Event()
994 server.start(flag)
995 # wait for it to start
996 flag.wait()
997 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000999 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001000 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001002 if connectionchatty:
1003 if support.verbose:
1004 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001005 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001006 s.write(arg)
1007 outdata = s.read()
1008 if connectionchatty:
1009 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001010 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001011 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001012 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001013 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1014 % (outdata[:20], len(outdata),
1015 indata[:20].lower(), len(indata)))
1016 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001017 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001018 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001019 sys.stdout.write(" client: closing connection.\n")
1020 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001021 finally:
1022 server.stop()
1023 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001024
Antoine Pitroub5218772010-05-21 09:56:06 +00001025 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1026 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001027 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001028 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001029 certtype = {
1030 ssl.CERT_NONE: "CERT_NONE",
1031 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1032 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1033 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001034 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001035 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001036 sys.stdout.write(formatstr %
1037 (ssl.get_protocol_name(client_protocol),
1038 ssl.get_protocol_name(server_protocol),
1039 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001040 client_context = ssl.SSLContext(client_protocol)
1041 client_context.options = ssl.OP_ALL | client_options
1042 server_context = ssl.SSLContext(server_protocol)
1043 server_context.options = ssl.OP_ALL | server_options
1044 for ctx in (client_context, server_context):
1045 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001046 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1047 # will send an SSLv3 hello (rather than SSLv2) starting from
1048 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001049 ctx.set_ciphers("ALL")
1050 ctx.load_cert_chain(CERTFILE)
1051 ctx.load_verify_locations(CERTFILE)
1052 try:
1053 server_params_test(client_context, server_context,
1054 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001055 # Protocol mismatch can result in either an SSLError, or a
1056 # "Connection reset by peer" error.
1057 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001058 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001059 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001060 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001061 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001062 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001063 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001064 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001065 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 "Client protocol %s succeeded with server protocol %s!"
1067 % (ssl.get_protocol_name(client_protocol),
1068 ssl.get_protocol_name(server_protocol)))
1069
1070
Bill Janssen6e027db2007-11-15 22:23:56 +00001071 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001072
Antoine Pitrou23df4832010-08-04 17:14:06 +00001073 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001074 def test_echo(self):
1075 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001076 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001078 for protocol in PROTOCOLS:
1079 context = ssl.SSLContext(protocol)
1080 context.load_cert_chain(CERTFILE)
1081 server_params_test(context, context,
1082 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001083
Antoine Pitrou480a1242010-04-28 21:37:09 +00001084 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001085 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001087 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1088 context.verify_mode = ssl.CERT_REQUIRED
1089 context.load_verify_locations(CERTFILE)
1090 context.load_cert_chain(CERTFILE)
1091 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001092 flag = threading.Event()
1093 server.start(flag)
1094 # wait for it to start
1095 flag.wait()
1096 # try to connect
1097 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001098 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001099 s.connect((HOST, server.port))
1100 cert = s.getpeercert()
1101 self.assertTrue(cert, "Can't get peer certificate.")
1102 cipher = s.cipher()
1103 if support.verbose:
1104 sys.stdout.write(pprint.pformat(cert) + '\n')
1105 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1106 if 'subject' not in cert:
1107 self.fail("No subject field in certificate: %s." %
1108 pprint.pformat(cert))
1109 if ((('organizationName', 'Python Software Foundation'),)
1110 not in cert['subject']):
1111 self.fail(
1112 "Missing or invalid 'organizationName' field in certificate subject; "
1113 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001114 self.assertIn('notBefore', cert)
1115 self.assertIn('notAfter', cert)
1116 before = ssl.cert_time_to_seconds(cert['notBefore'])
1117 after = ssl.cert_time_to_seconds(cert['notAfter'])
1118 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001119 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001120 finally:
1121 server.stop()
1122 server.join()
1123
Antoine Pitrou480a1242010-04-28 21:37:09 +00001124 def test_empty_cert(self):
1125 """Connecting with an empty cert file"""
1126 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1127 "nullcert.pem"))
1128 def test_malformed_cert(self):
1129 """Connecting with a badly formatted certificate (syntax error)"""
1130 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1131 "badcert.pem"))
1132 def test_nonexisting_cert(self):
1133 """Connecting with a non-existing cert file"""
1134 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1135 "wrongcert.pem"))
1136 def test_malformed_key(self):
1137 """Connecting with a badly formatted key (syntax error)"""
1138 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1139 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 def test_rude_shutdown(self):
1142 """A brutal shutdown of an SSL server should raise an IOError
1143 in the client when attempting handshake.
1144 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001145 listener_ready = threading.Event()
1146 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001147
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001148 s = socket.socket()
1149 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001150
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001151 # `listener` runs in a thread. It sits in an accept() until
1152 # the main thread connects. Then it rudely closes the socket,
1153 # and sets Event `listener_gone` to let the main thread know
1154 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001155 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001156 s.listen(5)
1157 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001158 newsock, addr = s.accept()
1159 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001160 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001161 listener_gone.set()
1162
1163 def connector():
1164 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001165 with socket.socket() as c:
1166 c.connect((HOST, port))
1167 listener_gone.wait()
1168 try:
1169 ssl_sock = ssl.wrap_socket(c)
1170 except IOError:
1171 pass
1172 else:
1173 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001174
1175 t = threading.Thread(target=listener)
1176 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001177 try:
1178 connector()
1179 finally:
1180 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001181
Antoine Pitrou23df4832010-08-04 17:14:06 +00001182 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001183 def test_protocol_sslv2(self):
1184 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001185 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001186 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001187 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1188 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1189 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1190 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1191 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1192 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001193 # SSLv23 client with specific SSL options
1194 if no_sslv2_implies_sslv3_hello():
1195 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1196 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1197 client_options=ssl.OP_NO_SSLv2)
1198 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1199 client_options=ssl.OP_NO_SSLv3)
1200 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1201 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001202
Antoine Pitrou23df4832010-08-04 17:14:06 +00001203 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001204 def test_protocol_sslv23(self):
1205 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001206 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001207 sys.stdout.write("\n")
1208 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001209 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001210 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001212 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001213 sys.stdout.write(
1214 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1215 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001216 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1217 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1218 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001219
Antoine Pitrou480a1242010-04-28 21:37:09 +00001220 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1221 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1222 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001223
Antoine Pitrou480a1242010-04-28 21:37:09 +00001224 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1225 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1226 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001227
Antoine Pitroub5218772010-05-21 09:56:06 +00001228 # Server with specific SSL options
1229 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1230 server_options=ssl.OP_NO_SSLv3)
1231 # Will choose TLSv1
1232 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1233 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1234 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1235 server_options=ssl.OP_NO_TLSv1)
1236
1237
Antoine Pitrou23df4832010-08-04 17:14:06 +00001238 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001239 def test_protocol_sslv3(self):
1240 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001241 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001242 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001243 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1244 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1245 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1246 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1247 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1248 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001249 if no_sslv2_implies_sslv3_hello():
1250 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1251 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1252 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001253
Antoine Pitrou23df4832010-08-04 17:14:06 +00001254 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001255 def test_protocol_tlsv1(self):
1256 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001257 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001258 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001259 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1260 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1261 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1262 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1263 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1264 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001265
Antoine Pitrou480a1242010-04-28 21:37:09 +00001266 def test_starttls(self):
1267 """Switching from clear text to encrypted and back again."""
1268 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 +00001269
Trent Nelson78520002008-04-10 20:54:35 +00001270 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001271 ssl_version=ssl.PROTOCOL_TLSv1,
1272 starttls_server=True,
1273 chatty=True,
1274 connectionchatty=True)
1275 flag = threading.Event()
1276 server.start(flag)
1277 # wait for it to start
1278 flag.wait()
1279 # try to connect
1280 wrapped = False
1281 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001282 s = socket.socket()
1283 s.setblocking(1)
1284 s.connect((HOST, server.port))
1285 if support.verbose:
1286 sys.stdout.write("\n")
1287 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001288 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001289 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001290 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001291 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001292 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001293 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001294 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001295 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001296 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001297 msg = outdata.strip().lower()
1298 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1299 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001300 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001301 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001302 " client: read %r from server, starting TLS...\n"
1303 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001304 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1305 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001306 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1307 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001308 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001309 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001310 " client: read %r from server, ending TLS...\n"
1311 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001312 s = conn.unwrap()
1313 wrapped = False
1314 else:
1315 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001316 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001317 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001318 if support.verbose:
1319 sys.stdout.write(" client: closing connection.\n")
1320 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001321 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001322 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001323 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001324 if wrapped:
1325 conn.close()
1326 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001327 s.close()
1328 finally:
1329 server.stop()
1330 server.join()
1331
Antoine Pitrou480a1242010-04-28 21:37:09 +00001332 def test_socketserver(self):
1333 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001334 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001335 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001336 if support.verbose:
1337 sys.stdout.write('\n')
1338 with open(CERTFILE, 'rb') as f:
1339 d1 = f.read()
1340 d2 = ''
1341 # now fetch the same data from the HTTPS server
1342 url = 'https://%s:%d/%s' % (
1343 HOST, server.port, os.path.split(CERTFILE)[1])
1344 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001345 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001346 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001347 if dlen and (int(dlen) > 0):
1348 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001349 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001350 sys.stdout.write(
1351 " client: read %d bytes from remote server '%s'\n"
1352 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001353 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001354 f.close()
1355 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001356
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 def test_asyncore_server(self):
1358 """Check the example asyncore integration."""
1359 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001360
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001361 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001362 sys.stdout.write("\n")
1363
Antoine Pitrou480a1242010-04-28 21:37:09 +00001364 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001365 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001366 flag = threading.Event()
1367 server.start(flag)
1368 # wait for it to start
1369 flag.wait()
1370 # try to connect
1371 try:
1372 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001373 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001374 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001375 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 " client: sending %r...\n" % indata)
1377 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001378 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001379 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001381 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001382 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1384 % (outdata[:20], len(outdata),
1385 indata[:20].lower(), len(indata)))
1386 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001387 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001388 sys.stdout.write(" client: closing connection.\n")
1389 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001390 if support.verbose:
1391 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001392 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001393 if support.verbose:
1394 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001395 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001396 if support.verbose:
1397 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001398 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001399 if support.verbose:
1400 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001401
Antoine Pitrou480a1242010-04-28 21:37:09 +00001402 def test_recv_send(self):
1403 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001404 if support.verbose:
1405 sys.stdout.write("\n")
1406
1407 server = ThreadedEchoServer(CERTFILE,
1408 certreqs=ssl.CERT_NONE,
1409 ssl_version=ssl.PROTOCOL_TLSv1,
1410 cacerts=CERTFILE,
1411 chatty=True,
1412 connectionchatty=False)
1413 flag = threading.Event()
1414 server.start(flag)
1415 # wait for it to start
1416 flag.wait()
1417 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001418 s = ssl.wrap_socket(socket.socket(),
1419 server_side=False,
1420 certfile=CERTFILE,
1421 ca_certs=CERTFILE,
1422 cert_reqs=ssl.CERT_NONE,
1423 ssl_version=ssl.PROTOCOL_TLSv1)
1424 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001425 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001426 # helper methods for standardising recv* method signatures
1427 def _recv_into():
1428 b = bytearray(b"\0"*100)
1429 count = s.recv_into(b)
1430 return b[:count]
1431
1432 def _recvfrom_into():
1433 b = bytearray(b"\0"*100)
1434 count, addr = s.recvfrom_into(b)
1435 return b[:count]
1436
1437 # (name, method, whether to expect success, *args)
1438 send_methods = [
1439 ('send', s.send, True, []),
1440 ('sendto', s.sendto, False, ["some.address"]),
1441 ('sendall', s.sendall, True, []),
1442 ]
1443 recv_methods = [
1444 ('recv', s.recv, True, []),
1445 ('recvfrom', s.recvfrom, False, ["some.address"]),
1446 ('recv_into', _recv_into, True, []),
1447 ('recvfrom_into', _recvfrom_into, False, []),
1448 ]
1449 data_prefix = "PREFIX_"
1450
1451 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001452 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001453 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001454 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001455 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001456 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001457 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001458 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001459 "<<{outdata:r}>> ({nout:d}) received; "
1460 "expected <<{indata:r}>> ({nin:d})\n".format(
1461 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001462 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001463 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001464 )
1465 )
1466 except ValueError as e:
1467 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001468 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001469 "Failed to send with method <<{name:s}>>; "
1470 "expected to succeed.\n".format(name=meth_name)
1471 )
1472 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001473 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001474 "Method <<{name:s}>> failed with unexpected "
1475 "exception message: {exp:s}\n".format(
1476 name=meth_name, exp=e
1477 )
1478 )
1479
1480 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001481 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001482 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001483 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001484 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001485 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001486 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001487 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001488 "<<{outdata:r}>> ({nout:d}) received; "
1489 "expected <<{indata:r}>> ({nin:d})\n".format(
1490 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001491 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001493 )
1494 )
1495 except ValueError as e:
1496 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001497 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001498 "Failed to receive with method <<{name:s}>>; "
1499 "expected to succeed.\n".format(name=meth_name)
1500 )
1501 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001502 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001503 "Method <<{name:s}>> failed with unexpected "
1504 "exception message: {exp:s}\n".format(
1505 name=meth_name, exp=e
1506 )
1507 )
1508 # consume data
1509 s.read()
1510
Antoine Pitrou480a1242010-04-28 21:37:09 +00001511 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001512 s.close()
1513 finally:
1514 server.stop()
1515 server.join()
1516
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001517 def test_handshake_timeout(self):
1518 # Issue #5103: SSL handshake must respect the socket timeout
1519 server = socket.socket(socket.AF_INET)
1520 host = "127.0.0.1"
1521 port = support.bind_port(server)
1522 started = threading.Event()
1523 finish = False
1524
1525 def serve():
1526 server.listen(5)
1527 started.set()
1528 conns = []
1529 while not finish:
1530 r, w, e = select.select([server], [], [], 0.1)
1531 if server in r:
1532 # Let the socket hang around rather than having
1533 # it closed by garbage collection.
1534 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001535 for sock in conns:
1536 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001537
1538 t = threading.Thread(target=serve)
1539 t.start()
1540 started.wait()
1541
1542 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001543 try:
1544 c = socket.socket(socket.AF_INET)
1545 c.settimeout(0.2)
1546 c.connect((host, port))
1547 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001548 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001549 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001550 finally:
1551 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001552 try:
1553 c = socket.socket(socket.AF_INET)
1554 c = ssl.wrap_socket(c)
1555 c.settimeout(0.2)
1556 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001557 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001558 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001559 finally:
1560 c.close()
1561 finally:
1562 finish = True
1563 t.join()
1564 server.close()
1565
Bill Janssen58afe4c2008-09-08 16:45:19 +00001566
Thomas Woutersed03b412007-08-28 21:37:11 +00001567def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001568 if support.verbose:
1569 plats = {
1570 'Linux': platform.linux_distribution,
1571 'Mac': platform.mac_ver,
1572 'Windows': platform.win32_ver,
1573 }
1574 for name, func in plats.items():
1575 plat = func()
1576 if plat and plat[0]:
1577 plat = '%s %r' % (name, plat)
1578 break
1579 else:
1580 plat = repr(platform.platform())
1581 print("test_ssl: testing with %r %r" %
1582 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1583 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001584 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001585
Antoine Pitrou152efa22010-05-16 18:19:27 +00001586 for filename in [
1587 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1588 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1589 BADCERT, BADKEY, EMPTYCERT]:
1590 if not os.path.exists(filename):
1591 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001592
Antoine Pitrou152efa22010-05-16 18:19:27 +00001593 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001594
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001595 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001596 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001597
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001598 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001599 thread_info = support.threading_setup()
1600 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001601 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001602
Antoine Pitrou480a1242010-04-28 21:37:09 +00001603 try:
1604 support.run_unittest(*tests)
1605 finally:
1606 if _have_threads:
1607 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001608
1609if __name__ == "__main__":
1610 test_main()