blob: bf08f6fe1eb5dec412ef4d10e0fbf6e168284e1b [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
Jeremy Hylton1afc1692008-06-18 20:49:58 +000014import urllib.parse, 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
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000029else:
30 PROTOCOLS = [
31 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
32 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
33 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000034
Benjamin Petersonee8712c2008-05-20 21:35:26 +000035HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
37data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038
Antoine Pitrou81564092010-10-08 23:06:24 +000039# The custom key and certificate files used in test_ssl are generated
40# using Lib/test/make_ssl_certs.py.
41# Other certificates are simply fetched from the Internet servers they
42# are meant to authenticate.
43
Antoine Pitrou152efa22010-05-16 18:19:27 +000044CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000045BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000046ONLYCERT = data_file("ssl_cert.pem")
47ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000048BYTES_ONLYCERT = os.fsencode(ONLYCERT)
49BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000050CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000051BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000052
53SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
54
55EMPTYCERT = data_file("nullcert.pem")
56BADCERT = data_file("badcert.pem")
57WRONGCERT = data_file("XXXnonexisting.pem")
58BADKEY = data_file("badkey.pem")
59
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Thomas Woutersed03b412007-08-28 21:37:11 +000061def handle_error(prefix):
62 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000063 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000064 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000065
Antoine Pitroub5218772010-05-21 09:56:06 +000066def can_clear_options():
67 # 0.9.8m or higher
68 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
69
70def no_sslv2_implies_sslv3_hello():
71 # 0.9.7h or higher
72 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
73
Thomas Woutersed03b412007-08-28 21:37:11 +000074
Antoine Pitrou23df4832010-08-04 17:14:06 +000075# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
76def skip_if_broken_ubuntu_ssl(func):
77 @functools.wraps(func)
78 def f(*args, **kwargs):
79 try:
80 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
81 except ssl.SSLError:
82 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
83 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
84 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
85 return func(*args, **kwargs)
86 return f
87
88
Antoine Pitrou152efa22010-05-16 18:19:27 +000089class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000090
Antoine Pitrou480a1242010-04-28 21:37:09 +000091 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000092 ssl.PROTOCOL_SSLv2
93 ssl.PROTOCOL_SSLv23
94 ssl.PROTOCOL_SSLv3
95 ssl.PROTOCOL_TLSv1
96 ssl.CERT_NONE
97 ssl.CERT_OPTIONAL
98 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000099
Antoine Pitrou480a1242010-04-28 21:37:09 +0000100 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000102 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000103 sys.stdout.write("\n RAND_status is %d (%s)\n"
104 % (v, (v and "sufficient randomness") or
105 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000106 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000107 ssl.RAND_egd(1)
108 except TypeError:
109 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000110 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000111 print("didn't raise TypeError")
112 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000113
Antoine Pitrou480a1242010-04-28 21:37:09 +0000114 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 # note that this uses an 'unofficial' function in _ssl.c,
116 # provided solely for this test, to exercise the certificate
117 # parsing code
118 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000119 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000121
Antoine Pitrou480a1242010-04-28 21:37:09 +0000122 def test_DER_to_PEM(self):
123 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
124 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000125 d1 = ssl.PEM_cert_to_DER_cert(pem)
126 p2 = ssl.DER_cert_to_PEM_cert(d1)
127 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000128 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000129 if not p2.startswith(ssl.PEM_HEADER + '\n'):
130 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
131 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
132 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000133
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000134 def test_openssl_version(self):
135 n = ssl.OPENSSL_VERSION_NUMBER
136 t = ssl.OPENSSL_VERSION_INFO
137 s = ssl.OPENSSL_VERSION
138 self.assertIsInstance(n, int)
139 self.assertIsInstance(t, tuple)
140 self.assertIsInstance(s, str)
141 # Some sanity checks follow
142 # >= 0.9
143 self.assertGreaterEqual(n, 0x900000)
144 # < 2.0
145 self.assertLess(n, 0x20000000)
146 major, minor, fix, patch, status = t
147 self.assertGreaterEqual(major, 0)
148 self.assertLess(major, 2)
149 self.assertGreaterEqual(minor, 0)
150 self.assertLess(minor, 256)
151 self.assertGreaterEqual(fix, 0)
152 self.assertLess(fix, 256)
153 self.assertGreaterEqual(patch, 0)
154 self.assertLessEqual(patch, 26)
155 self.assertGreaterEqual(status, 0)
156 self.assertLessEqual(status, 15)
157 # Version string as returned by OpenSSL, the format might change
158 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
159 (s, t))
160
Antoine Pitrou9d543662010-04-23 23:10:32 +0000161 @support.cpython_only
162 def test_refcycle(self):
163 # Issue #7943: an SSL object doesn't create reference cycles with
164 # itself.
165 s = socket.socket(socket.AF_INET)
166 ss = ssl.wrap_socket(s)
167 wr = weakref.ref(ss)
168 del ss
169 self.assertEqual(wr(), None)
170
Antoine Pitroua468adc2010-09-14 14:43:44 +0000171 def test_wrapped_unconnected(self):
172 # Methods on an unconnected SSLSocket propagate the original
173 # socket.error raise by the underlying socket object.
174 s = socket.socket(socket.AF_INET)
175 ss = ssl.wrap_socket(s)
176 self.assertRaises(socket.error, ss.recv, 1)
177 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
178 self.assertRaises(socket.error, ss.recvfrom, 1)
179 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
180 self.assertRaises(socket.error, ss.send, b'x')
181 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
182
Antoine Pitrou40f08742010-04-24 22:04:40 +0000183 def test_timeout(self):
184 # Issue #8524: when creating an SSL socket, the timeout of the
185 # original socket should be retained.
186 for timeout in (None, 0.0, 5.0):
187 s = socket.socket(socket.AF_INET)
188 s.settimeout(timeout)
189 ss = ssl.wrap_socket(s)
190 self.assertEqual(timeout, ss.gettimeout())
191
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000192 def test_errors(self):
193 sock = socket.socket()
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000194 self.assertRaisesRegexp(ValueError,
195 "certfile must be specified",
196 ssl.wrap_socket, sock, keyfile=CERTFILE)
197 self.assertRaisesRegexp(ValueError,
198 "certfile must be specified for server-side operations",
199 ssl.wrap_socket, sock, server_side=True)
200 self.assertRaisesRegexp(ValueError,
201 "certfile must be specified for server-side operations",
202 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000203 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
204 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
205 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000206 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000207 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT)
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:
210 ssl.wrap_socket(socket.socket(), certfile=CERTFILE, keyfile=WRONGCERT)
211 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000212 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000213 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000214 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000215
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000216 def test_match_hostname(self):
217 def ok(cert, hostname):
218 ssl.match_hostname(cert, hostname)
219 def fail(cert, hostname):
220 self.assertRaises(ssl.CertificateError,
221 ssl.match_hostname, cert, hostname)
222
223 cert = {'subject': ((('commonName', 'example.com'),),)}
224 ok(cert, 'example.com')
225 ok(cert, 'ExAmple.cOm')
226 fail(cert, 'www.example.com')
227 fail(cert, '.example.com')
228 fail(cert, 'example.org')
229 fail(cert, 'exampleXcom')
230
231 cert = {'subject': ((('commonName', '*.a.com'),),)}
232 ok(cert, 'foo.a.com')
233 fail(cert, 'bar.foo.a.com')
234 fail(cert, 'a.com')
235 fail(cert, 'Xa.com')
236 fail(cert, '.a.com')
237
238 cert = {'subject': ((('commonName', 'a.*.com'),),)}
239 ok(cert, 'a.foo.com')
240 fail(cert, 'a..com')
241 fail(cert, 'a.com')
242
243 cert = {'subject': ((('commonName', 'f*.com'),),)}
244 ok(cert, 'foo.com')
245 ok(cert, 'f.com')
246 fail(cert, 'bar.com')
247 fail(cert, 'foo.a.com')
248 fail(cert, 'bar.foo.com')
249
250 # Slightly fake real-world example
251 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
252 'subject': ((('commonName', 'linuxfrz.org'),),),
253 'subjectAltName': (('DNS', 'linuxfr.org'),
254 ('DNS', 'linuxfr.com'),
255 ('othername', '<unsupported>'))}
256 ok(cert, 'linuxfr.org')
257 ok(cert, 'linuxfr.com')
258 # Not a "DNS" entry
259 fail(cert, '<unsupported>')
260 # When there is a subjectAltName, commonName isn't used
261 fail(cert, 'linuxfrz.org')
262
263 # A pristine real-world example
264 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
265 'subject': ((('countryName', 'US'),),
266 (('stateOrProvinceName', 'California'),),
267 (('localityName', 'Mountain View'),),
268 (('organizationName', 'Google Inc'),),
269 (('commonName', 'mail.google.com'),))}
270 ok(cert, 'mail.google.com')
271 fail(cert, 'gmail.com')
272 # Only commonName is considered
273 fail(cert, 'California')
274
275 # Neither commonName nor subjectAltName
276 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
277 'subject': ((('countryName', 'US'),),
278 (('stateOrProvinceName', 'California'),),
279 (('localityName', 'Mountain View'),),
280 (('organizationName', 'Google Inc'),))}
281 fail(cert, 'mail.google.com')
282
283 # Empty cert / no cert
284 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
285 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
286
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000287
Antoine Pitrou152efa22010-05-16 18:19:27 +0000288class ContextTests(unittest.TestCase):
289
Antoine Pitrou23df4832010-08-04 17:14:06 +0000290 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000291 def test_constructor(self):
292 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
293 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
294 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
295 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
296 self.assertRaises(TypeError, ssl.SSLContext)
297 self.assertRaises(ValueError, ssl.SSLContext, -1)
298 self.assertRaises(ValueError, ssl.SSLContext, 42)
299
Antoine Pitrou23df4832010-08-04 17:14:06 +0000300 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000301 def test_protocol(self):
302 for proto in PROTOCOLS:
303 ctx = ssl.SSLContext(proto)
304 self.assertEqual(ctx.protocol, proto)
305
306 def test_ciphers(self):
307 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
308 ctx.set_ciphers("ALL")
309 ctx.set_ciphers("DEFAULT")
310 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000311 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000312
Antoine Pitrou23df4832010-08-04 17:14:06 +0000313 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000314 def test_options(self):
315 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
316 # OP_ALL is the default value
317 self.assertEqual(ssl.OP_ALL, ctx.options)
318 ctx.options |= ssl.OP_NO_SSLv2
319 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
320 ctx.options)
321 ctx.options |= ssl.OP_NO_SSLv3
322 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
323 ctx.options)
324 if can_clear_options():
325 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
326 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
327 ctx.options)
328 ctx.options = 0
329 self.assertEqual(0, ctx.options)
330 else:
331 with self.assertRaises(ValueError):
332 ctx.options = 0
333
Antoine Pitrou152efa22010-05-16 18:19:27 +0000334 def test_verify(self):
335 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
336 # Default value
337 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
338 ctx.verify_mode = ssl.CERT_OPTIONAL
339 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
340 ctx.verify_mode = ssl.CERT_REQUIRED
341 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
342 ctx.verify_mode = ssl.CERT_NONE
343 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
344 with self.assertRaises(TypeError):
345 ctx.verify_mode = None
346 with self.assertRaises(ValueError):
347 ctx.verify_mode = 42
348
349 def test_load_cert_chain(self):
350 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
351 # Combined key and cert in a single file
352 ctx.load_cert_chain(CERTFILE)
353 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
354 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000355 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000356 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000357 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000358 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
359 ctx.load_cert_chain(BADCERT)
360 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
361 ctx.load_cert_chain(EMPTYCERT)
362 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000363 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000364 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
365 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
366 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
367 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
368 ctx.load_cert_chain(ONLYCERT)
369 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
370 ctx.load_cert_chain(ONLYKEY)
371 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
372 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
373 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000374 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000375 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000376 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000377
378 def test_load_verify_locations(self):
379 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
380 ctx.load_verify_locations(CERTFILE)
381 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
382 ctx.load_verify_locations(BYTES_CERTFILE)
383 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
384 self.assertRaises(TypeError, ctx.load_verify_locations)
385 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000386 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000387 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000388 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000389 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
390 ctx.load_verify_locations(BADCERT)
391 ctx.load_verify_locations(CERTFILE, CAPATH)
392 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
393
Antoine Pitroub0182c82010-10-12 20:09:02 +0000394 def test_session_stats(self):
395 for proto in PROTOCOLS:
396 ctx = ssl.SSLContext(proto)
397 self.assertEqual(ctx.session_stats(), {
398 'number': 0,
399 'connect': 0,
400 'connect_good': 0,
401 'connect_renegotiate': 0,
402 'accept': 0,
403 'accept_good': 0,
404 'accept_renegotiate': 0,
405 'hits': 0,
406 'misses': 0,
407 'timeouts': 0,
408 'cache_full': 0,
409 })
410
Antoine Pitrou152efa22010-05-16 18:19:27 +0000411
Bill Janssen6e027db2007-11-15 22:23:56 +0000412class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000413
Antoine Pitrou480a1242010-04-28 21:37:09 +0000414 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000415 with support.transient_internet("svn.python.org"):
416 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
417 cert_reqs=ssl.CERT_NONE)
418 try:
419 s.connect(("svn.python.org", 443))
420 self.assertEqual({}, s.getpeercert())
421 finally:
422 s.close()
423
424 # this should fail because we have no verification certs
425 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
426 cert_reqs=ssl.CERT_REQUIRED)
427 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
428 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000429 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000430
Antoine Pitrou350c7222010-09-09 13:31:46 +0000431 # this should succeed because we specify the root cert
432 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
433 cert_reqs=ssl.CERT_REQUIRED,
434 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
435 try:
436 s.connect(("svn.python.org", 443))
437 self.assertTrue(s.getpeercert())
438 finally:
439 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000440
441 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000442 with support.transient_internet("svn.python.org"):
443 # Same as test_connect, but with a separately created context
444 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
445 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
446 s.connect(("svn.python.org", 443))
447 try:
448 self.assertEqual({}, s.getpeercert())
449 finally:
450 s.close()
451 # This should fail because we have no verification certs
452 ctx.verify_mode = ssl.CERT_REQUIRED
453 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
454 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
455 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000456 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000457 # This should succeed because we specify the root cert
458 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
459 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
460 s.connect(("svn.python.org", 443))
461 try:
462 cert = s.getpeercert()
463 self.assertTrue(cert)
464 finally:
465 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466
467 def test_connect_capath(self):
468 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000469 # NOTE: the subject hashing algorithm has been changed between
470 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
471 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000472 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000473 with support.transient_internet("svn.python.org"):
474 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
475 ctx.verify_mode = ssl.CERT_REQUIRED
476 ctx.load_verify_locations(capath=CAPATH)
477 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
478 s.connect(("svn.python.org", 443))
479 try:
480 cert = s.getpeercert()
481 self.assertTrue(cert)
482 finally:
483 s.close()
484 # Same with a bytes `capath` argument
485 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
486 ctx.verify_mode = ssl.CERT_REQUIRED
487 ctx.load_verify_locations(capath=BYTES_CAPATH)
488 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
489 s.connect(("svn.python.org", 443))
490 try:
491 cert = s.getpeercert()
492 self.assertTrue(cert)
493 finally:
494 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000495
Antoine Pitroue3220242010-04-24 11:13:53 +0000496 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
497 def test_makefile_close(self):
498 # Issue #5238: creating a file-like object with makefile() shouldn't
499 # delay closing the underlying "real socket" (here tested with its
500 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000501 with support.transient_internet("svn.python.org"):
502 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
503 ss.connect(("svn.python.org", 443))
504 fd = ss.fileno()
505 f = ss.makefile()
506 f.close()
507 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000508 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000509 # Closing the SSL socket should close the fd too
510 ss.close()
511 gc.collect()
512 with self.assertRaises(OSError) as e:
513 os.read(fd, 0)
514 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000515
Antoine Pitrou480a1242010-04-28 21:37:09 +0000516 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000517 with support.transient_internet("svn.python.org"):
518 s = socket.socket(socket.AF_INET)
519 s.connect(("svn.python.org", 443))
520 s.setblocking(False)
521 s = ssl.wrap_socket(s,
522 cert_reqs=ssl.CERT_NONE,
523 do_handshake_on_connect=False)
524 count = 0
525 while True:
526 try:
527 count += 1
528 s.do_handshake()
529 break
530 except ssl.SSLError as err:
531 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
532 select.select([s], [], [])
533 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
534 select.select([], [s], [])
535 else:
536 raise
537 s.close()
538 if support.verbose:
539 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000540
Antoine Pitrou480a1242010-04-28 21:37:09 +0000541 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000542 with support.transient_internet("svn.python.org"):
543 pem = ssl.get_server_certificate(("svn.python.org", 443))
544 if not pem:
545 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000546
Antoine Pitrou350c7222010-09-09 13:31:46 +0000547 try:
548 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
549 except ssl.SSLError as x:
550 #should fail
551 if support.verbose:
552 sys.stdout.write("%s\n" % x)
553 else:
554 self.fail("Got server certificate %s for svn.python.org!" % pem)
555
556 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
557 if not pem:
558 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000559 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000560 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000561
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000562 def test_ciphers(self):
563 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000564 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000565 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000566 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000567 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000568 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
569 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
570 s.connect(remote)
571 # Error checking can happen at instantiation or when connecting
572 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
573 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
574 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
575 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000576
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000577 def test_algorithms(self):
578 # Issue #8484: all algorithms should be available when verifying a
579 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000580 # SHA256 was added in OpenSSL 0.9.8
581 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
582 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000583 # NOTE: https://sha256.tbs-internet.com is another possible test host
584 remote = ("sha2.hboeck.de", 443)
585 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000586 with support.transient_internet("sha2.hboeck.de"):
587 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
588 cert_reqs=ssl.CERT_REQUIRED,
589 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000590 try:
591 s.connect(remote)
592 if support.verbose:
593 sys.stdout.write("\nCipher with %r is %r\n" %
594 (remote, s.cipher()))
595 sys.stdout.write("Certificate is:\n%s\n" %
596 pprint.pformat(s.getpeercert()))
597 finally:
598 s.close()
599
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000600
601try:
602 import threading
603except ImportError:
604 _have_threads = False
605else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000606 _have_threads = True
607
608 class ThreadedEchoServer(threading.Thread):
609
610 class ConnectionHandler(threading.Thread):
611
612 """A mildly complicated class, because we want it to work both
613 with and without the SSL wrapper around the socket connection, so
614 that we can test the STARTTLS functionality."""
615
Bill Janssen6e027db2007-11-15 22:23:56 +0000616 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000617 self.server = server
618 self.running = False
619 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000620 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000621 self.sock.setblocking(1)
622 self.sslconn = None
623 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000624 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000625
Antoine Pitrou480a1242010-04-28 21:37:09 +0000626 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000628 self.sslconn = self.server.context.wrap_socket(
629 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000630 except ssl.SSLError:
631 # XXX Various errors can have happened here, for example
632 # a mismatching protocol version, an invalid certificate,
633 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000635 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000636 self.running = False
637 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000638 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000640 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000641 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000642 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000643 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000644 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
645 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000646 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000647 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
648 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000649 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000650 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
651 return True
652
653 def read(self):
654 if self.sslconn:
655 return self.sslconn.read()
656 else:
657 return self.sock.recv(1024)
658
659 def write(self, bytes):
660 if self.sslconn:
661 return self.sslconn.write(bytes)
662 else:
663 return self.sock.send(bytes)
664
665 def close(self):
666 if self.sslconn:
667 self.sslconn.close()
668 else:
669 self.sock.close()
670
Antoine Pitrou480a1242010-04-28 21:37:09 +0000671 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000672 self.running = True
673 if not self.server.starttls_server:
674 if not self.wrap_conn():
675 return
676 while self.running:
677 try:
678 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000679 stripped = msg.strip()
680 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000681 # eof, so quit this handler
682 self.running = False
683 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000684 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000685 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000686 sys.stdout.write(" server: client closed connection\n")
687 self.close()
688 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000689 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000690 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000691 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000692 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000693 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000694 if not self.wrap_conn():
695 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000696 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000697 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000698 if support.verbose and self.server.connectionchatty:
699 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000700 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000701 self.sock = self.sslconn.unwrap()
702 self.sslconn = None
703 if support.verbose and self.server.connectionchatty:
704 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000706 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000707 self.server.connectionchatty):
708 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000709 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
710 % (msg, ctype, msg.lower(), ctype))
711 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000712 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000713 if self.server.chatty:
714 handle_error("Test server failure:\n")
715 self.close()
716 self.running = False
717 # normally, we'd just stop here, but for the test
718 # harness, we want to stop the server
719 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000720
Antoine Pitroub5218772010-05-21 09:56:06 +0000721 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000722 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000723 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000724 ciphers=None, context=None):
725 if context:
726 self.context = context
727 else:
728 self.context = ssl.SSLContext(ssl_version
729 if ssl_version is not None
730 else ssl.PROTOCOL_TLSv1)
731 self.context.verify_mode = (certreqs if certreqs is not None
732 else ssl.CERT_NONE)
733 if cacerts:
734 self.context.load_verify_locations(cacerts)
735 if certificate:
736 self.context.load_cert_chain(certificate)
737 if ciphers:
738 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 self.chatty = chatty
740 self.connectionchatty = connectionchatty
741 self.starttls_server = starttls_server
742 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000743 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000744 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000745 self.active = False
746 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000747 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000748
Antoine Pitrou480a1242010-04-28 21:37:09 +0000749 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750 self.flag = flag
751 threading.Thread.start(self)
752
Antoine Pitrou480a1242010-04-28 21:37:09 +0000753 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000754 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000755 self.sock.listen(5)
756 self.active = True
757 if self.flag:
758 # signal an event
759 self.flag.set()
760 while self.active:
761 try:
762 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000763 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000764 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000765 + repr(connaddr) + '\n')
766 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000767 handler.start()
768 except socket.timeout:
769 pass
770 except KeyboardInterrupt:
771 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000772 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000773
Antoine Pitrou480a1242010-04-28 21:37:09 +0000774 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000775 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000776
Bill Janssen54cc54c2007-12-14 22:08:56 +0000777 class OurHTTPSServer(threading.Thread):
778
779 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000780
781 class HTTPSServer(HTTPServer):
782
783 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000784 HTTPServer.__init__(self, server_address, RequestHandlerClass)
785 # we assume the certfile contains both private key and certificate
786 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787 self.allow_reuse_address = True
788
Bill Janssen6e027db2007-11-15 22:23:56 +0000789 def __str__(self):
790 return ('<%s %s:%s>' %
791 (self.__class__.__name__,
792 self.server_name,
793 self.server_port))
794
Antoine Pitrou480a1242010-04-28 21:37:09 +0000795 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000796 # override this to wrap socket with SSL
797 sock, addr = self.socket.accept()
798 sslconn = ssl.wrap_socket(sock, server_side=True,
799 certfile=self.certfile)
800 return sslconn, addr
801
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000802 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000803 # need to override translate_path to get a known root,
804 # instead of using os.curdir, since the test could be
805 # run from anywhere
806
807 server_version = "TestHTTPS/1.0"
808
809 root = None
810
811 def translate_path(self, path):
812 """Translate a /-separated PATH to the local filename syntax.
813
814 Components that mean special things to the local file system
815 (e.g. drive or directory names) are ignored. (XXX They should
816 probably be diagnosed.)
817
818 """
819 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000820 path = urllib.parse.urlparse(path)[2]
821 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000822 words = path.split('/')
823 words = filter(None, words)
824 path = self.root
825 for word in words:
826 drive, word = os.path.splitdrive(word)
827 head, word = os.path.split(word)
828 if word in self.root: continue
829 path = os.path.join(path, word)
830 return path
831
832 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000833 # we override this to suppress logging unless "verbose"
834
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000835 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000836 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
837 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000838 self.server.server_port,
839 self.request.cipher(),
840 self.log_date_time_string(),
841 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000842
843
Trent Nelson78520002008-04-10 20:54:35 +0000844 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000845 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
847 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000848 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
849 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000850 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000851 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000852
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000854 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000855
Antoine Pitrou480a1242010-04-28 21:37:09 +0000856 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000857 self.flag = flag
858 threading.Thread.start(self)
859
Antoine Pitrou480a1242010-04-28 21:37:09 +0000860 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 if self.flag:
862 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000863 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000864
Antoine Pitrou480a1242010-04-28 21:37:09 +0000865 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000866 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000867
868
Bill Janssen54cc54c2007-12-14 22:08:56 +0000869 class AsyncoreEchoServer(threading.Thread):
870
871 # this one's based on asyncore.dispatcher
872
873 class EchoServer (asyncore.dispatcher):
874
875 class ConnectionHandler (asyncore.dispatcher_with_send):
876
877 def __init__(self, conn, certfile):
878 self.socket = ssl.wrap_socket(conn, server_side=True,
879 certfile=certfile,
880 do_handshake_on_connect=False)
881 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000882 self._ssl_accepting = True
883 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000884
885 def readable(self):
886 if isinstance(self.socket, ssl.SSLSocket):
887 while self.socket.pending() > 0:
888 self.handle_read_event()
889 return True
890
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000891 def _do_ssl_handshake(self):
892 try:
893 self.socket.do_handshake()
894 except ssl.SSLError as err:
895 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
896 ssl.SSL_ERROR_WANT_WRITE):
897 return
898 elif err.args[0] == ssl.SSL_ERROR_EOF:
899 return self.handle_close()
900 raise
901 except socket.error as err:
902 if err.args[0] == errno.ECONNABORTED:
903 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000904 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000905 self._ssl_accepting = False
906
907 def handle_read(self):
908 if self._ssl_accepting:
909 self._do_ssl_handshake()
910 else:
911 data = self.recv(1024)
912 if support.verbose:
913 sys.stdout.write(" server: read %s from client\n" % repr(data))
914 if not data:
915 self.close()
916 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000917 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000918
919 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000920 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000921 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000922 sys.stdout.write(" server: closed connection %s\n" % self.socket)
923
924 def handle_error(self):
925 raise
926
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000927 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000928 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000929 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
930 self.port = support.bind_port(sock, '')
931 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000932 self.listen(5)
933
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000934 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000935 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000936 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
937 self.ConnectionHandler(sock_obj, self.certfile)
938
939 def handle_error(self):
940 raise
941
Trent Nelson78520002008-04-10 20:54:35 +0000942 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000943 self.flag = None
944 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000945 self.server = self.EchoServer(certfile)
946 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000947 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000948 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000949
950 def __str__(self):
951 return "<%s %s>" % (self.__class__.__name__, self.server)
952
953 def start (self, flag=None):
954 self.flag = flag
955 threading.Thread.start(self)
956
Antoine Pitrou480a1242010-04-28 21:37:09 +0000957 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000958 self.active = True
959 if self.flag:
960 self.flag.set()
961 while self.active:
962 try:
963 asyncore.loop(1)
964 except:
965 pass
966
Antoine Pitrou480a1242010-04-28 21:37:09 +0000967 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000968 self.active = False
969 self.server.close()
970
Antoine Pitrou480a1242010-04-28 21:37:09 +0000971 def bad_cert_test(certfile):
972 """
973 Launch a server with CERT_REQUIRED, and check that trying to
974 connect to it with the given client certificate fails.
975 """
Trent Nelson78520002008-04-10 20:54:35 +0000976 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000977 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000978 cacerts=CERTFILE, chatty=False,
979 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980 flag = threading.Event()
981 server.start(flag)
982 # wait for it to start
983 flag.wait()
984 # try to connect
985 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000986 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000987 s = ssl.wrap_socket(socket.socket(),
988 certfile=certfile,
989 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000990 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000992 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000993 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000994 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000995 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000996 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000997 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000998 if x.errno != errno.ENOENT:
999 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001000 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001001 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001003 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004 finally:
1005 server.stop()
1006 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001007
Antoine Pitroub5218772010-05-21 09:56:06 +00001008 def server_params_test(client_context, server_context, indata=b"FOO\n",
1009 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001010 """
1011 Launch a server, connect a client to it and try various reads
1012 and writes.
1013 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001014 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001015 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001016 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001017 flag = threading.Event()
1018 server.start(flag)
1019 # wait for it to start
1020 flag.wait()
1021 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001022 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001023 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001024 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001025 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001026 if connectionchatty:
1027 if support.verbose:
1028 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001029 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001030 s.write(arg)
1031 outdata = s.read()
1032 if connectionchatty:
1033 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001034 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001035 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001036 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001037 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1038 % (outdata[:20], len(outdata),
1039 indata[:20].lower(), len(indata)))
1040 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001041 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001042 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001043 sys.stdout.write(" client: closing connection.\n")
1044 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001045 finally:
1046 server.stop()
1047 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001048
Antoine Pitroub5218772010-05-21 09:56:06 +00001049 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1050 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001051 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001052 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001053 certtype = {
1054 ssl.CERT_NONE: "CERT_NONE",
1055 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1056 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1057 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001058 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001059 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001060 sys.stdout.write(formatstr %
1061 (ssl.get_protocol_name(client_protocol),
1062 ssl.get_protocol_name(server_protocol),
1063 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001064 client_context = ssl.SSLContext(client_protocol)
1065 client_context.options = ssl.OP_ALL | client_options
1066 server_context = ssl.SSLContext(server_protocol)
1067 server_context.options = ssl.OP_ALL | server_options
1068 for ctx in (client_context, server_context):
1069 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001070 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1071 # will send an SSLv3 hello (rather than SSLv2) starting from
1072 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001073 ctx.set_ciphers("ALL")
1074 ctx.load_cert_chain(CERTFILE)
1075 ctx.load_verify_locations(CERTFILE)
1076 try:
1077 server_params_test(client_context, server_context,
1078 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001079 # Protocol mismatch can result in either an SSLError, or a
1080 # "Connection reset by peer" error.
1081 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001082 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001083 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001084 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001085 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001086 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001087 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001088 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001089 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001090 "Client protocol %s succeeded with server protocol %s!"
1091 % (ssl.get_protocol_name(client_protocol),
1092 ssl.get_protocol_name(server_protocol)))
1093
1094
Bill Janssen6e027db2007-11-15 22:23:56 +00001095 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001096
Antoine Pitrou23df4832010-08-04 17:14:06 +00001097 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001098 def test_echo(self):
1099 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001100 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001101 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001102 for protocol in PROTOCOLS:
1103 context = ssl.SSLContext(protocol)
1104 context.load_cert_chain(CERTFILE)
1105 server_params_test(context, context,
1106 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001107
Antoine Pitrou480a1242010-04-28 21:37:09 +00001108 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001109 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001110 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001111 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1112 context.verify_mode = ssl.CERT_REQUIRED
1113 context.load_verify_locations(CERTFILE)
1114 context.load_cert_chain(CERTFILE)
1115 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001116 flag = threading.Event()
1117 server.start(flag)
1118 # wait for it to start
1119 flag.wait()
1120 # try to connect
1121 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001122 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001123 s.connect((HOST, server.port))
1124 cert = s.getpeercert()
1125 self.assertTrue(cert, "Can't get peer certificate.")
1126 cipher = s.cipher()
1127 if support.verbose:
1128 sys.stdout.write(pprint.pformat(cert) + '\n')
1129 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1130 if 'subject' not in cert:
1131 self.fail("No subject field in certificate: %s." %
1132 pprint.pformat(cert))
1133 if ((('organizationName', 'Python Software Foundation'),)
1134 not in cert['subject']):
1135 self.fail(
1136 "Missing or invalid 'organizationName' field in certificate subject; "
1137 "should be 'Python Software Foundation'.")
1138 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001139 finally:
1140 server.stop()
1141 server.join()
1142
Antoine Pitrou480a1242010-04-28 21:37:09 +00001143 def test_empty_cert(self):
1144 """Connecting with an empty cert file"""
1145 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1146 "nullcert.pem"))
1147 def test_malformed_cert(self):
1148 """Connecting with a badly formatted certificate (syntax error)"""
1149 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1150 "badcert.pem"))
1151 def test_nonexisting_cert(self):
1152 """Connecting with a non-existing cert file"""
1153 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1154 "wrongcert.pem"))
1155 def test_malformed_key(self):
1156 """Connecting with a badly formatted key (syntax error)"""
1157 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1158 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001159
Antoine Pitrou480a1242010-04-28 21:37:09 +00001160 def test_rude_shutdown(self):
1161 """A brutal shutdown of an SSL server should raise an IOError
1162 in the client when attempting handshake.
1163 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001164 listener_ready = threading.Event()
1165 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001166
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001167 s = socket.socket()
1168 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001169
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001170 # `listener` runs in a thread. It sits in an accept() until
1171 # the main thread connects. Then it rudely closes the socket,
1172 # and sets Event `listener_gone` to let the main thread know
1173 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001174 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001175 s.listen(5)
1176 listener_ready.set()
1177 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001178 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001179 listener_gone.set()
1180
1181 def connector():
1182 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001183 c = socket.socket()
1184 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001185 listener_gone.wait()
1186 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001187 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001188 except IOError:
1189 pass
1190 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001191 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001192
1193 t = threading.Thread(target=listener)
1194 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001195 try:
1196 connector()
1197 finally:
1198 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001199
Antoine Pitrou23df4832010-08-04 17:14:06 +00001200 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001201 def test_protocol_sslv2(self):
1202 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001203 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001204 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1206 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1207 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1208 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1209 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1210 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001211 # SSLv23 client with specific SSL options
1212 if no_sslv2_implies_sslv3_hello():
1213 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1214 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1215 client_options=ssl.OP_NO_SSLv2)
1216 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1217 client_options=ssl.OP_NO_SSLv3)
1218 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1219 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001220
Antoine Pitrou23df4832010-08-04 17:14:06 +00001221 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001222 def test_protocol_sslv23(self):
1223 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001224 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001225 sys.stdout.write("\n")
1226 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001227 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001228 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001229 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001230 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 sys.stdout.write(
1232 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1233 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001234 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1235 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1236 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001237
Antoine Pitrou480a1242010-04-28 21:37:09 +00001238 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1239 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1240 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1243 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1244 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001245
Antoine Pitroub5218772010-05-21 09:56:06 +00001246 # Server with specific SSL options
1247 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1248 server_options=ssl.OP_NO_SSLv3)
1249 # Will choose TLSv1
1250 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1251 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1252 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1253 server_options=ssl.OP_NO_TLSv1)
1254
1255
Antoine Pitrou23df4832010-08-04 17:14:06 +00001256 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001257 def test_protocol_sslv3(self):
1258 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001259 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001260 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001261 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1262 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1263 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1264 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1265 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1266 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001267 if no_sslv2_implies_sslv3_hello():
1268 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1269 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1270 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001271
Antoine Pitrou23df4832010-08-04 17:14:06 +00001272 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001273 def test_protocol_tlsv1(self):
1274 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001275 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001276 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001277 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1278 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1279 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1280 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1281 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1282 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001283
Antoine Pitrou480a1242010-04-28 21:37:09 +00001284 def test_starttls(self):
1285 """Switching from clear text to encrypted and back again."""
1286 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 +00001287
Trent Nelson78520002008-04-10 20:54:35 +00001288 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001289 ssl_version=ssl.PROTOCOL_TLSv1,
1290 starttls_server=True,
1291 chatty=True,
1292 connectionchatty=True)
1293 flag = threading.Event()
1294 server.start(flag)
1295 # wait for it to start
1296 flag.wait()
1297 # try to connect
1298 wrapped = False
1299 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001300 s = socket.socket()
1301 s.setblocking(1)
1302 s.connect((HOST, server.port))
1303 if support.verbose:
1304 sys.stdout.write("\n")
1305 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001306 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001307 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001308 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001309 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001310 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001311 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001312 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001313 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001314 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001315 msg = outdata.strip().lower()
1316 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1317 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001318 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001319 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001320 " client: read %r from server, starting TLS...\n"
1321 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001322 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1323 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001324 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1325 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001326 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001327 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001328 " client: read %r from server, ending TLS...\n"
1329 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001330 s = conn.unwrap()
1331 wrapped = False
1332 else:
1333 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001334 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001335 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001336 if support.verbose:
1337 sys.stdout.write(" client: closing connection.\n")
1338 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001339 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001340 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001342 if wrapped:
1343 conn.close()
1344 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001345 s.close()
1346 finally:
1347 server.stop()
1348 server.join()
1349
Antoine Pitrou480a1242010-04-28 21:37:09 +00001350 def test_socketserver(self):
1351 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001352 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001353 flag = threading.Event()
1354 server.start(flag)
1355 # wait for it to start
1356 flag.wait()
1357 # try to connect
1358 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001359 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001360 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001361 with open(CERTFILE, 'rb') as f:
1362 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001363 d2 = ''
1364 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001365 url = 'https://%s:%d/%s' % (
1366 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001367 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001368 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001369 if dlen and (int(dlen) > 0):
1370 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001371 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001372 sys.stdout.write(
1373 " client: read %d bytes from remote server '%s'\n"
1374 % (len(d2), server))
1375 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001376 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001377 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001378 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001379 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001380 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001381 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001382 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001383 server.join()
1384
Antoine Pitrou480a1242010-04-28 21:37:09 +00001385 def test_asyncore_server(self):
1386 """Check the example asyncore integration."""
1387 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001388
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001389 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001390 sys.stdout.write("\n")
1391
Antoine Pitrou480a1242010-04-28 21:37:09 +00001392 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001393 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001394 flag = threading.Event()
1395 server.start(flag)
1396 # wait for it to start
1397 flag.wait()
1398 # try to connect
1399 try:
1400 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001401 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001402 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001403 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001404 " client: sending %r...\n" % indata)
1405 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001406 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001407 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001408 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001409 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001410 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001411 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1412 % (outdata[:20], len(outdata),
1413 indata[:20].lower(), len(indata)))
1414 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001415 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001416 sys.stdout.write(" client: closing connection.\n")
1417 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001418 if support.verbose:
1419 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001420 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001421 if support.verbose:
1422 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001423 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001424 if support.verbose:
1425 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001426 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001427 if support.verbose:
1428 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001429
Antoine Pitrou480a1242010-04-28 21:37:09 +00001430 def test_recv_send(self):
1431 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001432 if support.verbose:
1433 sys.stdout.write("\n")
1434
1435 server = ThreadedEchoServer(CERTFILE,
1436 certreqs=ssl.CERT_NONE,
1437 ssl_version=ssl.PROTOCOL_TLSv1,
1438 cacerts=CERTFILE,
1439 chatty=True,
1440 connectionchatty=False)
1441 flag = threading.Event()
1442 server.start(flag)
1443 # wait for it to start
1444 flag.wait()
1445 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001446 s = ssl.wrap_socket(socket.socket(),
1447 server_side=False,
1448 certfile=CERTFILE,
1449 ca_certs=CERTFILE,
1450 cert_reqs=ssl.CERT_NONE,
1451 ssl_version=ssl.PROTOCOL_TLSv1)
1452 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001453 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001454 # helper methods for standardising recv* method signatures
1455 def _recv_into():
1456 b = bytearray(b"\0"*100)
1457 count = s.recv_into(b)
1458 return b[:count]
1459
1460 def _recvfrom_into():
1461 b = bytearray(b"\0"*100)
1462 count, addr = s.recvfrom_into(b)
1463 return b[:count]
1464
1465 # (name, method, whether to expect success, *args)
1466 send_methods = [
1467 ('send', s.send, True, []),
1468 ('sendto', s.sendto, False, ["some.address"]),
1469 ('sendall', s.sendall, True, []),
1470 ]
1471 recv_methods = [
1472 ('recv', s.recv, True, []),
1473 ('recvfrom', s.recvfrom, False, ["some.address"]),
1474 ('recv_into', _recv_into, True, []),
1475 ('recvfrom_into', _recvfrom_into, False, []),
1476 ]
1477 data_prefix = "PREFIX_"
1478
1479 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001480 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001481 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001482 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001483 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001484 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001485 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001486 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001487 "<<{outdata:r}>> ({nout:d}) received; "
1488 "expected <<{indata:r}>> ({nin:d})\n".format(
1489 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001490 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001492 )
1493 )
1494 except ValueError as e:
1495 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001496 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001497 "Failed to send with method <<{name:s}>>; "
1498 "expected to succeed.\n".format(name=meth_name)
1499 )
1500 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001501 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001502 "Method <<{name:s}>> failed with unexpected "
1503 "exception message: {exp:s}\n".format(
1504 name=meth_name, exp=e
1505 )
1506 )
1507
1508 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001509 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001510 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001511 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001512 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001513 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001514 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001515 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001516 "<<{outdata:r}>> ({nout:d}) received; "
1517 "expected <<{indata:r}>> ({nin:d})\n".format(
1518 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001519 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001520 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001521 )
1522 )
1523 except ValueError as e:
1524 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001525 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001526 "Failed to receive with method <<{name:s}>>; "
1527 "expected to succeed.\n".format(name=meth_name)
1528 )
1529 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001530 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001531 "Method <<{name:s}>> failed with unexpected "
1532 "exception message: {exp:s}\n".format(
1533 name=meth_name, exp=e
1534 )
1535 )
1536 # consume data
1537 s.read()
1538
Antoine Pitrou480a1242010-04-28 21:37:09 +00001539 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001540 s.close()
1541 finally:
1542 server.stop()
1543 server.join()
1544
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001545 def test_handshake_timeout(self):
1546 # Issue #5103: SSL handshake must respect the socket timeout
1547 server = socket.socket(socket.AF_INET)
1548 host = "127.0.0.1"
1549 port = support.bind_port(server)
1550 started = threading.Event()
1551 finish = False
1552
1553 def serve():
1554 server.listen(5)
1555 started.set()
1556 conns = []
1557 while not finish:
1558 r, w, e = select.select([server], [], [], 0.1)
1559 if server in r:
1560 # Let the socket hang around rather than having
1561 # it closed by garbage collection.
1562 conns.append(server.accept()[0])
1563
1564 t = threading.Thread(target=serve)
1565 t.start()
1566 started.wait()
1567
1568 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001569 try:
1570 c = socket.socket(socket.AF_INET)
1571 c.settimeout(0.2)
1572 c.connect((host, port))
1573 # Will attempt handshake and time out
1574 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1575 ssl.wrap_socket, c)
1576 finally:
1577 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001578 try:
1579 c = socket.socket(socket.AF_INET)
1580 c = ssl.wrap_socket(c)
1581 c.settimeout(0.2)
1582 # Will attempt handshake and time out
1583 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1584 c.connect, (host, port))
1585 finally:
1586 c.close()
1587 finally:
1588 finish = True
1589 t.join()
1590 server.close()
1591
Bill Janssen58afe4c2008-09-08 16:45:19 +00001592
Thomas Woutersed03b412007-08-28 21:37:11 +00001593def test_main(verbose=False):
1594 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001595 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001596
Antoine Pitrou15cee622010-08-04 16:45:21 +00001597 if support.verbose:
1598 plats = {
1599 'Linux': platform.linux_distribution,
1600 'Mac': platform.mac_ver,
1601 'Windows': platform.win32_ver,
1602 }
1603 for name, func in plats.items():
1604 plat = func()
1605 if plat and plat[0]:
1606 plat = '%s %r' % (name, plat)
1607 break
1608 else:
1609 plat = repr(platform.platform())
1610 print("test_ssl: testing with %r %r" %
1611 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1612 print(" under %s" % plat)
1613
Antoine Pitrou152efa22010-05-16 18:19:27 +00001614 for filename in [
1615 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1616 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1617 BADCERT, BADKEY, EMPTYCERT]:
1618 if not os.path.exists(filename):
1619 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001620
Antoine Pitrou152efa22010-05-16 18:19:27 +00001621 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001622
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001623 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001624 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001625
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001626 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001627 thread_info = support.threading_setup()
1628 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001629 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001630
Antoine Pitrou480a1242010-04-28 21:37:09 +00001631 try:
1632 support.run_unittest(*tests)
1633 finally:
1634 if _have_threads:
1635 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001636
1637if __name__ == "__main__":
1638 test_main()