blob: 1d26c11ed8bfe810e5d2e6050255001533917c6e [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)
Nick Coghlan96fe56a2011-08-22 11:55:57 +1000189 self.assertRaises(socket.error, ss.recvmsg, 1)
190 self.assertRaises(socket.error, ss.recvmsg_into, [bytearray(b'x')])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000191 self.assertRaises(socket.error, ss.send, b'x')
192 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
Nick Coghlan96fe56a2011-08-22 11:55:57 +1000193 self.assertRaises(socket.error, ss.sendmsg, [b'x'])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000194
Antoine Pitrou40f08742010-04-24 22:04:40 +0000195 def test_timeout(self):
196 # Issue #8524: when creating an SSL socket, the timeout of the
197 # original socket should be retained.
198 for timeout in (None, 0.0, 5.0):
199 s = socket.socket(socket.AF_INET)
200 s.settimeout(timeout)
201 ss = ssl.wrap_socket(s)
202 self.assertEqual(timeout, ss.gettimeout())
203
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000204 def test_errors(self):
205 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000206 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000207 "certfile must be specified",
208 ssl.wrap_socket, sock, keyfile=CERTFILE)
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)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000212 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000213 "certfile must be specified for server-side operations",
214 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000215 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000216 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000217 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000218 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000219 with socket.socket() as sock:
220 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000221 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000222 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000223 with socket.socket() as sock:
224 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000225 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000226 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000227 with socket.socket() as sock:
228 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000229 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000230
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000231 def test_match_hostname(self):
232 def ok(cert, hostname):
233 ssl.match_hostname(cert, hostname)
234 def fail(cert, hostname):
235 self.assertRaises(ssl.CertificateError,
236 ssl.match_hostname, cert, hostname)
237
238 cert = {'subject': ((('commonName', 'example.com'),),)}
239 ok(cert, 'example.com')
240 ok(cert, 'ExAmple.cOm')
241 fail(cert, 'www.example.com')
242 fail(cert, '.example.com')
243 fail(cert, 'example.org')
244 fail(cert, 'exampleXcom')
245
246 cert = {'subject': ((('commonName', '*.a.com'),),)}
247 ok(cert, 'foo.a.com')
248 fail(cert, 'bar.foo.a.com')
249 fail(cert, 'a.com')
250 fail(cert, 'Xa.com')
251 fail(cert, '.a.com')
252
253 cert = {'subject': ((('commonName', 'a.*.com'),),)}
254 ok(cert, 'a.foo.com')
255 fail(cert, 'a..com')
256 fail(cert, 'a.com')
257
258 cert = {'subject': ((('commonName', 'f*.com'),),)}
259 ok(cert, 'foo.com')
260 ok(cert, 'f.com')
261 fail(cert, 'bar.com')
262 fail(cert, 'foo.a.com')
263 fail(cert, 'bar.foo.com')
264
265 # Slightly fake real-world example
266 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
267 'subject': ((('commonName', 'linuxfrz.org'),),),
268 'subjectAltName': (('DNS', 'linuxfr.org'),
269 ('DNS', 'linuxfr.com'),
270 ('othername', '<unsupported>'))}
271 ok(cert, 'linuxfr.org')
272 ok(cert, 'linuxfr.com')
273 # Not a "DNS" entry
274 fail(cert, '<unsupported>')
275 # When there is a subjectAltName, commonName isn't used
276 fail(cert, 'linuxfrz.org')
277
278 # A pristine real-world example
279 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
280 'subject': ((('countryName', 'US'),),
281 (('stateOrProvinceName', 'California'),),
282 (('localityName', 'Mountain View'),),
283 (('organizationName', 'Google Inc'),),
284 (('commonName', 'mail.google.com'),))}
285 ok(cert, 'mail.google.com')
286 fail(cert, 'gmail.com')
287 # Only commonName is considered
288 fail(cert, 'California')
289
290 # Neither commonName nor subjectAltName
291 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
292 'subject': ((('countryName', 'US'),),
293 (('stateOrProvinceName', 'California'),),
294 (('localityName', 'Mountain View'),),
295 (('organizationName', 'Google Inc'),))}
296 fail(cert, 'mail.google.com')
297
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200298 # No DNS entry in subjectAltName but a commonName
299 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
300 'subject': ((('countryName', 'US'),),
301 (('stateOrProvinceName', 'California'),),
302 (('localityName', 'Mountain View'),),
303 (('commonName', 'mail.google.com'),)),
304 'subjectAltName': (('othername', 'blabla'), )}
305 ok(cert, 'mail.google.com')
306
307 # No DNS entry subjectAltName and no commonName
308 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
309 'subject': ((('countryName', 'US'),),
310 (('stateOrProvinceName', 'California'),),
311 (('localityName', 'Mountain View'),),
312 (('organizationName', 'Google Inc'),)),
313 'subjectAltName': (('othername', 'blabla'),)}
314 fail(cert, 'google.com')
315
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000316 # Empty cert / no cert
317 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
318 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
319
Antoine Pitroud5323212010-10-22 18:19:07 +0000320 def test_server_side(self):
321 # server_hostname doesn't work for server sockets
322 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000323 with socket.socket() as sock:
324 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
325 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000326
Antoine Pitroud6494802011-07-21 01:11:30 +0200327 def test_unknown_channel_binding(self):
328 # should raise ValueError for unknown type
329 s = socket.socket(socket.AF_INET)
330 ss = ssl.wrap_socket(s)
331 with self.assertRaises(ValueError):
332 ss.get_channel_binding("unknown-type")
333
334 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
335 "'tls-unique' channel binding not available")
336 def test_tls_unique_channel_binding(self):
337 # unconnected should return None for known type
338 s = socket.socket(socket.AF_INET)
339 ss = ssl.wrap_socket(s)
340 self.assertIsNone(ss.get_channel_binding("tls-unique"))
341 # the same for server-side
342 s = socket.socket(socket.AF_INET)
343 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
344 self.assertIsNone(ss.get_channel_binding("tls-unique"))
345
Antoine Pitrou152efa22010-05-16 18:19:27 +0000346class ContextTests(unittest.TestCase):
347
Antoine Pitrou23df4832010-08-04 17:14:06 +0000348 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000349 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200350 if hasattr(ssl, 'PROTOCOL_SSLv2'):
351 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000352 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
353 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
354 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
355 self.assertRaises(TypeError, ssl.SSLContext)
356 self.assertRaises(ValueError, ssl.SSLContext, -1)
357 self.assertRaises(ValueError, ssl.SSLContext, 42)
358
Antoine Pitrou23df4832010-08-04 17:14:06 +0000359 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000360 def test_protocol(self):
361 for proto in PROTOCOLS:
362 ctx = ssl.SSLContext(proto)
363 self.assertEqual(ctx.protocol, proto)
364
365 def test_ciphers(self):
366 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
367 ctx.set_ciphers("ALL")
368 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000369 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000370 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000371
Antoine Pitrou23df4832010-08-04 17:14:06 +0000372 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000373 def test_options(self):
374 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
375 # OP_ALL is the default value
376 self.assertEqual(ssl.OP_ALL, ctx.options)
377 ctx.options |= ssl.OP_NO_SSLv2
378 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
379 ctx.options)
380 ctx.options |= ssl.OP_NO_SSLv3
381 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
382 ctx.options)
383 if can_clear_options():
384 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
385 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
386 ctx.options)
387 ctx.options = 0
388 self.assertEqual(0, ctx.options)
389 else:
390 with self.assertRaises(ValueError):
391 ctx.options = 0
392
Antoine Pitrou152efa22010-05-16 18:19:27 +0000393 def test_verify(self):
394 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
395 # Default value
396 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
397 ctx.verify_mode = ssl.CERT_OPTIONAL
398 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
399 ctx.verify_mode = ssl.CERT_REQUIRED
400 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
401 ctx.verify_mode = ssl.CERT_NONE
402 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
403 with self.assertRaises(TypeError):
404 ctx.verify_mode = None
405 with self.assertRaises(ValueError):
406 ctx.verify_mode = 42
407
408 def test_load_cert_chain(self):
409 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
410 # Combined key and cert in a single file
411 ctx.load_cert_chain(CERTFILE)
412 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
413 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000414 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000415 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000416 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000417 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000418 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000419 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000420 ctx.load_cert_chain(EMPTYCERT)
421 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000422 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000423 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
424 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
425 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000426 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000427 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000428 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000429 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000430 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000431 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
432 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000433 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000434 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000435 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000436
437 def test_load_verify_locations(self):
438 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
439 ctx.load_verify_locations(CERTFILE)
440 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
441 ctx.load_verify_locations(BYTES_CERTFILE)
442 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
443 self.assertRaises(TypeError, ctx.load_verify_locations)
444 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000445 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000446 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000447 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000448 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000449 ctx.load_verify_locations(BADCERT)
450 ctx.load_verify_locations(CERTFILE, CAPATH)
451 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
452
Victor Stinner80f75e62011-01-29 11:31:20 +0000453 # Issue #10989: crash if the second argument type is invalid
454 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
455
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000456 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000457 def test_session_stats(self):
458 for proto in PROTOCOLS:
459 ctx = ssl.SSLContext(proto)
460 self.assertEqual(ctx.session_stats(), {
461 'number': 0,
462 'connect': 0,
463 'connect_good': 0,
464 'connect_renegotiate': 0,
465 'accept': 0,
466 'accept_good': 0,
467 'accept_renegotiate': 0,
468 'hits': 0,
469 'misses': 0,
470 'timeouts': 0,
471 'cache_full': 0,
472 })
473
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000474 def test_set_default_verify_paths(self):
475 # There's not much we can do to test that it acts as expected,
476 # so just check it doesn't crash or raise an exception.
477 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
478 ctx.set_default_verify_paths()
479
Antoine Pitrou152efa22010-05-16 18:19:27 +0000480
Bill Janssen6e027db2007-11-15 22:23:56 +0000481class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000482
Antoine Pitrou480a1242010-04-28 21:37:09 +0000483 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000484 with support.transient_internet("svn.python.org"):
485 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
486 cert_reqs=ssl.CERT_NONE)
487 try:
488 s.connect(("svn.python.org", 443))
489 self.assertEqual({}, s.getpeercert())
490 finally:
491 s.close()
492
493 # this should fail because we have no verification certs
494 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
495 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000496 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
497 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000498 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000499
Antoine Pitrou350c7222010-09-09 13:31:46 +0000500 # this should succeed because we specify the root cert
501 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
502 cert_reqs=ssl.CERT_REQUIRED,
503 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
504 try:
505 s.connect(("svn.python.org", 443))
506 self.assertTrue(s.getpeercert())
507 finally:
508 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000509
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000510 def test_connect_ex(self):
511 # Issue #11326: check connect_ex() implementation
512 with support.transient_internet("svn.python.org"):
513 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
514 cert_reqs=ssl.CERT_REQUIRED,
515 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
516 try:
517 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
518 self.assertTrue(s.getpeercert())
519 finally:
520 s.close()
521
522 def test_non_blocking_connect_ex(self):
523 # Issue #11326: non-blocking connect_ex() should allow handshake
524 # to proceed after the socket gets ready.
525 with support.transient_internet("svn.python.org"):
526 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
527 cert_reqs=ssl.CERT_REQUIRED,
528 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
529 do_handshake_on_connect=False)
530 try:
531 s.setblocking(False)
532 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000533 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
534 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000535 # Wait for connect to finish
536 select.select([], [s], [], 5.0)
537 # Non-blocking handshake
538 while True:
539 try:
540 s.do_handshake()
541 break
542 except ssl.SSLError as err:
543 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
544 select.select([s], [], [], 5.0)
545 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
546 select.select([], [s], [], 5.0)
547 else:
548 raise
549 # SSL established
550 self.assertTrue(s.getpeercert())
551 finally:
552 s.close()
553
Antoine Pitroub4410db2011-05-18 18:51:06 +0200554 def test_timeout_connect_ex(self):
555 # Issue #12065: on a timeout, connect_ex() should return the original
556 # errno (mimicking the behaviour of non-SSL sockets).
557 with support.transient_internet("svn.python.org"):
558 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
559 cert_reqs=ssl.CERT_REQUIRED,
560 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
561 do_handshake_on_connect=False)
562 try:
563 s.settimeout(0.0000001)
564 rc = s.connect_ex(('svn.python.org', 443))
565 if rc == 0:
566 self.skipTest("svn.python.org responded too quickly")
567 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
568 finally:
569 s.close()
570
Antoine Pitrou152efa22010-05-16 18:19:27 +0000571 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000572 with support.transient_internet("svn.python.org"):
573 # Same as test_connect, but with a separately created context
574 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
575 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
576 s.connect(("svn.python.org", 443))
577 try:
578 self.assertEqual({}, s.getpeercert())
579 finally:
580 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000581 # Same with a server hostname
582 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
583 server_hostname="svn.python.org")
584 if ssl.HAS_SNI:
585 s.connect(("svn.python.org", 443))
586 s.close()
587 else:
588 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000589 # This should fail because we have no verification certs
590 ctx.verify_mode = ssl.CERT_REQUIRED
591 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000592 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000593 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000594 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000595 # This should succeed because we specify the root cert
596 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
597 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
598 s.connect(("svn.python.org", 443))
599 try:
600 cert = s.getpeercert()
601 self.assertTrue(cert)
602 finally:
603 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000604
605 def test_connect_capath(self):
606 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000607 # NOTE: the subject hashing algorithm has been changed between
608 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
609 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000610 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000611 with support.transient_internet("svn.python.org"):
612 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
613 ctx.verify_mode = ssl.CERT_REQUIRED
614 ctx.load_verify_locations(capath=CAPATH)
615 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
616 s.connect(("svn.python.org", 443))
617 try:
618 cert = s.getpeercert()
619 self.assertTrue(cert)
620 finally:
621 s.close()
622 # Same with a bytes `capath` argument
623 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
624 ctx.verify_mode = ssl.CERT_REQUIRED
625 ctx.load_verify_locations(capath=BYTES_CAPATH)
626 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
627 s.connect(("svn.python.org", 443))
628 try:
629 cert = s.getpeercert()
630 self.assertTrue(cert)
631 finally:
632 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000633
Antoine Pitroue3220242010-04-24 11:13:53 +0000634 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
635 def test_makefile_close(self):
636 # Issue #5238: creating a file-like object with makefile() shouldn't
637 # delay closing the underlying "real socket" (here tested with its
638 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000639 with support.transient_internet("svn.python.org"):
640 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
641 ss.connect(("svn.python.org", 443))
642 fd = ss.fileno()
643 f = ss.makefile()
644 f.close()
645 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000646 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000647 # Closing the SSL socket should close the fd too
648 ss.close()
649 gc.collect()
650 with self.assertRaises(OSError) as e:
651 os.read(fd, 0)
652 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000653
Antoine Pitrou480a1242010-04-28 21:37:09 +0000654 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000655 with support.transient_internet("svn.python.org"):
656 s = socket.socket(socket.AF_INET)
657 s.connect(("svn.python.org", 443))
658 s.setblocking(False)
659 s = ssl.wrap_socket(s,
660 cert_reqs=ssl.CERT_NONE,
661 do_handshake_on_connect=False)
662 count = 0
663 while True:
664 try:
665 count += 1
666 s.do_handshake()
667 break
668 except ssl.SSLError as err:
669 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
670 select.select([s], [], [])
671 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
672 select.select([], [s], [])
673 else:
674 raise
675 s.close()
676 if support.verbose:
677 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000678
Antoine Pitrou480a1242010-04-28 21:37:09 +0000679 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200680 def _test_get_server_certificate(host, port, cert=None):
681 with support.transient_internet(host):
682 pem = ssl.get_server_certificate((host, port))
683 if not pem:
684 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200685
Antoine Pitrou15399c32011-04-28 19:23:55 +0200686 try:
687 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
688 except ssl.SSLError as x:
689 #should fail
690 if support.verbose:
691 sys.stdout.write("%s\n" % x)
692 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200693 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
694
Antoine Pitrou15399c32011-04-28 19:23:55 +0200695 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
696 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200697 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000698 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200699 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000700
Antoine Pitrou15399c32011-04-28 19:23:55 +0200701 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
702 if support.IPV6_ENABLED:
703 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000704
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000705 def test_ciphers(self):
706 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000707 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000708 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000709 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000710 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000711 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
712 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
713 s.connect(remote)
714 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000715 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000716 with socket.socket(socket.AF_INET) as sock:
717 s = ssl.wrap_socket(sock,
718 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
719 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000720
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000721 def test_algorithms(self):
722 # Issue #8484: all algorithms should be available when verifying a
723 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000724 # SHA256 was added in OpenSSL 0.9.8
725 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
726 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000727 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
728 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000729 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000730 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000731 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
732 cert_reqs=ssl.CERT_REQUIRED,
733 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000734 try:
735 s.connect(remote)
736 if support.verbose:
737 sys.stdout.write("\nCipher with %r is %r\n" %
738 (remote, s.cipher()))
739 sys.stdout.write("Certificate is:\n%s\n" %
740 pprint.pformat(s.getpeercert()))
741 finally:
742 s.close()
743
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000744
745try:
746 import threading
747except ImportError:
748 _have_threads = False
749else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750 _have_threads = True
751
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000752 from test.ssl_servers import make_https_server
753
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000754 class ThreadedEchoServer(threading.Thread):
755
756 class ConnectionHandler(threading.Thread):
757
758 """A mildly complicated class, because we want it to work both
759 with and without the SSL wrapper around the socket connection, so
760 that we can test the STARTTLS functionality."""
761
Bill Janssen6e027db2007-11-15 22:23:56 +0000762 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763 self.server = server
764 self.running = False
765 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000766 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000767 self.sock.setblocking(1)
768 self.sslconn = None
769 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000770 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000771
Antoine Pitrou480a1242010-04-28 21:37:09 +0000772 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000773 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000774 self.sslconn = self.server.context.wrap_socket(
775 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000776 except ssl.SSLError:
777 # XXX Various errors can have happened here, for example
778 # a mismatching protocol version, an invalid certificate,
779 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000780 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000781 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000782 self.running = False
783 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000784 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000785 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000786 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000787 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000788 cert = self.sslconn.getpeercert()
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(" client cert is " + pprint.pformat(cert) + "\n")
791 cert_binary = self.sslconn.getpeercert(True)
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(" cert binary is " + str(len(cert_binary)) + " bytes\n")
794 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000795 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000796 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
797 return True
798
799 def read(self):
800 if self.sslconn:
801 return self.sslconn.read()
802 else:
803 return self.sock.recv(1024)
804
805 def write(self, bytes):
806 if self.sslconn:
807 return self.sslconn.write(bytes)
808 else:
809 return self.sock.send(bytes)
810
811 def close(self):
812 if self.sslconn:
813 self.sslconn.close()
814 else:
815 self.sock.close()
816
Antoine Pitrou480a1242010-04-28 21:37:09 +0000817 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000818 self.running = True
819 if not self.server.starttls_server:
820 if not self.wrap_conn():
821 return
822 while self.running:
823 try:
824 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000825 stripped = msg.strip()
826 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000827 # eof, so quit this handler
828 self.running = False
829 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000830 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000831 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000832 sys.stdout.write(" server: client closed connection\n")
833 self.close()
834 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000835 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000836 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000837 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000838 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000839 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000840 if not self.wrap_conn():
841 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000842 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000843 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000844 if support.verbose and self.server.connectionchatty:
845 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000846 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000847 self.sock = self.sslconn.unwrap()
848 self.sslconn = None
849 if support.verbose and self.server.connectionchatty:
850 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200851 elif stripped == b'CB tls-unique':
852 if support.verbose and self.server.connectionchatty:
853 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
854 data = self.sslconn.get_channel_binding("tls-unique")
855 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000857 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000858 self.server.connectionchatty):
859 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000860 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
861 % (msg, ctype, msg.lower(), ctype))
862 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000863 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000864 if self.server.chatty:
865 handle_error("Test server failure:\n")
866 self.close()
867 self.running = False
868 # normally, we'd just stop here, but for the test
869 # harness, we want to stop the server
870 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000871
Antoine Pitroub5218772010-05-21 09:56:06 +0000872 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000873 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000874 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000875 ciphers=None, context=None):
876 if context:
877 self.context = context
878 else:
879 self.context = ssl.SSLContext(ssl_version
880 if ssl_version is not None
881 else ssl.PROTOCOL_TLSv1)
882 self.context.verify_mode = (certreqs if certreqs is not None
883 else ssl.CERT_NONE)
884 if cacerts:
885 self.context.load_verify_locations(cacerts)
886 if certificate:
887 self.context.load_cert_chain(certificate)
888 if ciphers:
889 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000890 self.chatty = chatty
891 self.connectionchatty = connectionchatty
892 self.starttls_server = starttls_server
893 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000894 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 self.active = False
897 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000898 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000899
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000901 self.flag = flag
902 threading.Thread.start(self)
903
Antoine Pitrou480a1242010-04-28 21:37:09 +0000904 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000905 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000906 self.sock.listen(5)
907 self.active = True
908 if self.flag:
909 # signal an event
910 self.flag.set()
911 while self.active:
912 try:
913 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000914 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000916 + repr(connaddr) + '\n')
917 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000918 handler.start()
919 except socket.timeout:
920 pass
921 except KeyboardInterrupt:
922 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000923 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924
Antoine Pitrou480a1242010-04-28 21:37:09 +0000925 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000926 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000927
Bill Janssen54cc54c2007-12-14 22:08:56 +0000928 class AsyncoreEchoServer(threading.Thread):
929
930 # this one's based on asyncore.dispatcher
931
932 class EchoServer (asyncore.dispatcher):
933
934 class ConnectionHandler (asyncore.dispatcher_with_send):
935
936 def __init__(self, conn, certfile):
937 self.socket = ssl.wrap_socket(conn, server_side=True,
938 certfile=certfile,
939 do_handshake_on_connect=False)
940 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000941 self._ssl_accepting = True
942 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000943
944 def readable(self):
945 if isinstance(self.socket, ssl.SSLSocket):
946 while self.socket.pending() > 0:
947 self.handle_read_event()
948 return True
949
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000950 def _do_ssl_handshake(self):
951 try:
952 self.socket.do_handshake()
953 except ssl.SSLError as err:
954 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
955 ssl.SSL_ERROR_WANT_WRITE):
956 return
957 elif err.args[0] == ssl.SSL_ERROR_EOF:
958 return self.handle_close()
959 raise
960 except socket.error as err:
961 if err.args[0] == errno.ECONNABORTED:
962 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000963 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000964 self._ssl_accepting = False
965
966 def handle_read(self):
967 if self._ssl_accepting:
968 self._do_ssl_handshake()
969 else:
970 data = self.recv(1024)
971 if support.verbose:
972 sys.stdout.write(" server: read %s from client\n" % repr(data))
973 if not data:
974 self.close()
975 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000976 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000977
978 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000979 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000980 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000981 sys.stdout.write(" server: closed connection %s\n" % self.socket)
982
983 def handle_error(self):
984 raise
985
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000986 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000987 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000988 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
989 self.port = support.bind_port(sock, '')
990 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000991 self.listen(5)
992
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000993 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000994 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000995 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
996 self.ConnectionHandler(sock_obj, self.certfile)
997
998 def handle_error(self):
999 raise
1000
Trent Nelson78520002008-04-10 20:54:35 +00001001 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001002 self.flag = None
1003 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001004 self.server = self.EchoServer(certfile)
1005 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001006 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001007 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001008
1009 def __str__(self):
1010 return "<%s %s>" % (self.__class__.__name__, self.server)
1011
1012 def start (self, flag=None):
1013 self.flag = flag
1014 threading.Thread.start(self)
1015
Antoine Pitrou480a1242010-04-28 21:37:09 +00001016 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001017 self.active = True
1018 if self.flag:
1019 self.flag.set()
1020 while self.active:
1021 try:
1022 asyncore.loop(1)
1023 except:
1024 pass
1025
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001027 self.active = False
1028 self.server.close()
1029
Antoine Pitrou480a1242010-04-28 21:37:09 +00001030 def bad_cert_test(certfile):
1031 """
1032 Launch a server with CERT_REQUIRED, and check that trying to
1033 connect to it with the given client certificate fails.
1034 """
Trent Nelson78520002008-04-10 20:54:35 +00001035 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001036 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001037 cacerts=CERTFILE, chatty=False,
1038 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001039 flag = threading.Event()
1040 server.start(flag)
1041 # wait for it to start
1042 flag.wait()
1043 # try to connect
1044 try:
Thomas Woutersed03b412007-08-28 21:37:11 +00001045 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001046 with socket.socket() as sock:
1047 s = ssl.wrap_socket(sock,
1048 certfile=certfile,
1049 ssl_version=ssl.PROTOCOL_TLSv1)
1050 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001051 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001052 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001053 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001054 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001055 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001056 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001057 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001058 if x.errno != errno.ENOENT:
1059 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001060 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001061 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001062 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001063 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001064 finally:
1065 server.stop()
1066 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001067
Antoine Pitroub5218772010-05-21 09:56:06 +00001068 def server_params_test(client_context, server_context, indata=b"FOO\n",
1069 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001070 """
1071 Launch a server, connect a client to it and try various reads
1072 and writes.
1073 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001074 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001075 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001076 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077 flag = threading.Event()
1078 server.start(flag)
1079 # wait for it to start
1080 flag.wait()
1081 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001082 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001083 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001084 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001085 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001086 if connectionchatty:
1087 if support.verbose:
1088 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001089 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001090 s.write(arg)
1091 outdata = s.read()
1092 if connectionchatty:
1093 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001094 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001095 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001096 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001097 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1098 % (outdata[:20], len(outdata),
1099 indata[:20].lower(), len(indata)))
1100 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001101 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001102 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001103 sys.stdout.write(" client: closing connection.\n")
1104 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001105 finally:
1106 server.stop()
1107 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +00001108
Antoine Pitroub5218772010-05-21 09:56:06 +00001109 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1110 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001111 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001113 certtype = {
1114 ssl.CERT_NONE: "CERT_NONE",
1115 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1116 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1117 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001118 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001119 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001120 sys.stdout.write(formatstr %
1121 (ssl.get_protocol_name(client_protocol),
1122 ssl.get_protocol_name(server_protocol),
1123 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001124 client_context = ssl.SSLContext(client_protocol)
1125 client_context.options = ssl.OP_ALL | client_options
1126 server_context = ssl.SSLContext(server_protocol)
1127 server_context.options = ssl.OP_ALL | server_options
1128 for ctx in (client_context, server_context):
1129 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001130 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1131 # will send an SSLv3 hello (rather than SSLv2) starting from
1132 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001133 ctx.set_ciphers("ALL")
1134 ctx.load_cert_chain(CERTFILE)
1135 ctx.load_verify_locations(CERTFILE)
1136 try:
1137 server_params_test(client_context, server_context,
1138 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001139 # Protocol mismatch can result in either an SSLError, or a
1140 # "Connection reset by peer" error.
1141 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001142 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001143 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001144 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001146 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001148 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001149 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 "Client protocol %s succeeded with server protocol %s!"
1151 % (ssl.get_protocol_name(client_protocol),
1152 ssl.get_protocol_name(server_protocol)))
1153
1154
Bill Janssen6e027db2007-11-15 22:23:56 +00001155 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156
Antoine Pitrou23df4832010-08-04 17:14:06 +00001157 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001158 def test_echo(self):
1159 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001160 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001161 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001162 for protocol in PROTOCOLS:
1163 context = ssl.SSLContext(protocol)
1164 context.load_cert_chain(CERTFILE)
1165 server_params_test(context, context,
1166 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167
Antoine Pitrou480a1242010-04-28 21:37:09 +00001168 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001169 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001170 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001171 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1172 context.verify_mode = ssl.CERT_REQUIRED
1173 context.load_verify_locations(CERTFILE)
1174 context.load_cert_chain(CERTFILE)
1175 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001176 flag = threading.Event()
1177 server.start(flag)
1178 # wait for it to start
1179 flag.wait()
1180 # try to connect
1181 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001182 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001183 s.connect((HOST, server.port))
1184 cert = s.getpeercert()
1185 self.assertTrue(cert, "Can't get peer certificate.")
1186 cipher = s.cipher()
1187 if support.verbose:
1188 sys.stdout.write(pprint.pformat(cert) + '\n')
1189 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1190 if 'subject' not in cert:
1191 self.fail("No subject field in certificate: %s." %
1192 pprint.pformat(cert))
1193 if ((('organizationName', 'Python Software Foundation'),)
1194 not in cert['subject']):
1195 self.fail(
1196 "Missing or invalid 'organizationName' field in certificate subject; "
1197 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001198 self.assertIn('notBefore', cert)
1199 self.assertIn('notAfter', cert)
1200 before = ssl.cert_time_to_seconds(cert['notBefore'])
1201 after = ssl.cert_time_to_seconds(cert['notAfter'])
1202 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001203 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001204 finally:
1205 server.stop()
1206 server.join()
1207
Antoine Pitrou480a1242010-04-28 21:37:09 +00001208 def test_empty_cert(self):
1209 """Connecting with an empty cert file"""
1210 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1211 "nullcert.pem"))
1212 def test_malformed_cert(self):
1213 """Connecting with a badly formatted certificate (syntax error)"""
1214 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1215 "badcert.pem"))
1216 def test_nonexisting_cert(self):
1217 """Connecting with a non-existing cert file"""
1218 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1219 "wrongcert.pem"))
1220 def test_malformed_key(self):
1221 """Connecting with a badly formatted key (syntax error)"""
1222 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1223 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001224
Antoine Pitrou480a1242010-04-28 21:37:09 +00001225 def test_rude_shutdown(self):
1226 """A brutal shutdown of an SSL server should raise an IOError
1227 in the client when attempting handshake.
1228 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001229 listener_ready = threading.Event()
1230 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001232 s = socket.socket()
1233 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001234
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001235 # `listener` runs in a thread. It sits in an accept() until
1236 # the main thread connects. Then it rudely closes the socket,
1237 # and sets Event `listener_gone` to let the main thread know
1238 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001239 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001240 s.listen(5)
1241 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001242 newsock, addr = s.accept()
1243 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001244 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001245 listener_gone.set()
1246
1247 def connector():
1248 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001249 with socket.socket() as c:
1250 c.connect((HOST, port))
1251 listener_gone.wait()
1252 try:
1253 ssl_sock = ssl.wrap_socket(c)
1254 except IOError:
1255 pass
1256 else:
1257 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001258
1259 t = threading.Thread(target=listener)
1260 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001261 try:
1262 connector()
1263 finally:
1264 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001265
Antoine Pitrou23df4832010-08-04 17:14:06 +00001266 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001267 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1268 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001269 def test_protocol_sslv2(self):
1270 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001271 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001272 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001273 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1274 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1275 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1276 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1277 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1278 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001279 # SSLv23 client with specific SSL options
1280 if no_sslv2_implies_sslv3_hello():
1281 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1282 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1283 client_options=ssl.OP_NO_SSLv2)
1284 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1285 client_options=ssl.OP_NO_SSLv3)
1286 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1287 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001288
Antoine Pitrou23df4832010-08-04 17:14:06 +00001289 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001290 def test_protocol_sslv23(self):
1291 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001292 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001293 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001294 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1295 try:
1296 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1297 except (ssl.SSLError, socket.error) as x:
1298 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1299 if support.verbose:
1300 sys.stdout.write(
1301 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1302 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001303 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1304 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1305 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001306
Antoine Pitrou480a1242010-04-28 21:37:09 +00001307 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1308 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1309 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001310
Antoine Pitrou480a1242010-04-28 21:37:09 +00001311 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1312 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1313 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001314
Antoine Pitroub5218772010-05-21 09:56:06 +00001315 # Server with specific SSL options
1316 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1317 server_options=ssl.OP_NO_SSLv3)
1318 # Will choose TLSv1
1319 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1320 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1321 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1322 server_options=ssl.OP_NO_TLSv1)
1323
1324
Antoine Pitrou23df4832010-08-04 17:14:06 +00001325 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 def test_protocol_sslv3(self):
1327 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001328 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001329 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001330 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1331 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1332 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001333 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1334 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001335 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1336 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001337 if no_sslv2_implies_sslv3_hello():
1338 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1339 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1340 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001341
Antoine Pitrou23df4832010-08-04 17:14:06 +00001342 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001343 def test_protocol_tlsv1(self):
1344 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001345 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001346 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001347 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1348 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1349 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001350 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1351 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1353 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001354
Antoine Pitrou480a1242010-04-28 21:37:09 +00001355 def test_starttls(self):
1356 """Switching from clear text to encrypted and back again."""
1357 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 +00001358
Trent Nelson78520002008-04-10 20:54:35 +00001359 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001360 ssl_version=ssl.PROTOCOL_TLSv1,
1361 starttls_server=True,
1362 chatty=True,
1363 connectionchatty=True)
1364 flag = threading.Event()
1365 server.start(flag)
1366 # wait for it to start
1367 flag.wait()
1368 # try to connect
1369 wrapped = False
1370 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001371 s = socket.socket()
1372 s.setblocking(1)
1373 s.connect((HOST, server.port))
1374 if support.verbose:
1375 sys.stdout.write("\n")
1376 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001377 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001378 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001379 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001380 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001382 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001383 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001384 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001385 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001386 msg = outdata.strip().lower()
1387 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1388 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001389 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001390 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 " client: read %r from server, starting TLS...\n"
1392 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001393 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1394 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1396 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001397 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001398 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001399 " client: read %r from server, ending TLS...\n"
1400 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001401 s = conn.unwrap()
1402 wrapped = False
1403 else:
1404 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001405 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001406 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001407 if support.verbose:
1408 sys.stdout.write(" client: closing connection.\n")
1409 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001410 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001411 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001412 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001413 if wrapped:
1414 conn.close()
1415 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001416 s.close()
1417 finally:
1418 server.stop()
1419 server.join()
1420
Antoine Pitrou480a1242010-04-28 21:37:09 +00001421 def test_socketserver(self):
1422 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001423 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001424 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001425 if support.verbose:
1426 sys.stdout.write('\n')
1427 with open(CERTFILE, 'rb') as f:
1428 d1 = f.read()
1429 d2 = ''
1430 # now fetch the same data from the HTTPS server
1431 url = 'https://%s:%d/%s' % (
1432 HOST, server.port, os.path.split(CERTFILE)[1])
1433 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001435 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001436 if dlen and (int(dlen) > 0):
1437 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001438 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001439 sys.stdout.write(
1440 " client: read %d bytes from remote server '%s'\n"
1441 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001442 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001443 f.close()
1444 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001445
Antoine Pitrou480a1242010-04-28 21:37:09 +00001446 def test_asyncore_server(self):
1447 """Check the example asyncore integration."""
1448 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001449
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001450 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001451 sys.stdout.write("\n")
1452
Antoine Pitrou480a1242010-04-28 21:37:09 +00001453 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001454 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001455 flag = threading.Event()
1456 server.start(flag)
1457 # wait for it to start
1458 flag.wait()
1459 # try to connect
1460 try:
1461 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001462 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001463 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001464 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001465 " client: sending %r...\n" % indata)
1466 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001467 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001468 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001469 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001470 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001471 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001472 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1473 % (outdata[:20], len(outdata),
1474 indata[:20].lower(), len(indata)))
1475 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001476 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001477 sys.stdout.write(" client: closing connection.\n")
1478 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001479 if support.verbose:
1480 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001481 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001482 if support.verbose:
1483 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001484 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001485 if support.verbose:
1486 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001487 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001488 if support.verbose:
1489 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001490
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 def test_recv_send(self):
1492 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001493 if support.verbose:
1494 sys.stdout.write("\n")
1495
1496 server = ThreadedEchoServer(CERTFILE,
1497 certreqs=ssl.CERT_NONE,
1498 ssl_version=ssl.PROTOCOL_TLSv1,
1499 cacerts=CERTFILE,
1500 chatty=True,
1501 connectionchatty=False)
1502 flag = threading.Event()
1503 server.start(flag)
1504 # wait for it to start
1505 flag.wait()
1506 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001507 s = ssl.wrap_socket(socket.socket(),
1508 server_side=False,
1509 certfile=CERTFILE,
1510 ca_certs=CERTFILE,
1511 cert_reqs=ssl.CERT_NONE,
1512 ssl_version=ssl.PROTOCOL_TLSv1)
1513 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001514 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001515 # helper methods for standardising recv* method signatures
1516 def _recv_into():
1517 b = bytearray(b"\0"*100)
1518 count = s.recv_into(b)
1519 return b[:count]
1520
1521 def _recvfrom_into():
1522 b = bytearray(b"\0"*100)
1523 count, addr = s.recvfrom_into(b)
1524 return b[:count]
1525
Nick Coghlan96fe56a2011-08-22 11:55:57 +10001526 def _recvmsg(*args, **kwargs):
1527 return s.recvmsg(*args, **kwargs)[0]
1528
1529 def _recvmsg_into(bufsize, *args, **kwargs):
1530 b = bytearray(bufsize)
1531 return bytes(b[:s.recvmsg_into([b], *args, **kwargs)[0]])
1532
1533 def _sendmsg(msg, *args, **kwargs):
1534 return s.sendmsg([msg])
1535
Bill Janssen58afe4c2008-09-08 16:45:19 +00001536 # (name, method, whether to expect success, *args)
1537 send_methods = [
1538 ('send', s.send, True, []),
1539 ('sendto', s.sendto, False, ["some.address"]),
Nick Coghlan96fe56a2011-08-22 11:55:57 +10001540 ('sendmsg', _sendmsg, False, []),
Bill Janssen58afe4c2008-09-08 16:45:19 +00001541 ('sendall', s.sendall, True, []),
1542 ]
1543 recv_methods = [
1544 ('recv', s.recv, True, []),
1545 ('recvfrom', s.recvfrom, False, ["some.address"]),
Nick Coghlan96fe56a2011-08-22 11:55:57 +10001546 ('recvmsg', _recvmsg, False, [100]),
Bill Janssen58afe4c2008-09-08 16:45:19 +00001547 ('recv_into', _recv_into, True, []),
1548 ('recvfrom_into', _recvfrom_into, False, []),
Nick Coghlan96fe56a2011-08-22 11:55:57 +10001549 ('recvmsg_into', _recvmsg_into, False, [100]),
Bill Janssen58afe4c2008-09-08 16:45:19 +00001550 ]
1551 data_prefix = "PREFIX_"
1552
1553 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001554 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001555 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001556 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001557 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001558 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001559 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001560 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001561 "<<{outdata:r}>> ({nout:d}) received; "
1562 "expected <<{indata:r}>> ({nin:d})\n".format(
1563 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001564 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001565 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001566 )
1567 )
1568 except ValueError as e:
1569 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001570 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001571 "Failed to send with method <<{name:s}>>; "
1572 "expected to succeed.\n".format(name=meth_name)
1573 )
1574 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001575 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001576 "Method <<{name:s}>> failed with unexpected "
1577 "exception message: {exp:s}\n".format(
1578 name=meth_name, exp=e
1579 )
1580 )
1581
1582 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001583 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001584 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001585 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001586 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001587 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001588 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001589 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001590 "<<{outdata:r}>> ({nout:d}) received; "
1591 "expected <<{indata:r}>> ({nin:d})\n".format(
1592 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001593 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001594 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001595 )
1596 )
1597 except ValueError as e:
1598 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001599 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001600 "Failed to receive with method <<{name:s}>>; "
1601 "expected to succeed.\n".format(name=meth_name)
1602 )
1603 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001604 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001605 "Method <<{name:s}>> failed with unexpected "
1606 "exception message: {exp:s}\n".format(
1607 name=meth_name, exp=e
1608 )
1609 )
1610 # consume data
1611 s.read()
1612
Antoine Pitrou480a1242010-04-28 21:37:09 +00001613 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001614 s.close()
1615 finally:
1616 server.stop()
1617 server.join()
1618
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001619 def test_handshake_timeout(self):
1620 # Issue #5103: SSL handshake must respect the socket timeout
1621 server = socket.socket(socket.AF_INET)
1622 host = "127.0.0.1"
1623 port = support.bind_port(server)
1624 started = threading.Event()
1625 finish = False
1626
1627 def serve():
1628 server.listen(5)
1629 started.set()
1630 conns = []
1631 while not finish:
1632 r, w, e = select.select([server], [], [], 0.1)
1633 if server in r:
1634 # Let the socket hang around rather than having
1635 # it closed by garbage collection.
1636 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001637 for sock in conns:
1638 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001639
1640 t = threading.Thread(target=serve)
1641 t.start()
1642 started.wait()
1643
1644 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001645 try:
1646 c = socket.socket(socket.AF_INET)
1647 c.settimeout(0.2)
1648 c.connect((host, port))
1649 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001650 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001651 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001652 finally:
1653 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001654 try:
1655 c = socket.socket(socket.AF_INET)
1656 c = ssl.wrap_socket(c)
1657 c.settimeout(0.2)
1658 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001659 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001660 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001661 finally:
1662 c.close()
1663 finally:
1664 finish = True
1665 t.join()
1666 server.close()
1667
Antoine Pitroud6494802011-07-21 01:11:30 +02001668 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1669 "'tls-unique' channel binding not available")
1670 def test_tls_unique_channel_binding(self):
1671 """Test tls-unique channel binding."""
1672 if support.verbose:
1673 sys.stdout.write("\n")
1674
1675 server = ThreadedEchoServer(CERTFILE,
1676 certreqs=ssl.CERT_NONE,
1677 ssl_version=ssl.PROTOCOL_TLSv1,
1678 cacerts=CERTFILE,
1679 chatty=True,
1680 connectionchatty=False)
1681 flag = threading.Event()
1682 server.start(flag)
1683 # wait for it to start
1684 flag.wait()
1685 # try to connect
1686 s = ssl.wrap_socket(socket.socket(),
1687 server_side=False,
1688 certfile=CERTFILE,
1689 ca_certs=CERTFILE,
1690 cert_reqs=ssl.CERT_NONE,
1691 ssl_version=ssl.PROTOCOL_TLSv1)
1692 s.connect((HOST, server.port))
1693 try:
1694 # get the data
1695 cb_data = s.get_channel_binding("tls-unique")
1696 if support.verbose:
1697 sys.stdout.write(" got channel binding data: {0!r}\n"
1698 .format(cb_data))
1699
1700 # check if it is sane
1701 self.assertIsNotNone(cb_data)
1702 self.assertEqual(len(cb_data), 12) # True for TLSv1
1703
1704 # and compare with the peers version
1705 s.write(b"CB tls-unique\n")
1706 peer_data_repr = s.read().strip()
1707 self.assertEqual(peer_data_repr,
1708 repr(cb_data).encode("us-ascii"))
1709 s.close()
1710
1711 # now, again
1712 s = ssl.wrap_socket(socket.socket(),
1713 server_side=False,
1714 certfile=CERTFILE,
1715 ca_certs=CERTFILE,
1716 cert_reqs=ssl.CERT_NONE,
1717 ssl_version=ssl.PROTOCOL_TLSv1)
1718 s.connect((HOST, server.port))
1719 new_cb_data = s.get_channel_binding("tls-unique")
1720 if support.verbose:
1721 sys.stdout.write(" got another channel binding data: {0!r}\n"
1722 .format(new_cb_data))
1723 # is it really unique
1724 self.assertNotEqual(cb_data, new_cb_data)
1725 self.assertIsNotNone(cb_data)
1726 self.assertEqual(len(cb_data), 12) # True for TLSv1
1727 s.write(b"CB tls-unique\n")
1728 peer_data_repr = s.read().strip()
1729 self.assertEqual(peer_data_repr,
1730 repr(new_cb_data).encode("us-ascii"))
1731 s.close()
1732 finally:
1733 server.stop()
1734 server.join()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001735
Thomas Woutersed03b412007-08-28 21:37:11 +00001736def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001737 if support.verbose:
1738 plats = {
1739 'Linux': platform.linux_distribution,
1740 'Mac': platform.mac_ver,
1741 'Windows': platform.win32_ver,
1742 }
1743 for name, func in plats.items():
1744 plat = func()
1745 if plat and plat[0]:
1746 plat = '%s %r' % (name, plat)
1747 break
1748 else:
1749 plat = repr(platform.platform())
1750 print("test_ssl: testing with %r %r" %
1751 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1752 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001753 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001754
Antoine Pitrou152efa22010-05-16 18:19:27 +00001755 for filename in [
1756 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1757 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1758 BADCERT, BADKEY, EMPTYCERT]:
1759 if not os.path.exists(filename):
1760 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001761
Antoine Pitrou152efa22010-05-16 18:19:27 +00001762 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001763
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001764 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001765 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001766
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001767 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001768 thread_info = support.threading_setup()
1769 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001770 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001771
Antoine Pitrou480a1242010-04-28 21:37:09 +00001772 try:
1773 support.run_unittest(*tests)
1774 finally:
1775 if _have_threads:
1776 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001777
1778if __name__ == "__main__":
1779 test_main()