blob: d1cb3f1b84cd70d8bdb6e039c532c501fa49d2b9 [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
32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Antoine Pitrou81564092010-10-08 23:06:24 +000034# The custom key and certificate files used in test_ssl are generated
35# using Lib/test/make_ssl_certs.py.
36# Other certificates are simply fetched from the Internet servers they
37# are meant to authenticate.
38
Antoine Pitrou152efa22010-05-16 18:19:27 +000039CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020054NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056
Thomas Woutersed03b412007-08-28 21:37:11 +000057def handle_error(prefix):
58 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000059 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000060 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000061
Antoine Pitroub5218772010-05-21 09:56:06 +000062def can_clear_options():
63 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020064 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000065
66def no_sslv2_implies_sslv3_hello():
67 # 0.9.7h or higher
68 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
69
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitrou23df4832010-08-04 17:14:06 +000071# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
72def skip_if_broken_ubuntu_ssl(func):
Victor Stinner17ca3232011-05-10 00:48:41 +020073 if hasattr(ssl, 'PROTOCOL_SSLv2'):
74 @functools.wraps(func)
75 def f(*args, **kwargs):
76 try:
77 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
78 except ssl.SSLError:
79 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
80 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
81 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
82 return func(*args, **kwargs)
83 return f
84 else:
85 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000086
87
Antoine Pitrou152efa22010-05-16 18:19:27 +000088class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000089
Antoine Pitrou480a1242010-04-28 21:37:09 +000090 def test_constants(self):
Victor Stinneree18b6f2011-05-10 00:38:00 +020091 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000092 ssl.PROTOCOL_SSLv23
93 ssl.PROTOCOL_SSLv3
94 ssl.PROTOCOL_TLSv1
95 ssl.CERT_NONE
96 ssl.CERT_OPTIONAL
97 ssl.CERT_REQUIRED
Antoine Pitroud5323212010-10-22 18:19:07 +000098 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +000099
Antoine Pitrou480a1242010-04-28 21:37:09 +0000100 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000102 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000103 sys.stdout.write("\n RAND_status is %d (%s)\n"
104 % (v, (v and "sufficient randomness") or
105 "insufficient randomness"))
Jesus Ceac8754a12012-09-11 02:00:58 +0200106 self.assertRaises(TypeError, ssl.RAND_egd, 1)
107 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000108 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000109
Antoine Pitrou480a1242010-04-28 21:37:09 +0000110 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000111 # note that this uses an 'unofficial' function in _ssl.c,
112 # provided solely for this test, to exercise the certificate
113 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000114 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000115 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000116 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200117 self.assertEqual(p['issuer'],
118 ((('countryName', 'XY'),),
119 (('localityName', 'Castle Anthrax'),),
120 (('organizationName', 'Python Software Foundation'),),
121 (('commonName', 'localhost'),))
122 )
123 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
124 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
125 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
126 self.assertEqual(p['subject'],
127 ((('countryName', 'XY'),),
128 (('localityName', 'Castle Anthrax'),),
129 (('organizationName', 'Python Software Foundation'),),
130 (('commonName', 'localhost'),))
131 )
132 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
133 # Issue #13034: the subjectAltName in some certificates
134 # (notably projects.developer.nokia.com:443) wasn't parsed
135 p = ssl._ssl._test_decode_cert(NOKIACERT)
136 if support.verbose:
137 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
138 self.assertEqual(p['subjectAltName'],
139 (('DNS', 'projects.developer.nokia.com'),
140 ('DNS', 'projects.forum.nokia.com'))
141 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000142
Antoine Pitrou480a1242010-04-28 21:37:09 +0000143 def test_DER_to_PEM(self):
144 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
145 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000146 d1 = ssl.PEM_cert_to_DER_cert(pem)
147 p2 = ssl.DER_cert_to_PEM_cert(d1)
148 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000149 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000150 if not p2.startswith(ssl.PEM_HEADER + '\n'):
151 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
152 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
153 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000154
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000155 def test_openssl_version(self):
156 n = ssl.OPENSSL_VERSION_NUMBER
157 t = ssl.OPENSSL_VERSION_INFO
158 s = ssl.OPENSSL_VERSION
159 self.assertIsInstance(n, int)
160 self.assertIsInstance(t, tuple)
161 self.assertIsInstance(s, str)
162 # Some sanity checks follow
163 # >= 0.9
164 self.assertGreaterEqual(n, 0x900000)
165 # < 2.0
166 self.assertLess(n, 0x20000000)
167 major, minor, fix, patch, status = t
168 self.assertGreaterEqual(major, 0)
169 self.assertLess(major, 2)
170 self.assertGreaterEqual(minor, 0)
171 self.assertLess(minor, 256)
172 self.assertGreaterEqual(fix, 0)
173 self.assertLess(fix, 256)
174 self.assertGreaterEqual(patch, 0)
175 self.assertLessEqual(patch, 26)
176 self.assertGreaterEqual(status, 0)
177 self.assertLessEqual(status, 15)
178 # Version string as returned by OpenSSL, the format might change
179 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
180 (s, t))
181
Antoine Pitrou9d543662010-04-23 23:10:32 +0000182 @support.cpython_only
183 def test_refcycle(self):
184 # Issue #7943: an SSL object doesn't create reference cycles with
185 # itself.
186 s = socket.socket(socket.AF_INET)
187 ss = ssl.wrap_socket(s)
188 wr = weakref.ref(ss)
189 del ss
190 self.assertEqual(wr(), None)
191
Antoine Pitroua468adc2010-09-14 14:43:44 +0000192 def test_wrapped_unconnected(self):
193 # Methods on an unconnected SSLSocket propagate the original
194 # socket.error raise by the underlying socket object.
195 s = socket.socket(socket.AF_INET)
196 ss = ssl.wrap_socket(s)
197 self.assertRaises(socket.error, ss.recv, 1)
198 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
199 self.assertRaises(socket.error, ss.recvfrom, 1)
200 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
201 self.assertRaises(socket.error, ss.send, b'x')
202 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
203
Antoine Pitrou40f08742010-04-24 22:04:40 +0000204 def test_timeout(self):
205 # Issue #8524: when creating an SSL socket, the timeout of the
206 # original socket should be retained.
207 for timeout in (None, 0.0, 5.0):
208 s = socket.socket(socket.AF_INET)
209 s.settimeout(timeout)
210 ss = ssl.wrap_socket(s)
211 self.assertEqual(timeout, ss.gettimeout())
212
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000213 def test_errors(self):
214 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000215 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000216 "certfile must be specified",
217 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000218 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000219 "certfile must be specified for server-side operations",
220 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000221 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000222 "certfile must be specified for server-side operations",
223 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000224 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000225 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000226 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000227 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000228 with socket.socket() as sock:
229 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000230 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000231 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000232 with socket.socket() as sock:
233 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000234 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000235 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000236 with socket.socket() as sock:
237 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000238 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000239
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000240 def test_match_hostname(self):
241 def ok(cert, hostname):
242 ssl.match_hostname(cert, hostname)
243 def fail(cert, hostname):
244 self.assertRaises(ssl.CertificateError,
245 ssl.match_hostname, cert, hostname)
246
247 cert = {'subject': ((('commonName', 'example.com'),),)}
248 ok(cert, 'example.com')
249 ok(cert, 'ExAmple.cOm')
250 fail(cert, 'www.example.com')
251 fail(cert, '.example.com')
252 fail(cert, 'example.org')
253 fail(cert, 'exampleXcom')
254
255 cert = {'subject': ((('commonName', '*.a.com'),),)}
256 ok(cert, 'foo.a.com')
257 fail(cert, 'bar.foo.a.com')
258 fail(cert, 'a.com')
259 fail(cert, 'Xa.com')
260 fail(cert, '.a.com')
261
262 cert = {'subject': ((('commonName', 'a.*.com'),),)}
263 ok(cert, 'a.foo.com')
264 fail(cert, 'a..com')
265 fail(cert, 'a.com')
266
267 cert = {'subject': ((('commonName', 'f*.com'),),)}
268 ok(cert, 'foo.com')
269 ok(cert, 'f.com')
270 fail(cert, 'bar.com')
271 fail(cert, 'foo.a.com')
272 fail(cert, 'bar.foo.com')
273
274 # Slightly fake real-world example
275 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
276 'subject': ((('commonName', 'linuxfrz.org'),),),
277 'subjectAltName': (('DNS', 'linuxfr.org'),
278 ('DNS', 'linuxfr.com'),
279 ('othername', '<unsupported>'))}
280 ok(cert, 'linuxfr.org')
281 ok(cert, 'linuxfr.com')
282 # Not a "DNS" entry
283 fail(cert, '<unsupported>')
284 # When there is a subjectAltName, commonName isn't used
285 fail(cert, 'linuxfrz.org')
286
287 # A pristine real-world example
288 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
289 'subject': ((('countryName', 'US'),),
290 (('stateOrProvinceName', 'California'),),
291 (('localityName', 'Mountain View'),),
292 (('organizationName', 'Google Inc'),),
293 (('commonName', 'mail.google.com'),))}
294 ok(cert, 'mail.google.com')
295 fail(cert, 'gmail.com')
296 # Only commonName is considered
297 fail(cert, 'California')
298
299 # Neither commonName nor subjectAltName
300 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
301 'subject': ((('countryName', 'US'),),
302 (('stateOrProvinceName', 'California'),),
303 (('localityName', 'Mountain View'),),
304 (('organizationName', 'Google Inc'),))}
305 fail(cert, 'mail.google.com')
306
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200307 # No DNS entry in subjectAltName but a commonName
308 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
309 'subject': ((('countryName', 'US'),),
310 (('stateOrProvinceName', 'California'),),
311 (('localityName', 'Mountain View'),),
312 (('commonName', 'mail.google.com'),)),
313 'subjectAltName': (('othername', 'blabla'), )}
314 ok(cert, 'mail.google.com')
315
316 # No DNS entry subjectAltName and no commonName
317 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
318 'subject': ((('countryName', 'US'),),
319 (('stateOrProvinceName', 'California'),),
320 (('localityName', 'Mountain View'),),
321 (('organizationName', 'Google Inc'),)),
322 'subjectAltName': (('othername', 'blabla'),)}
323 fail(cert, 'google.com')
324
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000325 # Empty cert / no cert
326 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
327 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
328
Antoine Pitroud5323212010-10-22 18:19:07 +0000329 def test_server_side(self):
330 # server_hostname doesn't work for server sockets
331 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000332 with socket.socket() as sock:
333 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
334 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000335
Antoine Pitrou152efa22010-05-16 18:19:27 +0000336class ContextTests(unittest.TestCase):
337
Antoine Pitrou23df4832010-08-04 17:14:06 +0000338 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000339 def test_constructor(self):
Victor Stinner17ca3232011-05-10 00:48:41 +0200340 if hasattr(ssl, 'PROTOCOL_SSLv2'):
341 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000342 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
343 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
344 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
345 self.assertRaises(TypeError, ssl.SSLContext)
346 self.assertRaises(ValueError, ssl.SSLContext, -1)
347 self.assertRaises(ValueError, ssl.SSLContext, 42)
348
Antoine Pitrou23df4832010-08-04 17:14:06 +0000349 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000350 def test_protocol(self):
351 for proto in PROTOCOLS:
352 ctx = ssl.SSLContext(proto)
353 self.assertEqual(ctx.protocol, proto)
354
355 def test_ciphers(self):
356 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
357 ctx.set_ciphers("ALL")
358 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000359 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000360 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000361
Antoine Pitrou23df4832010-08-04 17:14:06 +0000362 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000363 def test_options(self):
364 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
365 # OP_ALL is the default value
366 self.assertEqual(ssl.OP_ALL, ctx.options)
367 ctx.options |= ssl.OP_NO_SSLv2
368 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
369 ctx.options)
370 ctx.options |= ssl.OP_NO_SSLv3
371 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
372 ctx.options)
373 if can_clear_options():
374 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
375 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
376 ctx.options)
377 ctx.options = 0
378 self.assertEqual(0, ctx.options)
379 else:
380 with self.assertRaises(ValueError):
381 ctx.options = 0
382
Antoine Pitrou152efa22010-05-16 18:19:27 +0000383 def test_verify(self):
384 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
385 # Default value
386 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
387 ctx.verify_mode = ssl.CERT_OPTIONAL
388 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
389 ctx.verify_mode = ssl.CERT_REQUIRED
390 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
391 ctx.verify_mode = ssl.CERT_NONE
392 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
393 with self.assertRaises(TypeError):
394 ctx.verify_mode = None
395 with self.assertRaises(ValueError):
396 ctx.verify_mode = 42
397
398 def test_load_cert_chain(self):
399 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
400 # Combined key and cert in a single file
401 ctx.load_cert_chain(CERTFILE)
402 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
403 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000404 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000405 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000406 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000407 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000408 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000409 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000410 ctx.load_cert_chain(EMPTYCERT)
411 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000412 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000413 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
414 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
415 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000416 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000417 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000418 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000419 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000420 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000421 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
422 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000423 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000424 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000425 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000426
427 def test_load_verify_locations(self):
428 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
429 ctx.load_verify_locations(CERTFILE)
430 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
431 ctx.load_verify_locations(BYTES_CERTFILE)
432 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
433 self.assertRaises(TypeError, ctx.load_verify_locations)
434 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000435 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000436 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000437 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000438 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000439 ctx.load_verify_locations(BADCERT)
440 ctx.load_verify_locations(CERTFILE, CAPATH)
441 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
442
Victor Stinner80f75e62011-01-29 11:31:20 +0000443 # Issue #10989: crash if the second argument type is invalid
444 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
445
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000446 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000447 def test_session_stats(self):
448 for proto in PROTOCOLS:
449 ctx = ssl.SSLContext(proto)
450 self.assertEqual(ctx.session_stats(), {
451 'number': 0,
452 'connect': 0,
453 'connect_good': 0,
454 'connect_renegotiate': 0,
455 'accept': 0,
456 'accept_good': 0,
457 'accept_renegotiate': 0,
458 'hits': 0,
459 'misses': 0,
460 'timeouts': 0,
461 'cache_full': 0,
462 })
463
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000464 def test_set_default_verify_paths(self):
465 # There's not much we can do to test that it acts as expected,
466 # so just check it doesn't crash or raise an exception.
467 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
468 ctx.set_default_verify_paths()
469
Antoine Pitrou152efa22010-05-16 18:19:27 +0000470
Bill Janssen6e027db2007-11-15 22:23:56 +0000471class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000472
Antoine Pitrou480a1242010-04-28 21:37:09 +0000473 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000474 with support.transient_internet("svn.python.org"):
475 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
476 cert_reqs=ssl.CERT_NONE)
477 try:
478 s.connect(("svn.python.org", 443))
479 self.assertEqual({}, s.getpeercert())
480 finally:
481 s.close()
482
483 # this should fail because we have no verification certs
484 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
485 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000486 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
487 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000488 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000489
Antoine Pitrou350c7222010-09-09 13:31:46 +0000490 # this should succeed because we specify the root cert
491 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
492 cert_reqs=ssl.CERT_REQUIRED,
493 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
494 try:
495 s.connect(("svn.python.org", 443))
496 self.assertTrue(s.getpeercert())
497 finally:
498 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000499
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000500 def test_connect_ex(self):
501 # Issue #11326: check connect_ex() implementation
502 with support.transient_internet("svn.python.org"):
503 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
504 cert_reqs=ssl.CERT_REQUIRED,
505 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
506 try:
507 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
508 self.assertTrue(s.getpeercert())
509 finally:
510 s.close()
511
512 def test_non_blocking_connect_ex(self):
513 # Issue #11326: non-blocking connect_ex() should allow handshake
514 # to proceed after the socket gets ready.
515 with support.transient_internet("svn.python.org"):
516 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
517 cert_reqs=ssl.CERT_REQUIRED,
518 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
519 do_handshake_on_connect=False)
520 try:
521 s.setblocking(False)
522 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitroud1c98452011-02-27 15:45:16 +0000523 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
524 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000525 # Wait for connect to finish
526 select.select([], [s], [], 5.0)
527 # Non-blocking handshake
528 while True:
529 try:
530 s.do_handshake()
531 break
532 except ssl.SSLError as err:
533 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
534 select.select([s], [], [], 5.0)
535 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
536 select.select([], [s], [], 5.0)
537 else:
538 raise
539 # SSL established
540 self.assertTrue(s.getpeercert())
541 finally:
542 s.close()
543
Antoine Pitroub4410db2011-05-18 18:51:06 +0200544 def test_timeout_connect_ex(self):
545 # Issue #12065: on a timeout, connect_ex() should return the original
546 # errno (mimicking the behaviour of non-SSL sockets).
547 with support.transient_internet("svn.python.org"):
548 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
549 cert_reqs=ssl.CERT_REQUIRED,
550 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
551 do_handshake_on_connect=False)
552 try:
553 s.settimeout(0.0000001)
554 rc = s.connect_ex(('svn.python.org', 443))
555 if rc == 0:
556 self.skipTest("svn.python.org responded too quickly")
557 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
558 finally:
559 s.close()
560
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100561 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100562 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100563 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
564 cert_reqs=ssl.CERT_REQUIRED,
565 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
566 try:
567 self.assertEqual(errno.ECONNREFUSED,
568 s.connect_ex(("svn.python.org", 444)))
569 finally:
570 s.close()
571
Antoine Pitrou152efa22010-05-16 18:19:27 +0000572 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000573 with support.transient_internet("svn.python.org"):
574 # Same as test_connect, but with a separately created context
575 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
576 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
577 s.connect(("svn.python.org", 443))
578 try:
579 self.assertEqual({}, s.getpeercert())
580 finally:
581 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000582 # Same with a server hostname
583 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
584 server_hostname="svn.python.org")
585 if ssl.HAS_SNI:
586 s.connect(("svn.python.org", 443))
587 s.close()
588 else:
589 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000590 # This should fail because we have no verification certs
591 ctx.verify_mode = ssl.CERT_REQUIRED
592 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000593 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000594 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000595 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000596 # This should succeed because we specify the root cert
597 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
598 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
599 s.connect(("svn.python.org", 443))
600 try:
601 cert = s.getpeercert()
602 self.assertTrue(cert)
603 finally:
604 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000605
606 def test_connect_capath(self):
607 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000608 # NOTE: the subject hashing algorithm has been changed between
609 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
610 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000611 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000612 with support.transient_internet("svn.python.org"):
613 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
614 ctx.verify_mode = ssl.CERT_REQUIRED
615 ctx.load_verify_locations(capath=CAPATH)
616 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
617 s.connect(("svn.python.org", 443))
618 try:
619 cert = s.getpeercert()
620 self.assertTrue(cert)
621 finally:
622 s.close()
623 # Same with a bytes `capath` argument
624 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
625 ctx.verify_mode = ssl.CERT_REQUIRED
626 ctx.load_verify_locations(capath=BYTES_CAPATH)
627 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
628 s.connect(("svn.python.org", 443))
629 try:
630 cert = s.getpeercert()
631 self.assertTrue(cert)
632 finally:
633 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000634
Antoine Pitroue3220242010-04-24 11:13:53 +0000635 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
636 def test_makefile_close(self):
637 # Issue #5238: creating a file-like object with makefile() shouldn't
638 # delay closing the underlying "real socket" (here tested with its
639 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000640 with support.transient_internet("svn.python.org"):
641 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
642 ss.connect(("svn.python.org", 443))
643 fd = ss.fileno()
644 f = ss.makefile()
645 f.close()
646 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000647 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000648 # Closing the SSL socket should close the fd too
649 ss.close()
650 gc.collect()
651 with self.assertRaises(OSError) as e:
652 os.read(fd, 0)
653 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000654
Antoine Pitrou480a1242010-04-28 21:37:09 +0000655 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000656 with support.transient_internet("svn.python.org"):
657 s = socket.socket(socket.AF_INET)
658 s.connect(("svn.python.org", 443))
659 s.setblocking(False)
660 s = ssl.wrap_socket(s,
661 cert_reqs=ssl.CERT_NONE,
662 do_handshake_on_connect=False)
663 count = 0
664 while True:
665 try:
666 count += 1
667 s.do_handshake()
668 break
669 except ssl.SSLError as err:
670 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
671 select.select([s], [], [])
672 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
673 select.select([], [s], [])
674 else:
675 raise
676 s.close()
677 if support.verbose:
678 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000679
Antoine Pitrou480a1242010-04-28 21:37:09 +0000680 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000681 with support.transient_internet("svn.python.org"):
682 pem = ssl.get_server_certificate(("svn.python.org", 443))
683 if not pem:
684 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000685
Antoine Pitrou350c7222010-09-09 13:31:46 +0000686 try:
687 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
688 except ssl.SSLError as x:
689 #should fail
690 if support.verbose:
691 sys.stdout.write("%s\n" % x)
692 else:
693 self.fail("Got server certificate %s for svn.python.org!" % pem)
694
695 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
696 if not pem:
697 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000698 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000699 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000700
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000701 def test_ciphers(self):
702 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000703 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000704 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000705 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000706 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000707 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
708 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
709 s.connect(remote)
710 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000711 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000712 with socket.socket(socket.AF_INET) as sock:
713 s = ssl.wrap_socket(sock,
714 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
715 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000716
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000717 def test_algorithms(self):
718 # Issue #8484: all algorithms should be available when verifying a
719 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000720 # SHA256 was added in OpenSSL 0.9.8
721 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
722 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200723 # sha256.tbs-internet.com needs SNI to use the correct certificate
724 if not ssl.HAS_SNI:
725 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000726 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
727 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000728 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000729 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200730 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
731 ctx.verify_mode = ssl.CERT_REQUIRED
732 ctx.load_verify_locations(sha256_cert)
733 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
734 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000735 try:
736 s.connect(remote)
737 if support.verbose:
738 sys.stdout.write("\nCipher with %r is %r\n" %
739 (remote, s.cipher()))
740 sys.stdout.write("Certificate is:\n%s\n" %
741 pprint.pformat(s.getpeercert()))
742 finally:
743 s.close()
744
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000745
746try:
747 import threading
748except ImportError:
749 _have_threads = False
750else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000751 _have_threads = True
752
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000753 from test.ssl_servers import make_https_server
754
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000755 class ThreadedEchoServer(threading.Thread):
756
757 class ConnectionHandler(threading.Thread):
758
759 """A mildly complicated class, because we want it to work both
760 with and without the SSL wrapper around the socket connection, so
761 that we can test the STARTTLS functionality."""
762
Bill Janssen6e027db2007-11-15 22:23:56 +0000763 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000764 self.server = server
765 self.running = False
766 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000767 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000768 self.sock.setblocking(1)
769 self.sslconn = None
770 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000771 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000772
Antoine Pitrou480a1242010-04-28 21:37:09 +0000773 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000774 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000775 self.sslconn = self.server.context.wrap_socket(
776 self.sock, server_side=True)
Nadeem Vawda7b39b9b2013-03-03 22:31:21 +0100777 except (ssl.SSLError, socket.error) as e:
778 # Treat ECONNRESET as though it were an SSLError - OpenSSL
779 # on Ubuntu abruptly closes the connection when asked to use
780 # an unsupported protocol.
781 if (not isinstance(e, ssl.SSLError) and
782 e.errno != errno.ECONNRESET):
783 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000784 # XXX Various errors can have happened here, for example
785 # a mismatching protocol version, an invalid certificate,
786 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100787 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000788 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000789 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000790 self.running = False
791 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000792 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000793 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000794 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000795 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000796 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000797 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000798 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
799 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000800 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000801 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
802 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000803 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000804 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
805 return True
806
807 def read(self):
808 if self.sslconn:
809 return self.sslconn.read()
810 else:
811 return self.sock.recv(1024)
812
813 def write(self, bytes):
814 if self.sslconn:
815 return self.sslconn.write(bytes)
816 else:
817 return self.sock.send(bytes)
818
819 def close(self):
820 if self.sslconn:
821 self.sslconn.close()
822 else:
823 self.sock.close()
824
Antoine Pitrou480a1242010-04-28 21:37:09 +0000825 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000826 self.running = True
827 if not self.server.starttls_server:
828 if not self.wrap_conn():
829 return
830 while self.running:
831 try:
832 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000833 stripped = msg.strip()
834 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000835 # eof, so quit this handler
836 self.running = False
837 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000838 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000839 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000840 sys.stdout.write(" server: client closed connection\n")
841 self.close()
842 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000843 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000844 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000845 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000847 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848 if not self.wrap_conn():
849 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000850 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000851 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000852 if support.verbose and self.server.connectionchatty:
853 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000854 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000855 self.sock = self.sslconn.unwrap()
856 self.sslconn = None
857 if support.verbose and self.server.connectionchatty:
858 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000859 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000860 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 self.server.connectionchatty):
862 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000863 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
864 % (msg, ctype, msg.lower(), ctype))
865 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000866 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000867 if self.server.chatty:
868 handle_error("Test server failure:\n")
869 self.close()
870 self.running = False
871 # normally, we'd just stop here, but for the test
872 # harness, we want to stop the server
873 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000874
Antoine Pitroub5218772010-05-21 09:56:06 +0000875 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000876 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000877 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000878 ciphers=None, context=None):
879 if context:
880 self.context = context
881 else:
882 self.context = ssl.SSLContext(ssl_version
883 if ssl_version is not None
884 else ssl.PROTOCOL_TLSv1)
885 self.context.verify_mode = (certreqs if certreqs is not None
886 else ssl.CERT_NONE)
887 if cacerts:
888 self.context.load_verify_locations(cacerts)
889 if certificate:
890 self.context.load_cert_chain(certificate)
891 if ciphers:
892 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000893 self.chatty = chatty
894 self.connectionchatty = connectionchatty
895 self.starttls_server = starttls_server
896 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000897 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000899 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100900 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000901 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000902 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100904 def __enter__(self):
905 self.start(threading.Event())
906 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100907 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100908
909 def __exit__(self, *args):
910 self.stop()
911 self.join()
912
Antoine Pitrou480a1242010-04-28 21:37:09 +0000913 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000914 self.flag = flag
915 threading.Thread.start(self)
916
Antoine Pitrou480a1242010-04-28 21:37:09 +0000917 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000918 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919 self.sock.listen(5)
920 self.active = True
921 if self.flag:
922 # signal an event
923 self.flag.set()
924 while self.active:
925 try:
926 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000927 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000928 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000929 + repr(connaddr) + '\n')
930 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000931 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +0100932 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 except socket.timeout:
934 pass
935 except KeyboardInterrupt:
936 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000937 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938
Antoine Pitrou480a1242010-04-28 21:37:09 +0000939 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000940 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941
Bill Janssen54cc54c2007-12-14 22:08:56 +0000942 class AsyncoreEchoServer(threading.Thread):
943
944 # this one's based on asyncore.dispatcher
945
946 class EchoServer (asyncore.dispatcher):
947
948 class ConnectionHandler (asyncore.dispatcher_with_send):
949
950 def __init__(self, conn, certfile):
951 self.socket = ssl.wrap_socket(conn, server_side=True,
952 certfile=certfile,
953 do_handshake_on_connect=False)
954 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000955 self._ssl_accepting = True
956 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000957
958 def readable(self):
959 if isinstance(self.socket, ssl.SSLSocket):
960 while self.socket.pending() > 0:
961 self.handle_read_event()
962 return True
963
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000964 def _do_ssl_handshake(self):
965 try:
966 self.socket.do_handshake()
967 except ssl.SSLError as err:
968 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
969 ssl.SSL_ERROR_WANT_WRITE):
970 return
971 elif err.args[0] == ssl.SSL_ERROR_EOF:
972 return self.handle_close()
973 raise
974 except socket.error as err:
975 if err.args[0] == errno.ECONNABORTED:
976 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000977 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000978 self._ssl_accepting = False
979
980 def handle_read(self):
981 if self._ssl_accepting:
982 self._do_ssl_handshake()
983 else:
984 data = self.recv(1024)
985 if support.verbose:
986 sys.stdout.write(" server: read %s from client\n" % repr(data))
987 if not data:
988 self.close()
989 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000990 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000991
992 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000993 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000994 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000995 sys.stdout.write(" server: closed connection %s\n" % self.socket)
996
997 def handle_error(self):
998 raise
999
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001000 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001001 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001002 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1003 self.port = support.bind_port(sock, '')
1004 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001005 self.listen(5)
1006
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001007 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001008 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001009 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1010 self.ConnectionHandler(sock_obj, self.certfile)
1011
1012 def handle_error(self):
1013 raise
1014
Trent Nelson78520002008-04-10 20:54:35 +00001015 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001016 self.flag = None
1017 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001018 self.server = self.EchoServer(certfile)
1019 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001020 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001021 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001022
1023 def __str__(self):
1024 return "<%s %s>" % (self.__class__.__name__, self.server)
1025
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001026 def __enter__(self):
1027 self.start(threading.Event())
1028 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001029 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001030
1031 def __exit__(self, *args):
1032 if support.verbose:
1033 sys.stdout.write(" cleanup: stopping server.\n")
1034 self.stop()
1035 if support.verbose:
1036 sys.stdout.write(" cleanup: joining server thread.\n")
1037 self.join()
1038 if support.verbose:
1039 sys.stdout.write(" cleanup: successfully joined.\n")
1040
Bill Janssen54cc54c2007-12-14 22:08:56 +00001041 def start (self, flag=None):
1042 self.flag = flag
1043 threading.Thread.start(self)
1044
Antoine Pitrou480a1242010-04-28 21:37:09 +00001045 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001046 self.active = True
1047 if self.flag:
1048 self.flag.set()
1049 while self.active:
1050 try:
1051 asyncore.loop(1)
1052 except:
1053 pass
1054
Antoine Pitrou480a1242010-04-28 21:37:09 +00001055 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001056 self.active = False
1057 self.server.close()
1058
Antoine Pitrou480a1242010-04-28 21:37:09 +00001059 def bad_cert_test(certfile):
1060 """
1061 Launch a server with CERT_REQUIRED, and check that trying to
1062 connect to it with the given client certificate fails.
1063 """
Trent Nelson78520002008-04-10 20:54:35 +00001064 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001065 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001066 cacerts=CERTFILE, chatty=False,
1067 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001068 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001069 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001070 with socket.socket() as sock:
1071 s = ssl.wrap_socket(sock,
1072 certfile=certfile,
1073 ssl_version=ssl.PROTOCOL_TLSv1)
1074 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001075 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001076 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001077 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001078 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001079 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001080 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001081 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001082 if x.errno != errno.ENOENT:
1083 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001084 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001085 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001086 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001087 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001088
Antoine Pitroub5218772010-05-21 09:56:06 +00001089 def server_params_test(client_context, server_context, indata=b"FOO\n",
1090 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 """
1092 Launch a server, connect a client to it and try various reads
1093 and writes.
1094 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001095 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001096 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001097 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001098 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001099 with client_context.wrap_socket(socket.socket()) as s:
1100 s.connect((HOST, server.port))
1101 for arg in [indata, bytearray(indata), memoryview(indata)]:
1102 if connectionchatty:
1103 if support.verbose:
1104 sys.stdout.write(
1105 " client: sending %r...\n" % indata)
1106 s.write(arg)
1107 outdata = s.read()
1108 if connectionchatty:
1109 if support.verbose:
1110 sys.stdout.write(" client: read %r\n" % outdata)
1111 if outdata != indata.lower():
1112 raise AssertionError(
1113 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1114 % (outdata[:20], len(outdata),
1115 indata[:20].lower(), len(indata)))
1116 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001117 if connectionchatty:
1118 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001119 sys.stdout.write(" client: closing connection.\n")
1120 s.close()
Thomas Woutersed03b412007-08-28 21:37:11 +00001121
Antoine Pitroub5218772010-05-21 09:56:06 +00001122 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1123 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001124 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001125 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001126 certtype = {
1127 ssl.CERT_NONE: "CERT_NONE",
1128 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1129 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1130 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001131 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001132 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001133 sys.stdout.write(formatstr %
1134 (ssl.get_protocol_name(client_protocol),
1135 ssl.get_protocol_name(server_protocol),
1136 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001137 client_context = ssl.SSLContext(client_protocol)
1138 client_context.options = ssl.OP_ALL | client_options
1139 server_context = ssl.SSLContext(server_protocol)
1140 server_context.options = ssl.OP_ALL | server_options
1141 for ctx in (client_context, server_context):
1142 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001143 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1144 # will send an SSLv3 hello (rather than SSLv2) starting from
1145 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001146 ctx.set_ciphers("ALL")
1147 ctx.load_cert_chain(CERTFILE)
1148 ctx.load_verify_locations(CERTFILE)
1149 try:
1150 server_params_test(client_context, server_context,
1151 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001152 # Protocol mismatch can result in either an SSLError, or a
1153 # "Connection reset by peer" error.
1154 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001155 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001157 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001158 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001159 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001160 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001161 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001162 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163 "Client protocol %s succeeded with server protocol %s!"
1164 % (ssl.get_protocol_name(client_protocol),
1165 ssl.get_protocol_name(server_protocol)))
1166
1167
Bill Janssen6e027db2007-11-15 22:23:56 +00001168 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001169
Antoine Pitrou23df4832010-08-04 17:14:06 +00001170 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001171 def test_echo(self):
1172 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001173 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001175 for protocol in PROTOCOLS:
1176 context = ssl.SSLContext(protocol)
1177 context.load_cert_chain(CERTFILE)
1178 server_params_test(context, context,
1179 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001180
Antoine Pitrou480a1242010-04-28 21:37:09 +00001181 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001182 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001183 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001184 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1185 context.verify_mode = ssl.CERT_REQUIRED
1186 context.load_verify_locations(CERTFILE)
1187 context.load_cert_chain(CERTFILE)
1188 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001189 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001190 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001191 s.connect((HOST, server.port))
1192 cert = s.getpeercert()
1193 self.assertTrue(cert, "Can't get peer certificate.")
1194 cipher = s.cipher()
1195 if support.verbose:
1196 sys.stdout.write(pprint.pformat(cert) + '\n')
1197 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1198 if 'subject' not in cert:
1199 self.fail("No subject field in certificate: %s." %
1200 pprint.pformat(cert))
1201 if ((('organizationName', 'Python Software Foundation'),)
1202 not in cert['subject']):
1203 self.fail(
1204 "Missing or invalid 'organizationName' field in certificate subject; "
1205 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001206 self.assertIn('notBefore', cert)
1207 self.assertIn('notAfter', cert)
1208 before = ssl.cert_time_to_seconds(cert['notBefore'])
1209 after = ssl.cert_time_to_seconds(cert['notAfter'])
1210 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001211 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001212
Antoine Pitrou480a1242010-04-28 21:37:09 +00001213 def test_empty_cert(self):
1214 """Connecting with an empty cert file"""
1215 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1216 "nullcert.pem"))
1217 def test_malformed_cert(self):
1218 """Connecting with a badly formatted certificate (syntax error)"""
1219 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1220 "badcert.pem"))
1221 def test_nonexisting_cert(self):
1222 """Connecting with a non-existing cert file"""
1223 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1224 "wrongcert.pem"))
1225 def test_malformed_key(self):
1226 """Connecting with a badly formatted key (syntax error)"""
1227 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1228 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001229
Antoine Pitrou480a1242010-04-28 21:37:09 +00001230 def test_rude_shutdown(self):
1231 """A brutal shutdown of an SSL server should raise an IOError
1232 in the client when attempting handshake.
1233 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001234 listener_ready = threading.Event()
1235 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001236
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001237 s = socket.socket()
1238 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001239
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001240 # `listener` runs in a thread. It sits in an accept() until
1241 # the main thread connects. Then it rudely closes the socket,
1242 # and sets Event `listener_gone` to let the main thread know
1243 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001244 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001245 s.listen(5)
1246 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001247 newsock, addr = s.accept()
1248 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001249 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001250 listener_gone.set()
1251
1252 def connector():
1253 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001254 with socket.socket() as c:
1255 c.connect((HOST, port))
1256 listener_gone.wait()
1257 try:
1258 ssl_sock = ssl.wrap_socket(c)
1259 except IOError:
1260 pass
1261 else:
1262 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001263
1264 t = threading.Thread(target=listener)
1265 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001266 try:
1267 connector()
1268 finally:
1269 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001270
Antoine Pitrou23df4832010-08-04 17:14:06 +00001271 @skip_if_broken_ubuntu_ssl
Victor Stinneree18b6f2011-05-10 00:38:00 +02001272 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001273 def test_protocol_sslv2(self):
1274 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001275 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001276 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001277 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1278 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1279 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1280 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1281 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1282 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001283 # SSLv23 client with specific SSL options
1284 if no_sslv2_implies_sslv3_hello():
1285 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1286 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1287 client_options=ssl.OP_NO_SSLv2)
1288 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1289 client_options=ssl.OP_NO_SSLv3)
1290 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1291 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001292
Antoine Pitrou23df4832010-08-04 17:14:06 +00001293 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001294 def test_protocol_sslv23(self):
1295 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001296 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001297 sys.stdout.write("\n")
Victor Stinneree18b6f2011-05-10 00:38:00 +02001298 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1299 try:
1300 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1301 except (ssl.SSLError, socket.error) as x:
1302 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1303 if support.verbose:
1304 sys.stdout.write(
1305 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1306 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001307 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1308 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1309 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001310
Antoine Pitrou480a1242010-04-28 21:37:09 +00001311 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1312 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1313 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001314
Antoine Pitrou480a1242010-04-28 21:37:09 +00001315 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1316 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1317 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001318
Antoine Pitroub5218772010-05-21 09:56:06 +00001319 # Server with specific SSL options
1320 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1321 server_options=ssl.OP_NO_SSLv3)
1322 # Will choose TLSv1
1323 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1324 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1325 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1326 server_options=ssl.OP_NO_TLSv1)
1327
1328
Antoine Pitrou23df4832010-08-04 17:14:06 +00001329 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001330 def test_protocol_sslv3(self):
1331 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001332 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001333 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001334 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1335 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1336 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001337 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1338 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001339 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1340 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001342 if no_sslv2_implies_sslv3_hello():
1343 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1344 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1345 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001346
Antoine Pitrou23df4832010-08-04 17:14:06 +00001347 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001348 def test_protocol_tlsv1(self):
1349 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001350 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001351 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001352 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1353 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1354 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001355 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1356 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001357 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001358 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1359 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001360
Antoine Pitrou480a1242010-04-28 21:37:09 +00001361 def test_starttls(self):
1362 """Switching from clear text to encrypted and back again."""
1363 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 +00001364
Trent Nelson78520002008-04-10 20:54:35 +00001365 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001366 ssl_version=ssl.PROTOCOL_TLSv1,
1367 starttls_server=True,
1368 chatty=True,
1369 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001370 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001371 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001372 s = socket.socket()
1373 s.setblocking(1)
1374 s.connect((HOST, server.port))
1375 if support.verbose:
1376 sys.stdout.write("\n")
1377 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001378 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001379 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001381 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001382 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001383 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001384 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001385 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001386 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001387 msg = outdata.strip().lower()
1388 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1389 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001390 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001391 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001392 " client: read %r from server, starting TLS...\n"
1393 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001394 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1395 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1397 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001398 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001399 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 " client: read %r from server, ending TLS...\n"
1401 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001402 s = conn.unwrap()
1403 wrapped = False
1404 else:
1405 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001406 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001407 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001408 if support.verbose:
1409 sys.stdout.write(" client: closing connection.\n")
1410 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001411 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001412 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001413 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001414 if wrapped:
1415 conn.close()
1416 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001417 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001418
Antoine Pitrou480a1242010-04-28 21:37:09 +00001419 def test_socketserver(self):
1420 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001421 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001422 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001423 if support.verbose:
1424 sys.stdout.write('\n')
1425 with open(CERTFILE, 'rb') as f:
1426 d1 = f.read()
1427 d2 = ''
1428 # now fetch the same data from the HTTPS server
1429 url = 'https://%s:%d/%s' % (
1430 HOST, server.port, os.path.split(CERTFILE)[1])
1431 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001432 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001433 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434 if dlen and (int(dlen) > 0):
1435 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001436 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001437 sys.stdout.write(
1438 " client: read %d bytes from remote server '%s'\n"
1439 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001440 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001441 f.close()
1442 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001443
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 def test_asyncore_server(self):
1445 """Check the example asyncore integration."""
1446 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001447
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001448 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001449 sys.stdout.write("\n")
1450
Antoine Pitrou480a1242010-04-28 21:37:09 +00001451 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001452 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001453 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001454 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001455 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001456 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001457 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001458 " client: sending %r...\n" % indata)
1459 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001460 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001461 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001462 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001463 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001464 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001465 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1466 % (outdata[:20], len(outdata),
1467 indata[:20].lower(), len(indata)))
1468 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001469 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001470 sys.stdout.write(" client: closing connection.\n")
1471 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001472 if support.verbose:
1473 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001474
Antoine Pitrou480a1242010-04-28 21:37:09 +00001475 def test_recv_send(self):
1476 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001477 if support.verbose:
1478 sys.stdout.write("\n")
1479
1480 server = ThreadedEchoServer(CERTFILE,
1481 certreqs=ssl.CERT_NONE,
1482 ssl_version=ssl.PROTOCOL_TLSv1,
1483 cacerts=CERTFILE,
1484 chatty=True,
1485 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001486 with server:
1487 s = ssl.wrap_socket(socket.socket(),
1488 server_side=False,
1489 certfile=CERTFILE,
1490 ca_certs=CERTFILE,
1491 cert_reqs=ssl.CERT_NONE,
1492 ssl_version=ssl.PROTOCOL_TLSv1)
1493 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001494 # helper methods for standardising recv* method signatures
1495 def _recv_into():
1496 b = bytearray(b"\0"*100)
1497 count = s.recv_into(b)
1498 return b[:count]
1499
1500 def _recvfrom_into():
1501 b = bytearray(b"\0"*100)
1502 count, addr = s.recvfrom_into(b)
1503 return b[:count]
1504
1505 # (name, method, whether to expect success, *args)
1506 send_methods = [
1507 ('send', s.send, True, []),
1508 ('sendto', s.sendto, False, ["some.address"]),
1509 ('sendall', s.sendall, True, []),
1510 ]
1511 recv_methods = [
1512 ('recv', s.recv, True, []),
1513 ('recvfrom', s.recvfrom, False, ["some.address"]),
1514 ('recv_into', _recv_into, True, []),
1515 ('recvfrom_into', _recvfrom_into, False, []),
1516 ]
1517 data_prefix = "PREFIX_"
1518
1519 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001520 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001521 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001522 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001523 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001524 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001525 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001526 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001527 "<<{outdata:r}>> ({nout:d}) received; "
1528 "expected <<{indata:r}>> ({nin:d})\n".format(
1529 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001530 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001531 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001532 )
1533 )
1534 except ValueError as e:
1535 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001536 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001537 "Failed to send with method <<{name:s}>>; "
1538 "expected to succeed.\n".format(name=meth_name)
1539 )
1540 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001541 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001542 "Method <<{name:s}>> failed with unexpected "
1543 "exception message: {exp:s}\n".format(
1544 name=meth_name, exp=e
1545 )
1546 )
1547
1548 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001549 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001550 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001551 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001552 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001553 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001554 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001555 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001556 "<<{outdata:r}>> ({nout:d}) received; "
1557 "expected <<{indata:r}>> ({nin:d})\n".format(
1558 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001559 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001560 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001561 )
1562 )
1563 except ValueError as e:
1564 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001565 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001566 "Failed to receive with method <<{name:s}>>; "
1567 "expected to succeed.\n".format(name=meth_name)
1568 )
1569 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001570 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001571 "Method <<{name:s}>> failed with unexpected "
1572 "exception message: {exp:s}\n".format(
1573 name=meth_name, exp=e
1574 )
1575 )
1576 # consume data
1577 s.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001578 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001579 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001580
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001581 def test_handshake_timeout(self):
1582 # Issue #5103: SSL handshake must respect the socket timeout
1583 server = socket.socket(socket.AF_INET)
1584 host = "127.0.0.1"
1585 port = support.bind_port(server)
1586 started = threading.Event()
1587 finish = False
1588
1589 def serve():
1590 server.listen(5)
1591 started.set()
1592 conns = []
1593 while not finish:
1594 r, w, e = select.select([server], [], [], 0.1)
1595 if server in r:
1596 # Let the socket hang around rather than having
1597 # it closed by garbage collection.
1598 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001599 for sock in conns:
1600 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001601
1602 t = threading.Thread(target=serve)
1603 t.start()
1604 started.wait()
1605
1606 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001607 try:
1608 c = socket.socket(socket.AF_INET)
1609 c.settimeout(0.2)
1610 c.connect((host, port))
1611 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001612 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001613 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001614 finally:
1615 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001616 try:
1617 c = socket.socket(socket.AF_INET)
1618 c = ssl.wrap_socket(c)
1619 c.settimeout(0.2)
1620 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001621 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001622 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001623 finally:
1624 c.close()
1625 finally:
1626 finish = True
1627 t.join()
1628 server.close()
1629
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001630 def test_server_accept(self):
1631 # Issue #16357: accept() on a SSLSocket created through
1632 # SSLContext.wrap_socket().
1633 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1634 context.verify_mode = ssl.CERT_REQUIRED
1635 context.load_verify_locations(CERTFILE)
1636 context.load_cert_chain(CERTFILE)
1637 server = socket.socket(socket.AF_INET)
1638 host = "127.0.0.1"
1639 port = support.bind_port(server)
1640 server = context.wrap_socket(server, server_side=True)
1641
1642 evt = threading.Event()
1643 remote = None
1644 peer = None
1645 def serve():
1646 nonlocal remote, peer
1647 server.listen(5)
1648 # Block on the accept and wait on the connection to close.
1649 evt.set()
1650 remote, peer = server.accept()
1651 remote.recv(1)
1652
1653 t = threading.Thread(target=serve)
1654 t.start()
1655 # Client wait until server setup and perform a connect.
1656 evt.wait()
1657 client = context.wrap_socket(socket.socket())
1658 client.connect((host, port))
1659 client_addr = client.getsockname()
1660 client.close()
1661 t.join()
1662 # Sanity checks.
1663 self.assertIsInstance(remote, ssl.SSLSocket)
1664 self.assertEqual(peer, client_addr)
1665
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001666 def test_default_ciphers(self):
1667 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1668 try:
1669 # Force a set of weak ciphers on our client context
1670 context.set_ciphers("DES")
1671 except ssl.SSLError:
1672 self.skipTest("no DES cipher available")
1673 with ThreadedEchoServer(CERTFILE,
1674 ssl_version=ssl.PROTOCOL_SSLv23,
1675 chatty=False) as server:
1676 with socket.socket() as sock:
1677 s = context.wrap_socket(sock)
1678 with self.assertRaises((OSError, ssl.SSLError)):
1679 s.connect((HOST, server.port))
1680 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1681
Bill Janssen58afe4c2008-09-08 16:45:19 +00001682
Thomas Woutersed03b412007-08-28 21:37:11 +00001683def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001684 if support.verbose:
1685 plats = {
1686 'Linux': platform.linux_distribution,
1687 'Mac': platform.mac_ver,
1688 'Windows': platform.win32_ver,
1689 }
1690 for name, func in plats.items():
1691 plat = func()
1692 if plat and plat[0]:
1693 plat = '%s %r' % (name, plat)
1694 break
1695 else:
1696 plat = repr(platform.platform())
1697 print("test_ssl: testing with %r %r" %
1698 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1699 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001700 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001701
Antoine Pitrou152efa22010-05-16 18:19:27 +00001702 for filename in [
1703 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1704 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1705 BADCERT, BADKEY, EMPTYCERT]:
1706 if not os.path.exists(filename):
1707 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001708
Antoine Pitrou152efa22010-05-16 18:19:27 +00001709 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001710
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001711 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001712 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001713
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001714 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001715 thread_info = support.threading_setup()
1716 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001717 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001718
Antoine Pitrou480a1242010-04-28 21:37:09 +00001719 try:
1720 support.run_unittest(*tests)
1721 finally:
1722 if _have_threads:
1723 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001724
1725if __name__ == "__main__":
1726 test_main()