blob: f3f0c5445997878d8bc37d51b7baef9407e678ae [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
23PROTOCOLS = [
Victor Stinner3de49192011-05-09 00:42:58 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner3de49192011-05-09 00:42:58 +020027if hasattr(ssl, 'PROTOCOL_SSLv2'):
28 PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
Thomas Woutersed03b412007-08-28 21:37:11 +000029
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Antoine Pitrou81564092010-10-08 23:06:24 +000034# The custom key and certificate files used in test_ssl are generated
35# using Lib/test/make_ssl_certs.py.
36# Other certificates are simply fetched from the Internet servers they
37# are meant to authenticate.
38
Antoine Pitrou152efa22010-05-16 18:19:27 +000039CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
54
Thomas Woutersed03b412007-08-28 21:37:11 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056def handle_error(prefix):
57 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000059 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitroub5218772010-05-21 09:56:06 +000061def can_clear_options():
62 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020063 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000064
65def no_sslv2_implies_sslv3_hello():
66 # 0.9.7h or higher
67 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
68
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou23df4832010-08-04 17:14:06 +000070# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
71def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020072 if hasattr(ssl, 'PROTOCOL_SSLv2'):
73 @functools.wraps(func)
74 def f(*args, **kwargs):
75 try:
76 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
77 except ssl.SSLError:
78 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
79 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
80 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
81 return func(*args, **kwargs)
82 return f
83 else:
84 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000085
86
Antoine Pitrou152efa22010-05-16 18:19:27 +000087class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000088
Antoine Pitrou480a1242010-04-28 21:37:09 +000089 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020090 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000091 ssl.PROTOCOL_SSLv23
92 ssl.PROTOCOL_SSLv3
93 ssl.PROTOCOL_TLSv1
94 ssl.CERT_NONE
95 ssl.CERT_OPTIONAL
96 ssl.CERT_REQUIRED
Antoine Pitroud5323212010-10-22 18:19:07 +000097 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +000098
Antoine Pitrou480a1242010-04-28 21:37:09 +000099 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000100 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000101 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102 sys.stdout.write("\n RAND_status is %d (%s)\n"
103 % (v, (v and "sufficient randomness") or
104 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200105
106 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
107 self.assertEqual(len(data), 16)
108 self.assertEqual(is_cryptographic, v == 1)
109 if v:
110 data = ssl.RAND_bytes(16)
111 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200112 else:
113 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200114
Thomas Woutersed03b412007-08-28 21:37:11 +0000115 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000116 ssl.RAND_egd(1)
117 except TypeError:
118 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000119 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 print("didn't raise TypeError")
121 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000122
Antoine Pitrou480a1242010-04-28 21:37:09 +0000123 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000124 # note that this uses an 'unofficial' function in _ssl.c,
125 # provided solely for this test, to exercise the certificate
126 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000127 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000128 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000130
Antoine Pitrou480a1242010-04-28 21:37:09 +0000131 def test_DER_to_PEM(self):
132 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
133 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000134 d1 = ssl.PEM_cert_to_DER_cert(pem)
135 p2 = ssl.DER_cert_to_PEM_cert(d1)
136 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000137 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000138 if not p2.startswith(ssl.PEM_HEADER + '\n'):
139 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
140 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
141 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000142
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000143 def test_openssl_version(self):
144 n = ssl.OPENSSL_VERSION_NUMBER
145 t = ssl.OPENSSL_VERSION_INFO
146 s = ssl.OPENSSL_VERSION
147 self.assertIsInstance(n, int)
148 self.assertIsInstance(t, tuple)
149 self.assertIsInstance(s, str)
150 # Some sanity checks follow
151 # >= 0.9
152 self.assertGreaterEqual(n, 0x900000)
153 # < 2.0
154 self.assertLess(n, 0x20000000)
155 major, minor, fix, patch, status = t
156 self.assertGreaterEqual(major, 0)
157 self.assertLess(major, 2)
158 self.assertGreaterEqual(minor, 0)
159 self.assertLess(minor, 256)
160 self.assertGreaterEqual(fix, 0)
161 self.assertLess(fix, 256)
162 self.assertGreaterEqual(patch, 0)
163 self.assertLessEqual(patch, 26)
164 self.assertGreaterEqual(status, 0)
165 self.assertLessEqual(status, 15)
166 # Version string as returned by OpenSSL, the format might change
167 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
168 (s, t))
169
Antoine Pitrou9d543662010-04-23 23:10:32 +0000170 @support.cpython_only
171 def test_refcycle(self):
172 # Issue #7943: an SSL object doesn't create reference cycles with
173 # itself.
174 s = socket.socket(socket.AF_INET)
175 ss = ssl.wrap_socket(s)
176 wr = weakref.ref(ss)
177 del ss
178 self.assertEqual(wr(), None)
179
Antoine Pitroua468adc2010-09-14 14:43:44 +0000180 def test_wrapped_unconnected(self):
181 # Methods on an unconnected SSLSocket propagate the original
182 # socket.error raise by the underlying socket object.
183 s = socket.socket(socket.AF_INET)
184 ss = ssl.wrap_socket(s)
185 self.assertRaises(socket.error, ss.recv, 1)
186 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
187 self.assertRaises(socket.error, ss.recvfrom, 1)
188 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
189 self.assertRaises(socket.error, ss.send, b'x')
190 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
191
Antoine Pitrou40f08742010-04-24 22:04:40 +0000192 def test_timeout(self):
193 # Issue #8524: when creating an SSL socket, the timeout of the
194 # original socket should be retained.
195 for timeout in (None, 0.0, 5.0):
196 s = socket.socket(socket.AF_INET)
197 s.settimeout(timeout)
198 ss = ssl.wrap_socket(s)
199 self.assertEqual(timeout, ss.gettimeout())
200
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000201 def test_errors(self):
202 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000203 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000204 "certfile must be specified",
205 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000206 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000207 "certfile must be specified for server-side operations",
208 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000209 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000210 "certfile must be specified for server-side operations",
211 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000212 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000213 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000214 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000215 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000216 with socket.socket() as sock:
217 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000218 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000219 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000220 with socket.socket() as sock:
221 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000222 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000223 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000224 with socket.socket() as sock:
225 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000226 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000227
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000228 def test_match_hostname(self):
229 def ok(cert, hostname):
230 ssl.match_hostname(cert, hostname)
231 def fail(cert, hostname):
232 self.assertRaises(ssl.CertificateError,
233 ssl.match_hostname, cert, hostname)
234
235 cert = {'subject': ((('commonName', 'example.com'),),)}
236 ok(cert, 'example.com')
237 ok(cert, 'ExAmple.cOm')
238 fail(cert, 'www.example.com')
239 fail(cert, '.example.com')
240 fail(cert, 'example.org')
241 fail(cert, 'exampleXcom')
242
243 cert = {'subject': ((('commonName', '*.a.com'),),)}
244 ok(cert, 'foo.a.com')
245 fail(cert, 'bar.foo.a.com')
246 fail(cert, 'a.com')
247 fail(cert, 'Xa.com')
248 fail(cert, '.a.com')
249
250 cert = {'subject': ((('commonName', 'a.*.com'),),)}
251 ok(cert, 'a.foo.com')
252 fail(cert, 'a..com')
253 fail(cert, 'a.com')
254
255 cert = {'subject': ((('commonName', 'f*.com'),),)}
256 ok(cert, 'foo.com')
257 ok(cert, 'f.com')
258 fail(cert, 'bar.com')
259 fail(cert, 'foo.a.com')
260 fail(cert, 'bar.foo.com')
261
262 # Slightly fake real-world example
263 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
264 'subject': ((('commonName', 'linuxfrz.org'),),),
265 'subjectAltName': (('DNS', 'linuxfr.org'),
266 ('DNS', 'linuxfr.com'),
267 ('othername', '<unsupported>'))}
268 ok(cert, 'linuxfr.org')
269 ok(cert, 'linuxfr.com')
270 # Not a "DNS" entry
271 fail(cert, '<unsupported>')
272 # When there is a subjectAltName, commonName isn't used
273 fail(cert, 'linuxfrz.org')
274
275 # A pristine real-world example
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 (('commonName', 'mail.google.com'),))}
282 ok(cert, 'mail.google.com')
283 fail(cert, 'gmail.com')
284 # Only commonName is considered
285 fail(cert, 'California')
286
287 # Neither commonName nor subjectAltName
288 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
289 'subject': ((('countryName', 'US'),),
290 (('stateOrProvinceName', 'California'),),
291 (('localityName', 'Mountain View'),),
292 (('organizationName', 'Google Inc'),))}
293 fail(cert, 'mail.google.com')
294
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200295 # No DNS entry in subjectAltName but a commonName
296 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
297 'subject': ((('countryName', 'US'),),
298 (('stateOrProvinceName', 'California'),),
299 (('localityName', 'Mountain View'),),
300 (('commonName', 'mail.google.com'),)),
301 'subjectAltName': (('othername', 'blabla'), )}
302 ok(cert, 'mail.google.com')
303
304 # No DNS entry subjectAltName and no commonName
305 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
306 'subject': ((('countryName', 'US'),),
307 (('stateOrProvinceName', 'California'),),
308 (('localityName', 'Mountain View'),),
309 (('organizationName', 'Google Inc'),)),
310 'subjectAltName': (('othername', 'blabla'),)}
311 fail(cert, 'google.com')
312
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000313 # Empty cert / no cert
314 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
315 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
316
Antoine Pitroud5323212010-10-22 18:19:07 +0000317 def test_server_side(self):
318 # server_hostname doesn't work for server sockets
319 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000320 with socket.socket() as sock:
321 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
322 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000323
Antoine Pitroud6494802011-07-21 01:11:30 +0200324 def test_unknown_channel_binding(self):
325 # should raise ValueError for unknown type
326 s = socket.socket(socket.AF_INET)
327 ss = ssl.wrap_socket(s)
328 with self.assertRaises(ValueError):
329 ss.get_channel_binding("unknown-type")
330
331 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
332 "'tls-unique' channel binding not available")
333 def test_tls_unique_channel_binding(self):
334 # unconnected should return None for known type
335 s = socket.socket(socket.AF_INET)
336 ss = ssl.wrap_socket(s)
337 self.assertIsNone(ss.get_channel_binding("tls-unique"))
338 # the same for server-side
339 s = socket.socket(socket.AF_INET)
340 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
341 self.assertIsNone(ss.get_channel_binding("tls-unique"))
342
Antoine Pitrou152efa22010-05-16 18:19:27 +0000343class ContextTests(unittest.TestCase):
344
Antoine Pitrou23df4832010-08-04 17:14:06 +0000345 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000346 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200347 if hasattr(ssl, 'PROTOCOL_SSLv2'):
348 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000349 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
350 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
351 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
352 self.assertRaises(TypeError, ssl.SSLContext)
353 self.assertRaises(ValueError, ssl.SSLContext, -1)
354 self.assertRaises(ValueError, ssl.SSLContext, 42)
355
Antoine Pitrou23df4832010-08-04 17:14:06 +0000356 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000357 def test_protocol(self):
358 for proto in PROTOCOLS:
359 ctx = ssl.SSLContext(proto)
360 self.assertEqual(ctx.protocol, proto)
361
362 def test_ciphers(self):
363 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
364 ctx.set_ciphers("ALL")
365 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000366 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000367 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000368
Antoine Pitrou23df4832010-08-04 17:14:06 +0000369 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000370 def test_options(self):
371 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
372 # OP_ALL is the default value
373 self.assertEqual(ssl.OP_ALL, ctx.options)
374 ctx.options |= ssl.OP_NO_SSLv2
375 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
376 ctx.options)
377 ctx.options |= ssl.OP_NO_SSLv3
378 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
379 ctx.options)
380 if can_clear_options():
381 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
382 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
383 ctx.options)
384 ctx.options = 0
385 self.assertEqual(0, ctx.options)
386 else:
387 with self.assertRaises(ValueError):
388 ctx.options = 0
389
Antoine Pitrou152efa22010-05-16 18:19:27 +0000390 def test_verify(self):
391 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
392 # Default value
393 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
394 ctx.verify_mode = ssl.CERT_OPTIONAL
395 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
396 ctx.verify_mode = ssl.CERT_REQUIRED
397 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
398 ctx.verify_mode = ssl.CERT_NONE
399 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
400 with self.assertRaises(TypeError):
401 ctx.verify_mode = None
402 with self.assertRaises(ValueError):
403 ctx.verify_mode = 42
404
405 def test_load_cert_chain(self):
406 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
407 # Combined key and cert in a single file
408 ctx.load_cert_chain(CERTFILE)
409 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
410 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000411 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000412 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000413 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000414 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000415 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000416 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000417 ctx.load_cert_chain(EMPTYCERT)
418 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000419 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000420 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
421 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
422 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000423 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000424 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000425 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000426 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000427 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000428 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
429 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000430 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000431 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000432 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000433
434 def test_load_verify_locations(self):
435 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
436 ctx.load_verify_locations(CERTFILE)
437 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
438 ctx.load_verify_locations(BYTES_CERTFILE)
439 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
440 self.assertRaises(TypeError, ctx.load_verify_locations)
441 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000442 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000443 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000444 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000445 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000446 ctx.load_verify_locations(BADCERT)
447 ctx.load_verify_locations(CERTFILE, CAPATH)
448 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
449
Victor Stinner80f75e62011-01-29 11:31:20 +0000450 # Issue #10989: crash if the second argument type is invalid
451 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
452
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000453 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000454 def test_session_stats(self):
455 for proto in PROTOCOLS:
456 ctx = ssl.SSLContext(proto)
457 self.assertEqual(ctx.session_stats(), {
458 'number': 0,
459 'connect': 0,
460 'connect_good': 0,
461 'connect_renegotiate': 0,
462 'accept': 0,
463 'accept_good': 0,
464 'accept_renegotiate': 0,
465 'hits': 0,
466 'misses': 0,
467 'timeouts': 0,
468 'cache_full': 0,
469 })
470
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000471 def test_set_default_verify_paths(self):
472 # There's not much we can do to test that it acts as expected,
473 # so just check it doesn't crash or raise an exception.
474 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
475 ctx.set_default_verify_paths()
476
Antoine Pitrou152efa22010-05-16 18:19:27 +0000477
Bill Janssen6e027db2007-11-15 22:23:56 +0000478class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000479
Antoine Pitrou480a1242010-04-28 21:37:09 +0000480 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000481 with support.transient_internet("svn.python.org"):
482 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
483 cert_reqs=ssl.CERT_NONE)
484 try:
485 s.connect(("svn.python.org", 443))
486 self.assertEqual({}, s.getpeercert())
487 finally:
488 s.close()
489
490 # this should fail because we have no verification certs
491 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
492 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000493 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
494 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000495 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000496
Antoine Pitrou350c7222010-09-09 13:31:46 +0000497 # this should succeed because we specify the root cert
498 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
499 cert_reqs=ssl.CERT_REQUIRED,
500 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
501 try:
502 s.connect(("svn.python.org", 443))
503 self.assertTrue(s.getpeercert())
504 finally:
505 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000506
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000507 def test_connect_ex(self):
508 # Issue #11326: check connect_ex() implementation
509 with support.transient_internet("svn.python.org"):
510 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
511 cert_reqs=ssl.CERT_REQUIRED,
512 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
513 try:
514 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
515 self.assertTrue(s.getpeercert())
516 finally:
517 s.close()
518
519 def test_non_blocking_connect_ex(self):
520 # Issue #11326: non-blocking connect_ex() should allow handshake
521 # to proceed after the socket gets ready.
522 with support.transient_internet("svn.python.org"):
523 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
524 cert_reqs=ssl.CERT_REQUIRED,
525 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
526 do_handshake_on_connect=False)
527 try:
528 s.setblocking(False)
529 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000530 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
531 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000532 # Wait for connect to finish
533 select.select([], [s], [], 5.0)
534 # Non-blocking handshake
535 while True:
536 try:
537 s.do_handshake()
538 break
539 except ssl.SSLError as err:
540 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
541 select.select([s], [], [], 5.0)
542 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
543 select.select([], [s], [], 5.0)
544 else:
545 raise
546 # SSL established
547 self.assertTrue(s.getpeercert())
548 finally:
549 s.close()
550
Antoine Pitroub4410db2011-05-18 18:51:06 +0200551 def test_timeout_connect_ex(self):
552 # Issue #12065: on a timeout, connect_ex() should return the original
553 # errno (mimicking the behaviour of non-SSL sockets).
554 with support.transient_internet("svn.python.org"):
555 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
556 cert_reqs=ssl.CERT_REQUIRED,
557 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
558 do_handshake_on_connect=False)
559 try:
560 s.settimeout(0.0000001)
561 rc = s.connect_ex(('svn.python.org', 443))
562 if rc == 0:
563 self.skipTest("svn.python.org responded too quickly")
564 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
565 finally:
566 s.close()
567
Antoine Pitrou152efa22010-05-16 18:19:27 +0000568 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000569 with support.transient_internet("svn.python.org"):
570 # Same as test_connect, but with a separately created context
571 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
572 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
573 s.connect(("svn.python.org", 443))
574 try:
575 self.assertEqual({}, s.getpeercert())
576 finally:
577 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000578 # Same with a server hostname
579 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
580 server_hostname="svn.python.org")
581 if ssl.HAS_SNI:
582 s.connect(("svn.python.org", 443))
583 s.close()
584 else:
585 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000586 # This should fail because we have no verification certs
587 ctx.verify_mode = ssl.CERT_REQUIRED
588 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000589 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000590 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000591 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000592 # This should succeed because we specify the root cert
593 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
594 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
595 s.connect(("svn.python.org", 443))
596 try:
597 cert = s.getpeercert()
598 self.assertTrue(cert)
599 finally:
600 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000601
602 def test_connect_capath(self):
603 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000604 # NOTE: the subject hashing algorithm has been changed between
605 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
606 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000607 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000608 with support.transient_internet("svn.python.org"):
609 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
610 ctx.verify_mode = ssl.CERT_REQUIRED
611 ctx.load_verify_locations(capath=CAPATH)
612 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
613 s.connect(("svn.python.org", 443))
614 try:
615 cert = s.getpeercert()
616 self.assertTrue(cert)
617 finally:
618 s.close()
619 # Same with a bytes `capath` argument
620 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
621 ctx.verify_mode = ssl.CERT_REQUIRED
622 ctx.load_verify_locations(capath=BYTES_CAPATH)
623 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
624 s.connect(("svn.python.org", 443))
625 try:
626 cert = s.getpeercert()
627 self.assertTrue(cert)
628 finally:
629 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000630
Antoine Pitroue3220242010-04-24 11:13:53 +0000631 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
632 def test_makefile_close(self):
633 # Issue #5238: creating a file-like object with makefile() shouldn't
634 # delay closing the underlying "real socket" (here tested with its
635 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000636 with support.transient_internet("svn.python.org"):
637 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
638 ss.connect(("svn.python.org", 443))
639 fd = ss.fileno()
640 f = ss.makefile()
641 f.close()
642 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000643 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000644 # Closing the SSL socket should close the fd too
645 ss.close()
646 gc.collect()
647 with self.assertRaises(OSError) as e:
648 os.read(fd, 0)
649 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000650
Antoine Pitrou480a1242010-04-28 21:37:09 +0000651 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000652 with support.transient_internet("svn.python.org"):
653 s = socket.socket(socket.AF_INET)
654 s.connect(("svn.python.org", 443))
655 s.setblocking(False)
656 s = ssl.wrap_socket(s,
657 cert_reqs=ssl.CERT_NONE,
658 do_handshake_on_connect=False)
659 count = 0
660 while True:
661 try:
662 count += 1
663 s.do_handshake()
664 break
665 except ssl.SSLError as err:
666 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
667 select.select([s], [], [])
668 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
669 select.select([], [s], [])
670 else:
671 raise
672 s.close()
673 if support.verbose:
674 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000675
Antoine Pitrou480a1242010-04-28 21:37:09 +0000676 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200677 def _test_get_server_certificate(host, port, cert=None):
678 with support.transient_internet(host):
679 pem = ssl.get_server_certificate((host, port))
680 if not pem:
681 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200682
Antoine Pitrou15399c32011-04-28 19:23:55 +0200683 try:
684 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
685 except ssl.SSLError as x:
686 #should fail
687 if support.verbose:
688 sys.stdout.write("%s\n" % x)
689 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200690 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
691
Antoine Pitrou15399c32011-04-28 19:23:55 +0200692 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
693 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200694 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000695 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200696 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000697
Antoine Pitrou15399c32011-04-28 19:23:55 +0200698 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
699 if support.IPV6_ENABLED:
700 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000701
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000702 def test_ciphers(self):
703 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000704 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000705 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000706 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000707 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000708 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
709 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
710 s.connect(remote)
711 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000712 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000713 with socket.socket(socket.AF_INET) as sock:
714 s = ssl.wrap_socket(sock,
715 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
716 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000717
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000718 def test_algorithms(self):
719 # Issue #8484: all algorithms should be available when verifying a
720 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000721 # SHA256 was added in OpenSSL 0.9.8
722 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
723 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000724 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
725 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000726 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000727 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000728 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
729 cert_reqs=ssl.CERT_REQUIRED,
730 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000731 try:
732 s.connect(remote)
733 if support.verbose:
734 sys.stdout.write("\nCipher with %r is %r\n" %
735 (remote, s.cipher()))
736 sys.stdout.write("Certificate is:\n%s\n" %
737 pprint.pformat(s.getpeercert()))
738 finally:
739 s.close()
740
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000741
742try:
743 import threading
744except ImportError:
745 _have_threads = False
746else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000747 _have_threads = True
748
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000749 from test.ssl_servers import make_https_server
750
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000751 class ThreadedEchoServer(threading.Thread):
752
753 class ConnectionHandler(threading.Thread):
754
755 """A mildly complicated class, because we want it to work both
756 with and without the SSL wrapper around the socket connection, so
757 that we can test the STARTTLS functionality."""
758
Bill Janssen6e027db2007-11-15 22:23:56 +0000759 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000760 self.server = server
761 self.running = False
762 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000763 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000764 self.sock.setblocking(1)
765 self.sslconn = None
766 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000767 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000768
Antoine Pitrou480a1242010-04-28 21:37:09 +0000769 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000770 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000771 self.sslconn = self.server.context.wrap_socket(
772 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000773 except ssl.SSLError:
774 # XXX Various errors can have happened here, for example
775 # a mismatching protocol version, an invalid certificate,
776 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000777 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000778 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000779 self.running = False
780 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000781 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000782 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000784 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000785 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000786 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
788 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000789 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000790 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
791 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000792 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000793 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
794 return True
795
796 def read(self):
797 if self.sslconn:
798 return self.sslconn.read()
799 else:
800 return self.sock.recv(1024)
801
802 def write(self, bytes):
803 if self.sslconn:
804 return self.sslconn.write(bytes)
805 else:
806 return self.sock.send(bytes)
807
808 def close(self):
809 if self.sslconn:
810 self.sslconn.close()
811 else:
812 self.sock.close()
813
Antoine Pitrou480a1242010-04-28 21:37:09 +0000814 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000815 self.running = True
816 if not self.server.starttls_server:
817 if not self.wrap_conn():
818 return
819 while self.running:
820 try:
821 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000822 stripped = msg.strip()
823 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000824 # eof, so quit this handler
825 self.running = False
826 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000827 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000828 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829 sys.stdout.write(" server: client closed connection\n")
830 self.close()
831 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000832 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000833 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000834 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000835 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000836 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000837 if not self.wrap_conn():
838 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000839 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000840 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000841 if support.verbose and self.server.connectionchatty:
842 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000843 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000844 self.sock = self.sslconn.unwrap()
845 self.sslconn = None
846 if support.verbose and self.server.connectionchatty:
847 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200848 elif stripped == b'CB tls-unique':
849 if support.verbose and self.server.connectionchatty:
850 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
851 data = self.sslconn.get_channel_binding("tls-unique")
852 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000854 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000855 self.server.connectionchatty):
856 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000857 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
858 % (msg, ctype, msg.lower(), ctype))
859 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000860 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 if self.server.chatty:
862 handle_error("Test server failure:\n")
863 self.close()
864 self.running = False
865 # normally, we'd just stop here, but for the test
866 # harness, we want to stop the server
867 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868
Antoine Pitroub5218772010-05-21 09:56:06 +0000869 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000870 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000871 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000872 ciphers=None, context=None):
873 if context:
874 self.context = context
875 else:
876 self.context = ssl.SSLContext(ssl_version
877 if ssl_version is not None
878 else ssl.PROTOCOL_TLSv1)
879 self.context.verify_mode = (certreqs if certreqs is not None
880 else ssl.CERT_NONE)
881 if cacerts:
882 self.context.load_verify_locations(cacerts)
883 if certificate:
884 self.context.load_cert_chain(certificate)
885 if ciphers:
886 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000887 self.chatty = chatty
888 self.connectionchatty = connectionchatty
889 self.starttls_server = starttls_server
890 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000891 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000893 self.active = False
894 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000895 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896
Antoine Pitrou480a1242010-04-28 21:37:09 +0000897 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 self.flag = flag
899 threading.Thread.start(self)
900
Antoine Pitrou480a1242010-04-28 21:37:09 +0000901 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000902 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903 self.sock.listen(5)
904 self.active = True
905 if self.flag:
906 # signal an event
907 self.flag.set()
908 while self.active:
909 try:
910 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000911 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000912 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000913 + repr(connaddr) + '\n')
914 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 handler.start()
916 except socket.timeout:
917 pass
918 except KeyboardInterrupt:
919 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000920 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921
Antoine Pitrou480a1242010-04-28 21:37:09 +0000922 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924
Bill Janssen54cc54c2007-12-14 22:08:56 +0000925 class AsyncoreEchoServer(threading.Thread):
926
927 # this one's based on asyncore.dispatcher
928
929 class EchoServer (asyncore.dispatcher):
930
931 class ConnectionHandler (asyncore.dispatcher_with_send):
932
933 def __init__(self, conn, certfile):
934 self.socket = ssl.wrap_socket(conn, server_side=True,
935 certfile=certfile,
936 do_handshake_on_connect=False)
937 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000938 self._ssl_accepting = True
939 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000940
941 def readable(self):
942 if isinstance(self.socket, ssl.SSLSocket):
943 while self.socket.pending() > 0:
944 self.handle_read_event()
945 return True
946
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000947 def _do_ssl_handshake(self):
948 try:
949 self.socket.do_handshake()
950 except ssl.SSLError as err:
951 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
952 ssl.SSL_ERROR_WANT_WRITE):
953 return
954 elif err.args[0] == ssl.SSL_ERROR_EOF:
955 return self.handle_close()
956 raise
957 except socket.error as err:
958 if err.args[0] == errno.ECONNABORTED:
959 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000960 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000961 self._ssl_accepting = False
962
963 def handle_read(self):
964 if self._ssl_accepting:
965 self._do_ssl_handshake()
966 else:
967 data = self.recv(1024)
968 if support.verbose:
969 sys.stdout.write(" server: read %s from client\n" % repr(data))
970 if not data:
971 self.close()
972 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000973 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000974
975 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000976 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000977 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000978 sys.stdout.write(" server: closed connection %s\n" % self.socket)
979
980 def handle_error(self):
981 raise
982
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000983 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000984 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000985 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
986 self.port = support.bind_port(sock, '')
987 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000988 self.listen(5)
989
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000990 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000991 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000992 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
993 self.ConnectionHandler(sock_obj, self.certfile)
994
995 def handle_error(self):
996 raise
997
Trent Nelson78520002008-04-10 20:54:35 +0000998 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000999 self.flag = None
1000 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001001 self.server = self.EchoServer(certfile)
1002 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001003 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001004 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001005
1006 def __str__(self):
1007 return "<%s %s>" % (self.__class__.__name__, self.server)
1008
1009 def start (self, flag=None):
1010 self.flag = flag
1011 threading.Thread.start(self)
1012
Antoine Pitrou480a1242010-04-28 21:37:09 +00001013 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001014 self.active = True
1015 if self.flag:
1016 self.flag.set()
1017 while self.active:
1018 try:
1019 asyncore.loop(1)
1020 except:
1021 pass
1022
Antoine Pitrou480a1242010-04-28 21:37:09 +00001023 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001024 self.active = False
1025 self.server.close()
1026
Antoine Pitrou480a1242010-04-28 21:37:09 +00001027 def bad_cert_test(certfile):
1028 """
1029 Launch a server with CERT_REQUIRED, and check that trying to
1030 connect to it with the given client certificate fails.
1031 """
Trent Nelson78520002008-04-10 20:54:35 +00001032 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001033 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001034 cacerts=CERTFILE, chatty=False,
1035 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001036 flag = threading.Event()
1037 server.start(flag)
1038 # wait for it to start
1039 flag.wait()
1040 # try to connect
1041 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001042 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001043 with socket.socket() as sock:
1044 s = ssl.wrap_socket(sock,
1045 certfile=certfile,
1046 ssl_version=ssl.PROTOCOL_TLSv1)
1047 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001048 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001049 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001050 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001051 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001052 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001053 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001054 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001055 if x.errno != errno.ENOENT:
1056 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001057 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001058 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001059 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001060 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001061 finally:
1062 server.stop()
1063 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001064
Antoine Pitroub5218772010-05-21 09:56:06 +00001065 def server_params_test(client_context, server_context, indata=b"FOO\n",
1066 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 """
1068 Launch a server, connect a client to it and try various reads
1069 and writes.
1070 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001071 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001072 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001073 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001074 flag = threading.Event()
1075 server.start(flag)
1076 # wait for it to start
1077 flag.wait()
1078 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001079 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001080 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001081 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001082 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001083 if connectionchatty:
1084 if support.verbose:
1085 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001086 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001087 s.write(arg)
1088 outdata = s.read()
1089 if connectionchatty:
1090 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001092 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001093 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001094 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1095 % (outdata[:20], len(outdata),
1096 indata[:20].lower(), len(indata)))
1097 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001098 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001099 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001100 sys.stdout.write(" client: closing connection.\n")
1101 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001102 finally:
1103 server.stop()
1104 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001105
Antoine Pitroub5218772010-05-21 09:56:06 +00001106 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1107 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001108 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001110 certtype = {
1111 ssl.CERT_NONE: "CERT_NONE",
1112 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1113 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1114 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001115 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001116 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001117 sys.stdout.write(formatstr %
1118 (ssl.get_protocol_name(client_protocol),
1119 ssl.get_protocol_name(server_protocol),
1120 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001121 client_context = ssl.SSLContext(client_protocol)
1122 client_context.options = ssl.OP_ALL | client_options
1123 server_context = ssl.SSLContext(server_protocol)
1124 server_context.options = ssl.OP_ALL | server_options
1125 for ctx in (client_context, server_context):
1126 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001127 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1128 # will send an SSLv3 hello (rather than SSLv2) starting from
1129 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001130 ctx.set_ciphers("ALL")
1131 ctx.load_cert_chain(CERTFILE)
1132 ctx.load_verify_locations(CERTFILE)
1133 try:
1134 server_params_test(client_context, server_context,
1135 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001136 # Protocol mismatch can result in either an SSLError, or a
1137 # "Connection reset by peer" error.
1138 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001141 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001142 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001143 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001146 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147 "Client protocol %s succeeded with server protocol %s!"
1148 % (ssl.get_protocol_name(client_protocol),
1149 ssl.get_protocol_name(server_protocol)))
1150
1151
Bill Janssen6e027db2007-11-15 22:23:56 +00001152 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001153
Antoine Pitrou23df4832010-08-04 17:14:06 +00001154 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001155 def test_echo(self):
1156 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001157 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001158 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001159 for protocol in PROTOCOLS:
1160 context = ssl.SSLContext(protocol)
1161 context.load_cert_chain(CERTFILE)
1162 server_params_test(context, context,
1163 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001164
Antoine Pitrou480a1242010-04-28 21:37:09 +00001165 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001166 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001168 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1169 context.verify_mode = ssl.CERT_REQUIRED
1170 context.load_verify_locations(CERTFILE)
1171 context.load_cert_chain(CERTFILE)
1172 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001173 flag = threading.Event()
1174 server.start(flag)
1175 # wait for it to start
1176 flag.wait()
1177 # try to connect
1178 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001179 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001180 s.connect((HOST, server.port))
1181 cert = s.getpeercert()
1182 self.assertTrue(cert, "Can't get peer certificate.")
1183 cipher = s.cipher()
1184 if support.verbose:
1185 sys.stdout.write(pprint.pformat(cert) + '\n')
1186 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1187 if 'subject' not in cert:
1188 self.fail("No subject field in certificate: %s." %
1189 pprint.pformat(cert))
1190 if ((('organizationName', 'Python Software Foundation'),)
1191 not in cert['subject']):
1192 self.fail(
1193 "Missing or invalid 'organizationName' field in certificate subject; "
1194 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001195 self.assertIn('notBefore', cert)
1196 self.assertIn('notAfter', cert)
1197 before = ssl.cert_time_to_seconds(cert['notBefore'])
1198 after = ssl.cert_time_to_seconds(cert['notAfter'])
1199 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001200 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001201 finally:
1202 server.stop()
1203 server.join()
1204
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 def test_empty_cert(self):
1206 """Connecting with an empty cert file"""
1207 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1208 "nullcert.pem"))
1209 def test_malformed_cert(self):
1210 """Connecting with a badly formatted certificate (syntax error)"""
1211 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1212 "badcert.pem"))
1213 def test_nonexisting_cert(self):
1214 """Connecting with a non-existing cert file"""
1215 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1216 "wrongcert.pem"))
1217 def test_malformed_key(self):
1218 """Connecting with a badly formatted key (syntax error)"""
1219 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1220 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001221
Antoine Pitrou480a1242010-04-28 21:37:09 +00001222 def test_rude_shutdown(self):
1223 """A brutal shutdown of an SSL server should raise an IOError
1224 in the client when attempting handshake.
1225 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001226 listener_ready = threading.Event()
1227 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001228
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001229 s = socket.socket()
1230 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001231
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001232 # `listener` runs in a thread. It sits in an accept() until
1233 # the main thread connects. Then it rudely closes the socket,
1234 # and sets Event `listener_gone` to let the main thread know
1235 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001236 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001237 s.listen(5)
1238 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001239 newsock, addr = s.accept()
1240 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001241 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001242 listener_gone.set()
1243
1244 def connector():
1245 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001246 with socket.socket() as c:
1247 c.connect((HOST, port))
1248 listener_gone.wait()
1249 try:
1250 ssl_sock = ssl.wrap_socket(c)
1251 except IOError:
1252 pass
1253 else:
1254 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001255
1256 t = threading.Thread(target=listener)
1257 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001258 try:
1259 connector()
1260 finally:
1261 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001262
Antoine Pitrou23df4832010-08-04 17:14:06 +00001263 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001264 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1265 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001266 def test_protocol_sslv2(self):
1267 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001268 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001269 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001270 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1271 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1272 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1273 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1274 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1275 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001276 # SSLv23 client with specific SSL options
1277 if no_sslv2_implies_sslv3_hello():
1278 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1279 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1280 client_options=ssl.OP_NO_SSLv2)
1281 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1282 client_options=ssl.OP_NO_SSLv3)
1283 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1284 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001285
Antoine Pitrou23df4832010-08-04 17:14:06 +00001286 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001287 def test_protocol_sslv23(self):
1288 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001289 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001290 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001291 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1292 try:
1293 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1294 except (ssl.SSLError, socket.error) as x:
1295 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1296 if support.verbose:
1297 sys.stdout.write(
1298 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1299 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001300 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1301 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1302 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001303
Antoine Pitrou480a1242010-04-28 21:37:09 +00001304 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1305 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1306 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001307
Antoine Pitrou480a1242010-04-28 21:37:09 +00001308 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1309 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1310 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001311
Antoine Pitroub5218772010-05-21 09:56:06 +00001312 # Server with specific SSL options
1313 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1314 server_options=ssl.OP_NO_SSLv3)
1315 # Will choose TLSv1
1316 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1317 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1318 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1319 server_options=ssl.OP_NO_TLSv1)
1320
1321
Antoine Pitrou23df4832010-08-04 17:14:06 +00001322 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001323 def test_protocol_sslv3(self):
1324 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001325 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001326 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001327 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1328 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1329 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001330 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1331 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001332 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1333 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001334 if no_sslv2_implies_sslv3_hello():
1335 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1336 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1337 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001338
Antoine Pitrou23df4832010-08-04 17:14:06 +00001339 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001340 def test_protocol_tlsv1(self):
1341 """Connecting to a TLSv1 server with various client options"""
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 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1345 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1346 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001347 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1348 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001349 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1350 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001351
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 def test_starttls(self):
1353 """Switching from clear text to encrypted and back again."""
1354 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 +00001355
Trent Nelson78520002008-04-10 20:54:35 +00001356 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001357 ssl_version=ssl.PROTOCOL_TLSv1,
1358 starttls_server=True,
1359 chatty=True,
1360 connectionchatty=True)
1361 flag = threading.Event()
1362 server.start(flag)
1363 # wait for it to start
1364 flag.wait()
1365 # try to connect
1366 wrapped = False
1367 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001368 s = socket.socket()
1369 s.setblocking(1)
1370 s.connect((HOST, server.port))
1371 if support.verbose:
1372 sys.stdout.write("\n")
1373 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001374 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001375 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001377 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001378 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001379 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001380 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001382 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 msg = outdata.strip().lower()
1384 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1385 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001386 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001387 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001388 " client: read %r from server, starting TLS...\n"
1389 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001390 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1391 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001392 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1393 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001394 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001395 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 " client: read %r from server, ending TLS...\n"
1397 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001398 s = conn.unwrap()
1399 wrapped = False
1400 else:
1401 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001402 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001403 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001404 if support.verbose:
1405 sys.stdout.write(" client: closing connection.\n")
1406 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001407 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001408 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001409 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001410 if wrapped:
1411 conn.close()
1412 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001413 s.close()
1414 finally:
1415 server.stop()
1416 server.join()
1417
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 def test_socketserver(self):
1419 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001420 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001421 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001422 if support.verbose:
1423 sys.stdout.write('\n')
1424 with open(CERTFILE, 'rb') as f:
1425 d1 = f.read()
1426 d2 = ''
1427 # now fetch the same data from the HTTPS server
1428 url = 'https://%s:%d/%s' % (
1429 HOST, server.port, os.path.split(CERTFILE)[1])
1430 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001431 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001432 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001433 if dlen and (int(dlen) > 0):
1434 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001435 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001436 sys.stdout.write(
1437 " client: read %d bytes from remote server '%s'\n"
1438 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001439 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001440 f.close()
1441 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001442
Antoine Pitrou480a1242010-04-28 21:37:09 +00001443 def test_asyncore_server(self):
1444 """Check the example asyncore integration."""
1445 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001446
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001447 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001448 sys.stdout.write("\n")
1449
Antoine Pitrou480a1242010-04-28 21:37:09 +00001450 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001451 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001452 flag = threading.Event()
1453 server.start(flag)
1454 # wait for it to start
1455 flag.wait()
1456 # try to connect
1457 try:
1458 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001459 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001460 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001461 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001462 " client: sending %r...\n" % indata)
1463 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001464 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001465 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001466 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001467 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001468 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001469 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1470 % (outdata[:20], len(outdata),
1471 indata[:20].lower(), len(indata)))
1472 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001473 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001474 sys.stdout.write(" client: closing connection.\n")
1475 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001476 if support.verbose:
1477 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001478 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001479 if support.verbose:
1480 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001481 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001482 if support.verbose:
1483 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001484 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001485 if support.verbose:
1486 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001487
Antoine Pitrou480a1242010-04-28 21:37:09 +00001488 def test_recv_send(self):
1489 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001490 if support.verbose:
1491 sys.stdout.write("\n")
1492
1493 server = ThreadedEchoServer(CERTFILE,
1494 certreqs=ssl.CERT_NONE,
1495 ssl_version=ssl.PROTOCOL_TLSv1,
1496 cacerts=CERTFILE,
1497 chatty=True,
1498 connectionchatty=False)
1499 flag = threading.Event()
1500 server.start(flag)
1501 # wait for it to start
1502 flag.wait()
1503 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001504 s = ssl.wrap_socket(socket.socket(),
1505 server_side=False,
1506 certfile=CERTFILE,
1507 ca_certs=CERTFILE,
1508 cert_reqs=ssl.CERT_NONE,
1509 ssl_version=ssl.PROTOCOL_TLSv1)
1510 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001511 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001512 # helper methods for standardising recv* method signatures
1513 def _recv_into():
1514 b = bytearray(b"\0"*100)
1515 count = s.recv_into(b)
1516 return b[:count]
1517
1518 def _recvfrom_into():
1519 b = bytearray(b"\0"*100)
1520 count, addr = s.recvfrom_into(b)
1521 return b[:count]
1522
1523 # (name, method, whether to expect success, *args)
1524 send_methods = [
1525 ('send', s.send, True, []),
1526 ('sendto', s.sendto, False, ["some.address"]),
1527 ('sendall', s.sendall, True, []),
1528 ]
1529 recv_methods = [
1530 ('recv', s.recv, True, []),
1531 ('recvfrom', s.recvfrom, False, ["some.address"]),
1532 ('recv_into', _recv_into, True, []),
1533 ('recvfrom_into', _recvfrom_into, False, []),
1534 ]
1535 data_prefix = "PREFIX_"
1536
1537 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001538 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001539 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001540 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001541 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001542 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001543 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001544 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 "<<{outdata:r}>> ({nout:d}) received; "
1546 "expected <<{indata:r}>> ({nin:d})\n".format(
1547 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001548 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001549 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001550 )
1551 )
1552 except ValueError as e:
1553 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001554 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001555 "Failed to send with method <<{name:s}>>; "
1556 "expected to succeed.\n".format(name=meth_name)
1557 )
1558 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001559 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001560 "Method <<{name:s}>> failed with unexpected "
1561 "exception message: {exp:s}\n".format(
1562 name=meth_name, exp=e
1563 )
1564 )
1565
1566 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001568 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001569 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001570 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001571 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001572 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001573 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001574 "<<{outdata:r}>> ({nout:d}) received; "
1575 "expected <<{indata:r}>> ({nin:d})\n".format(
1576 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001577 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001578 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001579 )
1580 )
1581 except ValueError as e:
1582 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001583 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001584 "Failed to receive with method <<{name:s}>>; "
1585 "expected to succeed.\n".format(name=meth_name)
1586 )
1587 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001588 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001589 "Method <<{name:s}>> failed with unexpected "
1590 "exception message: {exp:s}\n".format(
1591 name=meth_name, exp=e
1592 )
1593 )
1594 # consume data
1595 s.read()
1596
Antoine Pitrou480a1242010-04-28 21:37:09 +00001597 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001598 s.close()
1599 finally:
1600 server.stop()
1601 server.join()
1602
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001603 def test_handshake_timeout(self):
1604 # Issue #5103: SSL handshake must respect the socket timeout
1605 server = socket.socket(socket.AF_INET)
1606 host = "127.0.0.1"
1607 port = support.bind_port(server)
1608 started = threading.Event()
1609 finish = False
1610
1611 def serve():
1612 server.listen(5)
1613 started.set()
1614 conns = []
1615 while not finish:
1616 r, w, e = select.select([server], [], [], 0.1)
1617 if server in r:
1618 # Let the socket hang around rather than having
1619 # it closed by garbage collection.
1620 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001621 for sock in conns:
1622 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001623
1624 t = threading.Thread(target=serve)
1625 t.start()
1626 started.wait()
1627
1628 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001629 try:
1630 c = socket.socket(socket.AF_INET)
1631 c.settimeout(0.2)
1632 c.connect((host, port))
1633 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001634 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001635 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001636 finally:
1637 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001638 try:
1639 c = socket.socket(socket.AF_INET)
1640 c = ssl.wrap_socket(c)
1641 c.settimeout(0.2)
1642 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001643 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001644 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001645 finally:
1646 c.close()
1647 finally:
1648 finish = True
1649 t.join()
1650 server.close()
1651
Antoine Pitroud6494802011-07-21 01:11:30 +02001652 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1653 "'tls-unique' channel binding not available")
1654 def test_tls_unique_channel_binding(self):
1655 """Test tls-unique channel binding."""
1656 if support.verbose:
1657 sys.stdout.write("\n")
1658
1659 server = ThreadedEchoServer(CERTFILE,
1660 certreqs=ssl.CERT_NONE,
1661 ssl_version=ssl.PROTOCOL_TLSv1,
1662 cacerts=CERTFILE,
1663 chatty=True,
1664 connectionchatty=False)
1665 flag = threading.Event()
1666 server.start(flag)
1667 # wait for it to start
1668 flag.wait()
1669 # try to connect
1670 s = ssl.wrap_socket(socket.socket(),
1671 server_side=False,
1672 certfile=CERTFILE,
1673 ca_certs=CERTFILE,
1674 cert_reqs=ssl.CERT_NONE,
1675 ssl_version=ssl.PROTOCOL_TLSv1)
1676 s.connect((HOST, server.port))
1677 try:
1678 # get the data
1679 cb_data = s.get_channel_binding("tls-unique")
1680 if support.verbose:
1681 sys.stdout.write(" got channel binding data: {0!r}\n"
1682 .format(cb_data))
1683
1684 # check if it is sane
1685 self.assertIsNotNone(cb_data)
1686 self.assertEqual(len(cb_data), 12) # True for TLSv1
1687
1688 # and compare with the peers version
1689 s.write(b"CB tls-unique\n")
1690 peer_data_repr = s.read().strip()
1691 self.assertEqual(peer_data_repr,
1692 repr(cb_data).encode("us-ascii"))
1693 s.close()
1694
1695 # now, again
1696 s = ssl.wrap_socket(socket.socket(),
1697 server_side=False,
1698 certfile=CERTFILE,
1699 ca_certs=CERTFILE,
1700 cert_reqs=ssl.CERT_NONE,
1701 ssl_version=ssl.PROTOCOL_TLSv1)
1702 s.connect((HOST, server.port))
1703 new_cb_data = s.get_channel_binding("tls-unique")
1704 if support.verbose:
1705 sys.stdout.write(" got another channel binding data: {0!r}\n"
1706 .format(new_cb_data))
1707 # is it really unique
1708 self.assertNotEqual(cb_data, new_cb_data)
1709 self.assertIsNotNone(cb_data)
1710 self.assertEqual(len(cb_data), 12) # True for TLSv1
1711 s.write(b"CB tls-unique\n")
1712 peer_data_repr = s.read().strip()
1713 self.assertEqual(peer_data_repr,
1714 repr(new_cb_data).encode("us-ascii"))
1715 s.close()
1716 finally:
1717 server.stop()
1718 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001719
Thomas Woutersed03b412007-08-28 21:37:11 +00001720def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001721 if support.verbose:
1722 plats = {
1723 'Linux': platform.linux_distribution,
1724 'Mac': platform.mac_ver,
1725 'Windows': platform.win32_ver,
1726 }
1727 for name, func in plats.items():
1728 plat = func()
1729 if plat and plat[0]:
1730 plat = '%s %r' % (name, plat)
1731 break
1732 else:
1733 plat = repr(platform.platform())
1734 print("test_ssl: testing with %r %r" %
1735 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1736 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001737 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001738
Antoine Pitrou152efa22010-05-16 18:19:27 +00001739 for filename in [
1740 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1741 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1742 BADCERT, BADKEY, EMPTYCERT]:
1743 if not os.path.exists(filename):
1744 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001745
Antoine Pitrou152efa22010-05-16 18:19:27 +00001746 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001747
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001748 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001749 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001750
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001751 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001752 thread_info = support.threading_setup()
1753 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001754 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001755
Antoine Pitrou480a1242010-04-28 21:37:09 +00001756 try:
1757 support.run_unittest(*tests)
1758 finally:
1759 if _have_threads:
1760 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001761
1762if __name__ == "__main__":
1763 test_main()