blob: 4f254a98f325966c22f7dcc8c7b7b40c597b7d5f [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)
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100777 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000778 # XXX Various errors can have happened here, for example
779 # a mismatching protocol version, an invalid certificate,
780 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100781 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000782 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000783 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000784 self.running = False
785 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000786 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000788 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000789 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000790 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000791 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000792 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
793 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000794 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000795 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
796 cipher = self.sslconn.cipher()
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(" server: connection cipher is now " + str(cipher) + "\n")
799 return True
800
801 def read(self):
802 if self.sslconn:
803 return self.sslconn.read()
804 else:
805 return self.sock.recv(1024)
806
807 def write(self, bytes):
808 if self.sslconn:
809 return self.sslconn.write(bytes)
810 else:
811 return self.sock.send(bytes)
812
813 def close(self):
814 if self.sslconn:
815 self.sslconn.close()
816 else:
817 self.sock.close()
818
Antoine Pitrou480a1242010-04-28 21:37:09 +0000819 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000820 self.running = True
821 if not self.server.starttls_server:
822 if not self.wrap_conn():
823 return
824 while self.running:
825 try:
826 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000827 stripped = msg.strip()
828 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829 # eof, so quit this handler
830 self.running = False
831 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000832 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000833 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000834 sys.stdout.write(" server: client closed connection\n")
835 self.close()
836 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000837 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000838 stripped == b'STARTTLS'):
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: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000841 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842 if not self.wrap_conn():
843 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000844 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000845 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000846 if support.verbose and self.server.connectionchatty:
847 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000848 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000849 self.sock = self.sslconn.unwrap()
850 self.sslconn = None
851 if support.verbose and self.server.connectionchatty:
852 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000854 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000855 self.server.connectionchatty):
856 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000857 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
858 % (msg, ctype, msg.lower(), ctype))
859 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000860 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861 if self.server.chatty:
862 handle_error("Test server failure:\n")
863 self.close()
864 self.running = False
865 # normally, we'd just stop here, but for the test
866 # harness, we want to stop the server
867 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868
Antoine Pitroub5218772010-05-21 09:56:06 +0000869 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000870 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000871 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000872 ciphers=None, context=None):
873 if context:
874 self.context = context
875 else:
876 self.context = ssl.SSLContext(ssl_version
877 if ssl_version is not None
878 else ssl.PROTOCOL_TLSv1)
879 self.context.verify_mode = (certreqs if certreqs is not None
880 else ssl.CERT_NONE)
881 if cacerts:
882 self.context.load_verify_locations(cacerts)
883 if certificate:
884 self.context.load_cert_chain(certificate)
885 if ciphers:
886 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000887 self.chatty = chatty
888 self.connectionchatty = connectionchatty
889 self.starttls_server = starttls_server
890 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000891 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000893 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100894 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000896 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000897
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100898 def __enter__(self):
899 self.start(threading.Event())
900 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100901 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100902
903 def __exit__(self, *args):
904 self.stop()
905 self.join()
906
Antoine Pitrou480a1242010-04-28 21:37:09 +0000907 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000908 self.flag = flag
909 threading.Thread.start(self)
910
Antoine Pitrou480a1242010-04-28 21:37:09 +0000911 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000912 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000913 self.sock.listen(5)
914 self.active = True
915 if self.flag:
916 # signal an event
917 self.flag.set()
918 while self.active:
919 try:
920 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000921 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000923 + repr(connaddr) + '\n')
924 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000925 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +0100926 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000927 except socket.timeout:
928 pass
929 except KeyboardInterrupt:
930 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000931 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000932
Antoine Pitrou480a1242010-04-28 21:37:09 +0000933 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000934 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935
Bill Janssen54cc54c2007-12-14 22:08:56 +0000936 class AsyncoreEchoServer(threading.Thread):
937
938 # this one's based on asyncore.dispatcher
939
940 class EchoServer (asyncore.dispatcher):
941
942 class ConnectionHandler (asyncore.dispatcher_with_send):
943
944 def __init__(self, conn, certfile):
945 self.socket = ssl.wrap_socket(conn, server_side=True,
946 certfile=certfile,
947 do_handshake_on_connect=False)
948 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000949 self._ssl_accepting = True
950 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000951
952 def readable(self):
953 if isinstance(self.socket, ssl.SSLSocket):
954 while self.socket.pending() > 0:
955 self.handle_read_event()
956 return True
957
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000958 def _do_ssl_handshake(self):
959 try:
960 self.socket.do_handshake()
961 except ssl.SSLError as err:
962 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
963 ssl.SSL_ERROR_WANT_WRITE):
964 return
965 elif err.args[0] == ssl.SSL_ERROR_EOF:
966 return self.handle_close()
967 raise
968 except socket.error as err:
969 if err.args[0] == errno.ECONNABORTED:
970 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000971 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000972 self._ssl_accepting = False
973
974 def handle_read(self):
975 if self._ssl_accepting:
976 self._do_ssl_handshake()
977 else:
978 data = self.recv(1024)
979 if support.verbose:
980 sys.stdout.write(" server: read %s from client\n" % repr(data))
981 if not data:
982 self.close()
983 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000984 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000985
986 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000987 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000988 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000989 sys.stdout.write(" server: closed connection %s\n" % self.socket)
990
991 def handle_error(self):
992 raise
993
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000994 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000995 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000996 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
997 self.port = support.bind_port(sock, '')
998 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000999 self.listen(5)
1000
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001001 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001002 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001003 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1004 self.ConnectionHandler(sock_obj, self.certfile)
1005
1006 def handle_error(self):
1007 raise
1008
Trent Nelson78520002008-04-10 20:54:35 +00001009 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001010 self.flag = None
1011 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001012 self.server = self.EchoServer(certfile)
1013 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001014 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001015 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001016
1017 def __str__(self):
1018 return "<%s %s>" % (self.__class__.__name__, self.server)
1019
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001020 def __enter__(self):
1021 self.start(threading.Event())
1022 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001023 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001024
1025 def __exit__(self, *args):
1026 if support.verbose:
1027 sys.stdout.write(" cleanup: stopping server.\n")
1028 self.stop()
1029 if support.verbose:
1030 sys.stdout.write(" cleanup: joining server thread.\n")
1031 self.join()
1032 if support.verbose:
1033 sys.stdout.write(" cleanup: successfully joined.\n")
1034
Bill Janssen54cc54c2007-12-14 22:08:56 +00001035 def start (self, flag=None):
1036 self.flag = flag
1037 threading.Thread.start(self)
1038
Antoine Pitrou480a1242010-04-28 21:37:09 +00001039 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001040 self.active = True
1041 if self.flag:
1042 self.flag.set()
1043 while self.active:
1044 try:
1045 asyncore.loop(1)
1046 except:
1047 pass
1048
Antoine Pitrou480a1242010-04-28 21:37:09 +00001049 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001050 self.active = False
1051 self.server.close()
1052
Antoine Pitrou480a1242010-04-28 21:37:09 +00001053 def bad_cert_test(certfile):
1054 """
1055 Launch a server with CERT_REQUIRED, and check that trying to
1056 connect to it with the given client certificate fails.
1057 """
Trent Nelson78520002008-04-10 20:54:35 +00001058 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001059 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001060 cacerts=CERTFILE, chatty=False,
1061 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001062 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001063 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001064 with socket.socket() as sock:
1065 s = ssl.wrap_socket(sock,
1066 certfile=certfile,
1067 ssl_version=ssl.PROTOCOL_TLSv1)
1068 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001069 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001070 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001071 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001072 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001073 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001074 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001075 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001076 if x.errno != errno.ENOENT:
1077 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001078 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001079 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001080 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001081 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001082
Antoine Pitroub5218772010-05-21 09:56:06 +00001083 def server_params_test(client_context, server_context, indata=b"FOO\n",
1084 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001085 """
1086 Launch a server, connect a client to it and try various reads
1087 and writes.
1088 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001089 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001090 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001091 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001092 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001093 with client_context.wrap_socket(socket.socket()) as s:
1094 s.connect((HOST, server.port))
1095 for arg in [indata, bytearray(indata), memoryview(indata)]:
1096 if connectionchatty:
1097 if support.verbose:
1098 sys.stdout.write(
1099 " client: sending %r...\n" % indata)
1100 s.write(arg)
1101 outdata = s.read()
1102 if connectionchatty:
1103 if support.verbose:
1104 sys.stdout.write(" client: read %r\n" % outdata)
1105 if outdata != indata.lower():
1106 raise AssertionError(
1107 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1108 % (outdata[:20], len(outdata),
1109 indata[:20].lower(), len(indata)))
1110 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001111 if connectionchatty:
1112 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001113 sys.stdout.write(" client: closing connection.\n")
1114 s.close()
Thomas Woutersed03b412007-08-28 21:37:11 +00001115
Antoine Pitroub5218772010-05-21 09:56:06 +00001116 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1117 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001118 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001119 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001120 certtype = {
1121 ssl.CERT_NONE: "CERT_NONE",
1122 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1123 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1124 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001125 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001126 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127 sys.stdout.write(formatstr %
1128 (ssl.get_protocol_name(client_protocol),
1129 ssl.get_protocol_name(server_protocol),
1130 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001131 client_context = ssl.SSLContext(client_protocol)
1132 client_context.options = ssl.OP_ALL | client_options
1133 server_context = ssl.SSLContext(server_protocol)
1134 server_context.options = ssl.OP_ALL | server_options
1135 for ctx in (client_context, server_context):
1136 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001137 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1138 # will send an SSLv3 hello (rather than SSLv2) starting from
1139 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001140 ctx.set_ciphers("ALL")
1141 ctx.load_cert_chain(CERTFILE)
1142 ctx.load_verify_locations(CERTFILE)
1143 try:
1144 server_params_test(client_context, server_context,
1145 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001146 # Protocol mismatch can result in either an SSLError, or a
1147 # "Connection reset by peer" error.
1148 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001149 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001151 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001153 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001154 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001155 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001156 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001157 "Client protocol %s succeeded with server protocol %s!"
1158 % (ssl.get_protocol_name(client_protocol),
1159 ssl.get_protocol_name(server_protocol)))
1160
1161
Bill Janssen6e027db2007-11-15 22:23:56 +00001162 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163
Antoine Pitrou23df4832010-08-04 17:14:06 +00001164 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001165 def test_echo(self):
1166 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001167 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001168 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001169 for protocol in PROTOCOLS:
1170 context = ssl.SSLContext(protocol)
1171 context.load_cert_chain(CERTFILE)
1172 server_params_test(context, context,
1173 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174
Antoine Pitrou480a1242010-04-28 21:37:09 +00001175 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001176 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001177 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001178 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1179 context.verify_mode = ssl.CERT_REQUIRED
1180 context.load_verify_locations(CERTFILE)
1181 context.load_cert_chain(CERTFILE)
1182 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001183 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001184 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001185 s.connect((HOST, server.port))
1186 cert = s.getpeercert()
1187 self.assertTrue(cert, "Can't get peer certificate.")
1188 cipher = s.cipher()
1189 if support.verbose:
1190 sys.stdout.write(pprint.pformat(cert) + '\n')
1191 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1192 if 'subject' not in cert:
1193 self.fail("No subject field in certificate: %s." %
1194 pprint.pformat(cert))
1195 if ((('organizationName', 'Python Software Foundation'),)
1196 not in cert['subject']):
1197 self.fail(
1198 "Missing or invalid 'organizationName' field in certificate subject; "
1199 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001200 self.assertIn('notBefore', cert)
1201 self.assertIn('notAfter', cert)
1202 before = ssl.cert_time_to_seconds(cert['notBefore'])
1203 after = ssl.cert_time_to_seconds(cert['notAfter'])
1204 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001205 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001206
Antoine Pitrou480a1242010-04-28 21:37:09 +00001207 def test_empty_cert(self):
1208 """Connecting with an empty cert file"""
1209 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1210 "nullcert.pem"))
1211 def test_malformed_cert(self):
1212 """Connecting with a badly formatted certificate (syntax error)"""
1213 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1214 "badcert.pem"))
1215 def test_nonexisting_cert(self):
1216 """Connecting with a non-existing cert file"""
1217 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1218 "wrongcert.pem"))
1219 def test_malformed_key(self):
1220 """Connecting with a badly formatted key (syntax error)"""
1221 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1222 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001223
Antoine Pitrou480a1242010-04-28 21:37:09 +00001224 def test_rude_shutdown(self):
1225 """A brutal shutdown of an SSL server should raise an IOError
1226 in the client when attempting handshake.
1227 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001228 listener_ready = threading.Event()
1229 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001230
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001231 s = socket.socket()
1232 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001233
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001234 # `listener` runs in a thread. It sits in an accept() until
1235 # the main thread connects. Then it rudely closes the socket,
1236 # and sets Event `listener_gone` to let the main thread know
1237 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001238 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001239 s.listen(5)
1240 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001241 newsock, addr = s.accept()
1242 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001243 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001244 listener_gone.set()
1245
1246 def connector():
1247 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001248 with socket.socket() as c:
1249 c.connect((HOST, port))
1250 listener_gone.wait()
1251 try:
1252 ssl_sock = ssl.wrap_socket(c)
1253 except IOError:
1254 pass
1255 else:
1256 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001257
1258 t = threading.Thread(target=listener)
1259 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001260 try:
1261 connector()
1262 finally:
1263 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001264
Antoine Pitrou23df4832010-08-04 17:14:06 +00001265 @skip_if_broken_ubuntu_ssl
Victor Stinneree18b6f2011-05-10 00:38:00 +02001266 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001267 def test_protocol_sslv2(self):
1268 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001269 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001270 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001271 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1272 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1273 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1274 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1275 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1276 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001277 # SSLv23 client with specific SSL options
1278 if no_sslv2_implies_sslv3_hello():
1279 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1280 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1281 client_options=ssl.OP_NO_SSLv2)
1282 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1283 client_options=ssl.OP_NO_SSLv3)
1284 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1285 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001286
Antoine Pitrou23df4832010-08-04 17:14:06 +00001287 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001288 def test_protocol_sslv23(self):
1289 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001290 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001291 sys.stdout.write("\n")
Victor Stinneree18b6f2011-05-10 00:38:00 +02001292 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1293 try:
1294 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1295 except (ssl.SSLError, socket.error) as x:
1296 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1297 if support.verbose:
1298 sys.stdout.write(
1299 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1300 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001301 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1302 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1303 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001304
Antoine Pitrou480a1242010-04-28 21:37:09 +00001305 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1306 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1307 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001308
Antoine Pitrou480a1242010-04-28 21:37:09 +00001309 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1310 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1311 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001312
Antoine Pitroub5218772010-05-21 09:56:06 +00001313 # Server with specific SSL options
1314 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1315 server_options=ssl.OP_NO_SSLv3)
1316 # Will choose TLSv1
1317 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1318 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1319 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1320 server_options=ssl.OP_NO_TLSv1)
1321
1322
Antoine Pitrou23df4832010-08-04 17:14:06 +00001323 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001324 def test_protocol_sslv3(self):
1325 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001326 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001327 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001328 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1329 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1330 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001331 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1332 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001333 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1334 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001335 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001336 if no_sslv2_implies_sslv3_hello():
1337 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1338 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1339 client_options=ssl.OP_NO_SSLv2)
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_tlsv1(self):
1343 """Connecting to a TLSv1 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")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001346 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1347 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1348 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001349 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1350 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001351 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001352 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1353 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001354
Antoine Pitrou480a1242010-04-28 21:37:09 +00001355 def test_starttls(self):
1356 """Switching from clear text to encrypted and back again."""
1357 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001358
Trent Nelson78520002008-04-10 20:54:35 +00001359 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001360 ssl_version=ssl.PROTOCOL_TLSv1,
1361 starttls_server=True,
1362 chatty=True,
1363 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001364 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001365 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001366 s = socket.socket()
1367 s.setblocking(1)
1368 s.connect((HOST, server.port))
1369 if support.verbose:
1370 sys.stdout.write("\n")
1371 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001372 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001373 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001374 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001375 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001377 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001378 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001379 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001380 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 msg = outdata.strip().lower()
1382 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1383 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001384 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001385 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001386 " client: read %r from server, starting TLS...\n"
1387 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001388 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1389 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001390 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1391 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001392 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001393 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001394 " client: read %r from server, ending TLS...\n"
1395 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001396 s = conn.unwrap()
1397 wrapped = False
1398 else:
1399 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001400 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001401 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001402 if support.verbose:
1403 sys.stdout.write(" client: closing connection.\n")
1404 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001405 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001406 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001407 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001408 if wrapped:
1409 conn.close()
1410 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001411 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001412
Antoine Pitrou480a1242010-04-28 21:37:09 +00001413 def test_socketserver(self):
1414 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001415 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001416 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001417 if support.verbose:
1418 sys.stdout.write('\n')
1419 with open(CERTFILE, 'rb') as f:
1420 d1 = f.read()
1421 d2 = ''
1422 # now fetch the same data from the HTTPS server
1423 url = 'https://%s:%d/%s' % (
1424 HOST, server.port, os.path.split(CERTFILE)[1])
1425 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001426 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001427 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001428 if dlen and (int(dlen) > 0):
1429 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001430 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001431 sys.stdout.write(
1432 " client: read %d bytes from remote server '%s'\n"
1433 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001434 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001435 f.close()
1436 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001437
Antoine Pitrou480a1242010-04-28 21:37:09 +00001438 def test_asyncore_server(self):
1439 """Check the example asyncore integration."""
1440 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001441
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001442 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001443 sys.stdout.write("\n")
1444
Antoine Pitrou480a1242010-04-28 21:37:09 +00001445 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001446 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001447 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001448 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001449 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001450 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001451 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001452 " client: sending %r...\n" % indata)
1453 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001454 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001455 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001456 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001457 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001458 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001459 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1460 % (outdata[:20], len(outdata),
1461 indata[:20].lower(), len(indata)))
1462 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001463 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001464 sys.stdout.write(" client: closing connection.\n")
1465 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001466 if support.verbose:
1467 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001468
Antoine Pitrou480a1242010-04-28 21:37:09 +00001469 def test_recv_send(self):
1470 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001471 if support.verbose:
1472 sys.stdout.write("\n")
1473
1474 server = ThreadedEchoServer(CERTFILE,
1475 certreqs=ssl.CERT_NONE,
1476 ssl_version=ssl.PROTOCOL_TLSv1,
1477 cacerts=CERTFILE,
1478 chatty=True,
1479 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001480 with server:
1481 s = ssl.wrap_socket(socket.socket(),
1482 server_side=False,
1483 certfile=CERTFILE,
1484 ca_certs=CERTFILE,
1485 cert_reqs=ssl.CERT_NONE,
1486 ssl_version=ssl.PROTOCOL_TLSv1)
1487 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001488 # helper methods for standardising recv* method signatures
1489 def _recv_into():
1490 b = bytearray(b"\0"*100)
1491 count = s.recv_into(b)
1492 return b[:count]
1493
1494 def _recvfrom_into():
1495 b = bytearray(b"\0"*100)
1496 count, addr = s.recvfrom_into(b)
1497 return b[:count]
1498
1499 # (name, method, whether to expect success, *args)
1500 send_methods = [
1501 ('send', s.send, True, []),
1502 ('sendto', s.sendto, False, ["some.address"]),
1503 ('sendall', s.sendall, True, []),
1504 ]
1505 recv_methods = [
1506 ('recv', s.recv, True, []),
1507 ('recvfrom', s.recvfrom, False, ["some.address"]),
1508 ('recv_into', _recv_into, True, []),
1509 ('recvfrom_into', _recvfrom_into, False, []),
1510 ]
1511 data_prefix = "PREFIX_"
1512
1513 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001514 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001515 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001516 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001517 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001518 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001519 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001520 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001521 "<<{outdata:r}>> ({nout:d}) received; "
1522 "expected <<{indata:r}>> ({nin:d})\n".format(
1523 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001524 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001525 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001526 )
1527 )
1528 except ValueError as e:
1529 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001530 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001531 "Failed to send with method <<{name:s}>>; "
1532 "expected to succeed.\n".format(name=meth_name)
1533 )
1534 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001535 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001536 "Method <<{name:s}>> failed with unexpected "
1537 "exception message: {exp:s}\n".format(
1538 name=meth_name, exp=e
1539 )
1540 )
1541
1542 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001543 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001544 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001546 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001547 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001548 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001549 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001550 "<<{outdata:r}>> ({nout:d}) received; "
1551 "expected <<{indata:r}>> ({nin:d})\n".format(
1552 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001553 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001554 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001555 )
1556 )
1557 except ValueError as e:
1558 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001559 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001560 "Failed to receive with method <<{name:s}>>; "
1561 "expected to succeed.\n".format(name=meth_name)
1562 )
1563 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001564 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001565 "Method <<{name:s}>> failed with unexpected "
1566 "exception message: {exp:s}\n".format(
1567 name=meth_name, exp=e
1568 )
1569 )
1570 # consume data
1571 s.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001572 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001573 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001574
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001575 def test_handshake_timeout(self):
1576 # Issue #5103: SSL handshake must respect the socket timeout
1577 server = socket.socket(socket.AF_INET)
1578 host = "127.0.0.1"
1579 port = support.bind_port(server)
1580 started = threading.Event()
1581 finish = False
1582
1583 def serve():
1584 server.listen(5)
1585 started.set()
1586 conns = []
1587 while not finish:
1588 r, w, e = select.select([server], [], [], 0.1)
1589 if server in r:
1590 # Let the socket hang around rather than having
1591 # it closed by garbage collection.
1592 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001593 for sock in conns:
1594 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001595
1596 t = threading.Thread(target=serve)
1597 t.start()
1598 started.wait()
1599
1600 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001601 try:
1602 c = socket.socket(socket.AF_INET)
1603 c.settimeout(0.2)
1604 c.connect((host, port))
1605 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001606 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001607 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001608 finally:
1609 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001610 try:
1611 c = socket.socket(socket.AF_INET)
1612 c = ssl.wrap_socket(c)
1613 c.settimeout(0.2)
1614 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001615 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001616 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001617 finally:
1618 c.close()
1619 finally:
1620 finish = True
1621 t.join()
1622 server.close()
1623
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001624 def test_server_accept(self):
1625 # Issue #16357: accept() on a SSLSocket created through
1626 # SSLContext.wrap_socket().
1627 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1628 context.verify_mode = ssl.CERT_REQUIRED
1629 context.load_verify_locations(CERTFILE)
1630 context.load_cert_chain(CERTFILE)
1631 server = socket.socket(socket.AF_INET)
1632 host = "127.0.0.1"
1633 port = support.bind_port(server)
1634 server = context.wrap_socket(server, server_side=True)
1635
1636 evt = threading.Event()
1637 remote = None
1638 peer = None
1639 def serve():
1640 nonlocal remote, peer
1641 server.listen(5)
1642 # Block on the accept and wait on the connection to close.
1643 evt.set()
1644 remote, peer = server.accept()
1645 remote.recv(1)
1646
1647 t = threading.Thread(target=serve)
1648 t.start()
1649 # Client wait until server setup and perform a connect.
1650 evt.wait()
1651 client = context.wrap_socket(socket.socket())
1652 client.connect((host, port))
1653 client_addr = client.getsockname()
1654 client.close()
1655 t.join()
1656 # Sanity checks.
1657 self.assertIsInstance(remote, ssl.SSLSocket)
1658 self.assertEqual(peer, client_addr)
1659
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001660 def test_default_ciphers(self):
1661 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1662 try:
1663 # Force a set of weak ciphers on our client context
1664 context.set_ciphers("DES")
1665 except ssl.SSLError:
1666 self.skipTest("no DES cipher available")
1667 with ThreadedEchoServer(CERTFILE,
1668 ssl_version=ssl.PROTOCOL_SSLv23,
1669 chatty=False) as server:
1670 with socket.socket() as sock:
1671 s = context.wrap_socket(sock)
1672 with self.assertRaises((OSError, ssl.SSLError)):
1673 s.connect((HOST, server.port))
1674 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1675
Bill Janssen58afe4c2008-09-08 16:45:19 +00001676
Thomas Woutersed03b412007-08-28 21:37:11 +00001677def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001678 if support.verbose:
1679 plats = {
1680 'Linux': platform.linux_distribution,
1681 'Mac': platform.mac_ver,
1682 'Windows': platform.win32_ver,
1683 }
1684 for name, func in plats.items():
1685 plat = func()
1686 if plat and plat[0]:
1687 plat = '%s %r' % (name, plat)
1688 break
1689 else:
1690 plat = repr(platform.platform())
1691 print("test_ssl: testing with %r %r" %
1692 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1693 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001694 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001695
Antoine Pitrou152efa22010-05-16 18:19:27 +00001696 for filename in [
1697 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1698 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1699 BADCERT, BADKEY, EMPTYCERT]:
1700 if not os.path.exists(filename):
1701 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001702
Antoine Pitrou152efa22010-05-16 18:19:27 +00001703 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001704
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001705 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001706 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001707
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001708 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001709 thread_info = support.threading_setup()
1710 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001711 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001712
Antoine Pitrou480a1242010-04-28 21:37:09 +00001713 try:
1714 support.run_unittest(*tests)
1715 finally:
1716 if _have_threads:
1717 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001718
1719if __name__ == "__main__":
1720 test_main()