blob: 2af2e5ce9f7e7f20997cab4c68973966df1fa612 [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"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000105 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 ssl.RAND_egd(1)
107 except TypeError:
108 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000109 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000110 print("didn't raise TypeError")
111 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000112
Antoine Pitrou480a1242010-04-28 21:37:09 +0000113 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 # note that this uses an 'unofficial' function in _ssl.c,
115 # provided solely for this test, to exercise the certificate
116 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000117 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000118 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000119 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000120
Antoine Pitrou480a1242010-04-28 21:37:09 +0000121 def test_DER_to_PEM(self):
122 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
123 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000124 d1 = ssl.PEM_cert_to_DER_cert(pem)
125 p2 = ssl.DER_cert_to_PEM_cert(d1)
126 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000127 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000128 if not p2.startswith(ssl.PEM_HEADER + '\n'):
129 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
130 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
131 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000133 def test_openssl_version(self):
134 n = ssl.OPENSSL_VERSION_NUMBER
135 t = ssl.OPENSSL_VERSION_INFO
136 s = ssl.OPENSSL_VERSION
137 self.assertIsInstance(n, int)
138 self.assertIsInstance(t, tuple)
139 self.assertIsInstance(s, str)
140 # Some sanity checks follow
141 # >= 0.9
142 self.assertGreaterEqual(n, 0x900000)
143 # < 2.0
144 self.assertLess(n, 0x20000000)
145 major, minor, fix, patch, status = t
146 self.assertGreaterEqual(major, 0)
147 self.assertLess(major, 2)
148 self.assertGreaterEqual(minor, 0)
149 self.assertLess(minor, 256)
150 self.assertGreaterEqual(fix, 0)
151 self.assertLess(fix, 256)
152 self.assertGreaterEqual(patch, 0)
153 self.assertLessEqual(patch, 26)
154 self.assertGreaterEqual(status, 0)
155 self.assertLessEqual(status, 15)
156 # Version string as returned by OpenSSL, the format might change
157 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
158 (s, t))
159
Antoine Pitrou9d543662010-04-23 23:10:32 +0000160 @support.cpython_only
161 def test_refcycle(self):
162 # Issue #7943: an SSL object doesn't create reference cycles with
163 # itself.
164 s = socket.socket(socket.AF_INET)
165 ss = ssl.wrap_socket(s)
166 wr = weakref.ref(ss)
167 del ss
168 self.assertEqual(wr(), None)
169
Antoine Pitroua468adc2010-09-14 14:43:44 +0000170 def test_wrapped_unconnected(self):
171 # Methods on an unconnected SSLSocket propagate the original
172 # socket.error raise by the underlying socket object.
173 s = socket.socket(socket.AF_INET)
174 ss = ssl.wrap_socket(s)
175 self.assertRaises(socket.error, ss.recv, 1)
176 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
177 self.assertRaises(socket.error, ss.recvfrom, 1)
178 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
179 self.assertRaises(socket.error, ss.send, b'x')
180 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
181
Antoine Pitrou40f08742010-04-24 22:04:40 +0000182 def test_timeout(self):
183 # Issue #8524: when creating an SSL socket, the timeout of the
184 # original socket should be retained.
185 for timeout in (None, 0.0, 5.0):
186 s = socket.socket(socket.AF_INET)
187 s.settimeout(timeout)
188 ss = ssl.wrap_socket(s)
189 self.assertEqual(timeout, ss.gettimeout())
190
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000191 def test_errors(self):
192 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000193 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000194 "certfile must be specified",
195 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000196 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000197 "certfile must be specified for server-side operations",
198 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000199 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000200 "certfile must be specified for server-side operations",
201 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000202 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000203 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000204 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000205 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000206 with socket.socket() as sock:
207 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000208 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000209 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000210 with socket.socket() as sock:
211 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000212 self.assertEqual(cm.exception.errno, errno.ENOENT)
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, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000216 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000217
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000218 def test_match_hostname(self):
219 def ok(cert, hostname):
220 ssl.match_hostname(cert, hostname)
221 def fail(cert, hostname):
222 self.assertRaises(ssl.CertificateError,
223 ssl.match_hostname, cert, hostname)
224
225 cert = {'subject': ((('commonName', 'example.com'),),)}
226 ok(cert, 'example.com')
227 ok(cert, 'ExAmple.cOm')
228 fail(cert, 'www.example.com')
229 fail(cert, '.example.com')
230 fail(cert, 'example.org')
231 fail(cert, 'exampleXcom')
232
233 cert = {'subject': ((('commonName', '*.a.com'),),)}
234 ok(cert, 'foo.a.com')
235 fail(cert, 'bar.foo.a.com')
236 fail(cert, 'a.com')
237 fail(cert, 'Xa.com')
238 fail(cert, '.a.com')
239
240 cert = {'subject': ((('commonName', 'a.*.com'),),)}
241 ok(cert, 'a.foo.com')
242 fail(cert, 'a..com')
243 fail(cert, 'a.com')
244
245 cert = {'subject': ((('commonName', 'f*.com'),),)}
246 ok(cert, 'foo.com')
247 ok(cert, 'f.com')
248 fail(cert, 'bar.com')
249 fail(cert, 'foo.a.com')
250 fail(cert, 'bar.foo.com')
251
252 # Slightly fake real-world example
253 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
254 'subject': ((('commonName', 'linuxfrz.org'),),),
255 'subjectAltName': (('DNS', 'linuxfr.org'),
256 ('DNS', 'linuxfr.com'),
257 ('othername', '<unsupported>'))}
258 ok(cert, 'linuxfr.org')
259 ok(cert, 'linuxfr.com')
260 # Not a "DNS" entry
261 fail(cert, '<unsupported>')
262 # When there is a subjectAltName, commonName isn't used
263 fail(cert, 'linuxfrz.org')
264
265 # A pristine real-world example
266 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
267 'subject': ((('countryName', 'US'),),
268 (('stateOrProvinceName', 'California'),),
269 (('localityName', 'Mountain View'),),
270 (('organizationName', 'Google Inc'),),
271 (('commonName', 'mail.google.com'),))}
272 ok(cert, 'mail.google.com')
273 fail(cert, 'gmail.com')
274 # Only commonName is considered
275 fail(cert, 'California')
276
277 # Neither commonName nor subjectAltName
278 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
279 'subject': ((('countryName', 'US'),),
280 (('stateOrProvinceName', 'California'),),
281 (('localityName', 'Mountain View'),),
282 (('organizationName', 'Google Inc'),))}
283 fail(cert, 'mail.google.com')
284
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200285 # No DNS entry in subjectAltName but a commonName
286 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
287 'subject': ((('countryName', 'US'),),
288 (('stateOrProvinceName', 'California'),),
289 (('localityName', 'Mountain View'),),
290 (('commonName', 'mail.google.com'),)),
291 'subjectAltName': (('othername', 'blabla'), )}
292 ok(cert, 'mail.google.com')
293
294 # No DNS entry subjectAltName and no commonName
295 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
296 'subject': ((('countryName', 'US'),),
297 (('stateOrProvinceName', 'California'),),
298 (('localityName', 'Mountain View'),),
299 (('organizationName', 'Google Inc'),)),
300 'subjectAltName': (('othername', 'blabla'),)}
301 fail(cert, 'google.com')
302
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000303 # Empty cert / no cert
304 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
305 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
306
Antoine Pitroud5323212010-10-22 18:19:07 +0000307 def test_server_side(self):
308 # server_hostname doesn't work for server sockets
309 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000310 with socket.socket() as sock:
311 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
312 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000313
Antoine Pitrou152efa22010-05-16 18:19:27 +0000314class ContextTests(unittest.TestCase):
315
Antoine Pitrou23df4832010-08-04 17:14:06 +0000316 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000317 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200318 if hasattr(ssl, 'PROTOCOL_SSLv2'):
319 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000320 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
321 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
322 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
323 self.assertRaises(TypeError, ssl.SSLContext)
324 self.assertRaises(ValueError, ssl.SSLContext, -1)
325 self.assertRaises(ValueError, ssl.SSLContext, 42)
326
Antoine Pitrou23df4832010-08-04 17:14:06 +0000327 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000328 def test_protocol(self):
329 for proto in PROTOCOLS:
330 ctx = ssl.SSLContext(proto)
331 self.assertEqual(ctx.protocol, proto)
332
333 def test_ciphers(self):
334 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
335 ctx.set_ciphers("ALL")
336 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000337 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000338 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000339
Antoine Pitrou23df4832010-08-04 17:14:06 +0000340 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000341 def test_options(self):
342 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
343 # OP_ALL is the default value
344 self.assertEqual(ssl.OP_ALL, ctx.options)
345 ctx.options |= ssl.OP_NO_SSLv2
346 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
347 ctx.options)
348 ctx.options |= ssl.OP_NO_SSLv3
349 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
350 ctx.options)
351 if can_clear_options():
352 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
353 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
354 ctx.options)
355 ctx.options = 0
356 self.assertEqual(0, ctx.options)
357 else:
358 with self.assertRaises(ValueError):
359 ctx.options = 0
360
Antoine Pitrou152efa22010-05-16 18:19:27 +0000361 def test_verify(self):
362 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
363 # Default value
364 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
365 ctx.verify_mode = ssl.CERT_OPTIONAL
366 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
367 ctx.verify_mode = ssl.CERT_REQUIRED
368 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
369 ctx.verify_mode = ssl.CERT_NONE
370 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
371 with self.assertRaises(TypeError):
372 ctx.verify_mode = None
373 with self.assertRaises(ValueError):
374 ctx.verify_mode = 42
375
376 def test_load_cert_chain(self):
377 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
378 # Combined key and cert in a single file
379 ctx.load_cert_chain(CERTFILE)
380 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
381 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000382 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000383 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000384 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000385 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000386 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000387 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000388 ctx.load_cert_chain(EMPTYCERT)
389 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000390 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000391 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
392 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
393 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000394 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000395 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000396 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000397 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000398 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000399 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
400 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000401 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000402 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000403 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000404
405 def test_load_verify_locations(self):
406 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
407 ctx.load_verify_locations(CERTFILE)
408 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
409 ctx.load_verify_locations(BYTES_CERTFILE)
410 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
411 self.assertRaises(TypeError, ctx.load_verify_locations)
412 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000413 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000414 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000415 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000416 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000417 ctx.load_verify_locations(BADCERT)
418 ctx.load_verify_locations(CERTFILE, CAPATH)
419 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
420
Victor Stinner80f75e62011-01-29 11:31:20 +0000421 # Issue #10989: crash if the second argument type is invalid
422 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
423
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000424 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000425 def test_session_stats(self):
426 for proto in PROTOCOLS:
427 ctx = ssl.SSLContext(proto)
428 self.assertEqual(ctx.session_stats(), {
429 'number': 0,
430 'connect': 0,
431 'connect_good': 0,
432 'connect_renegotiate': 0,
433 'accept': 0,
434 'accept_good': 0,
435 'accept_renegotiate': 0,
436 'hits': 0,
437 'misses': 0,
438 'timeouts': 0,
439 'cache_full': 0,
440 })
441
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000442 def test_set_default_verify_paths(self):
443 # There's not much we can do to test that it acts as expected,
444 # so just check it doesn't crash or raise an exception.
445 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
446 ctx.set_default_verify_paths()
447
Antoine Pitrou152efa22010-05-16 18:19:27 +0000448
Bill Janssen6e027db2007-11-15 22:23:56 +0000449class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000450
Antoine Pitrou480a1242010-04-28 21:37:09 +0000451 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000452 with support.transient_internet("svn.python.org"):
453 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
454 cert_reqs=ssl.CERT_NONE)
455 try:
456 s.connect(("svn.python.org", 443))
457 self.assertEqual({}, s.getpeercert())
458 finally:
459 s.close()
460
461 # this should fail because we have no verification certs
462 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
463 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000464 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
465 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000467
Antoine Pitrou350c7222010-09-09 13:31:46 +0000468 # this should succeed because we specify the root cert
469 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
470 cert_reqs=ssl.CERT_REQUIRED,
471 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
472 try:
473 s.connect(("svn.python.org", 443))
474 self.assertTrue(s.getpeercert())
475 finally:
476 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000477
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000478 def test_connect_ex(self):
479 # Issue #11326: check connect_ex() implementation
480 with support.transient_internet("svn.python.org"):
481 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
482 cert_reqs=ssl.CERT_REQUIRED,
483 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
484 try:
485 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
486 self.assertTrue(s.getpeercert())
487 finally:
488 s.close()
489
490 def test_non_blocking_connect_ex(self):
491 # Issue #11326: non-blocking connect_ex() should allow handshake
492 # to proceed after the socket gets ready.
493 with support.transient_internet("svn.python.org"):
494 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
495 cert_reqs=ssl.CERT_REQUIRED,
496 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
497 do_handshake_on_connect=False)
498 try:
499 s.setblocking(False)
500 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000501 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
502 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000503 # Wait for connect to finish
504 select.select([], [s], [], 5.0)
505 # Non-blocking handshake
506 while True:
507 try:
508 s.do_handshake()
509 break
510 except ssl.SSLError as err:
511 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
512 select.select([s], [], [], 5.0)
513 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
514 select.select([], [s], [], 5.0)
515 else:
516 raise
517 # SSL established
518 self.assertTrue(s.getpeercert())
519 finally:
520 s.close()
521
Antoine Pitrou152efa22010-05-16 18:19:27 +0000522 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000523 with support.transient_internet("svn.python.org"):
524 # Same as test_connect, but with a separately created context
525 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
526 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
527 s.connect(("svn.python.org", 443))
528 try:
529 self.assertEqual({}, s.getpeercert())
530 finally:
531 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000532 # Same with a server hostname
533 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
534 server_hostname="svn.python.org")
535 if ssl.HAS_SNI:
536 s.connect(("svn.python.org", 443))
537 s.close()
538 else:
539 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000540 # This should fail because we have no verification certs
541 ctx.verify_mode = ssl.CERT_REQUIRED
542 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000543 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000544 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000545 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000546 # This should succeed because we specify the root cert
547 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
548 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
549 s.connect(("svn.python.org", 443))
550 try:
551 cert = s.getpeercert()
552 self.assertTrue(cert)
553 finally:
554 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000555
556 def test_connect_capath(self):
557 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000558 # NOTE: the subject hashing algorithm has been changed between
559 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
560 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000561 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000562 with support.transient_internet("svn.python.org"):
563 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
564 ctx.verify_mode = ssl.CERT_REQUIRED
565 ctx.load_verify_locations(capath=CAPATH)
566 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
567 s.connect(("svn.python.org", 443))
568 try:
569 cert = s.getpeercert()
570 self.assertTrue(cert)
571 finally:
572 s.close()
573 # Same with a bytes `capath` argument
574 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
575 ctx.verify_mode = ssl.CERT_REQUIRED
576 ctx.load_verify_locations(capath=BYTES_CAPATH)
577 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
578 s.connect(("svn.python.org", 443))
579 try:
580 cert = s.getpeercert()
581 self.assertTrue(cert)
582 finally:
583 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000584
Antoine Pitroue3220242010-04-24 11:13:53 +0000585 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
586 def test_makefile_close(self):
587 # Issue #5238: creating a file-like object with makefile() shouldn't
588 # delay closing the underlying "real socket" (here tested with its
589 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000590 with support.transient_internet("svn.python.org"):
591 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
592 ss.connect(("svn.python.org", 443))
593 fd = ss.fileno()
594 f = ss.makefile()
595 f.close()
596 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000597 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000598 # Closing the SSL socket should close the fd too
599 ss.close()
600 gc.collect()
601 with self.assertRaises(OSError) as e:
602 os.read(fd, 0)
603 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000604
Antoine Pitrou480a1242010-04-28 21:37:09 +0000605 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000606 with support.transient_internet("svn.python.org"):
607 s = socket.socket(socket.AF_INET)
608 s.connect(("svn.python.org", 443))
609 s.setblocking(False)
610 s = ssl.wrap_socket(s,
611 cert_reqs=ssl.CERT_NONE,
612 do_handshake_on_connect=False)
613 count = 0
614 while True:
615 try:
616 count += 1
617 s.do_handshake()
618 break
619 except ssl.SSLError as err:
620 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
621 select.select([s], [], [])
622 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
623 select.select([], [s], [])
624 else:
625 raise
626 s.close()
627 if support.verbose:
628 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000629
Antoine Pitrou480a1242010-04-28 21:37:09 +0000630 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200631 def _test_get_server_certificate(host, port, cert=None):
632 with support.transient_internet(host):
633 pem = ssl.get_server_certificate((host, port))
634 if not pem:
635 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200636
Antoine Pitrou15399c32011-04-28 19:23:55 +0200637 try:
638 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
639 except ssl.SSLError as x:
640 #should fail
641 if support.verbose:
642 sys.stdout.write("%s\n" % x)
643 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200644 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
645
Antoine Pitrou15399c32011-04-28 19:23:55 +0200646 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
647 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200648 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000649 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200650 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000651
Antoine Pitrou15399c32011-04-28 19:23:55 +0200652 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
653 if support.IPV6_ENABLED:
654 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000655
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000656 def test_ciphers(self):
657 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000658 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000659 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000660 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000661 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000662 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
663 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
664 s.connect(remote)
665 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000666 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000667 with socket.socket(socket.AF_INET) as sock:
668 s = ssl.wrap_socket(sock,
669 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
670 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000671
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000672 def test_algorithms(self):
673 # Issue #8484: all algorithms should be available when verifying a
674 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000675 # SHA256 was added in OpenSSL 0.9.8
676 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
677 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000678 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
679 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000680 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000681 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000682 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
683 cert_reqs=ssl.CERT_REQUIRED,
684 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000685 try:
686 s.connect(remote)
687 if support.verbose:
688 sys.stdout.write("\nCipher with %r is %r\n" %
689 (remote, s.cipher()))
690 sys.stdout.write("Certificate is:\n%s\n" %
691 pprint.pformat(s.getpeercert()))
692 finally:
693 s.close()
694
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000695
696try:
697 import threading
698except ImportError:
699 _have_threads = False
700else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000701 _have_threads = True
702
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000703 from test.ssl_servers import make_https_server
704
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 class ThreadedEchoServer(threading.Thread):
706
707 class ConnectionHandler(threading.Thread):
708
709 """A mildly complicated class, because we want it to work both
710 with and without the SSL wrapper around the socket connection, so
711 that we can test the STARTTLS functionality."""
712
Bill Janssen6e027db2007-11-15 22:23:56 +0000713 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000714 self.server = server
715 self.running = False
716 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000717 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000718 self.sock.setblocking(1)
719 self.sslconn = None
720 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000721 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000722
Antoine Pitrou480a1242010-04-28 21:37:09 +0000723 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000724 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000725 self.sslconn = self.server.context.wrap_socket(
726 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000727 except ssl.SSLError:
728 # XXX Various errors can have happened here, for example
729 # a mismatching protocol version, an invalid certificate,
730 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000731 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000732 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000733 self.running = False
734 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000735 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000736 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000737 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000738 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000740 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000741 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
742 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000743 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000744 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
745 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000746 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000747 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
748 return True
749
750 def read(self):
751 if self.sslconn:
752 return self.sslconn.read()
753 else:
754 return self.sock.recv(1024)
755
756 def write(self, bytes):
757 if self.sslconn:
758 return self.sslconn.write(bytes)
759 else:
760 return self.sock.send(bytes)
761
762 def close(self):
763 if self.sslconn:
764 self.sslconn.close()
765 else:
766 self.sock.close()
767
Antoine Pitrou480a1242010-04-28 21:37:09 +0000768 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000769 self.running = True
770 if not self.server.starttls_server:
771 if not self.wrap_conn():
772 return
773 while self.running:
774 try:
775 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000776 stripped = msg.strip()
777 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000778 # eof, so quit this handler
779 self.running = False
780 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000781 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000782 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783 sys.stdout.write(" server: client closed connection\n")
784 self.close()
785 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000786 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000787 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000788 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000789 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000790 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000791 if not self.wrap_conn():
792 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000793 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000794 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000795 if support.verbose and self.server.connectionchatty:
796 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000797 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000798 self.sock = self.sslconn.unwrap()
799 self.sslconn = None
800 if support.verbose and self.server.connectionchatty:
801 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000802 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000803 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000804 self.server.connectionchatty):
805 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000806 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
807 % (msg, ctype, msg.lower(), ctype))
808 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000809 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000810 if self.server.chatty:
811 handle_error("Test server failure:\n")
812 self.close()
813 self.running = False
814 # normally, we'd just stop here, but for the test
815 # harness, we want to stop the server
816 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000817
Antoine Pitroub5218772010-05-21 09:56:06 +0000818 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000819 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000820 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000821 ciphers=None, context=None):
822 if context:
823 self.context = context
824 else:
825 self.context = ssl.SSLContext(ssl_version
826 if ssl_version is not None
827 else ssl.PROTOCOL_TLSv1)
828 self.context.verify_mode = (certreqs if certreqs is not None
829 else ssl.CERT_NONE)
830 if cacerts:
831 self.context.load_verify_locations(cacerts)
832 if certificate:
833 self.context.load_cert_chain(certificate)
834 if ciphers:
835 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000836 self.chatty = chatty
837 self.connectionchatty = connectionchatty
838 self.starttls_server = starttls_server
839 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000840 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000841 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842 self.active = False
843 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000844 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000845
Antoine Pitrou480a1242010-04-28 21:37:09 +0000846 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000847 self.flag = flag
848 threading.Thread.start(self)
849
Antoine Pitrou480a1242010-04-28 21:37:09 +0000850 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000851 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000852 self.sock.listen(5)
853 self.active = True
854 if self.flag:
855 # signal an event
856 self.flag.set()
857 while self.active:
858 try:
859 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000860 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000862 + repr(connaddr) + '\n')
863 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000864 handler.start()
865 except socket.timeout:
866 pass
867 except KeyboardInterrupt:
868 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000869 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870
Antoine Pitrou480a1242010-04-28 21:37:09 +0000871 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873
Bill Janssen54cc54c2007-12-14 22:08:56 +0000874 class AsyncoreEchoServer(threading.Thread):
875
876 # this one's based on asyncore.dispatcher
877
878 class EchoServer (asyncore.dispatcher):
879
880 class ConnectionHandler (asyncore.dispatcher_with_send):
881
882 def __init__(self, conn, certfile):
883 self.socket = ssl.wrap_socket(conn, server_side=True,
884 certfile=certfile,
885 do_handshake_on_connect=False)
886 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000887 self._ssl_accepting = True
888 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000889
890 def readable(self):
891 if isinstance(self.socket, ssl.SSLSocket):
892 while self.socket.pending() > 0:
893 self.handle_read_event()
894 return True
895
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000896 def _do_ssl_handshake(self):
897 try:
898 self.socket.do_handshake()
899 except ssl.SSLError as err:
900 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
901 ssl.SSL_ERROR_WANT_WRITE):
902 return
903 elif err.args[0] == ssl.SSL_ERROR_EOF:
904 return self.handle_close()
905 raise
906 except socket.error as err:
907 if err.args[0] == errno.ECONNABORTED:
908 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000909 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000910 self._ssl_accepting = False
911
912 def handle_read(self):
913 if self._ssl_accepting:
914 self._do_ssl_handshake()
915 else:
916 data = self.recv(1024)
917 if support.verbose:
918 sys.stdout.write(" server: read %s from client\n" % repr(data))
919 if not data:
920 self.close()
921 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000922 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000923
924 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000925 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000926 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000927 sys.stdout.write(" server: closed connection %s\n" % self.socket)
928
929 def handle_error(self):
930 raise
931
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000932 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000933 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000934 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
935 self.port = support.bind_port(sock, '')
936 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000937 self.listen(5)
938
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000939 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000940 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000941 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
942 self.ConnectionHandler(sock_obj, self.certfile)
943
944 def handle_error(self):
945 raise
946
Trent Nelson78520002008-04-10 20:54:35 +0000947 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000948 self.flag = None
949 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000950 self.server = self.EchoServer(certfile)
951 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000952 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000953 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000954
955 def __str__(self):
956 return "<%s %s>" % (self.__class__.__name__, self.server)
957
958 def start (self, flag=None):
959 self.flag = flag
960 threading.Thread.start(self)
961
Antoine Pitrou480a1242010-04-28 21:37:09 +0000962 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000963 self.active = True
964 if self.flag:
965 self.flag.set()
966 while self.active:
967 try:
968 asyncore.loop(1)
969 except:
970 pass
971
Antoine Pitrou480a1242010-04-28 21:37:09 +0000972 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000973 self.active = False
974 self.server.close()
975
Antoine Pitrou480a1242010-04-28 21:37:09 +0000976 def bad_cert_test(certfile):
977 """
978 Launch a server with CERT_REQUIRED, and check that trying to
979 connect to it with the given client certificate fails.
980 """
Trent Nelson78520002008-04-10 20:54:35 +0000981 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000982 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000983 cacerts=CERTFILE, chatty=False,
984 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000985 flag = threading.Event()
986 server.start(flag)
987 # wait for it to start
988 flag.wait()
989 # try to connect
990 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000991 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000992 with socket.socket() as sock:
993 s = ssl.wrap_socket(sock,
994 certfile=certfile,
995 ssl_version=ssl.PROTOCOL_TLSv1)
996 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000997 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000998 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000999 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001000 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001002 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001003 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001004 if x.errno != errno.ENOENT:
1005 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001006 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001007 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001008 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001009 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001010 finally:
1011 server.stop()
1012 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001013
Antoine Pitroub5218772010-05-21 09:56:06 +00001014 def server_params_test(client_context, server_context, indata=b"FOO\n",
1015 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001016 """
1017 Launch a server, connect a client to it and try various reads
1018 and writes.
1019 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001020 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001021 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001022 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001023 flag = threading.Event()
1024 server.start(flag)
1025 # wait for it to start
1026 flag.wait()
1027 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001028 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001029 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001030 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001031 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001032 if connectionchatty:
1033 if support.verbose:
1034 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001035 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001036 s.write(arg)
1037 outdata = s.read()
1038 if connectionchatty:
1039 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001040 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001041 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001042 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001043 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1044 % (outdata[:20], len(outdata),
1045 indata[:20].lower(), len(indata)))
1046 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001047 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001048 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001049 sys.stdout.write(" client: closing connection.\n")
1050 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001051 finally:
1052 server.stop()
1053 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001054
Antoine Pitroub5218772010-05-21 09:56:06 +00001055 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1056 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001057 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001058 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001059 certtype = {
1060 ssl.CERT_NONE: "CERT_NONE",
1061 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1062 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1063 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001064 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001065 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 sys.stdout.write(formatstr %
1067 (ssl.get_protocol_name(client_protocol),
1068 ssl.get_protocol_name(server_protocol),
1069 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001070 client_context = ssl.SSLContext(client_protocol)
1071 client_context.options = ssl.OP_ALL | client_options
1072 server_context = ssl.SSLContext(server_protocol)
1073 server_context.options = ssl.OP_ALL | server_options
1074 for ctx in (client_context, server_context):
1075 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001076 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1077 # will send an SSLv3 hello (rather than SSLv2) starting from
1078 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001079 ctx.set_ciphers("ALL")
1080 ctx.load_cert_chain(CERTFILE)
1081 ctx.load_verify_locations(CERTFILE)
1082 try:
1083 server_params_test(client_context, server_context,
1084 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001085 # Protocol mismatch can result in either an SSLError, or a
1086 # "Connection reset by peer" error.
1087 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001088 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001089 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001090 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001092 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001094 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001095 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001096 "Client protocol %s succeeded with server protocol %s!"
1097 % (ssl.get_protocol_name(client_protocol),
1098 ssl.get_protocol_name(server_protocol)))
1099
1100
Bill Janssen6e027db2007-11-15 22:23:56 +00001101 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001102
Antoine Pitrou23df4832010-08-04 17:14:06 +00001103 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001104 def test_echo(self):
1105 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001106 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001108 for protocol in PROTOCOLS:
1109 context = ssl.SSLContext(protocol)
1110 context.load_cert_chain(CERTFILE)
1111 server_params_test(context, context,
1112 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001113
Antoine Pitrou480a1242010-04-28 21:37:09 +00001114 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001115 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001116 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001117 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1118 context.verify_mode = ssl.CERT_REQUIRED
1119 context.load_verify_locations(CERTFILE)
1120 context.load_cert_chain(CERTFILE)
1121 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001122 flag = threading.Event()
1123 server.start(flag)
1124 # wait for it to start
1125 flag.wait()
1126 # try to connect
1127 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001128 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001129 s.connect((HOST, server.port))
1130 cert = s.getpeercert()
1131 self.assertTrue(cert, "Can't get peer certificate.")
1132 cipher = s.cipher()
1133 if support.verbose:
1134 sys.stdout.write(pprint.pformat(cert) + '\n')
1135 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1136 if 'subject' not in cert:
1137 self.fail("No subject field in certificate: %s." %
1138 pprint.pformat(cert))
1139 if ((('organizationName', 'Python Software Foundation'),)
1140 not in cert['subject']):
1141 self.fail(
1142 "Missing or invalid 'organizationName' field in certificate subject; "
1143 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001144 self.assertIn('notBefore', cert)
1145 self.assertIn('notAfter', cert)
1146 before = ssl.cert_time_to_seconds(cert['notBefore'])
1147 after = ssl.cert_time_to_seconds(cert['notAfter'])
1148 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001149 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 finally:
1151 server.stop()
1152 server.join()
1153
Antoine Pitrou480a1242010-04-28 21:37:09 +00001154 def test_empty_cert(self):
1155 """Connecting with an empty cert file"""
1156 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1157 "nullcert.pem"))
1158 def test_malformed_cert(self):
1159 """Connecting with a badly formatted certificate (syntax error)"""
1160 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1161 "badcert.pem"))
1162 def test_nonexisting_cert(self):
1163 """Connecting with a non-existing cert file"""
1164 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1165 "wrongcert.pem"))
1166 def test_malformed_key(self):
1167 """Connecting with a badly formatted key (syntax error)"""
1168 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1169 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001170
Antoine Pitrou480a1242010-04-28 21:37:09 +00001171 def test_rude_shutdown(self):
1172 """A brutal shutdown of an SSL server should raise an IOError
1173 in the client when attempting handshake.
1174 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001175 listener_ready = threading.Event()
1176 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001177
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001178 s = socket.socket()
1179 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001180
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001181 # `listener` runs in a thread. It sits in an accept() until
1182 # the main thread connects. Then it rudely closes the socket,
1183 # and sets Event `listener_gone` to let the main thread know
1184 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001185 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001186 s.listen(5)
1187 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001188 newsock, addr = s.accept()
1189 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001190 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001191 listener_gone.set()
1192
1193 def connector():
1194 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001195 with socket.socket() as c:
1196 c.connect((HOST, port))
1197 listener_gone.wait()
1198 try:
1199 ssl_sock = ssl.wrap_socket(c)
1200 except IOError:
1201 pass
1202 else:
1203 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001204
1205 t = threading.Thread(target=listener)
1206 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001207 try:
1208 connector()
1209 finally:
1210 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001211
Antoine Pitrou23df4832010-08-04 17:14:06 +00001212 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001213 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1214 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001215 def test_protocol_sslv2(self):
1216 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001217 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001218 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001219 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1220 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1221 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1222 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1223 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1224 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001225 # SSLv23 client with specific SSL options
1226 if no_sslv2_implies_sslv3_hello():
1227 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1228 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1229 client_options=ssl.OP_NO_SSLv2)
1230 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1231 client_options=ssl.OP_NO_SSLv3)
1232 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1233 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234
Antoine Pitrou23df4832010-08-04 17:14:06 +00001235 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001236 def test_protocol_sslv23(self):
1237 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001238 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001239 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001240 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1241 try:
1242 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1243 except (ssl.SSLError, socket.error) as x:
1244 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1245 if support.verbose:
1246 sys.stdout.write(
1247 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1248 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1250 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1251 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001252
Antoine Pitrou480a1242010-04-28 21:37:09 +00001253 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1254 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1255 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001256
Antoine Pitrou480a1242010-04-28 21:37:09 +00001257 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1258 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1259 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001260
Antoine Pitroub5218772010-05-21 09:56:06 +00001261 # Server with specific SSL options
1262 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1263 server_options=ssl.OP_NO_SSLv3)
1264 # Will choose TLSv1
1265 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1266 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1267 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1268 server_options=ssl.OP_NO_TLSv1)
1269
1270
Antoine Pitrou23df4832010-08-04 17:14:06 +00001271 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001272 def test_protocol_sslv3(self):
1273 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001274 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001275 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001276 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1277 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1278 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001279 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1280 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001281 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1282 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001283 if no_sslv2_implies_sslv3_hello():
1284 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1285 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1286 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001287
Antoine Pitrou23df4832010-08-04 17:14:06 +00001288 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001289 def test_protocol_tlsv1(self):
1290 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001291 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001292 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001293 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1294 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1295 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001296 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1297 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1299 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001300
Antoine Pitrou480a1242010-04-28 21:37:09 +00001301 def test_starttls(self):
1302 """Switching from clear text to encrypted and back again."""
1303 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 +00001304
Trent Nelson78520002008-04-10 20:54:35 +00001305 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001306 ssl_version=ssl.PROTOCOL_TLSv1,
1307 starttls_server=True,
1308 chatty=True,
1309 connectionchatty=True)
1310 flag = threading.Event()
1311 server.start(flag)
1312 # wait for it to start
1313 flag.wait()
1314 # try to connect
1315 wrapped = False
1316 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001317 s = socket.socket()
1318 s.setblocking(1)
1319 s.connect((HOST, server.port))
1320 if support.verbose:
1321 sys.stdout.write("\n")
1322 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001323 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001324 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001325 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001326 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001327 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001328 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001329 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001330 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001331 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001332 msg = outdata.strip().lower()
1333 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1334 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001335 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001336 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001337 " client: read %r from server, starting TLS...\n"
1338 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001339 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1340 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1342 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001343 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001344 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001345 " client: read %r from server, ending TLS...\n"
1346 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001347 s = conn.unwrap()
1348 wrapped = False
1349 else:
1350 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001351 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001353 if support.verbose:
1354 sys.stdout.write(" client: closing connection.\n")
1355 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001356 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001357 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001358 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001359 if wrapped:
1360 conn.close()
1361 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001362 s.close()
1363 finally:
1364 server.stop()
1365 server.join()
1366
Antoine Pitrou480a1242010-04-28 21:37:09 +00001367 def test_socketserver(self):
1368 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001369 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001370 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001371 if support.verbose:
1372 sys.stdout.write('\n')
1373 with open(CERTFILE, 'rb') as f:
1374 d1 = f.read()
1375 d2 = ''
1376 # now fetch the same data from the HTTPS server
1377 url = 'https://%s:%d/%s' % (
1378 HOST, server.port, os.path.split(CERTFILE)[1])
1379 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001380 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001381 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001382 if dlen and (int(dlen) > 0):
1383 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001384 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001385 sys.stdout.write(
1386 " client: read %d bytes from remote server '%s'\n"
1387 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001388 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001389 f.close()
1390 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001391
Antoine Pitrou480a1242010-04-28 21:37:09 +00001392 def test_asyncore_server(self):
1393 """Check the example asyncore integration."""
1394 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001395
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001396 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001397 sys.stdout.write("\n")
1398
Antoine Pitrou480a1242010-04-28 21:37:09 +00001399 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001400 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001401 flag = threading.Event()
1402 server.start(flag)
1403 # wait for it to start
1404 flag.wait()
1405 # try to connect
1406 try:
1407 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001408 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001409 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001410 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001411 " client: sending %r...\n" % indata)
1412 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001413 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001414 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001415 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001416 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001417 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1419 % (outdata[:20], len(outdata),
1420 indata[:20].lower(), len(indata)))
1421 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001422 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001423 sys.stdout.write(" client: closing connection.\n")
1424 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001425 if support.verbose:
1426 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001427 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001428 if support.verbose:
1429 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001430 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001431 if support.verbose:
1432 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001433 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001434 if support.verbose:
1435 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001436
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 def test_recv_send(self):
1438 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001439 if support.verbose:
1440 sys.stdout.write("\n")
1441
1442 server = ThreadedEchoServer(CERTFILE,
1443 certreqs=ssl.CERT_NONE,
1444 ssl_version=ssl.PROTOCOL_TLSv1,
1445 cacerts=CERTFILE,
1446 chatty=True,
1447 connectionchatty=False)
1448 flag = threading.Event()
1449 server.start(flag)
1450 # wait for it to start
1451 flag.wait()
1452 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001453 s = ssl.wrap_socket(socket.socket(),
1454 server_side=False,
1455 certfile=CERTFILE,
1456 ca_certs=CERTFILE,
1457 cert_reqs=ssl.CERT_NONE,
1458 ssl_version=ssl.PROTOCOL_TLSv1)
1459 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001460 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001461 # helper methods for standardising recv* method signatures
1462 def _recv_into():
1463 b = bytearray(b"\0"*100)
1464 count = s.recv_into(b)
1465 return b[:count]
1466
1467 def _recvfrom_into():
1468 b = bytearray(b"\0"*100)
1469 count, addr = s.recvfrom_into(b)
1470 return b[:count]
1471
1472 # (name, method, whether to expect success, *args)
1473 send_methods = [
1474 ('send', s.send, True, []),
1475 ('sendto', s.sendto, False, ["some.address"]),
1476 ('sendall', s.sendall, True, []),
1477 ]
1478 recv_methods = [
1479 ('recv', s.recv, True, []),
1480 ('recvfrom', s.recvfrom, False, ["some.address"]),
1481 ('recv_into', _recv_into, True, []),
1482 ('recvfrom_into', _recvfrom_into, False, []),
1483 ]
1484 data_prefix = "PREFIX_"
1485
1486 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001487 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001488 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001489 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001490 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001491 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001492 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001493 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001494 "<<{outdata:r}>> ({nout:d}) received; "
1495 "expected <<{indata:r}>> ({nin:d})\n".format(
1496 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001497 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001498 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001499 )
1500 )
1501 except ValueError as e:
1502 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001503 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001504 "Failed to send with method <<{name:s}>>; "
1505 "expected to succeed.\n".format(name=meth_name)
1506 )
1507 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001508 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001509 "Method <<{name:s}>> failed with unexpected "
1510 "exception message: {exp:s}\n".format(
1511 name=meth_name, exp=e
1512 )
1513 )
1514
1515 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001516 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001517 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001518 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001519 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001520 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001521 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001522 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001523 "<<{outdata:r}>> ({nout:d}) received; "
1524 "expected <<{indata:r}>> ({nin:d})\n".format(
1525 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001526 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001527 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001528 )
1529 )
1530 except ValueError as e:
1531 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001532 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001533 "Failed to receive with method <<{name:s}>>; "
1534 "expected to succeed.\n".format(name=meth_name)
1535 )
1536 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001537 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001538 "Method <<{name:s}>> failed with unexpected "
1539 "exception message: {exp:s}\n".format(
1540 name=meth_name, exp=e
1541 )
1542 )
1543 # consume data
1544 s.read()
1545
Antoine Pitrou480a1242010-04-28 21:37:09 +00001546 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001547 s.close()
1548 finally:
1549 server.stop()
1550 server.join()
1551
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001552 def test_handshake_timeout(self):
1553 # Issue #5103: SSL handshake must respect the socket timeout
1554 server = socket.socket(socket.AF_INET)
1555 host = "127.0.0.1"
1556 port = support.bind_port(server)
1557 started = threading.Event()
1558 finish = False
1559
1560 def serve():
1561 server.listen(5)
1562 started.set()
1563 conns = []
1564 while not finish:
1565 r, w, e = select.select([server], [], [], 0.1)
1566 if server in r:
1567 # Let the socket hang around rather than having
1568 # it closed by garbage collection.
1569 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001570 for sock in conns:
1571 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001572
1573 t = threading.Thread(target=serve)
1574 t.start()
1575 started.wait()
1576
1577 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001578 try:
1579 c = socket.socket(socket.AF_INET)
1580 c.settimeout(0.2)
1581 c.connect((host, port))
1582 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001583 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001584 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001585 finally:
1586 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001587 try:
1588 c = socket.socket(socket.AF_INET)
1589 c = ssl.wrap_socket(c)
1590 c.settimeout(0.2)
1591 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001592 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001593 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001594 finally:
1595 c.close()
1596 finally:
1597 finish = True
1598 t.join()
1599 server.close()
1600
Bill Janssen58afe4c2008-09-08 16:45:19 +00001601
Thomas Woutersed03b412007-08-28 21:37:11 +00001602def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001603 if support.verbose:
1604 plats = {
1605 'Linux': platform.linux_distribution,
1606 'Mac': platform.mac_ver,
1607 'Windows': platform.win32_ver,
1608 }
1609 for name, func in plats.items():
1610 plat = func()
1611 if plat and plat[0]:
1612 plat = '%s %r' % (name, plat)
1613 break
1614 else:
1615 plat = repr(platform.platform())
1616 print("test_ssl: testing with %r %r" %
1617 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1618 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001619 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001620
Antoine Pitrou152efa22010-05-16 18:19:27 +00001621 for filename in [
1622 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1623 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1624 BADCERT, BADKEY, EMPTYCERT]:
1625 if not os.path.exists(filename):
1626 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001627
Antoine Pitrou152efa22010-05-16 18:19:27 +00001628 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001629
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001630 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001631 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001632
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001633 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001634 thread_info = support.threading_setup()
1635 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001636 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001637
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 try:
1639 support.run_unittest(*tests)
1640 finally:
1641 if _have_threads:
1642 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001643
1644if __name__ == "__main__":
1645 test_main()