blob: f587945afdfb63b45f2bc8c9690a431e16518b0c [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 Stinner17ca3232011-05-10 00:48:41 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner17ca3232011-05-10 00:48:41 +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
Martin Panter3d81d932016-01-14 09:36:00 +000032def data_file(*name):
33 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000034
Antoine Pitrou81564092010-10-08 23:06:24 +000035# The custom key and certificate files used in test_ssl are generated
36# using Lib/test/make_ssl_certs.py.
37# Other certificates are simply fetched from the Internet servers they
38# are meant to authenticate.
39
Antoine Pitrou152efa22010-05-16 18:19:27 +000040CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000041BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000042ONLYCERT = data_file("ssl_cert.pem")
43ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000044BYTES_ONLYCERT = os.fsencode(ONLYCERT)
45BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000046CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000047BYTES_CAPATH = os.fsencode(CAPATH)
Martin Panter3d81d932016-01-14 09:36:00 +000048CAFILE_CACERT = data_file("capath", "5ed36f99.0")
Antoine Pitrou152efa22010-05-16 18:19:27 +000049
Martin Panter3d81d932016-01-14 09:36:00 +000050REMOTE_HOST = "self-signed.pythontest.net"
51REMOTE_ROOT_CERT = data_file("selfsigned_pythontestdotnet.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000052
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020057NOKIACERT = data_file("nokia.pem")
Georg Brandlec3c1032014-09-30 14:04:51 +020058NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000059
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Thomas Woutersed03b412007-08-28 21:37:11 +000061def handle_error(prefix):
62 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000063 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000064 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000065
Antoine Pitroub5218772010-05-21 09:56:06 +000066def can_clear_options():
67 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020068 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000069
70def no_sslv2_implies_sslv3_hello():
71 # 0.9.7h or higher
72 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
73
Thomas Woutersed03b412007-08-28 21:37:11 +000074
Antoine Pitrou23df4832010-08-04 17:14:06 +000075# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
76def skip_if_broken_ubuntu_ssl(func):
Victor Stinner17ca3232011-05-10 00:48:41 +020077 if hasattr(ssl, 'PROTOCOL_SSLv2'):
78 @functools.wraps(func)
79 def f(*args, **kwargs):
80 try:
81 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
82 except ssl.SSLError:
83 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
84 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
85 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
86 return func(*args, **kwargs)
87 return f
88 else:
89 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000090
91
Antoine Pitrou152efa22010-05-16 18:19:27 +000092class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Antoine Pitrou480a1242010-04-28 21:37:09 +000094 def test_constants(self):
Victor Stinneree18b6f2011-05-10 00:38:00 +020095 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 ssl.PROTOCOL_SSLv23
97 ssl.PROTOCOL_SSLv3
98 ssl.PROTOCOL_TLSv1
99 ssl.CERT_NONE
100 ssl.CERT_OPTIONAL
101 ssl.CERT_REQUIRED
Antoine Pitroud5323212010-10-22 18:19:07 +0000102 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000103
Antoine Pitrou480a1242010-04-28 21:37:09 +0000104 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000106 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000107 sys.stdout.write("\n RAND_status is %d (%s)\n"
108 % (v, (v and "sufficient randomness") or
109 "insufficient randomness"))
Jesus Ceac8754a12012-09-11 02:00:58 +0200110 self.assertRaises(TypeError, ssl.RAND_egd, 1)
111 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000112 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000113
Antoine Pitrou480a1242010-04-28 21:37:09 +0000114 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 # note that this uses an 'unofficial' function in _ssl.c,
116 # provided solely for this test, to exercise the certificate
117 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000118 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000119 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200121 self.assertEqual(p['issuer'],
122 ((('countryName', 'XY'),),
123 (('localityName', 'Castle Anthrax'),),
124 (('organizationName', 'Python Software Foundation'),),
125 (('commonName', 'localhost'),))
126 )
127 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
128 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
129 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
130 self.assertEqual(p['subject'],
131 ((('countryName', 'XY'),),
132 (('localityName', 'Castle Anthrax'),),
133 (('organizationName', 'Python Software Foundation'),),
134 (('commonName', 'localhost'),))
135 )
136 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
137 # Issue #13034: the subjectAltName in some certificates
138 # (notably projects.developer.nokia.com:443) wasn't parsed
139 p = ssl._ssl._test_decode_cert(NOKIACERT)
140 if support.verbose:
141 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
142 self.assertEqual(p['subjectAltName'],
143 (('DNS', 'projects.developer.nokia.com'),
144 ('DNS', 'projects.forum.nokia.com'))
145 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000146
Georg Brandlec3c1032014-09-30 14:04:51 +0200147 def test_parse_cert_CVE_2013_4073(self):
148 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
149 if support.verbose:
150 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
151 subject = ((('countryName', 'US'),),
152 (('stateOrProvinceName', 'Oregon'),),
153 (('localityName', 'Beaverton'),),
154 (('organizationName', 'Python Software Foundation'),),
155 (('organizationalUnitName', 'Python Core Development'),),
156 (('commonName', 'null.python.org\x00example.org'),),
157 (('emailAddress', 'python-dev@python.org'),))
158 self.assertEqual(p['subject'], subject)
159 self.assertEqual(p['issuer'], subject)
160 self.assertEqual(p['subjectAltName'],
161 (('DNS', 'altnull.python.org\x00example.com'),
162 ('email', 'null@python.org\x00user@example.org'),
163 ('URI', 'http://null.python.org\x00http://example.org'),
164 ('IP Address', '192.0.2.1'),
165 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
166 )
167
Antoine Pitrou480a1242010-04-28 21:37:09 +0000168 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000169 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000170 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000171 d1 = ssl.PEM_cert_to_DER_cert(pem)
172 p2 = ssl.DER_cert_to_PEM_cert(d1)
173 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000174 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000175 if not p2.startswith(ssl.PEM_HEADER + '\n'):
176 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
177 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
178 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000179
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000180 def test_openssl_version(self):
181 n = ssl.OPENSSL_VERSION_NUMBER
182 t = ssl.OPENSSL_VERSION_INFO
183 s = ssl.OPENSSL_VERSION
184 self.assertIsInstance(n, int)
185 self.assertIsInstance(t, tuple)
186 self.assertIsInstance(s, str)
187 # Some sanity checks follow
188 # >= 0.9
189 self.assertGreaterEqual(n, 0x900000)
190 # < 2.0
191 self.assertLess(n, 0x20000000)
192 major, minor, fix, patch, status = t
193 self.assertGreaterEqual(major, 0)
194 self.assertLess(major, 2)
195 self.assertGreaterEqual(minor, 0)
196 self.assertLess(minor, 256)
197 self.assertGreaterEqual(fix, 0)
198 self.assertLess(fix, 256)
199 self.assertGreaterEqual(patch, 0)
200 self.assertLessEqual(patch, 26)
201 self.assertGreaterEqual(status, 0)
202 self.assertLessEqual(status, 15)
203 # Version string as returned by OpenSSL, the format might change
204 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
205 (s, t))
206
Antoine Pitrou9d543662010-04-23 23:10:32 +0000207 @support.cpython_only
208 def test_refcycle(self):
209 # Issue #7943: an SSL object doesn't create reference cycles with
210 # itself.
211 s = socket.socket(socket.AF_INET)
212 ss = ssl.wrap_socket(s)
213 wr = weakref.ref(ss)
214 del ss
215 self.assertEqual(wr(), None)
216
Antoine Pitroua468adc2010-09-14 14:43:44 +0000217 def test_wrapped_unconnected(self):
218 # Methods on an unconnected SSLSocket propagate the original
219 # socket.error raise by the underlying socket object.
220 s = socket.socket(socket.AF_INET)
221 ss = ssl.wrap_socket(s)
222 self.assertRaises(socket.error, ss.recv, 1)
223 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
224 self.assertRaises(socket.error, ss.recvfrom, 1)
225 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
226 self.assertRaises(socket.error, ss.send, b'x')
227 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
228
Antoine Pitrou40f08742010-04-24 22:04:40 +0000229 def test_timeout(self):
230 # Issue #8524: when creating an SSL socket, the timeout of the
231 # original socket should be retained.
232 for timeout in (None, 0.0, 5.0):
233 s = socket.socket(socket.AF_INET)
234 s.settimeout(timeout)
235 ss = ssl.wrap_socket(s)
236 self.assertEqual(timeout, ss.gettimeout())
237
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000238 def test_errors(self):
239 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000240 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000241 "certfile must be specified",
242 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000243 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000244 "certfile must be specified for server-side operations",
245 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000246 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000247 "certfile must be specified for server-side operations",
248 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000249 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000250 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000251 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000252 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000253 with socket.socket() as sock:
254 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000255 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000256 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000257 with socket.socket() as sock:
258 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000259 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000260 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000261 with socket.socket() as sock:
262 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000263 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000264
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000265 def test_match_hostname(self):
266 def ok(cert, hostname):
267 ssl.match_hostname(cert, hostname)
268 def fail(cert, hostname):
269 self.assertRaises(ssl.CertificateError,
270 ssl.match_hostname, cert, hostname)
271
272 cert = {'subject': ((('commonName', 'example.com'),),)}
273 ok(cert, 'example.com')
274 ok(cert, 'ExAmple.cOm')
275 fail(cert, 'www.example.com')
276 fail(cert, '.example.com')
277 fail(cert, 'example.org')
278 fail(cert, 'exampleXcom')
279
280 cert = {'subject': ((('commonName', '*.a.com'),),)}
281 ok(cert, 'foo.a.com')
282 fail(cert, 'bar.foo.a.com')
283 fail(cert, 'a.com')
284 fail(cert, 'Xa.com')
285 fail(cert, '.a.com')
286
287 cert = {'subject': ((('commonName', 'a.*.com'),),)}
288 ok(cert, 'a.foo.com')
289 fail(cert, 'a..com')
290 fail(cert, 'a.com')
291
292 cert = {'subject': ((('commonName', 'f*.com'),),)}
293 ok(cert, 'foo.com')
294 ok(cert, 'f.com')
295 fail(cert, 'bar.com')
296 fail(cert, 'foo.a.com')
297 fail(cert, 'bar.foo.com')
298
Georg Brandlec3c1032014-09-30 14:04:51 +0200299 # NULL bytes are bad, CVE-2013-4073
300 cert = {'subject': ((('commonName',
301 'null.python.org\x00example.org'),),)}
302 ok(cert, 'null.python.org\x00example.org') # or raise an error?
303 fail(cert, 'example.org')
304 fail(cert, 'null.python.org')
305
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000306 # Slightly fake real-world example
307 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
308 'subject': ((('commonName', 'linuxfrz.org'),),),
309 'subjectAltName': (('DNS', 'linuxfr.org'),
310 ('DNS', 'linuxfr.com'),
311 ('othername', '<unsupported>'))}
312 ok(cert, 'linuxfr.org')
313 ok(cert, 'linuxfr.com')
314 # Not a "DNS" entry
315 fail(cert, '<unsupported>')
316 # When there is a subjectAltName, commonName isn't used
317 fail(cert, 'linuxfrz.org')
318
319 # A pristine real-world example
320 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
321 'subject': ((('countryName', 'US'),),
322 (('stateOrProvinceName', 'California'),),
323 (('localityName', 'Mountain View'),),
324 (('organizationName', 'Google Inc'),),
325 (('commonName', 'mail.google.com'),))}
326 ok(cert, 'mail.google.com')
327 fail(cert, 'gmail.com')
328 # Only commonName is considered
329 fail(cert, 'California')
330
331 # Neither commonName nor subjectAltName
332 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
333 'subject': ((('countryName', 'US'),),
334 (('stateOrProvinceName', 'California'),),
335 (('localityName', 'Mountain View'),),
336 (('organizationName', 'Google Inc'),))}
337 fail(cert, 'mail.google.com')
338
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200339 # No DNS entry in subjectAltName but a commonName
340 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
341 'subject': ((('countryName', 'US'),),
342 (('stateOrProvinceName', 'California'),),
343 (('localityName', 'Mountain View'),),
344 (('commonName', 'mail.google.com'),)),
345 'subjectAltName': (('othername', 'blabla'), )}
346 ok(cert, 'mail.google.com')
347
348 # No DNS entry subjectAltName and no commonName
349 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
350 'subject': ((('countryName', 'US'),),
351 (('stateOrProvinceName', 'California'),),
352 (('localityName', 'Mountain View'),),
353 (('organizationName', 'Google Inc'),)),
354 'subjectAltName': (('othername', 'blabla'),)}
355 fail(cert, 'google.com')
356
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000357 # Empty cert / no cert
358 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
359 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
360
Antoine Pitrou86d53ca2013-05-18 17:56:42 +0200361 # Issue #17980: avoid denials of service by refusing more than one
362 # wildcard per fragment.
363 cert = {'subject': ((('commonName', 'a*b.com'),),)}
364 ok(cert, 'axxb.com')
365 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
366 ok(cert, 'axxb.com')
367 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
368 with self.assertRaises(ssl.CertificateError) as cm:
369 ssl.match_hostname(cert, 'axxbxxc.com')
370 self.assertIn("too many wildcards", str(cm.exception))
371
Antoine Pitroud5323212010-10-22 18:19:07 +0000372 def test_server_side(self):
373 # server_hostname doesn't work for server sockets
374 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000375 with socket.socket() as sock:
376 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
377 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000378
Antoine Pitrou152efa22010-05-16 18:19:27 +0000379class ContextTests(unittest.TestCase):
380
Antoine Pitrou23df4832010-08-04 17:14:06 +0000381 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000382 def test_constructor(self):
Victor Stinner17ca3232011-05-10 00:48:41 +0200383 if hasattr(ssl, 'PROTOCOL_SSLv2'):
384 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000385 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
386 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
387 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
388 self.assertRaises(TypeError, ssl.SSLContext)
389 self.assertRaises(ValueError, ssl.SSLContext, -1)
390 self.assertRaises(ValueError, ssl.SSLContext, 42)
391
Antoine Pitrou23df4832010-08-04 17:14:06 +0000392 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000393 def test_protocol(self):
394 for proto in PROTOCOLS:
395 ctx = ssl.SSLContext(proto)
396 self.assertEqual(ctx.protocol, proto)
397
398 def test_ciphers(self):
399 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
400 ctx.set_ciphers("ALL")
401 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000402 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000403 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000404
Antoine Pitrou23df4832010-08-04 17:14:06 +0000405 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000406 def test_options(self):
407 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
408 # OP_ALL is the default value
409 self.assertEqual(ssl.OP_ALL, ctx.options)
410 ctx.options |= ssl.OP_NO_SSLv2
411 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
412 ctx.options)
413 ctx.options |= ssl.OP_NO_SSLv3
414 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
415 ctx.options)
416 if can_clear_options():
417 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
418 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
419 ctx.options)
420 ctx.options = 0
421 self.assertEqual(0, ctx.options)
422 else:
423 with self.assertRaises(ValueError):
424 ctx.options = 0
425
Antoine Pitrou152efa22010-05-16 18:19:27 +0000426 def test_verify(self):
427 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
428 # Default value
429 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
430 ctx.verify_mode = ssl.CERT_OPTIONAL
431 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
432 ctx.verify_mode = ssl.CERT_REQUIRED
433 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
434 ctx.verify_mode = ssl.CERT_NONE
435 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
436 with self.assertRaises(TypeError):
437 ctx.verify_mode = None
438 with self.assertRaises(ValueError):
439 ctx.verify_mode = 42
440
441 def test_load_cert_chain(self):
442 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
443 # Combined key and cert in a single file
444 ctx.load_cert_chain(CERTFILE)
445 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
446 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000447 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000448 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000449 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000450 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000451 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000452 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000453 ctx.load_cert_chain(EMPTYCERT)
454 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000455 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000456 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
457 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
458 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000459 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000460 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000461 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000462 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000463 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000464 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
465 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000466 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000467 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +0000468 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000469
470 def test_load_verify_locations(self):
471 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
472 ctx.load_verify_locations(CERTFILE)
473 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
474 ctx.load_verify_locations(BYTES_CERTFILE)
475 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
476 self.assertRaises(TypeError, ctx.load_verify_locations)
477 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000478 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000479 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000480 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000481 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000482 ctx.load_verify_locations(BADCERT)
483 ctx.load_verify_locations(CERTFILE, CAPATH)
484 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
485
Victor Stinner80f75e62011-01-29 11:31:20 +0000486 # Issue #10989: crash if the second argument type is invalid
487 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
488
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000489 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000490 def test_session_stats(self):
491 for proto in PROTOCOLS:
492 ctx = ssl.SSLContext(proto)
493 self.assertEqual(ctx.session_stats(), {
494 'number': 0,
495 'connect': 0,
496 'connect_good': 0,
497 'connect_renegotiate': 0,
498 'accept': 0,
499 'accept_good': 0,
500 'accept_renegotiate': 0,
501 'hits': 0,
502 'misses': 0,
503 'timeouts': 0,
504 'cache_full': 0,
505 })
506
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000507 def test_set_default_verify_paths(self):
508 # There's not much we can do to test that it acts as expected,
509 # so just check it doesn't crash or raise an exception.
510 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
511 ctx.set_default_verify_paths()
512
Antoine Pitrou152efa22010-05-16 18:19:27 +0000513
Bill Janssen6e027db2007-11-15 22:23:56 +0000514class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000515
Antoine Pitrou480a1242010-04-28 21:37:09 +0000516 def test_connect(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000517 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000518 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
519 cert_reqs=ssl.CERT_NONE)
520 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000521 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000522 self.assertEqual({}, s.getpeercert())
523 finally:
524 s.close()
525
526 # this should fail because we have no verification certs
527 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
528 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000529 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Martin Panter3d81d932016-01-14 09:36:00 +0000530 s.connect, (REMOTE_HOST, 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000531 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000532
Antoine Pitrou350c7222010-09-09 13:31:46 +0000533 # this should succeed because we specify the root cert
534 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
535 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000536 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000537 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000538 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000539 self.assertTrue(s.getpeercert())
540 finally:
541 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000542
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000543 def test_connect_ex(self):
544 # Issue #11326: check connect_ex() implementation
Martin Panter3d81d932016-01-14 09:36:00 +0000545 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000546 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
547 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000548 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000549 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000550 self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000551 self.assertTrue(s.getpeercert())
552 finally:
553 s.close()
554
555 def test_non_blocking_connect_ex(self):
556 # Issue #11326: non-blocking connect_ex() should allow handshake
557 # to proceed after the socket gets ready.
Martin Panter3d81d932016-01-14 09:36:00 +0000558 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000559 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
560 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000561 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000562 do_handshake_on_connect=False)
563 try:
564 s.setblocking(False)
Martin Panter3d81d932016-01-14 09:36:00 +0000565 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitroud1c98452011-02-27 15:45:16 +0000566 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
567 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000568 # Wait for connect to finish
569 select.select([], [s], [], 5.0)
570 # Non-blocking handshake
571 while True:
572 try:
573 s.do_handshake()
574 break
575 except ssl.SSLError as err:
576 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
577 select.select([s], [], [], 5.0)
578 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
579 select.select([], [s], [], 5.0)
580 else:
581 raise
582 # SSL established
583 self.assertTrue(s.getpeercert())
584 finally:
585 s.close()
586
Antoine Pitroub4410db2011-05-18 18:51:06 +0200587 def test_timeout_connect_ex(self):
588 # Issue #12065: on a timeout, connect_ex() should return the original
589 # errno (mimicking the behaviour of non-SSL sockets).
Martin Panter3d81d932016-01-14 09:36:00 +0000590 with support.transient_internet(REMOTE_HOST):
Antoine Pitroub4410db2011-05-18 18:51:06 +0200591 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
592 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000593 ca_certs=REMOTE_ROOT_CERT,
Antoine Pitroub4410db2011-05-18 18:51:06 +0200594 do_handshake_on_connect=False)
595 try:
596 s.settimeout(0.0000001)
Martin Panter3d81d932016-01-14 09:36:00 +0000597 rc = s.connect_ex((REMOTE_HOST, 443))
Antoine Pitroub4410db2011-05-18 18:51:06 +0200598 if rc == 0:
Martin Panter3d81d932016-01-14 09:36:00 +0000599 self.skipTest("REMOTE_HOST responded too quickly")
Antoine Pitroub4410db2011-05-18 18:51:06 +0200600 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
601 finally:
602 s.close()
603
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100604 def test_connect_ex_error(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000605 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100606 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
607 cert_reqs=ssl.CERT_REQUIRED,
Martin Panter3d81d932016-01-14 09:36:00 +0000608 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100609 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000610 rc = s.connect_ex((REMOTE_HOST, 444))
Martin Panter035583b2016-01-15 01:16:41 +0000611 errors = (
612 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT)
613 self.assertIn(rc, errors)
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100614 finally:
615 s.close()
616
Antoine Pitrou152efa22010-05-16 18:19:27 +0000617 def test_connect_with_context(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000618 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000619 # Same as test_connect, but with a separately created context
620 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
621 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000622 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000623 try:
624 self.assertEqual({}, s.getpeercert())
625 finally:
626 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000627 # Same with a server hostname
628 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3d81d932016-01-14 09:36:00 +0000629 server_hostname=REMOTE_HOST)
Antoine Pitroud5323212010-10-22 18:19:07 +0000630 if ssl.HAS_SNI:
Martin Panter3d81d932016-01-14 09:36:00 +0000631 s.connect((REMOTE_HOST, 443))
Antoine Pitroud5323212010-10-22 18:19:07 +0000632 s.close()
633 else:
Martin Panter3d81d932016-01-14 09:36:00 +0000634 self.assertRaises(ValueError, s.connect, (REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000635 # This should fail because we have no verification certs
636 ctx.verify_mode = ssl.CERT_REQUIRED
637 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000638 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Martin Panter3d81d932016-01-14 09:36:00 +0000639 s.connect, (REMOTE_HOST, 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000640 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000641 # This should succeed because we specify the root cert
Martin Panter3d81d932016-01-14 09:36:00 +0000642 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000643 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000644 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000645 try:
646 cert = s.getpeercert()
647 self.assertTrue(cert)
648 finally:
649 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000650
651 def test_connect_capath(self):
652 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000653 # NOTE: the subject hashing algorithm has been changed between
654 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
655 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000656 # filename) for this test to be portable across OpenSSL releases.
Martin Panter3d81d932016-01-14 09:36:00 +0000657 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000658 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
659 ctx.verify_mode = ssl.CERT_REQUIRED
660 ctx.load_verify_locations(capath=CAPATH)
661 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000662 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000663 try:
664 cert = s.getpeercert()
665 self.assertTrue(cert)
666 finally:
667 s.close()
668 # Same with a bytes `capath` argument
669 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
670 ctx.verify_mode = ssl.CERT_REQUIRED
671 ctx.load_verify_locations(capath=BYTES_CAPATH)
672 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000673 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000674 try:
675 cert = s.getpeercert()
676 self.assertTrue(cert)
677 finally:
678 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000679
Antoine Pitroue3220242010-04-24 11:13:53 +0000680 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
681 def test_makefile_close(self):
682 # Issue #5238: creating a file-like object with makefile() shouldn't
683 # delay closing the underlying "real socket" (here tested with its
684 # file descriptor, hence skipping the test under Windows).
Martin Panter3d81d932016-01-14 09:36:00 +0000685 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000686 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000687 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000688 fd = ss.fileno()
689 f = ss.makefile()
690 f.close()
691 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000692 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000693 # Closing the SSL socket should close the fd too
694 ss.close()
695 gc.collect()
696 with self.assertRaises(OSError) as e:
697 os.read(fd, 0)
698 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000699
Antoine Pitrou480a1242010-04-28 21:37:09 +0000700 def test_non_blocking_handshake(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000701 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000702 s = socket.socket(socket.AF_INET)
Martin Panter3d81d932016-01-14 09:36:00 +0000703 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000704 s.setblocking(False)
705 s = ssl.wrap_socket(s,
706 cert_reqs=ssl.CERT_NONE,
707 do_handshake_on_connect=False)
708 count = 0
709 while True:
710 try:
711 count += 1
712 s.do_handshake()
713 break
714 except ssl.SSLError as err:
715 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
716 select.select([s], [], [])
717 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
718 select.select([], [s], [])
719 else:
720 raise
721 s.close()
722 if support.verbose:
723 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000724
Antoine Pitrou480a1242010-04-28 21:37:09 +0000725 def test_get_server_certificate(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000726 with support.transient_internet(REMOTE_HOST):
727 pem = ssl.get_server_certificate((REMOTE_HOST, 443),
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500728 ssl.PROTOCOL_SSLv23)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000729 if not pem:
Martin Panter3d81d932016-01-14 09:36:00 +0000730 self.fail("No server certificate on REMOTE_HOST:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000731
Antoine Pitrou350c7222010-09-09 13:31:46 +0000732 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000733 pem = ssl.get_server_certificate((REMOTE_HOST, 443),
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500734 ssl.PROTOCOL_SSLv23,
735 ca_certs=CERTFILE)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000736 except ssl.SSLError as x:
737 #should fail
738 if support.verbose:
739 sys.stdout.write("%s\n" % x)
740 else:
Martin Panter3d81d932016-01-14 09:36:00 +0000741 self.fail("Got server certificate %s for REMOTE_HOST!" % pem)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000742
Martin Panter3d81d932016-01-14 09:36:00 +0000743 pem = ssl.get_server_certificate((REMOTE_HOST, 443),
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500744 ssl.PROTOCOL_SSLv23,
Martin Panter3d81d932016-01-14 09:36:00 +0000745 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000746 if not pem:
Martin Panter3d81d932016-01-14 09:36:00 +0000747 self.fail("No server certificate on REMOTE_HOST:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000748 if support.verbose:
Martin Panter3d81d932016-01-14 09:36:00 +0000749 sys.stdout.write("\nVerified certificate for REMOTE_HOST:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000750
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000751 def test_ciphers(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000752 remote = (REMOTE_HOST, 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000753 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000754 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000755 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000756 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000757 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
758 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
759 s.connect(remote)
760 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000761 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000762 with socket.socket(socket.AF_INET) as sock:
763 s = ssl.wrap_socket(sock,
764 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
765 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000766
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000767 def test_algorithms(self):
768 # Issue #8484: all algorithms should be available when verifying a
769 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000770 # SHA256 was added in OpenSSL 0.9.8
771 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
772 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200773 # sha256.tbs-internet.com needs SNI to use the correct certificate
774 if not ssl.HAS_SNI:
775 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000776 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
777 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000778 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000779 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200780 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
781 ctx.verify_mode = ssl.CERT_REQUIRED
782 ctx.load_verify_locations(sha256_cert)
783 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
784 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000785 try:
786 s.connect(remote)
787 if support.verbose:
788 sys.stdout.write("\nCipher with %r is %r\n" %
789 (remote, s.cipher()))
790 sys.stdout.write("Certificate is:\n%s\n" %
791 pprint.pformat(s.getpeercert()))
792 finally:
793 s.close()
794
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000795
796try:
797 import threading
798except ImportError:
799 _have_threads = False
800else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000801 _have_threads = True
802
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000803 from test.ssl_servers import make_https_server
804
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000805 class ThreadedEchoServer(threading.Thread):
806
807 class ConnectionHandler(threading.Thread):
808
809 """A mildly complicated class, because we want it to work both
810 with and without the SSL wrapper around the socket connection, so
811 that we can test the STARTTLS functionality."""
812
Bill Janssen6e027db2007-11-15 22:23:56 +0000813 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000814 self.server = server
815 self.running = False
816 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000817 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000818 self.sock.setblocking(1)
819 self.sslconn = None
820 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000821 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000822
Antoine Pitrou480a1242010-04-28 21:37:09 +0000823 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000824 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000825 self.sslconn = self.server.context.wrap_socket(
826 self.sock, server_side=True)
Nadeem Vawda7b39b9b2013-03-03 22:31:21 +0100827 except (ssl.SSLError, socket.error) as e:
828 # Treat ECONNRESET as though it were an SSLError - OpenSSL
829 # on Ubuntu abruptly closes the connection when asked to use
830 # an unsupported protocol.
831 if (not isinstance(e, ssl.SSLError) and
832 e.errno != errno.ECONNRESET):
833 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000834 # XXX Various errors can have happened here, for example
835 # a mismatching protocol version, an invalid certificate,
836 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100837 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000838 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000839 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000840 self.running = False
841 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000842 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000843 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000844 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000845 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000847 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
849 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000850 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
852 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000853 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000854 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
855 return True
856
857 def read(self):
858 if self.sslconn:
859 return self.sslconn.read()
860 else:
861 return self.sock.recv(1024)
862
863 def write(self, bytes):
864 if self.sslconn:
865 return self.sslconn.write(bytes)
866 else:
867 return self.sock.send(bytes)
868
869 def close(self):
870 if self.sslconn:
871 self.sslconn.close()
872 else:
873 self.sock.close()
874
Antoine Pitrou480a1242010-04-28 21:37:09 +0000875 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000876 self.running = True
877 if not self.server.starttls_server:
878 if not self.wrap_conn():
879 return
880 while self.running:
881 try:
882 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000883 stripped = msg.strip()
884 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000885 # eof, so quit this handler
886 self.running = False
887 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000888 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000889 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000890 sys.stdout.write(" server: client closed connection\n")
891 self.close()
892 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000893 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000894 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000895 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000897 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 if not self.wrap_conn():
899 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000900 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000901 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000902 if support.verbose and self.server.connectionchatty:
903 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000904 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000905 self.sock = self.sslconn.unwrap()
906 self.sslconn = None
907 if support.verbose and self.server.connectionchatty:
908 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000910 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911 self.server.connectionchatty):
912 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000913 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
914 % (msg, ctype, msg.lower(), ctype))
915 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000916 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000917 if self.server.chatty:
918 handle_error("Test server failure:\n")
919 self.close()
920 self.running = False
921 # normally, we'd just stop here, but for the test
922 # harness, we want to stop the server
923 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924
Antoine Pitroub5218772010-05-21 09:56:06 +0000925 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000926 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000927 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000928 ciphers=None, context=None):
929 if context:
930 self.context = context
931 else:
932 self.context = ssl.SSLContext(ssl_version
933 if ssl_version is not None
934 else ssl.PROTOCOL_TLSv1)
935 self.context.verify_mode = (certreqs if certreqs is not None
936 else ssl.CERT_NONE)
937 if cacerts:
938 self.context.load_verify_locations(cacerts)
939 if certificate:
940 self.context.load_cert_chain(certificate)
941 if ciphers:
942 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000943 self.chatty = chatty
944 self.connectionchatty = connectionchatty
945 self.starttls_server = starttls_server
946 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000947 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000948 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100950 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000952 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100954 def __enter__(self):
955 self.start(threading.Event())
956 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100957 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100958
959 def __exit__(self, *args):
960 self.stop()
961 self.join()
962
Antoine Pitrou480a1242010-04-28 21:37:09 +0000963 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000964 self.flag = flag
965 threading.Thread.start(self)
966
Antoine Pitrou480a1242010-04-28 21:37:09 +0000967 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000968 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000969 self.sock.listen(5)
970 self.active = True
971 if self.flag:
972 # signal an event
973 self.flag.set()
974 while self.active:
975 try:
976 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000977 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000979 + repr(connaddr) + '\n')
980 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +0100982 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000983 except socket.timeout:
984 pass
985 except KeyboardInterrupt:
986 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000987 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000988
Antoine Pitrou480a1242010-04-28 21:37:09 +0000989 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991
Bill Janssen54cc54c2007-12-14 22:08:56 +0000992 class AsyncoreEchoServer(threading.Thread):
993
994 # this one's based on asyncore.dispatcher
995
996 class EchoServer (asyncore.dispatcher):
997
998 class ConnectionHandler (asyncore.dispatcher_with_send):
999
1000 def __init__(self, conn, certfile):
1001 self.socket = ssl.wrap_socket(conn, server_side=True,
1002 certfile=certfile,
1003 do_handshake_on_connect=False)
1004 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001005 self._ssl_accepting = True
1006 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001007
1008 def readable(self):
1009 if isinstance(self.socket, ssl.SSLSocket):
1010 while self.socket.pending() > 0:
1011 self.handle_read_event()
1012 return True
1013
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001014 def _do_ssl_handshake(self):
1015 try:
1016 self.socket.do_handshake()
1017 except ssl.SSLError as err:
1018 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
1019 ssl.SSL_ERROR_WANT_WRITE):
1020 return
1021 elif err.args[0] == ssl.SSL_ERROR_EOF:
1022 return self.handle_close()
1023 raise
1024 except socket.error as err:
1025 if err.args[0] == errno.ECONNABORTED:
1026 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001027 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001028 self._ssl_accepting = False
1029
1030 def handle_read(self):
1031 if self._ssl_accepting:
1032 self._do_ssl_handshake()
1033 else:
1034 data = self.recv(1024)
1035 if support.verbose:
1036 sys.stdout.write(" server: read %s from client\n" % repr(data))
1037 if not data:
1038 self.close()
1039 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001040 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001041
1042 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001043 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001044 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001045 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1046
1047 def handle_error(self):
1048 raise
1049
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001050 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001051 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001052 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1053 self.port = support.bind_port(sock, '')
1054 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001055 self.listen(5)
1056
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001057 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001058 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001059 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1060 self.ConnectionHandler(sock_obj, self.certfile)
1061
1062 def handle_error(self):
1063 raise
1064
Trent Nelson78520002008-04-10 20:54:35 +00001065 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001066 self.flag = None
1067 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001068 self.server = self.EchoServer(certfile)
1069 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001070 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001071 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001072
1073 def __str__(self):
1074 return "<%s %s>" % (self.__class__.__name__, self.server)
1075
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001076 def __enter__(self):
1077 self.start(threading.Event())
1078 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001079 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001080
1081 def __exit__(self, *args):
1082 if support.verbose:
1083 sys.stdout.write(" cleanup: stopping server.\n")
1084 self.stop()
1085 if support.verbose:
1086 sys.stdout.write(" cleanup: joining server thread.\n")
1087 self.join()
1088 if support.verbose:
1089 sys.stdout.write(" cleanup: successfully joined.\n")
1090
Bill Janssen54cc54c2007-12-14 22:08:56 +00001091 def start (self, flag=None):
1092 self.flag = flag
1093 threading.Thread.start(self)
1094
Antoine Pitrou480a1242010-04-28 21:37:09 +00001095 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001096 self.active = True
1097 if self.flag:
1098 self.flag.set()
1099 while self.active:
1100 try:
1101 asyncore.loop(1)
1102 except:
1103 pass
1104
Antoine Pitrou480a1242010-04-28 21:37:09 +00001105 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001106 self.active = False
1107 self.server.close()
1108
Antoine Pitrou480a1242010-04-28 21:37:09 +00001109 def bad_cert_test(certfile):
1110 """
1111 Launch a server with CERT_REQUIRED, and check that trying to
1112 connect to it with the given client certificate fails.
1113 """
Trent Nelson78520002008-04-10 20:54:35 +00001114 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001115 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001116 cacerts=CERTFILE, chatty=False,
1117 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001118 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001119 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001120 with socket.socket() as sock:
1121 s = ssl.wrap_socket(sock,
1122 certfile=certfile,
1123 ssl_version=ssl.PROTOCOL_TLSv1)
1124 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001126 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001127 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001128 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001129 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001130 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001131 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001132 if x.errno != errno.ENOENT:
1133 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001134 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001135 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001136 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001137 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001138
Antoine Pitroub5218772010-05-21 09:56:06 +00001139 def server_params_test(client_context, server_context, indata=b"FOO\n",
1140 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 """
1142 Launch a server, connect a client to it and try various reads
1143 and writes.
1144 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001145 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001146 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001147 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001148 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001149 with client_context.wrap_socket(socket.socket()) as s:
1150 s.connect((HOST, server.port))
1151 for arg in [indata, bytearray(indata), memoryview(indata)]:
1152 if connectionchatty:
1153 if support.verbose:
1154 sys.stdout.write(
1155 " client: sending %r...\n" % indata)
1156 s.write(arg)
1157 outdata = s.read()
1158 if connectionchatty:
1159 if support.verbose:
1160 sys.stdout.write(" client: read %r\n" % outdata)
1161 if outdata != indata.lower():
1162 raise AssertionError(
1163 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1164 % (outdata[:20], len(outdata),
1165 indata[:20].lower(), len(indata)))
1166 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001167 if connectionchatty:
1168 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001169 sys.stdout.write(" client: closing connection.\n")
1170 s.close()
Thomas Woutersed03b412007-08-28 21:37:11 +00001171
Antoine Pitroub5218772010-05-21 09:56:06 +00001172 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1173 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001174 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001175 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001176 certtype = {
1177 ssl.CERT_NONE: "CERT_NONE",
1178 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1179 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1180 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001181 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001183 sys.stdout.write(formatstr %
1184 (ssl.get_protocol_name(client_protocol),
1185 ssl.get_protocol_name(server_protocol),
1186 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001187 client_context = ssl.SSLContext(client_protocol)
1188 client_context.options = ssl.OP_ALL | client_options
1189 server_context = ssl.SSLContext(server_protocol)
1190 server_context.options = ssl.OP_ALL | server_options
1191 for ctx in (client_context, server_context):
1192 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001193 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1194 # will send an SSLv3 hello (rather than SSLv2) starting from
1195 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001196 ctx.set_ciphers("ALL")
1197 ctx.load_cert_chain(CERTFILE)
1198 ctx.load_verify_locations(CERTFILE)
1199 try:
1200 server_params_test(client_context, server_context,
1201 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001202 # Protocol mismatch can result in either an SSLError, or a
1203 # "Connection reset by peer" error.
1204 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001206 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001207 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001208 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001209 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001210 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001211 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001212 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001213 "Client protocol %s succeeded with server protocol %s!"
1214 % (ssl.get_protocol_name(client_protocol),
1215 ssl.get_protocol_name(server_protocol)))
1216
1217
Bill Janssen6e027db2007-11-15 22:23:56 +00001218 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001219
Antoine Pitrou23df4832010-08-04 17:14:06 +00001220 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001221 def test_echo(self):
1222 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001223 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001224 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001225 for protocol in PROTOCOLS:
1226 context = ssl.SSLContext(protocol)
1227 context.load_cert_chain(CERTFILE)
1228 server_params_test(context, context,
1229 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001230
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001232 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001233 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001234 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1235 context.verify_mode = ssl.CERT_REQUIRED
1236 context.load_verify_locations(CERTFILE)
1237 context.load_cert_chain(CERTFILE)
1238 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001239 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001240 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001241 s.connect((HOST, server.port))
1242 cert = s.getpeercert()
1243 self.assertTrue(cert, "Can't get peer certificate.")
1244 cipher = s.cipher()
1245 if support.verbose:
1246 sys.stdout.write(pprint.pformat(cert) + '\n')
1247 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1248 if 'subject' not in cert:
1249 self.fail("No subject field in certificate: %s." %
1250 pprint.pformat(cert))
1251 if ((('organizationName', 'Python Software Foundation'),)
1252 not in cert['subject']):
1253 self.fail(
1254 "Missing or invalid 'organizationName' field in certificate subject; "
1255 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001256 self.assertIn('notBefore', cert)
1257 self.assertIn('notAfter', cert)
1258 before = ssl.cert_time_to_seconds(cert['notBefore'])
1259 after = ssl.cert_time_to_seconds(cert['notAfter'])
1260 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001261 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001262
Antoine Pitrou480a1242010-04-28 21:37:09 +00001263 def test_empty_cert(self):
1264 """Connecting with an empty cert file"""
1265 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1266 "nullcert.pem"))
1267 def test_malformed_cert(self):
1268 """Connecting with a badly formatted certificate (syntax error)"""
1269 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1270 "badcert.pem"))
1271 def test_nonexisting_cert(self):
1272 """Connecting with a non-existing cert file"""
1273 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1274 "wrongcert.pem"))
1275 def test_malformed_key(self):
1276 """Connecting with a badly formatted key (syntax error)"""
1277 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1278 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001279
Antoine Pitrou480a1242010-04-28 21:37:09 +00001280 def test_rude_shutdown(self):
1281 """A brutal shutdown of an SSL server should raise an IOError
1282 in the client when attempting handshake.
1283 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001284 listener_ready = threading.Event()
1285 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001286
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001287 s = socket.socket()
1288 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001289
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001290 # `listener` runs in a thread. It sits in an accept() until
1291 # the main thread connects. Then it rudely closes the socket,
1292 # and sets Event `listener_gone` to let the main thread know
1293 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001294 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001295 s.listen(5)
1296 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001297 newsock, addr = s.accept()
1298 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001299 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001300 listener_gone.set()
1301
1302 def connector():
1303 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001304 with socket.socket() as c:
1305 c.connect((HOST, port))
1306 listener_gone.wait()
1307 try:
1308 ssl_sock = ssl.wrap_socket(c)
1309 except IOError:
1310 pass
1311 else:
1312 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001313
1314 t = threading.Thread(target=listener)
1315 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001316 try:
1317 connector()
1318 finally:
1319 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001320
Antoine Pitrou23df4832010-08-04 17:14:06 +00001321 @skip_if_broken_ubuntu_ssl
Victor Stinneree18b6f2011-05-10 00:38:00 +02001322 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001323 def test_protocol_sslv2(self):
1324 """Connecting to an SSLv2 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_SSLv2, ssl.PROTOCOL_SSLv2, True)
1328 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1329 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1330 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1331 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1332 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001333 # SSLv23 client with specific SSL options
1334 if no_sslv2_implies_sslv3_hello():
1335 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1336 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1337 client_options=ssl.OP_NO_SSLv2)
1338 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1339 client_options=ssl.OP_NO_SSLv3)
1340 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1341 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001342
Antoine Pitrou23df4832010-08-04 17:14:06 +00001343 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001344 def test_protocol_sslv23(self):
1345 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001346 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001347 sys.stdout.write("\n")
Victor Stinneree18b6f2011-05-10 00:38:00 +02001348 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1349 try:
1350 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1351 except (ssl.SSLError, socket.error) as x:
1352 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1353 if support.verbose:
1354 sys.stdout.write(
1355 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1356 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1358 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1359 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001360
Antoine Pitrou480a1242010-04-28 21:37:09 +00001361 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1362 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1363 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001364
Antoine Pitrou480a1242010-04-28 21:37:09 +00001365 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1366 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1367 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001368
Antoine Pitroub5218772010-05-21 09:56:06 +00001369 # Server with specific SSL options
1370 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1371 server_options=ssl.OP_NO_SSLv3)
1372 # Will choose TLSv1
1373 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1374 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1375 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1376 server_options=ssl.OP_NO_TLSv1)
1377
1378
Antoine Pitrou23df4832010-08-04 17:14:06 +00001379 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 def test_protocol_sslv3(self):
1381 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001382 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001383 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001384 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1385 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1386 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001387 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1388 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001389 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1390 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001392 if no_sslv2_implies_sslv3_hello():
1393 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1394 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1395 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001396
Antoine Pitrou23df4832010-08-04 17:14:06 +00001397 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001398 def test_protocol_tlsv1(self):
1399 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001400 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001401 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001402 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1403 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1404 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001405 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1406 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001407 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001408 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1409 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001410
Antoine Pitrou480a1242010-04-28 21:37:09 +00001411 def test_starttls(self):
1412 """Switching from clear text to encrypted and back again."""
1413 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 +00001414
Trent Nelson78520002008-04-10 20:54:35 +00001415 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001416 ssl_version=ssl.PROTOCOL_TLSv1,
1417 starttls_server=True,
1418 chatty=True,
1419 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001420 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001421 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001422 s = socket.socket()
1423 s.setblocking(1)
1424 s.connect((HOST, server.port))
1425 if support.verbose:
1426 sys.stdout.write("\n")
1427 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001428 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001429 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001430 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001431 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001432 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001433 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001436 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 msg = outdata.strip().lower()
1438 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1439 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001440 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001441 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001442 " client: read %r from server, starting TLS...\n"
1443 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001444 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1445 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001446 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1447 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001448 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001449 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001450 " client: read %r from server, ending TLS...\n"
1451 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001452 s = conn.unwrap()
1453 wrapped = False
1454 else:
1455 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001456 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001457 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001458 if support.verbose:
1459 sys.stdout.write(" client: closing connection.\n")
1460 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001461 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001462 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001463 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001464 if wrapped:
1465 conn.close()
1466 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001467 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001468
Antoine Pitrou480a1242010-04-28 21:37:09 +00001469 def test_socketserver(self):
1470 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001471 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001472 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001473 if support.verbose:
1474 sys.stdout.write('\n')
1475 with open(CERTFILE, 'rb') as f:
1476 d1 = f.read()
1477 d2 = ''
1478 # now fetch the same data from the HTTPS server
1479 url = 'https://%s:%d/%s' % (
1480 HOST, server.port, os.path.split(CERTFILE)[1])
1481 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001482 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001483 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001484 if dlen and (int(dlen) > 0):
1485 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001486 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001487 sys.stdout.write(
1488 " client: read %d bytes from remote server '%s'\n"
1489 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001490 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001491 f.close()
1492 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001493
Antoine Pitrou480a1242010-04-28 21:37:09 +00001494 def test_asyncore_server(self):
1495 """Check the example asyncore integration."""
1496 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001497
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001498 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001499 sys.stdout.write("\n")
1500
Antoine Pitrou480a1242010-04-28 21:37:09 +00001501 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001502 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001503 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001504 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001505 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001506 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001507 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001508 " client: sending %r...\n" % indata)
1509 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001510 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001511 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001512 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001513 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001514 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001515 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1516 % (outdata[:20], len(outdata),
1517 indata[:20].lower(), len(indata)))
1518 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001519 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001520 sys.stdout.write(" client: closing connection.\n")
1521 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001522 if support.verbose:
1523 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001524
Antoine Pitrou480a1242010-04-28 21:37:09 +00001525 def test_recv_send(self):
1526 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001527 if support.verbose:
1528 sys.stdout.write("\n")
1529
1530 server = ThreadedEchoServer(CERTFILE,
1531 certreqs=ssl.CERT_NONE,
1532 ssl_version=ssl.PROTOCOL_TLSv1,
1533 cacerts=CERTFILE,
1534 chatty=True,
1535 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001536 with server:
1537 s = ssl.wrap_socket(socket.socket(),
1538 server_side=False,
1539 certfile=CERTFILE,
1540 ca_certs=CERTFILE,
1541 cert_reqs=ssl.CERT_NONE,
1542 ssl_version=ssl.PROTOCOL_TLSv1)
1543 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001544 # helper methods for standardising recv* method signatures
1545 def _recv_into():
1546 b = bytearray(b"\0"*100)
1547 count = s.recv_into(b)
1548 return b[:count]
1549
1550 def _recvfrom_into():
1551 b = bytearray(b"\0"*100)
1552 count, addr = s.recvfrom_into(b)
1553 return b[:count]
1554
1555 # (name, method, whether to expect success, *args)
1556 send_methods = [
1557 ('send', s.send, True, []),
1558 ('sendto', s.sendto, False, ["some.address"]),
1559 ('sendall', s.sendall, True, []),
1560 ]
1561 recv_methods = [
1562 ('recv', s.recv, True, []),
1563 ('recvfrom', s.recvfrom, False, ["some.address"]),
1564 ('recv_into', _recv_into, True, []),
1565 ('recvfrom_into', _recvfrom_into, False, []),
1566 ]
1567 data_prefix = "PREFIX_"
1568
1569 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001570 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001571 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001572 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001573 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001574 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001575 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001576 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001577 "<<{outdata:r}>> ({nout:d}) received; "
1578 "expected <<{indata:r}>> ({nin:d})\n".format(
1579 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001580 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001581 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001582 )
1583 )
1584 except ValueError as e:
1585 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001586 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001587 "Failed to send with method <<{name:s}>>; "
1588 "expected to succeed.\n".format(name=meth_name)
1589 )
1590 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001591 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001592 "Method <<{name:s}>> failed with unexpected "
1593 "exception message: {exp:s}\n".format(
1594 name=meth_name, exp=e
1595 )
1596 )
1597
1598 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001599 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001600 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001601 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001602 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001603 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001604 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001605 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001606 "<<{outdata:r}>> ({nout:d}) received; "
1607 "expected <<{indata:r}>> ({nin:d})\n".format(
1608 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001609 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001610 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001611 )
1612 )
1613 except ValueError as e:
1614 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001615 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001616 "Failed to receive with method <<{name:s}>>; "
1617 "expected to succeed.\n".format(name=meth_name)
1618 )
1619 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001620 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001621 "Method <<{name:s}>> failed with unexpected "
1622 "exception message: {exp:s}\n".format(
1623 name=meth_name, exp=e
1624 )
1625 )
1626 # consume data
1627 s.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001628 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001629 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001630
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001631 def test_handshake_timeout(self):
1632 # Issue #5103: SSL handshake must respect the socket timeout
1633 server = socket.socket(socket.AF_INET)
1634 host = "127.0.0.1"
1635 port = support.bind_port(server)
1636 started = threading.Event()
1637 finish = False
1638
1639 def serve():
1640 server.listen(5)
1641 started.set()
1642 conns = []
1643 while not finish:
1644 r, w, e = select.select([server], [], [], 0.1)
1645 if server in r:
1646 # Let the socket hang around rather than having
1647 # it closed by garbage collection.
1648 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001649 for sock in conns:
1650 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001651
1652 t = threading.Thread(target=serve)
1653 t.start()
1654 started.wait()
1655
1656 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001657 try:
1658 c = socket.socket(socket.AF_INET)
1659 c.settimeout(0.2)
1660 c.connect((host, port))
1661 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001662 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001663 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001664 finally:
1665 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001666 try:
1667 c = socket.socket(socket.AF_INET)
1668 c = ssl.wrap_socket(c)
1669 c.settimeout(0.2)
1670 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001671 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001672 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001673 finally:
1674 c.close()
1675 finally:
1676 finish = True
1677 t.join()
1678 server.close()
1679
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001680 def test_server_accept(self):
1681 # Issue #16357: accept() on a SSLSocket created through
1682 # SSLContext.wrap_socket().
1683 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1684 context.verify_mode = ssl.CERT_REQUIRED
1685 context.load_verify_locations(CERTFILE)
1686 context.load_cert_chain(CERTFILE)
1687 server = socket.socket(socket.AF_INET)
1688 host = "127.0.0.1"
1689 port = support.bind_port(server)
1690 server = context.wrap_socket(server, server_side=True)
1691
1692 evt = threading.Event()
1693 remote = None
1694 peer = None
1695 def serve():
1696 nonlocal remote, peer
1697 server.listen(5)
1698 # Block on the accept and wait on the connection to close.
1699 evt.set()
1700 remote, peer = server.accept()
1701 remote.recv(1)
1702
1703 t = threading.Thread(target=serve)
1704 t.start()
1705 # Client wait until server setup and perform a connect.
1706 evt.wait()
1707 client = context.wrap_socket(socket.socket())
1708 client.connect((host, port))
1709 client_addr = client.getsockname()
1710 client.close()
1711 t.join()
1712 # Sanity checks.
1713 self.assertIsInstance(remote, ssl.SSLSocket)
1714 self.assertEqual(peer, client_addr)
1715
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001716 def test_default_ciphers(self):
1717 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1718 try:
1719 # Force a set of weak ciphers on our client context
1720 context.set_ciphers("DES")
1721 except ssl.SSLError:
1722 self.skipTest("no DES cipher available")
1723 with ThreadedEchoServer(CERTFILE,
1724 ssl_version=ssl.PROTOCOL_SSLv23,
1725 chatty=False) as server:
1726 with socket.socket() as sock:
1727 s = context.wrap_socket(sock)
1728 with self.assertRaises((OSError, ssl.SSLError)):
1729 s.connect((HOST, server.port))
1730 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1731
Bill Janssen58afe4c2008-09-08 16:45:19 +00001732
Thomas Woutersed03b412007-08-28 21:37:11 +00001733def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001734 if support.verbose:
1735 plats = {
1736 'Linux': platform.linux_distribution,
1737 'Mac': platform.mac_ver,
1738 'Windows': platform.win32_ver,
1739 }
1740 for name, func in plats.items():
1741 plat = func()
1742 if plat and plat[0]:
1743 plat = '%s %r' % (name, plat)
1744 break
1745 else:
1746 plat = repr(platform.platform())
1747 print("test_ssl: testing with %r %r" %
1748 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1749 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001750 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001751
Antoine Pitrou152efa22010-05-16 18:19:27 +00001752 for filename in [
Martin Panter3d81d932016-01-14 09:36:00 +00001753 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00001754 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1755 BADCERT, BADKEY, EMPTYCERT]:
1756 if not os.path.exists(filename):
1757 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001758
Antoine Pitrou152efa22010-05-16 18:19:27 +00001759 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001760
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001761 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001762 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001763
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001764 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001765 thread_info = support.threading_setup()
1766 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001767 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001768
Antoine Pitrou480a1242010-04-28 21:37:09 +00001769 try:
1770 support.run_unittest(*tests)
1771 finally:
1772 if _have_threads:
1773 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001774
1775if __name__ == "__main__":
1776 test_main()