blob: 8c219756e1f0e96b2adddeba98264bf03057f125 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
23PROTOCOLS = [
Victor Stinner3de49192011-05-09 00:42:58 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner3de49192011-05-09 00:42:58 +020027if hasattr(ssl, 'PROTOCOL_SSLv2'):
28 PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
Thomas Woutersed03b412007-08-28 21:37:11 +000029
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Antoine Pitrou81564092010-10-08 23:06:24 +000034# The custom key and certificate files used in test_ssl are generated
35# using Lib/test/make_ssl_certs.py.
36# Other certificates are simply fetched from the Internet servers they
37# are meant to authenticate.
38
Antoine Pitrou152efa22010-05-16 18:19:27 +000039CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
54
Thomas Woutersed03b412007-08-28 21:37:11 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056def handle_error(prefix):
57 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000059 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitroub5218772010-05-21 09:56:06 +000061def can_clear_options():
62 # 0.9.8m or higher
63 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
64
65def no_sslv2_implies_sslv3_hello():
66 # 0.9.7h or higher
67 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
68
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou23df4832010-08-04 17:14:06 +000070# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
71def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020072 if hasattr(ssl, 'PROTOCOL_SSLv2'):
73 @functools.wraps(func)
74 def f(*args, **kwargs):
75 try:
76 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
77 except ssl.SSLError:
78 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
79 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
80 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
81 return func(*args, **kwargs)
82 return f
83 else:
84 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000085
86
Antoine Pitrou152efa22010-05-16 18:19:27 +000087class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000088
Antoine Pitrou480a1242010-04-28 21:37:09 +000089 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020090 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000091 ssl.PROTOCOL_SSLv23
92 ssl.PROTOCOL_SSLv3
93 ssl.PROTOCOL_TLSv1
94 ssl.CERT_NONE
95 ssl.CERT_OPTIONAL
96 ssl.CERT_REQUIRED
Antoine Pitroud5323212010-10-22 18:19:07 +000097 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +000098
Antoine Pitrou480a1242010-04-28 21:37:09 +000099 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000100 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000101 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102 sys.stdout.write("\n RAND_status is %d (%s)\n"
103 % (v, (v and "sufficient randomness") or
104 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200105
106 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
107 self.assertEqual(len(data), 16)
108 self.assertEqual(is_cryptographic, v == 1)
109 if v:
110 data = ssl.RAND_bytes(16)
111 self.assertEqual(len(data), 16)
112
Thomas Woutersed03b412007-08-28 21:37:11 +0000113 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 ssl.RAND_egd(1)
115 except TypeError:
116 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000117 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000118 print("didn't raise TypeError")
119 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000120
Antoine Pitrou480a1242010-04-28 21:37:09 +0000121 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000122 # note that this uses an 'unofficial' function in _ssl.c,
123 # provided solely for this test, to exercise the certificate
124 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000125 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000126 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000128
Antoine Pitrou480a1242010-04-28 21:37:09 +0000129 def test_DER_to_PEM(self):
130 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
131 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132 d1 = ssl.PEM_cert_to_DER_cert(pem)
133 p2 = ssl.DER_cert_to_PEM_cert(d1)
134 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000135 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000136 if not p2.startswith(ssl.PEM_HEADER + '\n'):
137 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
138 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
139 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000140
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000141 def test_openssl_version(self):
142 n = ssl.OPENSSL_VERSION_NUMBER
143 t = ssl.OPENSSL_VERSION_INFO
144 s = ssl.OPENSSL_VERSION
145 self.assertIsInstance(n, int)
146 self.assertIsInstance(t, tuple)
147 self.assertIsInstance(s, str)
148 # Some sanity checks follow
149 # >= 0.9
150 self.assertGreaterEqual(n, 0x900000)
151 # < 2.0
152 self.assertLess(n, 0x20000000)
153 major, minor, fix, patch, status = t
154 self.assertGreaterEqual(major, 0)
155 self.assertLess(major, 2)
156 self.assertGreaterEqual(minor, 0)
157 self.assertLess(minor, 256)
158 self.assertGreaterEqual(fix, 0)
159 self.assertLess(fix, 256)
160 self.assertGreaterEqual(patch, 0)
161 self.assertLessEqual(patch, 26)
162 self.assertGreaterEqual(status, 0)
163 self.assertLessEqual(status, 15)
164 # Version string as returned by OpenSSL, the format might change
165 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
166 (s, t))
167
Antoine Pitrou9d543662010-04-23 23:10:32 +0000168 @support.cpython_only
169 def test_refcycle(self):
170 # Issue #7943: an SSL object doesn't create reference cycles with
171 # itself.
172 s = socket.socket(socket.AF_INET)
173 ss = ssl.wrap_socket(s)
174 wr = weakref.ref(ss)
175 del ss
176 self.assertEqual(wr(), None)
177
Antoine Pitroua468adc2010-09-14 14:43:44 +0000178 def test_wrapped_unconnected(self):
179 # Methods on an unconnected SSLSocket propagate the original
180 # socket.error raise by the underlying socket object.
181 s = socket.socket(socket.AF_INET)
182 ss = ssl.wrap_socket(s)
183 self.assertRaises(socket.error, ss.recv, 1)
184 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
185 self.assertRaises(socket.error, ss.recvfrom, 1)
186 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
187 self.assertRaises(socket.error, ss.send, b'x')
188 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
189
Antoine Pitrou40f08742010-04-24 22:04:40 +0000190 def test_timeout(self):
191 # Issue #8524: when creating an SSL socket, the timeout of the
192 # original socket should be retained.
193 for timeout in (None, 0.0, 5.0):
194 s = socket.socket(socket.AF_INET)
195 s.settimeout(timeout)
196 ss = ssl.wrap_socket(s)
197 self.assertEqual(timeout, ss.gettimeout())
198
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000199 def test_errors(self):
200 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000201 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000202 "certfile must be specified",
203 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000204 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000205 "certfile must be specified for server-side operations",
206 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000207 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000208 "certfile must be specified for server-side operations",
209 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000210 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000211 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000212 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000213 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000214 with socket.socket() as sock:
215 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000216 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000217 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000218 with socket.socket() as sock:
219 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000220 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000221 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000222 with socket.socket() as sock:
223 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000224 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000225
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000226 def test_match_hostname(self):
227 def ok(cert, hostname):
228 ssl.match_hostname(cert, hostname)
229 def fail(cert, hostname):
230 self.assertRaises(ssl.CertificateError,
231 ssl.match_hostname, cert, hostname)
232
233 cert = {'subject': ((('commonName', 'example.com'),),)}
234 ok(cert, 'example.com')
235 ok(cert, 'ExAmple.cOm')
236 fail(cert, 'www.example.com')
237 fail(cert, '.example.com')
238 fail(cert, 'example.org')
239 fail(cert, 'exampleXcom')
240
241 cert = {'subject': ((('commonName', '*.a.com'),),)}
242 ok(cert, 'foo.a.com')
243 fail(cert, 'bar.foo.a.com')
244 fail(cert, 'a.com')
245 fail(cert, 'Xa.com')
246 fail(cert, '.a.com')
247
248 cert = {'subject': ((('commonName', 'a.*.com'),),)}
249 ok(cert, 'a.foo.com')
250 fail(cert, 'a..com')
251 fail(cert, 'a.com')
252
253 cert = {'subject': ((('commonName', 'f*.com'),),)}
254 ok(cert, 'foo.com')
255 ok(cert, 'f.com')
256 fail(cert, 'bar.com')
257 fail(cert, 'foo.a.com')
258 fail(cert, 'bar.foo.com')
259
260 # Slightly fake real-world example
261 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
262 'subject': ((('commonName', 'linuxfrz.org'),),),
263 'subjectAltName': (('DNS', 'linuxfr.org'),
264 ('DNS', 'linuxfr.com'),
265 ('othername', '<unsupported>'))}
266 ok(cert, 'linuxfr.org')
267 ok(cert, 'linuxfr.com')
268 # Not a "DNS" entry
269 fail(cert, '<unsupported>')
270 # When there is a subjectAltName, commonName isn't used
271 fail(cert, 'linuxfrz.org')
272
273 # A pristine real-world example
274 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
275 'subject': ((('countryName', 'US'),),
276 (('stateOrProvinceName', 'California'),),
277 (('localityName', 'Mountain View'),),
278 (('organizationName', 'Google Inc'),),
279 (('commonName', 'mail.google.com'),))}
280 ok(cert, 'mail.google.com')
281 fail(cert, 'gmail.com')
282 # Only commonName is considered
283 fail(cert, 'California')
284
285 # Neither commonName nor subjectAltName
286 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
287 'subject': ((('countryName', 'US'),),
288 (('stateOrProvinceName', 'California'),),
289 (('localityName', 'Mountain View'),),
290 (('organizationName', 'Google Inc'),))}
291 fail(cert, 'mail.google.com')
292
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200293 # No DNS entry in subjectAltName but a commonName
294 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
295 'subject': ((('countryName', 'US'),),
296 (('stateOrProvinceName', 'California'),),
297 (('localityName', 'Mountain View'),),
298 (('commonName', 'mail.google.com'),)),
299 'subjectAltName': (('othername', 'blabla'), )}
300 ok(cert, 'mail.google.com')
301
302 # No DNS entry subjectAltName and no commonName
303 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
304 'subject': ((('countryName', 'US'),),
305 (('stateOrProvinceName', 'California'),),
306 (('localityName', 'Mountain View'),),
307 (('organizationName', 'Google Inc'),)),
308 'subjectAltName': (('othername', 'blabla'),)}
309 fail(cert, 'google.com')
310
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000311 # Empty cert / no cert
312 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
313 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
314
Antoine Pitroud5323212010-10-22 18:19:07 +0000315 def test_server_side(self):
316 # server_hostname doesn't work for server sockets
317 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000318 with socket.socket() as sock:
319 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
320 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000321
Antoine Pitrou152efa22010-05-16 18:19:27 +0000322class ContextTests(unittest.TestCase):
323
Antoine Pitrou23df4832010-08-04 17:14:06 +0000324 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000325 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200326 if hasattr(ssl, 'PROTOCOL_SSLv2'):
327 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000328 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
329 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
330 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
331 self.assertRaises(TypeError, ssl.SSLContext)
332 self.assertRaises(ValueError, ssl.SSLContext, -1)
333 self.assertRaises(ValueError, ssl.SSLContext, 42)
334
Antoine Pitrou23df4832010-08-04 17:14:06 +0000335 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000336 def test_protocol(self):
337 for proto in PROTOCOLS:
338 ctx = ssl.SSLContext(proto)
339 self.assertEqual(ctx.protocol, proto)
340
341 def test_ciphers(self):
342 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
343 ctx.set_ciphers("ALL")
344 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000345 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000346 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000347
Antoine Pitrou23df4832010-08-04 17:14:06 +0000348 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000349 def test_options(self):
350 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
351 # OP_ALL is the default value
352 self.assertEqual(ssl.OP_ALL, ctx.options)
353 ctx.options |= ssl.OP_NO_SSLv2
354 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
355 ctx.options)
356 ctx.options |= ssl.OP_NO_SSLv3
357 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
358 ctx.options)
359 if can_clear_options():
360 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
361 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
362 ctx.options)
363 ctx.options = 0
364 self.assertEqual(0, ctx.options)
365 else:
366 with self.assertRaises(ValueError):
367 ctx.options = 0
368
Antoine Pitrou152efa22010-05-16 18:19:27 +0000369 def test_verify(self):
370 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
371 # Default value
372 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
373 ctx.verify_mode = ssl.CERT_OPTIONAL
374 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
375 ctx.verify_mode = ssl.CERT_REQUIRED
376 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
377 ctx.verify_mode = ssl.CERT_NONE
378 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
379 with self.assertRaises(TypeError):
380 ctx.verify_mode = None
381 with self.assertRaises(ValueError):
382 ctx.verify_mode = 42
383
384 def test_load_cert_chain(self):
385 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
386 # Combined key and cert in a single file
387 ctx.load_cert_chain(CERTFILE)
388 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
389 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000390 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000391 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000392 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000393 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000394 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000395 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000396 ctx.load_cert_chain(EMPTYCERT)
397 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000398 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000399 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
400 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
401 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000402 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000403 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000404 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000405 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000406 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000407 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
408 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000409 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000410 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000411 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000412
413 def test_load_verify_locations(self):
414 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
415 ctx.load_verify_locations(CERTFILE)
416 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
417 ctx.load_verify_locations(BYTES_CERTFILE)
418 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
419 self.assertRaises(TypeError, ctx.load_verify_locations)
420 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000421 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000422 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000423 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000424 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000425 ctx.load_verify_locations(BADCERT)
426 ctx.load_verify_locations(CERTFILE, CAPATH)
427 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
428
Victor Stinner80f75e62011-01-29 11:31:20 +0000429 # Issue #10989: crash if the second argument type is invalid
430 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
431
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000432 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000433 def test_session_stats(self):
434 for proto in PROTOCOLS:
435 ctx = ssl.SSLContext(proto)
436 self.assertEqual(ctx.session_stats(), {
437 'number': 0,
438 'connect': 0,
439 'connect_good': 0,
440 'connect_renegotiate': 0,
441 'accept': 0,
442 'accept_good': 0,
443 'accept_renegotiate': 0,
444 'hits': 0,
445 'misses': 0,
446 'timeouts': 0,
447 'cache_full': 0,
448 })
449
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000450 def test_set_default_verify_paths(self):
451 # There's not much we can do to test that it acts as expected,
452 # so just check it doesn't crash or raise an exception.
453 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
454 ctx.set_default_verify_paths()
455
Antoine Pitrou152efa22010-05-16 18:19:27 +0000456
Bill Janssen6e027db2007-11-15 22:23:56 +0000457class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000458
Antoine Pitrou480a1242010-04-28 21:37:09 +0000459 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000460 with support.transient_internet("svn.python.org"):
461 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
462 cert_reqs=ssl.CERT_NONE)
463 try:
464 s.connect(("svn.python.org", 443))
465 self.assertEqual({}, s.getpeercert())
466 finally:
467 s.close()
468
469 # this should fail because we have no verification certs
470 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
471 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000472 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
473 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000474 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000475
Antoine Pitrou350c7222010-09-09 13:31:46 +0000476 # this should succeed because we specify the root cert
477 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
478 cert_reqs=ssl.CERT_REQUIRED,
479 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
480 try:
481 s.connect(("svn.python.org", 443))
482 self.assertTrue(s.getpeercert())
483 finally:
484 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000485
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000486 def test_connect_ex(self):
487 # Issue #11326: check connect_ex() implementation
488 with support.transient_internet("svn.python.org"):
489 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
490 cert_reqs=ssl.CERT_REQUIRED,
491 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
492 try:
493 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
494 self.assertTrue(s.getpeercert())
495 finally:
496 s.close()
497
498 def test_non_blocking_connect_ex(self):
499 # Issue #11326: non-blocking connect_ex() should allow handshake
500 # to proceed after the socket gets ready.
501 with support.transient_internet("svn.python.org"):
502 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
503 cert_reqs=ssl.CERT_REQUIRED,
504 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
505 do_handshake_on_connect=False)
506 try:
507 s.setblocking(False)
508 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000509 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
510 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000511 # Wait for connect to finish
512 select.select([], [s], [], 5.0)
513 # Non-blocking handshake
514 while True:
515 try:
516 s.do_handshake()
517 break
518 except ssl.SSLError as err:
519 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
520 select.select([s], [], [], 5.0)
521 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
522 select.select([], [s], [], 5.0)
523 else:
524 raise
525 # SSL established
526 self.assertTrue(s.getpeercert())
527 finally:
528 s.close()
529
Antoine Pitroub4410db2011-05-18 18:51:06 +0200530 def test_timeout_connect_ex(self):
531 # Issue #12065: on a timeout, connect_ex() should return the original
532 # errno (mimicking the behaviour of non-SSL sockets).
533 with support.transient_internet("svn.python.org"):
534 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
535 cert_reqs=ssl.CERT_REQUIRED,
536 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
537 do_handshake_on_connect=False)
538 try:
539 s.settimeout(0.0000001)
540 rc = s.connect_ex(('svn.python.org', 443))
541 if rc == 0:
542 self.skipTest("svn.python.org responded too quickly")
543 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
544 finally:
545 s.close()
546
Antoine Pitrou152efa22010-05-16 18:19:27 +0000547 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000548 with support.transient_internet("svn.python.org"):
549 # Same as test_connect, but with a separately created context
550 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
551 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
552 s.connect(("svn.python.org", 443))
553 try:
554 self.assertEqual({}, s.getpeercert())
555 finally:
556 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000557 # Same with a server hostname
558 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
559 server_hostname="svn.python.org")
560 if ssl.HAS_SNI:
561 s.connect(("svn.python.org", 443))
562 s.close()
563 else:
564 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000565 # This should fail because we have no verification certs
566 ctx.verify_mode = ssl.CERT_REQUIRED
567 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000568 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000569 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000570 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000571 # This should succeed because we specify the root cert
572 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
573 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
574 s.connect(("svn.python.org", 443))
575 try:
576 cert = s.getpeercert()
577 self.assertTrue(cert)
578 finally:
579 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000580
581 def test_connect_capath(self):
582 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000583 # NOTE: the subject hashing algorithm has been changed between
584 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
585 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000586 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000587 with support.transient_internet("svn.python.org"):
588 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
589 ctx.verify_mode = ssl.CERT_REQUIRED
590 ctx.load_verify_locations(capath=CAPATH)
591 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
592 s.connect(("svn.python.org", 443))
593 try:
594 cert = s.getpeercert()
595 self.assertTrue(cert)
596 finally:
597 s.close()
598 # Same with a bytes `capath` argument
599 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
600 ctx.verify_mode = ssl.CERT_REQUIRED
601 ctx.load_verify_locations(capath=BYTES_CAPATH)
602 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
603 s.connect(("svn.python.org", 443))
604 try:
605 cert = s.getpeercert()
606 self.assertTrue(cert)
607 finally:
608 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000609
Antoine Pitroue3220242010-04-24 11:13:53 +0000610 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
611 def test_makefile_close(self):
612 # Issue #5238: creating a file-like object with makefile() shouldn't
613 # delay closing the underlying "real socket" (here tested with its
614 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000615 with support.transient_internet("svn.python.org"):
616 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
617 ss.connect(("svn.python.org", 443))
618 fd = ss.fileno()
619 f = ss.makefile()
620 f.close()
621 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000622 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000623 # Closing the SSL socket should close the fd too
624 ss.close()
625 gc.collect()
626 with self.assertRaises(OSError) as e:
627 os.read(fd, 0)
628 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000629
Antoine Pitrou480a1242010-04-28 21:37:09 +0000630 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000631 with support.transient_internet("svn.python.org"):
632 s = socket.socket(socket.AF_INET)
633 s.connect(("svn.python.org", 443))
634 s.setblocking(False)
635 s = ssl.wrap_socket(s,
636 cert_reqs=ssl.CERT_NONE,
637 do_handshake_on_connect=False)
638 count = 0
639 while True:
640 try:
641 count += 1
642 s.do_handshake()
643 break
644 except ssl.SSLError as err:
645 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
646 select.select([s], [], [])
647 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
648 select.select([], [s], [])
649 else:
650 raise
651 s.close()
652 if support.verbose:
653 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000654
Antoine Pitrou480a1242010-04-28 21:37:09 +0000655 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200656 def _test_get_server_certificate(host, port, cert=None):
657 with support.transient_internet(host):
658 pem = ssl.get_server_certificate((host, port))
659 if not pem:
660 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200661
Antoine Pitrou15399c32011-04-28 19:23:55 +0200662 try:
663 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
664 except ssl.SSLError as x:
665 #should fail
666 if support.verbose:
667 sys.stdout.write("%s\n" % x)
668 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200669 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
670
Antoine Pitrou15399c32011-04-28 19:23:55 +0200671 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
672 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200673 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000674 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200675 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000676
Antoine Pitrou15399c32011-04-28 19:23:55 +0200677 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
678 if support.IPV6_ENABLED:
679 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000680
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000681 def test_ciphers(self):
682 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000683 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000684 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000685 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000686 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000687 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
688 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
689 s.connect(remote)
690 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000691 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000692 with socket.socket(socket.AF_INET) as sock:
693 s = ssl.wrap_socket(sock,
694 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
695 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000696
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000697 def test_algorithms(self):
698 # Issue #8484: all algorithms should be available when verifying a
699 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000700 # SHA256 was added in OpenSSL 0.9.8
701 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
702 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000703 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
704 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000705 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000706 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000707 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
708 cert_reqs=ssl.CERT_REQUIRED,
709 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000710 try:
711 s.connect(remote)
712 if support.verbose:
713 sys.stdout.write("\nCipher with %r is %r\n" %
714 (remote, s.cipher()))
715 sys.stdout.write("Certificate is:\n%s\n" %
716 pprint.pformat(s.getpeercert()))
717 finally:
718 s.close()
719
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000720
721try:
722 import threading
723except ImportError:
724 _have_threads = False
725else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000726 _have_threads = True
727
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000728 from test.ssl_servers import make_https_server
729
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000730 class ThreadedEchoServer(threading.Thread):
731
732 class ConnectionHandler(threading.Thread):
733
734 """A mildly complicated class, because we want it to work both
735 with and without the SSL wrapper around the socket connection, so
736 that we can test the STARTTLS functionality."""
737
Bill Janssen6e027db2007-11-15 22:23:56 +0000738 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 self.server = server
740 self.running = False
741 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000742 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000743 self.sock.setblocking(1)
744 self.sslconn = None
745 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000746 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000747
Antoine Pitrou480a1242010-04-28 21:37:09 +0000748 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000749 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000750 self.sslconn = self.server.context.wrap_socket(
751 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000752 except ssl.SSLError:
753 # XXX Various errors can have happened here, for example
754 # a mismatching protocol version, an invalid certificate,
755 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000757 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000758 self.running = False
759 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000760 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000761 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000762 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000763 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000764 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000765 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000766 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
767 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000768 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000769 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
770 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000771 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000772 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
773 return True
774
775 def read(self):
776 if self.sslconn:
777 return self.sslconn.read()
778 else:
779 return self.sock.recv(1024)
780
781 def write(self, bytes):
782 if self.sslconn:
783 return self.sslconn.write(bytes)
784 else:
785 return self.sock.send(bytes)
786
787 def close(self):
788 if self.sslconn:
789 self.sslconn.close()
790 else:
791 self.sock.close()
792
Antoine Pitrou480a1242010-04-28 21:37:09 +0000793 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000794 self.running = True
795 if not self.server.starttls_server:
796 if not self.wrap_conn():
797 return
798 while self.running:
799 try:
800 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000801 stripped = msg.strip()
802 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000803 # eof, so quit this handler
804 self.running = False
805 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000806 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000807 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000808 sys.stdout.write(" server: client closed connection\n")
809 self.close()
810 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000811 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000812 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000813 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000814 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000815 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000816 if not self.wrap_conn():
817 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000818 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000819 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000820 if support.verbose and self.server.connectionchatty:
821 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000822 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000823 self.sock = self.sslconn.unwrap()
824 self.sslconn = None
825 if support.verbose and self.server.connectionchatty:
826 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000827 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000828 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829 self.server.connectionchatty):
830 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000831 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
832 % (msg, ctype, msg.lower(), ctype))
833 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000834 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000835 if self.server.chatty:
836 handle_error("Test server failure:\n")
837 self.close()
838 self.running = False
839 # normally, we'd just stop here, but for the test
840 # harness, we want to stop the server
841 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842
Antoine Pitroub5218772010-05-21 09:56:06 +0000843 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000844 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000845 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000846 ciphers=None, context=None):
847 if context:
848 self.context = context
849 else:
850 self.context = ssl.SSLContext(ssl_version
851 if ssl_version is not None
852 else ssl.PROTOCOL_TLSv1)
853 self.context.verify_mode = (certreqs if certreqs is not None
854 else ssl.CERT_NONE)
855 if cacerts:
856 self.context.load_verify_locations(cacerts)
857 if certificate:
858 self.context.load_cert_chain(certificate)
859 if ciphers:
860 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 self.chatty = chatty
862 self.connectionchatty = connectionchatty
863 self.starttls_server = starttls_server
864 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000865 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000867 self.active = False
868 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000869 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870
Antoine Pitrou480a1242010-04-28 21:37:09 +0000871 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 self.flag = flag
873 threading.Thread.start(self)
874
Antoine Pitrou480a1242010-04-28 21:37:09 +0000875 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000876 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000877 self.sock.listen(5)
878 self.active = True
879 if self.flag:
880 # signal an event
881 self.flag.set()
882 while self.active:
883 try:
884 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000885 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000887 + repr(connaddr) + '\n')
888 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000889 handler.start()
890 except socket.timeout:
891 pass
892 except KeyboardInterrupt:
893 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000894 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895
Antoine Pitrou480a1242010-04-28 21:37:09 +0000896 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000897 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898
Bill Janssen54cc54c2007-12-14 22:08:56 +0000899 class AsyncoreEchoServer(threading.Thread):
900
901 # this one's based on asyncore.dispatcher
902
903 class EchoServer (asyncore.dispatcher):
904
905 class ConnectionHandler (asyncore.dispatcher_with_send):
906
907 def __init__(self, conn, certfile):
908 self.socket = ssl.wrap_socket(conn, server_side=True,
909 certfile=certfile,
910 do_handshake_on_connect=False)
911 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000912 self._ssl_accepting = True
913 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000914
915 def readable(self):
916 if isinstance(self.socket, ssl.SSLSocket):
917 while self.socket.pending() > 0:
918 self.handle_read_event()
919 return True
920
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000921 def _do_ssl_handshake(self):
922 try:
923 self.socket.do_handshake()
924 except ssl.SSLError as err:
925 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
926 ssl.SSL_ERROR_WANT_WRITE):
927 return
928 elif err.args[0] == ssl.SSL_ERROR_EOF:
929 return self.handle_close()
930 raise
931 except socket.error as err:
932 if err.args[0] == errno.ECONNABORTED:
933 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000934 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000935 self._ssl_accepting = False
936
937 def handle_read(self):
938 if self._ssl_accepting:
939 self._do_ssl_handshake()
940 else:
941 data = self.recv(1024)
942 if support.verbose:
943 sys.stdout.write(" server: read %s from client\n" % repr(data))
944 if not data:
945 self.close()
946 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000947 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000948
949 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000950 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000951 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000952 sys.stdout.write(" server: closed connection %s\n" % self.socket)
953
954 def handle_error(self):
955 raise
956
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000957 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000958 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000959 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
960 self.port = support.bind_port(sock, '')
961 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000962 self.listen(5)
963
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000964 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000965 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000966 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
967 self.ConnectionHandler(sock_obj, self.certfile)
968
969 def handle_error(self):
970 raise
971
Trent Nelson78520002008-04-10 20:54:35 +0000972 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000973 self.flag = None
974 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000975 self.server = self.EchoServer(certfile)
976 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000977 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000978 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000979
980 def __str__(self):
981 return "<%s %s>" % (self.__class__.__name__, self.server)
982
983 def start (self, flag=None):
984 self.flag = flag
985 threading.Thread.start(self)
986
Antoine Pitrou480a1242010-04-28 21:37:09 +0000987 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000988 self.active = True
989 if self.flag:
990 self.flag.set()
991 while self.active:
992 try:
993 asyncore.loop(1)
994 except:
995 pass
996
Antoine Pitrou480a1242010-04-28 21:37:09 +0000997 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000998 self.active = False
999 self.server.close()
1000
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 def bad_cert_test(certfile):
1002 """
1003 Launch a server with CERT_REQUIRED, and check that trying to
1004 connect to it with the given client certificate fails.
1005 """
Trent Nelson78520002008-04-10 20:54:35 +00001006 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001008 cacerts=CERTFILE, chatty=False,
1009 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001010 flag = threading.Event()
1011 server.start(flag)
1012 # wait for it to start
1013 flag.wait()
1014 # try to connect
1015 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001016 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001017 with socket.socket() as sock:
1018 s = ssl.wrap_socket(sock,
1019 certfile=certfile,
1020 ssl_version=ssl.PROTOCOL_TLSv1)
1021 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001022 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001023 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001024 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001025 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001027 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001028 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001029 if x.errno != errno.ENOENT:
1030 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001031 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001032 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001033 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001034 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001035 finally:
1036 server.stop()
1037 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001038
Antoine Pitroub5218772010-05-21 09:56:06 +00001039 def server_params_test(client_context, server_context, indata=b"FOO\n",
1040 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001041 """
1042 Launch a server, connect a client to it and try various reads
1043 and writes.
1044 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001045 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001046 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001047 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001048 flag = threading.Event()
1049 server.start(flag)
1050 # wait for it to start
1051 flag.wait()
1052 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001053 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001054 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001055 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001056 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001057 if connectionchatty:
1058 if support.verbose:
1059 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001060 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001061 s.write(arg)
1062 outdata = s.read()
1063 if connectionchatty:
1064 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001065 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001066 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001067 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001068 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1069 % (outdata[:20], len(outdata),
1070 indata[:20].lower(), len(indata)))
1071 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001072 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001073 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001074 sys.stdout.write(" client: closing connection.\n")
1075 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001076 finally:
1077 server.stop()
1078 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001079
Antoine Pitroub5218772010-05-21 09:56:06 +00001080 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1081 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001082 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001083 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001084 certtype = {
1085 ssl.CERT_NONE: "CERT_NONE",
1086 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1087 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1088 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001089 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001090 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001091 sys.stdout.write(formatstr %
1092 (ssl.get_protocol_name(client_protocol),
1093 ssl.get_protocol_name(server_protocol),
1094 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001095 client_context = ssl.SSLContext(client_protocol)
1096 client_context.options = ssl.OP_ALL | client_options
1097 server_context = ssl.SSLContext(server_protocol)
1098 server_context.options = ssl.OP_ALL | server_options
1099 for ctx in (client_context, server_context):
1100 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001101 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1102 # will send an SSLv3 hello (rather than SSLv2) starting from
1103 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001104 ctx.set_ciphers("ALL")
1105 ctx.load_cert_chain(CERTFILE)
1106 ctx.load_verify_locations(CERTFILE)
1107 try:
1108 server_params_test(client_context, server_context,
1109 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001110 # Protocol mismatch can result in either an SSLError, or a
1111 # "Connection reset by peer" error.
1112 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001113 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001114 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001115 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001116 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001117 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001118 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001119 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001120 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001121 "Client protocol %s succeeded with server protocol %s!"
1122 % (ssl.get_protocol_name(client_protocol),
1123 ssl.get_protocol_name(server_protocol)))
1124
1125
Bill Janssen6e027db2007-11-15 22:23:56 +00001126 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127
Antoine Pitrou23df4832010-08-04 17:14:06 +00001128 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001129 def test_echo(self):
1130 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001131 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001132 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001133 for protocol in PROTOCOLS:
1134 context = ssl.SSLContext(protocol)
1135 context.load_cert_chain(CERTFILE)
1136 server_params_test(context, context,
1137 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001138
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001140 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001141 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001142 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1143 context.verify_mode = ssl.CERT_REQUIRED
1144 context.load_verify_locations(CERTFILE)
1145 context.load_cert_chain(CERTFILE)
1146 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147 flag = threading.Event()
1148 server.start(flag)
1149 # wait for it to start
1150 flag.wait()
1151 # try to connect
1152 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001153 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001154 s.connect((HOST, server.port))
1155 cert = s.getpeercert()
1156 self.assertTrue(cert, "Can't get peer certificate.")
1157 cipher = s.cipher()
1158 if support.verbose:
1159 sys.stdout.write(pprint.pformat(cert) + '\n')
1160 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1161 if 'subject' not in cert:
1162 self.fail("No subject field in certificate: %s." %
1163 pprint.pformat(cert))
1164 if ((('organizationName', 'Python Software Foundation'),)
1165 not in cert['subject']):
1166 self.fail(
1167 "Missing or invalid 'organizationName' field in certificate subject; "
1168 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001169 self.assertIn('notBefore', cert)
1170 self.assertIn('notAfter', cert)
1171 before = ssl.cert_time_to_seconds(cert['notBefore'])
1172 after = ssl.cert_time_to_seconds(cert['notAfter'])
1173 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001174 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001175 finally:
1176 server.stop()
1177 server.join()
1178
Antoine Pitrou480a1242010-04-28 21:37:09 +00001179 def test_empty_cert(self):
1180 """Connecting with an empty cert file"""
1181 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1182 "nullcert.pem"))
1183 def test_malformed_cert(self):
1184 """Connecting with a badly formatted certificate (syntax error)"""
1185 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1186 "badcert.pem"))
1187 def test_nonexisting_cert(self):
1188 """Connecting with a non-existing cert file"""
1189 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1190 "wrongcert.pem"))
1191 def test_malformed_key(self):
1192 """Connecting with a badly formatted key (syntax error)"""
1193 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1194 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001195
Antoine Pitrou480a1242010-04-28 21:37:09 +00001196 def test_rude_shutdown(self):
1197 """A brutal shutdown of an SSL server should raise an IOError
1198 in the client when attempting handshake.
1199 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001200 listener_ready = threading.Event()
1201 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001202
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001203 s = socket.socket()
1204 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001205
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001206 # `listener` runs in a thread. It sits in an accept() until
1207 # the main thread connects. Then it rudely closes the socket,
1208 # and sets Event `listener_gone` to let the main thread know
1209 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001210 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001211 s.listen(5)
1212 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001213 newsock, addr = s.accept()
1214 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001215 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001216 listener_gone.set()
1217
1218 def connector():
1219 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001220 with socket.socket() as c:
1221 c.connect((HOST, port))
1222 listener_gone.wait()
1223 try:
1224 ssl_sock = ssl.wrap_socket(c)
1225 except IOError:
1226 pass
1227 else:
1228 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001229
1230 t = threading.Thread(target=listener)
1231 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001232 try:
1233 connector()
1234 finally:
1235 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001236
Antoine Pitrou23df4832010-08-04 17:14:06 +00001237 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001238 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1239 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001240 def test_protocol_sslv2(self):
1241 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001242 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001244 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1245 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1246 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1247 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1248 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1249 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001250 # SSLv23 client with specific SSL options
1251 if no_sslv2_implies_sslv3_hello():
1252 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1253 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1254 client_options=ssl.OP_NO_SSLv2)
1255 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1256 client_options=ssl.OP_NO_SSLv3)
1257 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1258 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001259
Antoine Pitrou23df4832010-08-04 17:14:06 +00001260 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001261 def test_protocol_sslv23(self):
1262 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001263 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001264 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001265 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1266 try:
1267 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1268 except (ssl.SSLError, socket.error) as x:
1269 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1270 if support.verbose:
1271 sys.stdout.write(
1272 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1273 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001274 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1275 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1276 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001277
Antoine Pitrou480a1242010-04-28 21:37:09 +00001278 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1279 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1280 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001281
Antoine Pitrou480a1242010-04-28 21:37:09 +00001282 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1283 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1284 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001285
Antoine Pitroub5218772010-05-21 09:56:06 +00001286 # Server with specific SSL options
1287 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1288 server_options=ssl.OP_NO_SSLv3)
1289 # Will choose TLSv1
1290 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1291 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1292 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1293 server_options=ssl.OP_NO_TLSv1)
1294
1295
Antoine Pitrou23df4832010-08-04 17:14:06 +00001296 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001297 def test_protocol_sslv3(self):
1298 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001299 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001300 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001301 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1302 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1303 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001304 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1305 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001306 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1307 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001308 if no_sslv2_implies_sslv3_hello():
1309 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1310 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1311 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001312
Antoine Pitrou23df4832010-08-04 17:14:06 +00001313 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001314 def test_protocol_tlsv1(self):
1315 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001316 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001317 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001318 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1319 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1320 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001321 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1322 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001323 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1324 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001325
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 def test_starttls(self):
1327 """Switching from clear text to encrypted and back again."""
1328 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 +00001329
Trent Nelson78520002008-04-10 20:54:35 +00001330 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001331 ssl_version=ssl.PROTOCOL_TLSv1,
1332 starttls_server=True,
1333 chatty=True,
1334 connectionchatty=True)
1335 flag = threading.Event()
1336 server.start(flag)
1337 # wait for it to start
1338 flag.wait()
1339 # try to connect
1340 wrapped = False
1341 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001342 s = socket.socket()
1343 s.setblocking(1)
1344 s.connect((HOST, server.port))
1345 if support.verbose:
1346 sys.stdout.write("\n")
1347 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001348 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001349 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001350 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001351 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001353 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001354 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001355 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001356 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 msg = outdata.strip().lower()
1358 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1359 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001360 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001361 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001362 " client: read %r from server, starting TLS...\n"
1363 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001364 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1365 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001366 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1367 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001368 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001369 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001370 " client: read %r from server, ending TLS...\n"
1371 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001372 s = conn.unwrap()
1373 wrapped = False
1374 else:
1375 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001376 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001377 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001378 if support.verbose:
1379 sys.stdout.write(" client: closing connection.\n")
1380 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001382 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001384 if wrapped:
1385 conn.close()
1386 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001387 s.close()
1388 finally:
1389 server.stop()
1390 server.join()
1391
Antoine Pitrou480a1242010-04-28 21:37:09 +00001392 def test_socketserver(self):
1393 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001394 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001396 if support.verbose:
1397 sys.stdout.write('\n')
1398 with open(CERTFILE, 'rb') as f:
1399 d1 = f.read()
1400 d2 = ''
1401 # now fetch the same data from the HTTPS server
1402 url = 'https://%s:%d/%s' % (
1403 HOST, server.port, os.path.split(CERTFILE)[1])
1404 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001405 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001406 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001407 if dlen and (int(dlen) > 0):
1408 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001409 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001410 sys.stdout.write(
1411 " client: read %d bytes from remote server '%s'\n"
1412 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001413 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001414 f.close()
1415 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001416
Antoine Pitrou480a1242010-04-28 21:37:09 +00001417 def test_asyncore_server(self):
1418 """Check the example asyncore integration."""
1419 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001420
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001421 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001422 sys.stdout.write("\n")
1423
Antoine Pitrou480a1242010-04-28 21:37:09 +00001424 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001425 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001426 flag = threading.Event()
1427 server.start(flag)
1428 # wait for it to start
1429 flag.wait()
1430 # try to connect
1431 try:
1432 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001433 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001434 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001435 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001436 " client: sending %r...\n" % indata)
1437 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001438 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001439 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001440 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001441 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001442 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001443 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1444 % (outdata[:20], len(outdata),
1445 indata[:20].lower(), len(indata)))
1446 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001447 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001448 sys.stdout.write(" client: closing connection.\n")
1449 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001450 if support.verbose:
1451 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001452 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001453 if support.verbose:
1454 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001455 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001456 if support.verbose:
1457 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001458 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001459 if support.verbose:
1460 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001461
Antoine Pitrou480a1242010-04-28 21:37:09 +00001462 def test_recv_send(self):
1463 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001464 if support.verbose:
1465 sys.stdout.write("\n")
1466
1467 server = ThreadedEchoServer(CERTFILE,
1468 certreqs=ssl.CERT_NONE,
1469 ssl_version=ssl.PROTOCOL_TLSv1,
1470 cacerts=CERTFILE,
1471 chatty=True,
1472 connectionchatty=False)
1473 flag = threading.Event()
1474 server.start(flag)
1475 # wait for it to start
1476 flag.wait()
1477 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001478 s = ssl.wrap_socket(socket.socket(),
1479 server_side=False,
1480 certfile=CERTFILE,
1481 ca_certs=CERTFILE,
1482 cert_reqs=ssl.CERT_NONE,
1483 ssl_version=ssl.PROTOCOL_TLSv1)
1484 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001485 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001486 # helper methods for standardising recv* method signatures
1487 def _recv_into():
1488 b = bytearray(b"\0"*100)
1489 count = s.recv_into(b)
1490 return b[:count]
1491
1492 def _recvfrom_into():
1493 b = bytearray(b"\0"*100)
1494 count, addr = s.recvfrom_into(b)
1495 return b[:count]
1496
1497 # (name, method, whether to expect success, *args)
1498 send_methods = [
1499 ('send', s.send, True, []),
1500 ('sendto', s.sendto, False, ["some.address"]),
1501 ('sendall', s.sendall, True, []),
1502 ]
1503 recv_methods = [
1504 ('recv', s.recv, True, []),
1505 ('recvfrom', s.recvfrom, False, ["some.address"]),
1506 ('recv_into', _recv_into, True, []),
1507 ('recvfrom_into', _recvfrom_into, False, []),
1508 ]
1509 data_prefix = "PREFIX_"
1510
1511 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001512 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001513 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001514 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001515 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001516 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001517 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001518 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001519 "<<{outdata:r}>> ({nout:d}) received; "
1520 "expected <<{indata:r}>> ({nin:d})\n".format(
1521 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001522 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001523 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001524 )
1525 )
1526 except ValueError as e:
1527 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001528 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001529 "Failed to send with method <<{name:s}>>; "
1530 "expected to succeed.\n".format(name=meth_name)
1531 )
1532 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001533 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001534 "Method <<{name:s}>> failed with unexpected "
1535 "exception message: {exp:s}\n".format(
1536 name=meth_name, exp=e
1537 )
1538 )
1539
1540 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001541 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001542 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001543 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001544 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001545 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001546 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001547 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001548 "<<{outdata:r}>> ({nout:d}) received; "
1549 "expected <<{indata:r}>> ({nin:d})\n".format(
1550 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001551 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001552 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001553 )
1554 )
1555 except ValueError as e:
1556 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001557 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001558 "Failed to receive with method <<{name:s}>>; "
1559 "expected to succeed.\n".format(name=meth_name)
1560 )
1561 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001562 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001563 "Method <<{name:s}>> failed with unexpected "
1564 "exception message: {exp:s}\n".format(
1565 name=meth_name, exp=e
1566 )
1567 )
1568 # consume data
1569 s.read()
1570
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001572 s.close()
1573 finally:
1574 server.stop()
1575 server.join()
1576
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001577 def test_handshake_timeout(self):
1578 # Issue #5103: SSL handshake must respect the socket timeout
1579 server = socket.socket(socket.AF_INET)
1580 host = "127.0.0.1"
1581 port = support.bind_port(server)
1582 started = threading.Event()
1583 finish = False
1584
1585 def serve():
1586 server.listen(5)
1587 started.set()
1588 conns = []
1589 while not finish:
1590 r, w, e = select.select([server], [], [], 0.1)
1591 if server in r:
1592 # Let the socket hang around rather than having
1593 # it closed by garbage collection.
1594 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001595 for sock in conns:
1596 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001597
1598 t = threading.Thread(target=serve)
1599 t.start()
1600 started.wait()
1601
1602 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001603 try:
1604 c = socket.socket(socket.AF_INET)
1605 c.settimeout(0.2)
1606 c.connect((host, port))
1607 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001608 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001609 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001610 finally:
1611 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001612 try:
1613 c = socket.socket(socket.AF_INET)
1614 c = ssl.wrap_socket(c)
1615 c.settimeout(0.2)
1616 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001617 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001618 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001619 finally:
1620 c.close()
1621 finally:
1622 finish = True
1623 t.join()
1624 server.close()
1625
Bill Janssen58afe4c2008-09-08 16:45:19 +00001626
Thomas Woutersed03b412007-08-28 21:37:11 +00001627def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001628 if support.verbose:
1629 plats = {
1630 'Linux': platform.linux_distribution,
1631 'Mac': platform.mac_ver,
1632 'Windows': platform.win32_ver,
1633 }
1634 for name, func in plats.items():
1635 plat = func()
1636 if plat and plat[0]:
1637 plat = '%s %r' % (name, plat)
1638 break
1639 else:
1640 plat = repr(platform.platform())
1641 print("test_ssl: testing with %r %r" %
1642 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1643 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001644 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001645
Antoine Pitrou152efa22010-05-16 18:19:27 +00001646 for filename in [
1647 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1648 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1649 BADCERT, BADKEY, EMPTYCERT]:
1650 if not os.path.exists(filename):
1651 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001652
Antoine Pitrou152efa22010-05-16 18:19:27 +00001653 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001654
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001655 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001656 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001657
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001658 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001659 thread_info = support.threading_setup()
1660 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001661 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001662
Antoine Pitrou480a1242010-04-28 21:37:09 +00001663 try:
1664 support.run_unittest(*tests)
1665 finally:
1666 if _have_threads:
1667 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001668
1669if __name__ == "__main__":
1670 test_main()