blob: b4ec4d52b5736251dd1b3846c4dac5de76c8e251 [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
394
Bill Janssen6e027db2007-11-15 22:23:56 +0000395class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000396
Antoine Pitrou480a1242010-04-28 21:37:09 +0000397 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000398 with support.transient_internet("svn.python.org"):
399 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
400 cert_reqs=ssl.CERT_NONE)
401 try:
402 s.connect(("svn.python.org", 443))
403 self.assertEqual({}, s.getpeercert())
404 finally:
405 s.close()
406
407 # this should fail because we have no verification certs
408 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
409 cert_reqs=ssl.CERT_REQUIRED)
410 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
411 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000412 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000413
Antoine Pitrou350c7222010-09-09 13:31:46 +0000414 # this should succeed because we specify the root cert
415 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
416 cert_reqs=ssl.CERT_REQUIRED,
417 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
418 try:
419 s.connect(("svn.python.org", 443))
420 self.assertTrue(s.getpeercert())
421 finally:
422 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000423
424 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000425 with support.transient_internet("svn.python.org"):
426 # Same as test_connect, but with a separately created context
427 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
428 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
429 s.connect(("svn.python.org", 443))
430 try:
431 self.assertEqual({}, s.getpeercert())
432 finally:
433 s.close()
434 # This should fail because we have no verification certs
435 ctx.verify_mode = ssl.CERT_REQUIRED
436 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
437 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
438 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000439 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000440 # This should succeed because we specify the root cert
441 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
442 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
443 s.connect(("svn.python.org", 443))
444 try:
445 cert = s.getpeercert()
446 self.assertTrue(cert)
447 finally:
448 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000449
450 def test_connect_capath(self):
451 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000452 # NOTE: the subject hashing algorithm has been changed between
453 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
454 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000455 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000456 with support.transient_internet("svn.python.org"):
457 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
458 ctx.verify_mode = ssl.CERT_REQUIRED
459 ctx.load_verify_locations(capath=CAPATH)
460 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
461 s.connect(("svn.python.org", 443))
462 try:
463 cert = s.getpeercert()
464 self.assertTrue(cert)
465 finally:
466 s.close()
467 # Same with a bytes `capath` argument
468 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
469 ctx.verify_mode = ssl.CERT_REQUIRED
470 ctx.load_verify_locations(capath=BYTES_CAPATH)
471 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
472 s.connect(("svn.python.org", 443))
473 try:
474 cert = s.getpeercert()
475 self.assertTrue(cert)
476 finally:
477 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000478
Antoine Pitroue3220242010-04-24 11:13:53 +0000479 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
480 def test_makefile_close(self):
481 # Issue #5238: creating a file-like object with makefile() shouldn't
482 # delay closing the underlying "real socket" (here tested with its
483 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000484 with support.transient_internet("svn.python.org"):
485 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
486 ss.connect(("svn.python.org", 443))
487 fd = ss.fileno()
488 f = ss.makefile()
489 f.close()
490 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000491 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000492 # Closing the SSL socket should close the fd too
493 ss.close()
494 gc.collect()
495 with self.assertRaises(OSError) as e:
496 os.read(fd, 0)
497 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000498
Antoine Pitrou480a1242010-04-28 21:37:09 +0000499 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000500 with support.transient_internet("svn.python.org"):
501 s = socket.socket(socket.AF_INET)
502 s.connect(("svn.python.org", 443))
503 s.setblocking(False)
504 s = ssl.wrap_socket(s,
505 cert_reqs=ssl.CERT_NONE,
506 do_handshake_on_connect=False)
507 count = 0
508 while True:
509 try:
510 count += 1
511 s.do_handshake()
512 break
513 except ssl.SSLError as err:
514 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
515 select.select([s], [], [])
516 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
517 select.select([], [s], [])
518 else:
519 raise
520 s.close()
521 if support.verbose:
522 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000523
Antoine Pitrou480a1242010-04-28 21:37:09 +0000524 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000525 with support.transient_internet("svn.python.org"):
526 pem = ssl.get_server_certificate(("svn.python.org", 443))
527 if not pem:
528 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000529
Antoine Pitrou350c7222010-09-09 13:31:46 +0000530 try:
531 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
532 except ssl.SSLError as x:
533 #should fail
534 if support.verbose:
535 sys.stdout.write("%s\n" % x)
536 else:
537 self.fail("Got server certificate %s for svn.python.org!" % pem)
538
539 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
540 if not pem:
541 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000542 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000543 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000544
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000545 def test_ciphers(self):
546 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000547 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000548 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000549 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000550 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000551 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
552 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
553 s.connect(remote)
554 # Error checking can happen at instantiation or when connecting
555 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
556 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
557 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
558 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000559
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000560 def test_algorithms(self):
561 # Issue #8484: all algorithms should be available when verifying a
562 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000563 # SHA256 was added in OpenSSL 0.9.8
564 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
565 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000566 # NOTE: https://sha256.tbs-internet.com is another possible test host
567 remote = ("sha2.hboeck.de", 443)
568 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000569 with support.transient_internet("sha2.hboeck.de"):
570 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
571 cert_reqs=ssl.CERT_REQUIRED,
572 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000573 try:
574 s.connect(remote)
575 if support.verbose:
576 sys.stdout.write("\nCipher with %r is %r\n" %
577 (remote, s.cipher()))
578 sys.stdout.write("Certificate is:\n%s\n" %
579 pprint.pformat(s.getpeercert()))
580 finally:
581 s.close()
582
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000583
584try:
585 import threading
586except ImportError:
587 _have_threads = False
588else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000589 _have_threads = True
590
591 class ThreadedEchoServer(threading.Thread):
592
593 class ConnectionHandler(threading.Thread):
594
595 """A mildly complicated class, because we want it to work both
596 with and without the SSL wrapper around the socket connection, so
597 that we can test the STARTTLS functionality."""
598
Bill Janssen6e027db2007-11-15 22:23:56 +0000599 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000600 self.server = server
601 self.running = False
602 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000603 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000604 self.sock.setblocking(1)
605 self.sslconn = None
606 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000607 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000608
Antoine Pitrou480a1242010-04-28 21:37:09 +0000609 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000610 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000611 self.sslconn = self.server.context.wrap_socket(
612 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000613 except ssl.SSLError:
614 # XXX Various errors can have happened here, for example
615 # a mismatching protocol version, an invalid certificate,
616 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000617 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000618 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000619 self.running = False
620 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000621 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000622 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000623 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000624 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000625 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000626 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
628 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000629 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000630 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
631 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000632 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000633 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
634 return True
635
636 def read(self):
637 if self.sslconn:
638 return self.sslconn.read()
639 else:
640 return self.sock.recv(1024)
641
642 def write(self, bytes):
643 if self.sslconn:
644 return self.sslconn.write(bytes)
645 else:
646 return self.sock.send(bytes)
647
648 def close(self):
649 if self.sslconn:
650 self.sslconn.close()
651 else:
652 self.sock.close()
653
Antoine Pitrou480a1242010-04-28 21:37:09 +0000654 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000655 self.running = True
656 if not self.server.starttls_server:
657 if not self.wrap_conn():
658 return
659 while self.running:
660 try:
661 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000662 stripped = msg.strip()
663 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000664 # eof, so quit this handler
665 self.running = False
666 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000667 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000668 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000669 sys.stdout.write(" server: client closed connection\n")
670 self.close()
671 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000672 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000673 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000674 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000675 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000676 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000677 if not self.wrap_conn():
678 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000679 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000680 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000681 if support.verbose and self.server.connectionchatty:
682 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000683 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000684 self.sock = self.sslconn.unwrap()
685 self.sslconn = None
686 if support.verbose and self.server.connectionchatty:
687 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000688 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000689 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000690 self.server.connectionchatty):
691 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000692 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
693 % (msg, ctype, msg.lower(), ctype))
694 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000695 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000696 if self.server.chatty:
697 handle_error("Test server failure:\n")
698 self.close()
699 self.running = False
700 # normally, we'd just stop here, but for the test
701 # harness, we want to stop the server
702 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000703
Antoine Pitroub5218772010-05-21 09:56:06 +0000704 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000705 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000706 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000707 ciphers=None, context=None):
708 if context:
709 self.context = context
710 else:
711 self.context = ssl.SSLContext(ssl_version
712 if ssl_version is not None
713 else ssl.PROTOCOL_TLSv1)
714 self.context.verify_mode = (certreqs if certreqs is not None
715 else ssl.CERT_NONE)
716 if cacerts:
717 self.context.load_verify_locations(cacerts)
718 if certificate:
719 self.context.load_cert_chain(certificate)
720 if ciphers:
721 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000722 self.chatty = chatty
723 self.connectionchatty = connectionchatty
724 self.starttls_server = starttls_server
725 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000726 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000727 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000728 self.active = False
729 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000730 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000731
Antoine Pitrou480a1242010-04-28 21:37:09 +0000732 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000733 self.flag = flag
734 threading.Thread.start(self)
735
Antoine Pitrou480a1242010-04-28 21:37:09 +0000736 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000737 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000738 self.sock.listen(5)
739 self.active = True
740 if self.flag:
741 # signal an event
742 self.flag.set()
743 while self.active:
744 try:
745 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000746 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000747 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000748 + repr(connaddr) + '\n')
749 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750 handler.start()
751 except socket.timeout:
752 pass
753 except KeyboardInterrupt:
754 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000755 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756
Antoine Pitrou480a1242010-04-28 21:37:09 +0000757 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000758 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000759
Bill Janssen54cc54c2007-12-14 22:08:56 +0000760 class OurHTTPSServer(threading.Thread):
761
762 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763
764 class HTTPSServer(HTTPServer):
765
766 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000767 HTTPServer.__init__(self, server_address, RequestHandlerClass)
768 # we assume the certfile contains both private key and certificate
769 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000770 self.allow_reuse_address = True
771
Bill Janssen6e027db2007-11-15 22:23:56 +0000772 def __str__(self):
773 return ('<%s %s:%s>' %
774 (self.__class__.__name__,
775 self.server_name,
776 self.server_port))
777
Antoine Pitrou480a1242010-04-28 21:37:09 +0000778 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000779 # override this to wrap socket with SSL
780 sock, addr = self.socket.accept()
781 sslconn = ssl.wrap_socket(sock, server_side=True,
782 certfile=self.certfile)
783 return sslconn, addr
784
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000785 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000786 # need to override translate_path to get a known root,
787 # instead of using os.curdir, since the test could be
788 # run from anywhere
789
790 server_version = "TestHTTPS/1.0"
791
792 root = None
793
794 def translate_path(self, path):
795 """Translate a /-separated PATH to the local filename syntax.
796
797 Components that mean special things to the local file system
798 (e.g. drive or directory names) are ignored. (XXX They should
799 probably be diagnosed.)
800
801 """
802 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000803 path = urllib.parse.urlparse(path)[2]
804 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000805 words = path.split('/')
806 words = filter(None, words)
807 path = self.root
808 for word in words:
809 drive, word = os.path.splitdrive(word)
810 head, word = os.path.split(word)
811 if word in self.root: continue
812 path = os.path.join(path, word)
813 return path
814
815 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000816 # we override this to suppress logging unless "verbose"
817
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000818 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000819 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
820 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000821 self.server.server_port,
822 self.request.cipher(),
823 self.log_date_time_string(),
824 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000825
826
Trent Nelson78520002008-04-10 20:54:35 +0000827 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000828 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
830 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000831 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
832 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000833 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000834 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000835
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000836 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000837 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000838
Antoine Pitrou480a1242010-04-28 21:37:09 +0000839 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000840 self.flag = flag
841 threading.Thread.start(self)
842
Antoine Pitrou480a1242010-04-28 21:37:09 +0000843 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000844 if self.flag:
845 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000846 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000847
Antoine Pitrou480a1242010-04-28 21:37:09 +0000848 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000849 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850
851
Bill Janssen54cc54c2007-12-14 22:08:56 +0000852 class AsyncoreEchoServer(threading.Thread):
853
854 # this one's based on asyncore.dispatcher
855
856 class EchoServer (asyncore.dispatcher):
857
858 class ConnectionHandler (asyncore.dispatcher_with_send):
859
860 def __init__(self, conn, certfile):
861 self.socket = ssl.wrap_socket(conn, server_side=True,
862 certfile=certfile,
863 do_handshake_on_connect=False)
864 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000865 self._ssl_accepting = True
866 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000867
868 def readable(self):
869 if isinstance(self.socket, ssl.SSLSocket):
870 while self.socket.pending() > 0:
871 self.handle_read_event()
872 return True
873
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000874 def _do_ssl_handshake(self):
875 try:
876 self.socket.do_handshake()
877 except ssl.SSLError as err:
878 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
879 ssl.SSL_ERROR_WANT_WRITE):
880 return
881 elif err.args[0] == ssl.SSL_ERROR_EOF:
882 return self.handle_close()
883 raise
884 except socket.error as err:
885 if err.args[0] == errno.ECONNABORTED:
886 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000887 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000888 self._ssl_accepting = False
889
890 def handle_read(self):
891 if self._ssl_accepting:
892 self._do_ssl_handshake()
893 else:
894 data = self.recv(1024)
895 if support.verbose:
896 sys.stdout.write(" server: read %s from client\n" % repr(data))
897 if not data:
898 self.close()
899 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000901
902 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000903 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000904 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000905 sys.stdout.write(" server: closed connection %s\n" % self.socket)
906
907 def handle_error(self):
908 raise
909
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000910 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000911 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000912 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
913 self.port = support.bind_port(sock, '')
914 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000915 self.listen(5)
916
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000917 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000918 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000919 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
920 self.ConnectionHandler(sock_obj, self.certfile)
921
922 def handle_error(self):
923 raise
924
Trent Nelson78520002008-04-10 20:54:35 +0000925 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000926 self.flag = None
927 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000928 self.server = self.EchoServer(certfile)
929 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000930 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000931 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000932
933 def __str__(self):
934 return "<%s %s>" % (self.__class__.__name__, self.server)
935
936 def start (self, flag=None):
937 self.flag = flag
938 threading.Thread.start(self)
939
Antoine Pitrou480a1242010-04-28 21:37:09 +0000940 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000941 self.active = True
942 if self.flag:
943 self.flag.set()
944 while self.active:
945 try:
946 asyncore.loop(1)
947 except:
948 pass
949
Antoine Pitrou480a1242010-04-28 21:37:09 +0000950 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000951 self.active = False
952 self.server.close()
953
Antoine Pitrou480a1242010-04-28 21:37:09 +0000954 def bad_cert_test(certfile):
955 """
956 Launch a server with CERT_REQUIRED, and check that trying to
957 connect to it with the given client certificate fails.
958 """
Trent Nelson78520002008-04-10 20:54:35 +0000959 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000961 cacerts=CERTFILE, chatty=False,
962 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963 flag = threading.Event()
964 server.start(flag)
965 # wait for it to start
966 flag.wait()
967 # try to connect
968 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000969 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 s = ssl.wrap_socket(socket.socket(),
971 certfile=certfile,
972 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000973 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000974 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000975 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000976 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000977 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000978 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000979 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000980 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000981 if x.errno != errno.ENOENT:
982 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000983 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000984 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000985 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000986 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000987 finally:
988 server.stop()
989 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000990
Antoine Pitroub5218772010-05-21 09:56:06 +0000991 def server_params_test(client_context, server_context, indata=b"FOO\n",
992 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000993 """
994 Launch a server, connect a client to it and try various reads
995 and writes.
996 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000997 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000999 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001000 flag = threading.Event()
1001 server.start(flag)
1002 # wait for it to start
1003 flag.wait()
1004 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001005 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001006 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001007 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001008 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001009 if connectionchatty:
1010 if support.verbose:
1011 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001012 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001013 s.write(arg)
1014 outdata = s.read()
1015 if connectionchatty:
1016 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001017 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001018 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001019 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001020 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1021 % (outdata[:20], len(outdata),
1022 indata[:20].lower(), len(indata)))
1023 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001024 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001025 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001026 sys.stdout.write(" client: closing connection.\n")
1027 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001028 finally:
1029 server.stop()
1030 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001031
Antoine Pitroub5218772010-05-21 09:56:06 +00001032 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1033 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001034 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001035 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001036 certtype = {
1037 ssl.CERT_NONE: "CERT_NONE",
1038 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1039 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1040 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001041 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001042 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001043 sys.stdout.write(formatstr %
1044 (ssl.get_protocol_name(client_protocol),
1045 ssl.get_protocol_name(server_protocol),
1046 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001047 client_context = ssl.SSLContext(client_protocol)
1048 client_context.options = ssl.OP_ALL | client_options
1049 server_context = ssl.SSLContext(server_protocol)
1050 server_context.options = ssl.OP_ALL | server_options
1051 for ctx in (client_context, server_context):
1052 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001053 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1054 # will send an SSLv3 hello (rather than SSLv2) starting from
1055 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001056 ctx.set_ciphers("ALL")
1057 ctx.load_cert_chain(CERTFILE)
1058 ctx.load_verify_locations(CERTFILE)
1059 try:
1060 server_params_test(client_context, server_context,
1061 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001062 # Protocol mismatch can result in either an SSLError, or a
1063 # "Connection reset by peer" error.
1064 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001065 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001067 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001068 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001069 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001070 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001071 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001072 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073 "Client protocol %s succeeded with server protocol %s!"
1074 % (ssl.get_protocol_name(client_protocol),
1075 ssl.get_protocol_name(server_protocol)))
1076
1077
Bill Janssen6e027db2007-11-15 22:23:56 +00001078 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001079
Antoine Pitrou23df4832010-08-04 17:14:06 +00001080 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001081 def test_echo(self):
1082 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001083 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001084 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001085 for protocol in PROTOCOLS:
1086 context = ssl.SSLContext(protocol)
1087 context.load_cert_chain(CERTFILE)
1088 server_params_test(context, context,
1089 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001090
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001092 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001094 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1095 context.verify_mode = ssl.CERT_REQUIRED
1096 context.load_verify_locations(CERTFILE)
1097 context.load_cert_chain(CERTFILE)
1098 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001099 flag = threading.Event()
1100 server.start(flag)
1101 # wait for it to start
1102 flag.wait()
1103 # try to connect
1104 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001105 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001106 s.connect((HOST, server.port))
1107 cert = s.getpeercert()
1108 self.assertTrue(cert, "Can't get peer certificate.")
1109 cipher = s.cipher()
1110 if support.verbose:
1111 sys.stdout.write(pprint.pformat(cert) + '\n')
1112 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1113 if 'subject' not in cert:
1114 self.fail("No subject field in certificate: %s." %
1115 pprint.pformat(cert))
1116 if ((('organizationName', 'Python Software Foundation'),)
1117 not in cert['subject']):
1118 self.fail(
1119 "Missing or invalid 'organizationName' field in certificate subject; "
1120 "should be 'Python Software Foundation'.")
1121 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001122 finally:
1123 server.stop()
1124 server.join()
1125
Antoine Pitrou480a1242010-04-28 21:37:09 +00001126 def test_empty_cert(self):
1127 """Connecting with an empty cert file"""
1128 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1129 "nullcert.pem"))
1130 def test_malformed_cert(self):
1131 """Connecting with a badly formatted certificate (syntax error)"""
1132 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1133 "badcert.pem"))
1134 def test_nonexisting_cert(self):
1135 """Connecting with a non-existing cert file"""
1136 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1137 "wrongcert.pem"))
1138 def test_malformed_key(self):
1139 """Connecting with a badly formatted key (syntax error)"""
1140 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1141 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001142
Antoine Pitrou480a1242010-04-28 21:37:09 +00001143 def test_rude_shutdown(self):
1144 """A brutal shutdown of an SSL server should raise an IOError
1145 in the client when attempting handshake.
1146 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001147 listener_ready = threading.Event()
1148 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001149
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001150 s = socket.socket()
1151 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001152
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001153 # `listener` runs in a thread. It sits in an accept() until
1154 # the main thread connects. Then it rudely closes the socket,
1155 # and sets Event `listener_gone` to let the main thread know
1156 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001157 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001158 s.listen(5)
1159 listener_ready.set()
1160 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001161 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001162 listener_gone.set()
1163
1164 def connector():
1165 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001166 c = socket.socket()
1167 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001168 listener_gone.wait()
1169 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001170 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001171 except IOError:
1172 pass
1173 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001174 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001175
1176 t = threading.Thread(target=listener)
1177 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001178 try:
1179 connector()
1180 finally:
1181 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001182
Antoine Pitrou23df4832010-08-04 17:14:06 +00001183 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001184 def test_protocol_sslv2(self):
1185 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001186 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001187 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001188 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1189 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1190 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1191 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1192 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1193 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001194 # SSLv23 client with specific SSL options
1195 if no_sslv2_implies_sslv3_hello():
1196 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1197 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1198 client_options=ssl.OP_NO_SSLv2)
1199 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1200 client_options=ssl.OP_NO_SSLv3)
1201 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1202 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001203
Antoine Pitrou23df4832010-08-04 17:14:06 +00001204 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 def test_protocol_sslv23(self):
1206 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001207 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001208 sys.stdout.write("\n")
1209 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001210 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001211 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001212 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001213 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001214 sys.stdout.write(
1215 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1216 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001217 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1218 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1219 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001220
Antoine Pitrou480a1242010-04-28 21:37:09 +00001221 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1222 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1223 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001224
Antoine Pitrou480a1242010-04-28 21:37:09 +00001225 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1226 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1227 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001228
Antoine Pitroub5218772010-05-21 09:56:06 +00001229 # Server with specific SSL options
1230 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1231 server_options=ssl.OP_NO_SSLv3)
1232 # Will choose TLSv1
1233 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1234 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1235 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1236 server_options=ssl.OP_NO_TLSv1)
1237
1238
Antoine Pitrou23df4832010-08-04 17:14:06 +00001239 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001240 def test_protocol_sslv3(self):
1241 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001242 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001243 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001244 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1245 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1246 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1247 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1248 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1249 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001250 if no_sslv2_implies_sslv3_hello():
1251 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1252 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1253 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001254
Antoine Pitrou23df4832010-08-04 17:14:06 +00001255 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001256 def test_protocol_tlsv1(self):
1257 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001258 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001259 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001260 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1261 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1262 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1263 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1264 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1265 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001266
Antoine Pitrou480a1242010-04-28 21:37:09 +00001267 def test_starttls(self):
1268 """Switching from clear text to encrypted and back again."""
1269 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 +00001270
Trent Nelson78520002008-04-10 20:54:35 +00001271 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001272 ssl_version=ssl.PROTOCOL_TLSv1,
1273 starttls_server=True,
1274 chatty=True,
1275 connectionchatty=True)
1276 flag = threading.Event()
1277 server.start(flag)
1278 # wait for it to start
1279 flag.wait()
1280 # try to connect
1281 wrapped = False
1282 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001283 s = socket.socket()
1284 s.setblocking(1)
1285 s.connect((HOST, server.port))
1286 if support.verbose:
1287 sys.stdout.write("\n")
1288 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001289 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001290 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001291 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001292 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001293 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001294 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001295 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001296 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001297 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 msg = outdata.strip().lower()
1299 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1300 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001301 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001302 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001303 " client: read %r from server, starting TLS...\n"
1304 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001305 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1306 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001307 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1308 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001309 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001310 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001311 " client: read %r from server, ending TLS...\n"
1312 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001313 s = conn.unwrap()
1314 wrapped = False
1315 else:
1316 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001317 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001318 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001319 if support.verbose:
1320 sys.stdout.write(" client: closing connection.\n")
1321 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001322 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001323 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001324 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001325 if wrapped:
1326 conn.close()
1327 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001328 s.close()
1329 finally:
1330 server.stop()
1331 server.join()
1332
Antoine Pitrou480a1242010-04-28 21:37:09 +00001333 def test_socketserver(self):
1334 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001335 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001336 flag = threading.Event()
1337 server.start(flag)
1338 # wait for it to start
1339 flag.wait()
1340 # try to connect
1341 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001342 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001343 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001344 with open(CERTFILE, 'rb') as f:
1345 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001346 d2 = ''
1347 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001348 url = 'https://%s:%d/%s' % (
1349 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001350 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001351 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001352 if dlen and (int(dlen) > 0):
1353 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001354 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001355 sys.stdout.write(
1356 " client: read %d bytes from remote server '%s'\n"
1357 % (len(d2), server))
1358 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001359 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001360 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001361 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001362 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001363 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001364 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001365 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001366 server.join()
1367
Antoine Pitrou480a1242010-04-28 21:37:09 +00001368 def test_asyncore_server(self):
1369 """Check the example asyncore integration."""
1370 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001371
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001372 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001373 sys.stdout.write("\n")
1374
Antoine Pitrou480a1242010-04-28 21:37:09 +00001375 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001376 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001377 flag = threading.Event()
1378 server.start(flag)
1379 # wait for it to start
1380 flag.wait()
1381 # try to connect
1382 try:
1383 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001384 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001385 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001386 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001387 " client: sending %r...\n" % indata)
1388 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001389 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001390 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001392 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001393 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001394 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1395 % (outdata[:20], len(outdata),
1396 indata[:20].lower(), len(indata)))
1397 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001398 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001399 sys.stdout.write(" client: closing connection.\n")
1400 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001401 if support.verbose:
1402 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001403 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001404 if support.verbose:
1405 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001406 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001407 if support.verbose:
1408 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001409 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001410 if support.verbose:
1411 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001412
Antoine Pitrou480a1242010-04-28 21:37:09 +00001413 def test_recv_send(self):
1414 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001415 if support.verbose:
1416 sys.stdout.write("\n")
1417
1418 server = ThreadedEchoServer(CERTFILE,
1419 certreqs=ssl.CERT_NONE,
1420 ssl_version=ssl.PROTOCOL_TLSv1,
1421 cacerts=CERTFILE,
1422 chatty=True,
1423 connectionchatty=False)
1424 flag = threading.Event()
1425 server.start(flag)
1426 # wait for it to start
1427 flag.wait()
1428 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001429 s = ssl.wrap_socket(socket.socket(),
1430 server_side=False,
1431 certfile=CERTFILE,
1432 ca_certs=CERTFILE,
1433 cert_reqs=ssl.CERT_NONE,
1434 ssl_version=ssl.PROTOCOL_TLSv1)
1435 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001436 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001437 # helper methods for standardising recv* method signatures
1438 def _recv_into():
1439 b = bytearray(b"\0"*100)
1440 count = s.recv_into(b)
1441 return b[:count]
1442
1443 def _recvfrom_into():
1444 b = bytearray(b"\0"*100)
1445 count, addr = s.recvfrom_into(b)
1446 return b[:count]
1447
1448 # (name, method, whether to expect success, *args)
1449 send_methods = [
1450 ('send', s.send, True, []),
1451 ('sendto', s.sendto, False, ["some.address"]),
1452 ('sendall', s.sendall, True, []),
1453 ]
1454 recv_methods = [
1455 ('recv', s.recv, True, []),
1456 ('recvfrom', s.recvfrom, False, ["some.address"]),
1457 ('recv_into', _recv_into, True, []),
1458 ('recvfrom_into', _recvfrom_into, False, []),
1459 ]
1460 data_prefix = "PREFIX_"
1461
1462 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001463 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001464 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001465 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001466 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001467 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001468 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001469 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001470 "<<{outdata:r}>> ({nout:d}) received; "
1471 "expected <<{indata:r}>> ({nin:d})\n".format(
1472 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001473 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001474 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001475 )
1476 )
1477 except ValueError as e:
1478 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001479 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001480 "Failed to send with method <<{name:s}>>; "
1481 "expected to succeed.\n".format(name=meth_name)
1482 )
1483 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001484 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001485 "Method <<{name:s}>> failed with unexpected "
1486 "exception message: {exp:s}\n".format(
1487 name=meth_name, exp=e
1488 )
1489 )
1490
1491 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001493 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001494 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001495 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001496 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001497 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001498 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001499 "<<{outdata:r}>> ({nout:d}) received; "
1500 "expected <<{indata:r}>> ({nin:d})\n".format(
1501 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001502 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001503 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001504 )
1505 )
1506 except ValueError as e:
1507 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001508 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001509 "Failed to receive with method <<{name:s}>>; "
1510 "expected to succeed.\n".format(name=meth_name)
1511 )
1512 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001513 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001514 "Method <<{name:s}>> failed with unexpected "
1515 "exception message: {exp:s}\n".format(
1516 name=meth_name, exp=e
1517 )
1518 )
1519 # consume data
1520 s.read()
1521
Antoine Pitrou480a1242010-04-28 21:37:09 +00001522 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001523 s.close()
1524 finally:
1525 server.stop()
1526 server.join()
1527
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001528 def test_handshake_timeout(self):
1529 # Issue #5103: SSL handshake must respect the socket timeout
1530 server = socket.socket(socket.AF_INET)
1531 host = "127.0.0.1"
1532 port = support.bind_port(server)
1533 started = threading.Event()
1534 finish = False
1535
1536 def serve():
1537 server.listen(5)
1538 started.set()
1539 conns = []
1540 while not finish:
1541 r, w, e = select.select([server], [], [], 0.1)
1542 if server in r:
1543 # Let the socket hang around rather than having
1544 # it closed by garbage collection.
1545 conns.append(server.accept()[0])
1546
1547 t = threading.Thread(target=serve)
1548 t.start()
1549 started.wait()
1550
1551 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001552 try:
1553 c = socket.socket(socket.AF_INET)
1554 c.settimeout(0.2)
1555 c.connect((host, port))
1556 # Will attempt handshake and time out
1557 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1558 ssl.wrap_socket, c)
1559 finally:
1560 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001561 try:
1562 c = socket.socket(socket.AF_INET)
1563 c = ssl.wrap_socket(c)
1564 c.settimeout(0.2)
1565 # Will attempt handshake and time out
1566 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1567 c.connect, (host, port))
1568 finally:
1569 c.close()
1570 finally:
1571 finish = True
1572 t.join()
1573 server.close()
1574
Bill Janssen58afe4c2008-09-08 16:45:19 +00001575
Thomas Woutersed03b412007-08-28 21:37:11 +00001576def test_main(verbose=False):
1577 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001578 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001579
Antoine Pitrou15cee622010-08-04 16:45:21 +00001580 if support.verbose:
1581 plats = {
1582 'Linux': platform.linux_distribution,
1583 'Mac': platform.mac_ver,
1584 'Windows': platform.win32_ver,
1585 }
1586 for name, func in plats.items():
1587 plat = func()
1588 if plat and plat[0]:
1589 plat = '%s %r' % (name, plat)
1590 break
1591 else:
1592 plat = repr(platform.platform())
1593 print("test_ssl: testing with %r %r" %
1594 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1595 print(" under %s" % plat)
1596
Antoine Pitrou152efa22010-05-16 18:19:27 +00001597 for filename in [
1598 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1599 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1600 BADCERT, BADKEY, EMPTYCERT]:
1601 if not os.path.exists(filename):
1602 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001603
Antoine Pitrou152efa22010-05-16 18:19:27 +00001604 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001605
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001606 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001607 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001608
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001609 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001610 thread_info = support.threading_setup()
1611 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001612 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001613
Antoine Pitrou480a1242010-04-28 21:37:09 +00001614 try:
1615 support.run_unittest(*tests)
1616 finally:
1617 if _have_threads:
1618 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001619
1620if __name__ == "__main__":
1621 test_main()