blob: 69a80d0a57288f7c40fb8e0e57384a6c5a0ecb64 [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))
611 self.assertIn(rc, (errno.ECONNREFUSED, errno.EHOSTUNREACH))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100612 finally:
613 s.close()
614
Antoine Pitrou152efa22010-05-16 18:19:27 +0000615 def test_connect_with_context(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000616 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000617 # Same as test_connect, but with a separately created context
618 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
619 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000620 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000621 try:
622 self.assertEqual({}, s.getpeercert())
623 finally:
624 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000625 # Same with a server hostname
626 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3d81d932016-01-14 09:36:00 +0000627 server_hostname=REMOTE_HOST)
Antoine Pitroud5323212010-10-22 18:19:07 +0000628 if ssl.HAS_SNI:
Martin Panter3d81d932016-01-14 09:36:00 +0000629 s.connect((REMOTE_HOST, 443))
Antoine Pitroud5323212010-10-22 18:19:07 +0000630 s.close()
631 else:
Martin Panter3d81d932016-01-14 09:36:00 +0000632 self.assertRaises(ValueError, s.connect, (REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000633 # This should fail because we have no verification certs
634 ctx.verify_mode = ssl.CERT_REQUIRED
635 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000636 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Martin Panter3d81d932016-01-14 09:36:00 +0000637 s.connect, (REMOTE_HOST, 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000638 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000639 # This should succeed because we specify the root cert
Martin Panter3d81d932016-01-14 09:36:00 +0000640 ctx.load_verify_locations(REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000641 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000642 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000643 try:
644 cert = s.getpeercert()
645 self.assertTrue(cert)
646 finally:
647 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000648
649 def test_connect_capath(self):
650 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000651 # NOTE: the subject hashing algorithm has been changed between
652 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
653 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000654 # filename) for this test to be portable across OpenSSL releases.
Martin Panter3d81d932016-01-14 09:36:00 +0000655 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000656 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
657 ctx.verify_mode = ssl.CERT_REQUIRED
658 ctx.load_verify_locations(capath=CAPATH)
659 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000660 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000661 try:
662 cert = s.getpeercert()
663 self.assertTrue(cert)
664 finally:
665 s.close()
666 # Same with a bytes `capath` argument
667 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
668 ctx.verify_mode = ssl.CERT_REQUIRED
669 ctx.load_verify_locations(capath=BYTES_CAPATH)
670 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000671 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000672 try:
673 cert = s.getpeercert()
674 self.assertTrue(cert)
675 finally:
676 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000677
Antoine Pitroue3220242010-04-24 11:13:53 +0000678 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
679 def test_makefile_close(self):
680 # Issue #5238: creating a file-like object with makefile() shouldn't
681 # delay closing the underlying "real socket" (here tested with its
682 # file descriptor, hence skipping the test under Windows).
Martin Panter3d81d932016-01-14 09:36:00 +0000683 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000684 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3d81d932016-01-14 09:36:00 +0000685 ss.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000686 fd = ss.fileno()
687 f = ss.makefile()
688 f.close()
689 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000690 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000691 # Closing the SSL socket should close the fd too
692 ss.close()
693 gc.collect()
694 with self.assertRaises(OSError) as e:
695 os.read(fd, 0)
696 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000697
Antoine Pitrou480a1242010-04-28 21:37:09 +0000698 def test_non_blocking_handshake(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000699 with support.transient_internet(REMOTE_HOST):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000700 s = socket.socket(socket.AF_INET)
Martin Panter3d81d932016-01-14 09:36:00 +0000701 s.connect((REMOTE_HOST, 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000702 s.setblocking(False)
703 s = ssl.wrap_socket(s,
704 cert_reqs=ssl.CERT_NONE,
705 do_handshake_on_connect=False)
706 count = 0
707 while True:
708 try:
709 count += 1
710 s.do_handshake()
711 break
712 except ssl.SSLError as err:
713 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
714 select.select([s], [], [])
715 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
716 select.select([], [s], [])
717 else:
718 raise
719 s.close()
720 if support.verbose:
721 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000722
Antoine Pitrou480a1242010-04-28 21:37:09 +0000723 def test_get_server_certificate(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000724 with support.transient_internet(REMOTE_HOST):
725 pem = ssl.get_server_certificate((REMOTE_HOST, 443),
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500726 ssl.PROTOCOL_SSLv23)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000727 if not pem:
Martin Panter3d81d932016-01-14 09:36:00 +0000728 self.fail("No server certificate on REMOTE_HOST:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000729
Antoine Pitrou350c7222010-09-09 13:31:46 +0000730 try:
Martin Panter3d81d932016-01-14 09:36:00 +0000731 pem = ssl.get_server_certificate((REMOTE_HOST, 443),
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500732 ssl.PROTOCOL_SSLv23,
733 ca_certs=CERTFILE)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000734 except ssl.SSLError as x:
735 #should fail
736 if support.verbose:
737 sys.stdout.write("%s\n" % x)
738 else:
Martin Panter3d81d932016-01-14 09:36:00 +0000739 self.fail("Got server certificate %s for REMOTE_HOST!" % pem)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000740
Martin Panter3d81d932016-01-14 09:36:00 +0000741 pem = ssl.get_server_certificate((REMOTE_HOST, 443),
Benjamin Petersoncf25c5c2014-03-12 18:05:53 -0500742 ssl.PROTOCOL_SSLv23,
Martin Panter3d81d932016-01-14 09:36:00 +0000743 ca_certs=REMOTE_ROOT_CERT)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000744 if not pem:
Martin Panter3d81d932016-01-14 09:36:00 +0000745 self.fail("No server certificate on REMOTE_HOST:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000746 if support.verbose:
Martin Panter3d81d932016-01-14 09:36:00 +0000747 sys.stdout.write("\nVerified certificate for REMOTE_HOST:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000748
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000749 def test_ciphers(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000750 remote = (REMOTE_HOST, 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000751 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000752 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000753 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000754 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000755 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
756 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
757 s.connect(remote)
758 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000759 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000760 with socket.socket(socket.AF_INET) as sock:
761 s = ssl.wrap_socket(sock,
762 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
763 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000764
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000765 def test_algorithms(self):
766 # Issue #8484: all algorithms should be available when verifying a
767 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000768 # SHA256 was added in OpenSSL 0.9.8
769 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
770 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200771 # sha256.tbs-internet.com needs SNI to use the correct certificate
772 if not ssl.HAS_SNI:
773 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000774 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
775 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000776 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000777 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200778 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
779 ctx.verify_mode = ssl.CERT_REQUIRED
780 ctx.load_verify_locations(sha256_cert)
781 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
782 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000783 try:
784 s.connect(remote)
785 if support.verbose:
786 sys.stdout.write("\nCipher with %r is %r\n" %
787 (remote, s.cipher()))
788 sys.stdout.write("Certificate is:\n%s\n" %
789 pprint.pformat(s.getpeercert()))
790 finally:
791 s.close()
792
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000793
794try:
795 import threading
796except ImportError:
797 _have_threads = False
798else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000799 _have_threads = True
800
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000801 from test.ssl_servers import make_https_server
802
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000803 class ThreadedEchoServer(threading.Thread):
804
805 class ConnectionHandler(threading.Thread):
806
807 """A mildly complicated class, because we want it to work both
808 with and without the SSL wrapper around the socket connection, so
809 that we can test the STARTTLS functionality."""
810
Bill Janssen6e027db2007-11-15 22:23:56 +0000811 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000812 self.server = server
813 self.running = False
814 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000815 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000816 self.sock.setblocking(1)
817 self.sslconn = None
818 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000819 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000820
Antoine Pitrou480a1242010-04-28 21:37:09 +0000821 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000822 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000823 self.sslconn = self.server.context.wrap_socket(
824 self.sock, server_side=True)
Nadeem Vawda7b39b9b2013-03-03 22:31:21 +0100825 except (ssl.SSLError, socket.error) as e:
826 # Treat ECONNRESET as though it were an SSLError - OpenSSL
827 # on Ubuntu abruptly closes the connection when asked to use
828 # an unsupported protocol.
829 if (not isinstance(e, ssl.SSLError) and
830 e.errno != errno.ECONNRESET):
831 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000832 # XXX Various errors can have happened here, for example
833 # a mismatching protocol version, an invalid certificate,
834 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100835 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000836 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000837 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000838 self.running = False
839 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000840 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000841 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000843 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000844 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000845 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
847 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000848 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000849 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
850 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000851 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000852 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
853 return True
854
855 def read(self):
856 if self.sslconn:
857 return self.sslconn.read()
858 else:
859 return self.sock.recv(1024)
860
861 def write(self, bytes):
862 if self.sslconn:
863 return self.sslconn.write(bytes)
864 else:
865 return self.sock.send(bytes)
866
867 def close(self):
868 if self.sslconn:
869 self.sslconn.close()
870 else:
871 self.sock.close()
872
Antoine Pitrou480a1242010-04-28 21:37:09 +0000873 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000874 self.running = True
875 if not self.server.starttls_server:
876 if not self.wrap_conn():
877 return
878 while self.running:
879 try:
880 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000881 stripped = msg.strip()
882 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000883 # eof, so quit this handler
884 self.running = False
885 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000886 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000887 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000888 sys.stdout.write(" server: client closed connection\n")
889 self.close()
890 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000891 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000892 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000893 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000894 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000895 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 if not self.wrap_conn():
897 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000898 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000899 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000900 if support.verbose and self.server.connectionchatty:
901 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000902 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000903 self.sock = self.sslconn.unwrap()
904 self.sslconn = None
905 if support.verbose and self.server.connectionchatty:
906 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000908 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 self.server.connectionchatty):
910 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000911 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
912 % (msg, ctype, msg.lower(), ctype))
913 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000914 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 if self.server.chatty:
916 handle_error("Test server failure:\n")
917 self.close()
918 self.running = False
919 # normally, we'd just stop here, but for the test
920 # harness, we want to stop the server
921 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922
Antoine Pitroub5218772010-05-21 09:56:06 +0000923 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000924 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000925 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000926 ciphers=None, context=None):
927 if context:
928 self.context = context
929 else:
930 self.context = ssl.SSLContext(ssl_version
931 if ssl_version is not None
932 else ssl.PROTOCOL_TLSv1)
933 self.context.verify_mode = (certreqs if certreqs is not None
934 else ssl.CERT_NONE)
935 if cacerts:
936 self.context.load_verify_locations(cacerts)
937 if certificate:
938 self.context.load_cert_chain(certificate)
939 if ciphers:
940 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941 self.chatty = chatty
942 self.connectionchatty = connectionchatty
943 self.starttls_server = starttls_server
944 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000945 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000946 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100948 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000950 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100952 def __enter__(self):
953 self.start(threading.Event())
954 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100955 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100956
957 def __exit__(self, *args):
958 self.stop()
959 self.join()
960
Antoine Pitrou480a1242010-04-28 21:37:09 +0000961 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000962 self.flag = flag
963 threading.Thread.start(self)
964
Antoine Pitrou480a1242010-04-28 21:37:09 +0000965 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000966 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000967 self.sock.listen(5)
968 self.active = True
969 if self.flag:
970 # signal an event
971 self.flag.set()
972 while self.active:
973 try:
974 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000975 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000976 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000977 + repr(connaddr) + '\n')
978 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +0100980 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 except socket.timeout:
982 pass
983 except KeyboardInterrupt:
984 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000985 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986
Antoine Pitrou480a1242010-04-28 21:37:09 +0000987 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000988 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000989
Bill Janssen54cc54c2007-12-14 22:08:56 +0000990 class AsyncoreEchoServer(threading.Thread):
991
992 # this one's based on asyncore.dispatcher
993
994 class EchoServer (asyncore.dispatcher):
995
996 class ConnectionHandler (asyncore.dispatcher_with_send):
997
998 def __init__(self, conn, certfile):
999 self.socket = ssl.wrap_socket(conn, server_side=True,
1000 certfile=certfile,
1001 do_handshake_on_connect=False)
1002 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001003 self._ssl_accepting = True
1004 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001005
1006 def readable(self):
1007 if isinstance(self.socket, ssl.SSLSocket):
1008 while self.socket.pending() > 0:
1009 self.handle_read_event()
1010 return True
1011
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001012 def _do_ssl_handshake(self):
1013 try:
1014 self.socket.do_handshake()
1015 except ssl.SSLError as err:
1016 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
1017 ssl.SSL_ERROR_WANT_WRITE):
1018 return
1019 elif err.args[0] == ssl.SSL_ERROR_EOF:
1020 return self.handle_close()
1021 raise
1022 except socket.error as err:
1023 if err.args[0] == errno.ECONNABORTED:
1024 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001025 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001026 self._ssl_accepting = False
1027
1028 def handle_read(self):
1029 if self._ssl_accepting:
1030 self._do_ssl_handshake()
1031 else:
1032 data = self.recv(1024)
1033 if support.verbose:
1034 sys.stdout.write(" server: read %s from client\n" % repr(data))
1035 if not data:
1036 self.close()
1037 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001038 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001039
1040 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001041 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001042 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001043 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1044
1045 def handle_error(self):
1046 raise
1047
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001048 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001049 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001050 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1051 self.port = support.bind_port(sock, '')
1052 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001053 self.listen(5)
1054
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001055 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001056 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001057 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1058 self.ConnectionHandler(sock_obj, self.certfile)
1059
1060 def handle_error(self):
1061 raise
1062
Trent Nelson78520002008-04-10 20:54:35 +00001063 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001064 self.flag = None
1065 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001066 self.server = self.EchoServer(certfile)
1067 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001068 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001069 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001070
1071 def __str__(self):
1072 return "<%s %s>" % (self.__class__.__name__, self.server)
1073
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001074 def __enter__(self):
1075 self.start(threading.Event())
1076 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001077 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001078
1079 def __exit__(self, *args):
1080 if support.verbose:
1081 sys.stdout.write(" cleanup: stopping server.\n")
1082 self.stop()
1083 if support.verbose:
1084 sys.stdout.write(" cleanup: joining server thread.\n")
1085 self.join()
1086 if support.verbose:
1087 sys.stdout.write(" cleanup: successfully joined.\n")
1088
Bill Janssen54cc54c2007-12-14 22:08:56 +00001089 def start (self, flag=None):
1090 self.flag = flag
1091 threading.Thread.start(self)
1092
Antoine Pitrou480a1242010-04-28 21:37:09 +00001093 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001094 self.active = True
1095 if self.flag:
1096 self.flag.set()
1097 while self.active:
1098 try:
1099 asyncore.loop(1)
1100 except:
1101 pass
1102
Antoine Pitrou480a1242010-04-28 21:37:09 +00001103 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001104 self.active = False
1105 self.server.close()
1106
Antoine Pitrou480a1242010-04-28 21:37:09 +00001107 def bad_cert_test(certfile):
1108 """
1109 Launch a server with CERT_REQUIRED, and check that trying to
1110 connect to it with the given client certificate fails.
1111 """
Trent Nelson78520002008-04-10 20:54:35 +00001112 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001113 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001114 cacerts=CERTFILE, chatty=False,
1115 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001116 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001117 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001118 with socket.socket() as sock:
1119 s = ssl.wrap_socket(sock,
1120 certfile=certfile,
1121 ssl_version=ssl.PROTOCOL_TLSv1)
1122 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001123 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001124 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001125 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001126 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001127 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001128 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001129 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001130 if x.errno != errno.ENOENT:
1131 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001132 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001133 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001134 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001135 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001136
Antoine Pitroub5218772010-05-21 09:56:06 +00001137 def server_params_test(client_context, server_context, indata=b"FOO\n",
1138 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 """
1140 Launch a server, connect a client to it and try various reads
1141 and writes.
1142 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001143 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001145 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001146 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001147 with client_context.wrap_socket(socket.socket()) as s:
1148 s.connect((HOST, server.port))
1149 for arg in [indata, bytearray(indata), memoryview(indata)]:
1150 if connectionchatty:
1151 if support.verbose:
1152 sys.stdout.write(
1153 " client: sending %r...\n" % indata)
1154 s.write(arg)
1155 outdata = s.read()
1156 if connectionchatty:
1157 if support.verbose:
1158 sys.stdout.write(" client: read %r\n" % outdata)
1159 if outdata != indata.lower():
1160 raise AssertionError(
1161 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1162 % (outdata[:20], len(outdata),
1163 indata[:20].lower(), len(indata)))
1164 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001165 if connectionchatty:
1166 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001167 sys.stdout.write(" client: closing connection.\n")
1168 s.close()
Thomas Woutersed03b412007-08-28 21:37:11 +00001169
Antoine Pitroub5218772010-05-21 09:56:06 +00001170 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1171 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001172 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001173 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 certtype = {
1175 ssl.CERT_NONE: "CERT_NONE",
1176 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1177 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1178 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001179 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001181 sys.stdout.write(formatstr %
1182 (ssl.get_protocol_name(client_protocol),
1183 ssl.get_protocol_name(server_protocol),
1184 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001185 client_context = ssl.SSLContext(client_protocol)
1186 client_context.options = ssl.OP_ALL | client_options
1187 server_context = ssl.SSLContext(server_protocol)
1188 server_context.options = ssl.OP_ALL | server_options
1189 for ctx in (client_context, server_context):
1190 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001191 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1192 # will send an SSLv3 hello (rather than SSLv2) starting from
1193 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001194 ctx.set_ciphers("ALL")
1195 ctx.load_cert_chain(CERTFILE)
1196 ctx.load_verify_locations(CERTFILE)
1197 try:
1198 server_params_test(client_context, server_context,
1199 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001200 # Protocol mismatch can result in either an SSLError, or a
1201 # "Connection reset by peer" error.
1202 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001203 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001204 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001205 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001206 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001207 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001208 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001209 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001210 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 "Client protocol %s succeeded with server protocol %s!"
1212 % (ssl.get_protocol_name(client_protocol),
1213 ssl.get_protocol_name(server_protocol)))
1214
1215
Bill Janssen6e027db2007-11-15 22:23:56 +00001216 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001217
Antoine Pitrou23df4832010-08-04 17:14:06 +00001218 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001219 def test_echo(self):
1220 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001221 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001222 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001223 for protocol in PROTOCOLS:
1224 context = ssl.SSLContext(protocol)
1225 context.load_cert_chain(CERTFILE)
1226 server_params_test(context, context,
1227 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001228
Antoine Pitrou480a1242010-04-28 21:37:09 +00001229 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001230 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001232 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1233 context.verify_mode = ssl.CERT_REQUIRED
1234 context.load_verify_locations(CERTFILE)
1235 context.load_cert_chain(CERTFILE)
1236 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001237 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001238 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001239 s.connect((HOST, server.port))
1240 cert = s.getpeercert()
1241 self.assertTrue(cert, "Can't get peer certificate.")
1242 cipher = s.cipher()
1243 if support.verbose:
1244 sys.stdout.write(pprint.pformat(cert) + '\n')
1245 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1246 if 'subject' not in cert:
1247 self.fail("No subject field in certificate: %s." %
1248 pprint.pformat(cert))
1249 if ((('organizationName', 'Python Software Foundation'),)
1250 not in cert['subject']):
1251 self.fail(
1252 "Missing or invalid 'organizationName' field in certificate subject; "
1253 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001254 self.assertIn('notBefore', cert)
1255 self.assertIn('notAfter', cert)
1256 before = ssl.cert_time_to_seconds(cert['notBefore'])
1257 after = ssl.cert_time_to_seconds(cert['notAfter'])
1258 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001259 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001260
Antoine Pitrou480a1242010-04-28 21:37:09 +00001261 def test_empty_cert(self):
1262 """Connecting with an empty cert file"""
1263 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1264 "nullcert.pem"))
1265 def test_malformed_cert(self):
1266 """Connecting with a badly formatted certificate (syntax error)"""
1267 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1268 "badcert.pem"))
1269 def test_nonexisting_cert(self):
1270 """Connecting with a non-existing cert file"""
1271 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1272 "wrongcert.pem"))
1273 def test_malformed_key(self):
1274 """Connecting with a badly formatted key (syntax error)"""
1275 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1276 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001277
Antoine Pitrou480a1242010-04-28 21:37:09 +00001278 def test_rude_shutdown(self):
1279 """A brutal shutdown of an SSL server should raise an IOError
1280 in the client when attempting handshake.
1281 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001282 listener_ready = threading.Event()
1283 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001284
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001285 s = socket.socket()
1286 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001287
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001288 # `listener` runs in a thread. It sits in an accept() until
1289 # the main thread connects. Then it rudely closes the socket,
1290 # and sets Event `listener_gone` to let the main thread know
1291 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001292 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001293 s.listen(5)
1294 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001295 newsock, addr = s.accept()
1296 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001297 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001298 listener_gone.set()
1299
1300 def connector():
1301 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001302 with socket.socket() as c:
1303 c.connect((HOST, port))
1304 listener_gone.wait()
1305 try:
1306 ssl_sock = ssl.wrap_socket(c)
1307 except IOError:
1308 pass
1309 else:
1310 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001311
1312 t = threading.Thread(target=listener)
1313 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001314 try:
1315 connector()
1316 finally:
1317 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001318
Antoine Pitrou23df4832010-08-04 17:14:06 +00001319 @skip_if_broken_ubuntu_ssl
Victor Stinneree18b6f2011-05-10 00:38:00 +02001320 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001321 def test_protocol_sslv2(self):
1322 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001323 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001324 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001325 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1326 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1327 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1328 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1329 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1330 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001331 # SSLv23 client with specific SSL options
1332 if no_sslv2_implies_sslv3_hello():
1333 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1334 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1335 client_options=ssl.OP_NO_SSLv2)
1336 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1337 client_options=ssl.OP_NO_SSLv3)
1338 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1339 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001340
Antoine Pitrou23df4832010-08-04 17:14:06 +00001341 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001342 def test_protocol_sslv23(self):
1343 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001344 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001345 sys.stdout.write("\n")
Victor Stinneree18b6f2011-05-10 00:38:00 +02001346 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1347 try:
1348 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1349 except (ssl.SSLError, socket.error) as x:
1350 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1351 if support.verbose:
1352 sys.stdout.write(
1353 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1354 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001355 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1356 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1357 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001358
Antoine Pitrou480a1242010-04-28 21:37:09 +00001359 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1360 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1361 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001362
Antoine Pitrou480a1242010-04-28 21:37:09 +00001363 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1364 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1365 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001366
Antoine Pitroub5218772010-05-21 09:56:06 +00001367 # Server with specific SSL options
1368 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1369 server_options=ssl.OP_NO_SSLv3)
1370 # Will choose TLSv1
1371 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1372 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1373 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1374 server_options=ssl.OP_NO_TLSv1)
1375
1376
Antoine Pitrou23df4832010-08-04 17:14:06 +00001377 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001378 def test_protocol_sslv3(self):
1379 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001380 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001381 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001382 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1383 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1384 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001385 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1386 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001387 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1388 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001390 if no_sslv2_implies_sslv3_hello():
1391 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1392 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1393 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001394
Antoine Pitrou23df4832010-08-04 17:14:06 +00001395 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 def test_protocol_tlsv1(self):
1397 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001398 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001399 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1401 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1402 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001403 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1404 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001405 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001406 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1407 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001408
Antoine Pitrou480a1242010-04-28 21:37:09 +00001409 def test_starttls(self):
1410 """Switching from clear text to encrypted and back again."""
1411 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 +00001412
Trent Nelson78520002008-04-10 20:54:35 +00001413 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001414 ssl_version=ssl.PROTOCOL_TLSv1,
1415 starttls_server=True,
1416 chatty=True,
1417 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001418 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001419 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001420 s = socket.socket()
1421 s.setblocking(1)
1422 s.connect((HOST, server.port))
1423 if support.verbose:
1424 sys.stdout.write("\n")
1425 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001426 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001427 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001428 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001429 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001430 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001431 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001432 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001433 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001434 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 msg = outdata.strip().lower()
1436 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1437 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001438 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001439 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001440 " client: read %r from server, starting TLS...\n"
1441 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001442 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1443 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1445 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001446 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001447 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 " client: read %r from server, ending TLS...\n"
1449 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001450 s = conn.unwrap()
1451 wrapped = False
1452 else:
1453 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001454 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001455 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001456 if support.verbose:
1457 sys.stdout.write(" client: closing connection.\n")
1458 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001459 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001460 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001461 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001462 if wrapped:
1463 conn.close()
1464 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001465 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001466
Antoine Pitrou480a1242010-04-28 21:37:09 +00001467 def test_socketserver(self):
1468 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001469 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001470 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001471 if support.verbose:
1472 sys.stdout.write('\n')
1473 with open(CERTFILE, 'rb') as f:
1474 d1 = f.read()
1475 d2 = ''
1476 # now fetch the same data from the HTTPS server
1477 url = 'https://%s:%d/%s' % (
1478 HOST, server.port, os.path.split(CERTFILE)[1])
1479 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001480 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001481 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001482 if dlen and (int(dlen) > 0):
1483 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001484 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001485 sys.stdout.write(
1486 " client: read %d bytes from remote server '%s'\n"
1487 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001488 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001489 f.close()
1490 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001491
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 def test_asyncore_server(self):
1493 """Check the example asyncore integration."""
1494 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001495
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001496 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001497 sys.stdout.write("\n")
1498
Antoine Pitrou480a1242010-04-28 21:37:09 +00001499 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001500 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001501 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001502 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001503 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001504 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001505 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001506 " client: sending %r...\n" % indata)
1507 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001508 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001509 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001510 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001511 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001512 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001513 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1514 % (outdata[:20], len(outdata),
1515 indata[:20].lower(), len(indata)))
1516 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001517 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001518 sys.stdout.write(" client: closing connection.\n")
1519 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001520 if support.verbose:
1521 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001522
Antoine Pitrou480a1242010-04-28 21:37:09 +00001523 def test_recv_send(self):
1524 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001525 if support.verbose:
1526 sys.stdout.write("\n")
1527
1528 server = ThreadedEchoServer(CERTFILE,
1529 certreqs=ssl.CERT_NONE,
1530 ssl_version=ssl.PROTOCOL_TLSv1,
1531 cacerts=CERTFILE,
1532 chatty=True,
1533 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001534 with server:
1535 s = ssl.wrap_socket(socket.socket(),
1536 server_side=False,
1537 certfile=CERTFILE,
1538 ca_certs=CERTFILE,
1539 cert_reqs=ssl.CERT_NONE,
1540 ssl_version=ssl.PROTOCOL_TLSv1)
1541 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001542 # helper methods for standardising recv* method signatures
1543 def _recv_into():
1544 b = bytearray(b"\0"*100)
1545 count = s.recv_into(b)
1546 return b[:count]
1547
1548 def _recvfrom_into():
1549 b = bytearray(b"\0"*100)
1550 count, addr = s.recvfrom_into(b)
1551 return b[:count]
1552
1553 # (name, method, whether to expect success, *args)
1554 send_methods = [
1555 ('send', s.send, True, []),
1556 ('sendto', s.sendto, False, ["some.address"]),
1557 ('sendall', s.sendall, True, []),
1558 ]
1559 recv_methods = [
1560 ('recv', s.recv, True, []),
1561 ('recvfrom', s.recvfrom, False, ["some.address"]),
1562 ('recv_into', _recv_into, True, []),
1563 ('recvfrom_into', _recvfrom_into, False, []),
1564 ]
1565 data_prefix = "PREFIX_"
1566
1567 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001568 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001569 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001570 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001571 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001572 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001573 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001574 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001575 "<<{outdata:r}>> ({nout:d}) received; "
1576 "expected <<{indata:r}>> ({nin:d})\n".format(
1577 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001578 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001579 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001580 )
1581 )
1582 except ValueError as e:
1583 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001584 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001585 "Failed to send with method <<{name:s}>>; "
1586 "expected to succeed.\n".format(name=meth_name)
1587 )
1588 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001589 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001590 "Method <<{name:s}>> failed with unexpected "
1591 "exception message: {exp:s}\n".format(
1592 name=meth_name, exp=e
1593 )
1594 )
1595
1596 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001597 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001598 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001599 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001600 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001601 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001602 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001603 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001604 "<<{outdata:r}>> ({nout:d}) received; "
1605 "expected <<{indata:r}>> ({nin:d})\n".format(
1606 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001607 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001608 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001609 )
1610 )
1611 except ValueError as e:
1612 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001613 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001614 "Failed to receive with method <<{name:s}>>; "
1615 "expected to succeed.\n".format(name=meth_name)
1616 )
1617 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001618 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001619 "Method <<{name:s}>> failed with unexpected "
1620 "exception message: {exp:s}\n".format(
1621 name=meth_name, exp=e
1622 )
1623 )
1624 # consume data
1625 s.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001626 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001627 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001628
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001629 def test_handshake_timeout(self):
1630 # Issue #5103: SSL handshake must respect the socket timeout
1631 server = socket.socket(socket.AF_INET)
1632 host = "127.0.0.1"
1633 port = support.bind_port(server)
1634 started = threading.Event()
1635 finish = False
1636
1637 def serve():
1638 server.listen(5)
1639 started.set()
1640 conns = []
1641 while not finish:
1642 r, w, e = select.select([server], [], [], 0.1)
1643 if server in r:
1644 # Let the socket hang around rather than having
1645 # it closed by garbage collection.
1646 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001647 for sock in conns:
1648 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001649
1650 t = threading.Thread(target=serve)
1651 t.start()
1652 started.wait()
1653
1654 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001655 try:
1656 c = socket.socket(socket.AF_INET)
1657 c.settimeout(0.2)
1658 c.connect((host, port))
1659 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001660 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001661 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001662 finally:
1663 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001664 try:
1665 c = socket.socket(socket.AF_INET)
1666 c = ssl.wrap_socket(c)
1667 c.settimeout(0.2)
1668 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001669 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001670 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001671 finally:
1672 c.close()
1673 finally:
1674 finish = True
1675 t.join()
1676 server.close()
1677
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001678 def test_server_accept(self):
1679 # Issue #16357: accept() on a SSLSocket created through
1680 # SSLContext.wrap_socket().
1681 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1682 context.verify_mode = ssl.CERT_REQUIRED
1683 context.load_verify_locations(CERTFILE)
1684 context.load_cert_chain(CERTFILE)
1685 server = socket.socket(socket.AF_INET)
1686 host = "127.0.0.1"
1687 port = support.bind_port(server)
1688 server = context.wrap_socket(server, server_side=True)
1689
1690 evt = threading.Event()
1691 remote = None
1692 peer = None
1693 def serve():
1694 nonlocal remote, peer
1695 server.listen(5)
1696 # Block on the accept and wait on the connection to close.
1697 evt.set()
1698 remote, peer = server.accept()
1699 remote.recv(1)
1700
1701 t = threading.Thread(target=serve)
1702 t.start()
1703 # Client wait until server setup and perform a connect.
1704 evt.wait()
1705 client = context.wrap_socket(socket.socket())
1706 client.connect((host, port))
1707 client_addr = client.getsockname()
1708 client.close()
1709 t.join()
1710 # Sanity checks.
1711 self.assertIsInstance(remote, ssl.SSLSocket)
1712 self.assertEqual(peer, client_addr)
1713
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001714 def test_default_ciphers(self):
1715 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1716 try:
1717 # Force a set of weak ciphers on our client context
1718 context.set_ciphers("DES")
1719 except ssl.SSLError:
1720 self.skipTest("no DES cipher available")
1721 with ThreadedEchoServer(CERTFILE,
1722 ssl_version=ssl.PROTOCOL_SSLv23,
1723 chatty=False) as server:
1724 with socket.socket() as sock:
1725 s = context.wrap_socket(sock)
1726 with self.assertRaises((OSError, ssl.SSLError)):
1727 s.connect((HOST, server.port))
1728 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1729
Bill Janssen58afe4c2008-09-08 16:45:19 +00001730
Thomas Woutersed03b412007-08-28 21:37:11 +00001731def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001732 if support.verbose:
1733 plats = {
1734 'Linux': platform.linux_distribution,
1735 'Mac': platform.mac_ver,
1736 'Windows': platform.win32_ver,
1737 }
1738 for name, func in plats.items():
1739 plat = func()
1740 if plat and plat[0]:
1741 plat = '%s %r' % (name, plat)
1742 break
1743 else:
1744 plat = repr(platform.platform())
1745 print("test_ssl: testing with %r %r" %
1746 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1747 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001748 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001749
Antoine Pitrou152efa22010-05-16 18:19:27 +00001750 for filename in [
Martin Panter3d81d932016-01-14 09:36:00 +00001751 CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00001752 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1753 BADCERT, BADKEY, EMPTYCERT]:
1754 if not os.path.exists(filename):
1755 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001756
Antoine Pitrou152efa22010-05-16 18:19:27 +00001757 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001758
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001759 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001760 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001761
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001762 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001763 thread_info = support.threading_setup()
1764 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001765 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001766
Antoine Pitrou480a1242010-04-28 21:37:09 +00001767 try:
1768 support.run_unittest(*tests)
1769 finally:
1770 if _have_threads:
1771 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001772
1773if __name__ == "__main__":
1774 test_main()