blob: c6c26bcee3af12536a568364566bc43d83d11726 [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"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000106 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000107 ssl.RAND_egd(1)
108 except TypeError:
109 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000110 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000111 print("didn't raise TypeError")
112 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000113
Antoine Pitrou480a1242010-04-28 21:37:09 +0000114 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 # note that this uses an 'unofficial' function in _ssl.c,
116 # provided solely for this test, to exercise the certificate
117 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000118 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000119 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200121 self.assertEqual(p['issuer'],
122 ((('countryName', 'XY'),),
123 (('localityName', 'Castle Anthrax'),),
124 (('organizationName', 'Python Software Foundation'),),
125 (('commonName', 'localhost'),))
126 )
127 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
128 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
129 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
130 self.assertEqual(p['subject'],
131 ((('countryName', 'XY'),),
132 (('localityName', 'Castle Anthrax'),),
133 (('organizationName', 'Python Software Foundation'),),
134 (('commonName', 'localhost'),))
135 )
136 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
137 # Issue #13034: the subjectAltName in some certificates
138 # (notably projects.developer.nokia.com:443) wasn't parsed
139 p = ssl._ssl._test_decode_cert(NOKIACERT)
140 if support.verbose:
141 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
142 self.assertEqual(p['subjectAltName'],
143 (('DNS', 'projects.developer.nokia.com'),
144 ('DNS', 'projects.forum.nokia.com'))
145 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000146
Antoine Pitrou480a1242010-04-28 21:37:09 +0000147 def test_DER_to_PEM(self):
148 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
149 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000150 d1 = ssl.PEM_cert_to_DER_cert(pem)
151 p2 = ssl.DER_cert_to_PEM_cert(d1)
152 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000153 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000154 if not p2.startswith(ssl.PEM_HEADER + '\n'):
155 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
156 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
157 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000158
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000159 def test_openssl_version(self):
160 n = ssl.OPENSSL_VERSION_NUMBER
161 t = ssl.OPENSSL_VERSION_INFO
162 s = ssl.OPENSSL_VERSION
163 self.assertIsInstance(n, int)
164 self.assertIsInstance(t, tuple)
165 self.assertIsInstance(s, str)
166 # Some sanity checks follow
167 # >= 0.9
168 self.assertGreaterEqual(n, 0x900000)
169 # < 2.0
170 self.assertLess(n, 0x20000000)
171 major, minor, fix, patch, status = t
172 self.assertGreaterEqual(major, 0)
173 self.assertLess(major, 2)
174 self.assertGreaterEqual(minor, 0)
175 self.assertLess(minor, 256)
176 self.assertGreaterEqual(fix, 0)
177 self.assertLess(fix, 256)
178 self.assertGreaterEqual(patch, 0)
179 self.assertLessEqual(patch, 26)
180 self.assertGreaterEqual(status, 0)
181 self.assertLessEqual(status, 15)
182 # Version string as returned by OpenSSL, the format might change
183 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
184 (s, t))
185
Antoine Pitrou9d543662010-04-23 23:10:32 +0000186 @support.cpython_only
187 def test_refcycle(self):
188 # Issue #7943: an SSL object doesn't create reference cycles with
189 # itself.
190 s = socket.socket(socket.AF_INET)
191 ss = ssl.wrap_socket(s)
192 wr = weakref.ref(ss)
193 del ss
194 self.assertEqual(wr(), None)
195
Antoine Pitroua468adc2010-09-14 14:43:44 +0000196 def test_wrapped_unconnected(self):
197 # Methods on an unconnected SSLSocket propagate the original
198 # socket.error raise by the underlying socket object.
199 s = socket.socket(socket.AF_INET)
200 ss = ssl.wrap_socket(s)
201 self.assertRaises(socket.error, ss.recv, 1)
202 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
203 self.assertRaises(socket.error, ss.recvfrom, 1)
204 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
205 self.assertRaises(socket.error, ss.send, b'x')
206 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
207
Antoine Pitrou40f08742010-04-24 22:04:40 +0000208 def test_timeout(self):
209 # Issue #8524: when creating an SSL socket, the timeout of the
210 # original socket should be retained.
211 for timeout in (None, 0.0, 5.0):
212 s = socket.socket(socket.AF_INET)
213 s.settimeout(timeout)
214 ss = ssl.wrap_socket(s)
215 self.assertEqual(timeout, ss.gettimeout())
216
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000217 def test_errors(self):
218 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000219 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000220 "certfile must be specified",
221 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000222 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000223 "certfile must be specified for server-side operations",
224 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000225 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000226 "certfile must be specified for server-side operations",
227 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000228 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000229 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000230 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +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=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000234 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +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=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000238 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000239 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000240 with socket.socket() as sock:
241 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000242 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000243
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000244 def test_match_hostname(self):
245 def ok(cert, hostname):
246 ssl.match_hostname(cert, hostname)
247 def fail(cert, hostname):
248 self.assertRaises(ssl.CertificateError,
249 ssl.match_hostname, cert, hostname)
250
251 cert = {'subject': ((('commonName', 'example.com'),),)}
252 ok(cert, 'example.com')
253 ok(cert, 'ExAmple.cOm')
254 fail(cert, 'www.example.com')
255 fail(cert, '.example.com')
256 fail(cert, 'example.org')
257 fail(cert, 'exampleXcom')
258
259 cert = {'subject': ((('commonName', '*.a.com'),),)}
260 ok(cert, 'foo.a.com')
261 fail(cert, 'bar.foo.a.com')
262 fail(cert, 'a.com')
263 fail(cert, 'Xa.com')
264 fail(cert, '.a.com')
265
266 cert = {'subject': ((('commonName', 'a.*.com'),),)}
267 ok(cert, 'a.foo.com')
268 fail(cert, 'a..com')
269 fail(cert, 'a.com')
270
271 cert = {'subject': ((('commonName', 'f*.com'),),)}
272 ok(cert, 'foo.com')
273 ok(cert, 'f.com')
274 fail(cert, 'bar.com')
275 fail(cert, 'foo.a.com')
276 fail(cert, 'bar.foo.com')
277
278 # Slightly fake real-world example
279 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
280 'subject': ((('commonName', 'linuxfrz.org'),),),
281 'subjectAltName': (('DNS', 'linuxfr.org'),
282 ('DNS', 'linuxfr.com'),
283 ('othername', '<unsupported>'))}
284 ok(cert, 'linuxfr.org')
285 ok(cert, 'linuxfr.com')
286 # Not a "DNS" entry
287 fail(cert, '<unsupported>')
288 # When there is a subjectAltName, commonName isn't used
289 fail(cert, 'linuxfrz.org')
290
291 # A pristine real-world example
292 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
293 'subject': ((('countryName', 'US'),),
294 (('stateOrProvinceName', 'California'),),
295 (('localityName', 'Mountain View'),),
296 (('organizationName', 'Google Inc'),),
297 (('commonName', 'mail.google.com'),))}
298 ok(cert, 'mail.google.com')
299 fail(cert, 'gmail.com')
300 # Only commonName is considered
301 fail(cert, 'California')
302
303 # Neither commonName nor subjectAltName
304 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
305 'subject': ((('countryName', 'US'),),
306 (('stateOrProvinceName', 'California'),),
307 (('localityName', 'Mountain View'),),
308 (('organizationName', 'Google Inc'),))}
309 fail(cert, 'mail.google.com')
310
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200311 # No DNS entry in subjectAltName but a commonName
312 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
313 'subject': ((('countryName', 'US'),),
314 (('stateOrProvinceName', 'California'),),
315 (('localityName', 'Mountain View'),),
316 (('commonName', 'mail.google.com'),)),
317 'subjectAltName': (('othername', 'blabla'), )}
318 ok(cert, 'mail.google.com')
319
320 # No DNS entry subjectAltName and no commonName
321 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
322 'subject': ((('countryName', 'US'),),
323 (('stateOrProvinceName', 'California'),),
324 (('localityName', 'Mountain View'),),
325 (('organizationName', 'Google Inc'),)),
326 'subjectAltName': (('othername', 'blabla'),)}
327 fail(cert, 'google.com')
328
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000329 # Empty cert / no cert
330 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
331 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
332
Antoine Pitroud5323212010-10-22 18:19:07 +0000333 def test_server_side(self):
334 # server_hostname doesn't work for server sockets
335 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000336 with socket.socket() as sock:
337 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
338 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000339
Antoine Pitrou152efa22010-05-16 18:19:27 +0000340class ContextTests(unittest.TestCase):
341
Antoine Pitrou23df4832010-08-04 17:14:06 +0000342 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000343 def test_constructor(self):
Victor Stinner17ca3232011-05-10 00:48:41 +0200344 if hasattr(ssl, 'PROTOCOL_SSLv2'):
345 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000346 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
347 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
348 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
349 self.assertRaises(TypeError, ssl.SSLContext)
350 self.assertRaises(ValueError, ssl.SSLContext, -1)
351 self.assertRaises(ValueError, ssl.SSLContext, 42)
352
Antoine Pitrou23df4832010-08-04 17:14:06 +0000353 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000354 def test_protocol(self):
355 for proto in PROTOCOLS:
356 ctx = ssl.SSLContext(proto)
357 self.assertEqual(ctx.protocol, proto)
358
359 def test_ciphers(self):
360 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
361 ctx.set_ciphers("ALL")
362 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000363 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000364 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000365
Antoine Pitrou23df4832010-08-04 17:14:06 +0000366 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000367 def test_options(self):
368 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
369 # OP_ALL is the default value
370 self.assertEqual(ssl.OP_ALL, ctx.options)
371 ctx.options |= ssl.OP_NO_SSLv2
372 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
373 ctx.options)
374 ctx.options |= ssl.OP_NO_SSLv3
375 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
376 ctx.options)
377 if can_clear_options():
378 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
379 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
380 ctx.options)
381 ctx.options = 0
382 self.assertEqual(0, ctx.options)
383 else:
384 with self.assertRaises(ValueError):
385 ctx.options = 0
386
Antoine Pitrou152efa22010-05-16 18:19:27 +0000387 def test_verify(self):
388 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
389 # Default value
390 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
391 ctx.verify_mode = ssl.CERT_OPTIONAL
392 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
393 ctx.verify_mode = ssl.CERT_REQUIRED
394 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
395 ctx.verify_mode = ssl.CERT_NONE
396 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
397 with self.assertRaises(TypeError):
398 ctx.verify_mode = None
399 with self.assertRaises(ValueError):
400 ctx.verify_mode = 42
401
402 def test_load_cert_chain(self):
403 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
404 # Combined key and cert in a single file
405 ctx.load_cert_chain(CERTFILE)
406 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
407 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000408 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000409 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000410 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000411 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000412 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000413 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000414 ctx.load_cert_chain(EMPTYCERT)
415 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000416 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000417 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
418 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
419 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_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(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000422 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000423 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000424 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000425 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
426 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000427 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000428 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000429 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000430
431 def test_load_verify_locations(self):
432 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
433 ctx.load_verify_locations(CERTFILE)
434 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
435 ctx.load_verify_locations(BYTES_CERTFILE)
436 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
437 self.assertRaises(TypeError, ctx.load_verify_locations)
438 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000439 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000440 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000441 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000442 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000443 ctx.load_verify_locations(BADCERT)
444 ctx.load_verify_locations(CERTFILE, CAPATH)
445 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
446
Victor Stinner80f75e62011-01-29 11:31:20 +0000447 # Issue #10989: crash if the second argument type is invalid
448 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
449
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000450 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000451 def test_session_stats(self):
452 for proto in PROTOCOLS:
453 ctx = ssl.SSLContext(proto)
454 self.assertEqual(ctx.session_stats(), {
455 'number': 0,
456 'connect': 0,
457 'connect_good': 0,
458 'connect_renegotiate': 0,
459 'accept': 0,
460 'accept_good': 0,
461 'accept_renegotiate': 0,
462 'hits': 0,
463 'misses': 0,
464 'timeouts': 0,
465 'cache_full': 0,
466 })
467
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000468 def test_set_default_verify_paths(self):
469 # There's not much we can do to test that it acts as expected,
470 # so just check it doesn't crash or raise an exception.
471 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
472 ctx.set_default_verify_paths()
473
Antoine Pitrou152efa22010-05-16 18:19:27 +0000474
Bill Janssen6e027db2007-11-15 22:23:56 +0000475class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000476
Antoine Pitrou480a1242010-04-28 21:37:09 +0000477 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000478 with support.transient_internet("svn.python.org"):
479 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
480 cert_reqs=ssl.CERT_NONE)
481 try:
482 s.connect(("svn.python.org", 443))
483 self.assertEqual({}, s.getpeercert())
484 finally:
485 s.close()
486
487 # this should fail because we have no verification certs
488 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
489 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000490 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
491 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000492 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493
Antoine Pitrou350c7222010-09-09 13:31:46 +0000494 # this should succeed because we specify the root cert
495 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
496 cert_reqs=ssl.CERT_REQUIRED,
497 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
498 try:
499 s.connect(("svn.python.org", 443))
500 self.assertTrue(s.getpeercert())
501 finally:
502 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000503
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000504 def test_connect_ex(self):
505 # Issue #11326: check connect_ex() implementation
506 with support.transient_internet("svn.python.org"):
507 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
508 cert_reqs=ssl.CERT_REQUIRED,
509 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
510 try:
511 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
512 self.assertTrue(s.getpeercert())
513 finally:
514 s.close()
515
516 def test_non_blocking_connect_ex(self):
517 # Issue #11326: non-blocking connect_ex() should allow handshake
518 # to proceed after the socket gets ready.
519 with support.transient_internet("svn.python.org"):
520 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
521 cert_reqs=ssl.CERT_REQUIRED,
522 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
523 do_handshake_on_connect=False)
524 try:
525 s.setblocking(False)
526 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitroud1c98452011-02-27 15:45:16 +0000527 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
528 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitrou86cbfec2011-02-26 23:25:34 +0000529 # Wait for connect to finish
530 select.select([], [s], [], 5.0)
531 # Non-blocking handshake
532 while True:
533 try:
534 s.do_handshake()
535 break
536 except ssl.SSLError as err:
537 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
538 select.select([s], [], [], 5.0)
539 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
540 select.select([], [s], [], 5.0)
541 else:
542 raise
543 # SSL established
544 self.assertTrue(s.getpeercert())
545 finally:
546 s.close()
547
Antoine Pitroub4410db2011-05-18 18:51:06 +0200548 def test_timeout_connect_ex(self):
549 # Issue #12065: on a timeout, connect_ex() should return the original
550 # errno (mimicking the behaviour of non-SSL sockets).
551 with support.transient_internet("svn.python.org"):
552 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
553 cert_reqs=ssl.CERT_REQUIRED,
554 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
555 do_handshake_on_connect=False)
556 try:
557 s.settimeout(0.0000001)
558 rc = s.connect_ex(('svn.python.org', 443))
559 if rc == 0:
560 self.skipTest("svn.python.org responded too quickly")
561 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
562 finally:
563 s.close()
564
Antoine Pitrou152efa22010-05-16 18:19:27 +0000565 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000566 with support.transient_internet("svn.python.org"):
567 # Same as test_connect, but with a separately created context
568 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
569 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
570 s.connect(("svn.python.org", 443))
571 try:
572 self.assertEqual({}, s.getpeercert())
573 finally:
574 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000575 # Same with a server hostname
576 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
577 server_hostname="svn.python.org")
578 if ssl.HAS_SNI:
579 s.connect(("svn.python.org", 443))
580 s.close()
581 else:
582 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000583 # This should fail because we have no verification certs
584 ctx.verify_mode = ssl.CERT_REQUIRED
585 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000586 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000587 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000588 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000589 # This should succeed because we specify the root cert
590 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
591 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
592 s.connect(("svn.python.org", 443))
593 try:
594 cert = s.getpeercert()
595 self.assertTrue(cert)
596 finally:
597 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000598
599 def test_connect_capath(self):
600 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000601 # NOTE: the subject hashing algorithm has been changed between
602 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
603 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000604 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000605 with support.transient_internet("svn.python.org"):
606 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
607 ctx.verify_mode = ssl.CERT_REQUIRED
608 ctx.load_verify_locations(capath=CAPATH)
609 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
610 s.connect(("svn.python.org", 443))
611 try:
612 cert = s.getpeercert()
613 self.assertTrue(cert)
614 finally:
615 s.close()
616 # Same with a bytes `capath` argument
617 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
618 ctx.verify_mode = ssl.CERT_REQUIRED
619 ctx.load_verify_locations(capath=BYTES_CAPATH)
620 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
621 s.connect(("svn.python.org", 443))
622 try:
623 cert = s.getpeercert()
624 self.assertTrue(cert)
625 finally:
626 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627
Antoine Pitroue3220242010-04-24 11:13:53 +0000628 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
629 def test_makefile_close(self):
630 # Issue #5238: creating a file-like object with makefile() shouldn't
631 # delay closing the underlying "real socket" (here tested with its
632 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000633 with support.transient_internet("svn.python.org"):
634 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
635 ss.connect(("svn.python.org", 443))
636 fd = ss.fileno()
637 f = ss.makefile()
638 f.close()
639 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000640 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000641 # Closing the SSL socket should close the fd too
642 ss.close()
643 gc.collect()
644 with self.assertRaises(OSError) as e:
645 os.read(fd, 0)
646 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000647
Antoine Pitrou480a1242010-04-28 21:37:09 +0000648 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000649 with support.transient_internet("svn.python.org"):
650 s = socket.socket(socket.AF_INET)
651 s.connect(("svn.python.org", 443))
652 s.setblocking(False)
653 s = ssl.wrap_socket(s,
654 cert_reqs=ssl.CERT_NONE,
655 do_handshake_on_connect=False)
656 count = 0
657 while True:
658 try:
659 count += 1
660 s.do_handshake()
661 break
662 except ssl.SSLError as err:
663 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
664 select.select([s], [], [])
665 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
666 select.select([], [s], [])
667 else:
668 raise
669 s.close()
670 if support.verbose:
671 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000672
Antoine Pitrou480a1242010-04-28 21:37:09 +0000673 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000674 with support.transient_internet("svn.python.org"):
675 pem = ssl.get_server_certificate(("svn.python.org", 443))
676 if not pem:
677 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000678
Antoine Pitrou350c7222010-09-09 13:31:46 +0000679 try:
680 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
681 except ssl.SSLError as x:
682 #should fail
683 if support.verbose:
684 sys.stdout.write("%s\n" % x)
685 else:
686 self.fail("Got server certificate %s for svn.python.org!" % pem)
687
688 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
689 if not pem:
690 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000691 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000692 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000693
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000694 def test_ciphers(self):
695 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000696 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000697 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000698 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000699 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000700 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
701 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
702 s.connect(remote)
703 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000704 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000705 with socket.socket(socket.AF_INET) as sock:
706 s = ssl.wrap_socket(sock,
707 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
708 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000709
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000710 def test_algorithms(self):
711 # Issue #8484: all algorithms should be available when verifying a
712 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000713 # SHA256 was added in OpenSSL 0.9.8
714 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
715 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000716 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
717 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000718 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000719 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000720 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
721 cert_reqs=ssl.CERT_REQUIRED,
722 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000723 try:
724 s.connect(remote)
725 if support.verbose:
726 sys.stdout.write("\nCipher with %r is %r\n" %
727 (remote, s.cipher()))
728 sys.stdout.write("Certificate is:\n%s\n" %
729 pprint.pformat(s.getpeercert()))
730 finally:
731 s.close()
732
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000733
734try:
735 import threading
736except ImportError:
737 _have_threads = False
738else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 _have_threads = True
740
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000741 from test.ssl_servers import make_https_server
742
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000743 class ThreadedEchoServer(threading.Thread):
744
745 class ConnectionHandler(threading.Thread):
746
747 """A mildly complicated class, because we want it to work both
748 with and without the SSL wrapper around the socket connection, so
749 that we can test the STARTTLS functionality."""
750
Bill Janssen6e027db2007-11-15 22:23:56 +0000751 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000752 self.server = server
753 self.running = False
754 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000755 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756 self.sock.setblocking(1)
757 self.sslconn = None
758 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000759 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000760
Antoine Pitrou480a1242010-04-28 21:37:09 +0000761 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000762 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000763 self.sslconn = self.server.context.wrap_socket(
764 self.sock, server_side=True)
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100765 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000766 # XXX Various errors can have happened here, for example
767 # a mismatching protocol version, an invalid certificate,
768 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100769 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000770 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000771 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000772 self.running = False
773 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000774 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000775 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000776 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000777 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000778 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000779 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000780 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
781 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000782 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
784 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000785 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000786 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
787 return True
788
789 def read(self):
790 if self.sslconn:
791 return self.sslconn.read()
792 else:
793 return self.sock.recv(1024)
794
795 def write(self, bytes):
796 if self.sslconn:
797 return self.sslconn.write(bytes)
798 else:
799 return self.sock.send(bytes)
800
801 def close(self):
802 if self.sslconn:
803 self.sslconn.close()
804 else:
805 self.sock.close()
806
Antoine Pitrou480a1242010-04-28 21:37:09 +0000807 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000808 self.running = True
809 if not self.server.starttls_server:
810 if not self.wrap_conn():
811 return
812 while self.running:
813 try:
814 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000815 stripped = msg.strip()
816 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000817 # eof, so quit this handler
818 self.running = False
819 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000820 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000821 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000822 sys.stdout.write(" server: client closed connection\n")
823 self.close()
824 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000825 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000826 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000827 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000828 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000829 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000830 if not self.wrap_conn():
831 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000832 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000833 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000834 if support.verbose and self.server.connectionchatty:
835 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000836 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000837 self.sock = self.sslconn.unwrap()
838 self.sslconn = None
839 if support.verbose and self.server.connectionchatty:
840 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000841 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000842 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000843 self.server.connectionchatty):
844 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000845 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
846 % (msg, ctype, msg.lower(), ctype))
847 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000848 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000849 if self.server.chatty:
850 handle_error("Test server failure:\n")
851 self.close()
852 self.running = False
853 # normally, we'd just stop here, but for the test
854 # harness, we want to stop the server
855 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856
Antoine Pitroub5218772010-05-21 09:56:06 +0000857 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000858 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000859 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000860 ciphers=None, context=None):
861 if context:
862 self.context = context
863 else:
864 self.context = ssl.SSLContext(ssl_version
865 if ssl_version is not None
866 else ssl.PROTOCOL_TLSv1)
867 self.context.verify_mode = (certreqs if certreqs is not None
868 else ssl.CERT_NONE)
869 if cacerts:
870 self.context.load_verify_locations(cacerts)
871 if certificate:
872 self.context.load_cert_chain(certificate)
873 if ciphers:
874 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000875 self.chatty = chatty
876 self.connectionchatty = connectionchatty
877 self.starttls_server = starttls_server
878 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000879 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000880 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100882 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000883 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000884 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000885
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100886 def __enter__(self):
887 self.start(threading.Event())
888 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100889 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100890
891 def __exit__(self, *args):
892 self.stop()
893 self.join()
894
Antoine Pitrou480a1242010-04-28 21:37:09 +0000895 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 self.flag = flag
897 threading.Thread.start(self)
898
Antoine Pitrou480a1242010-04-28 21:37:09 +0000899 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000900 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000901 self.sock.listen(5)
902 self.active = True
903 if self.flag:
904 # signal an event
905 self.flag.set()
906 while self.active:
907 try:
908 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000909 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000910 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000911 + repr(connaddr) + '\n')
912 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000913 handler.start()
914 except socket.timeout:
915 pass
916 except KeyboardInterrupt:
917 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000918 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919
Antoine Pitrou480a1242010-04-28 21:37:09 +0000920 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922
Bill Janssen54cc54c2007-12-14 22:08:56 +0000923 class AsyncoreEchoServer(threading.Thread):
924
925 # this one's based on asyncore.dispatcher
926
927 class EchoServer (asyncore.dispatcher):
928
929 class ConnectionHandler (asyncore.dispatcher_with_send):
930
931 def __init__(self, conn, certfile):
932 self.socket = ssl.wrap_socket(conn, server_side=True,
933 certfile=certfile,
934 do_handshake_on_connect=False)
935 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000936 self._ssl_accepting = True
937 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000938
939 def readable(self):
940 if isinstance(self.socket, ssl.SSLSocket):
941 while self.socket.pending() > 0:
942 self.handle_read_event()
943 return True
944
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000945 def _do_ssl_handshake(self):
946 try:
947 self.socket.do_handshake()
948 except ssl.SSLError as err:
949 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
950 ssl.SSL_ERROR_WANT_WRITE):
951 return
952 elif err.args[0] == ssl.SSL_ERROR_EOF:
953 return self.handle_close()
954 raise
955 except socket.error as err:
956 if err.args[0] == errno.ECONNABORTED:
957 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000958 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000959 self._ssl_accepting = False
960
961 def handle_read(self):
962 if self._ssl_accepting:
963 self._do_ssl_handshake()
964 else:
965 data = self.recv(1024)
966 if support.verbose:
967 sys.stdout.write(" server: read %s from client\n" % repr(data))
968 if not data:
969 self.close()
970 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000971 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000972
973 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000974 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000975 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000976 sys.stdout.write(" server: closed connection %s\n" % self.socket)
977
978 def handle_error(self):
979 raise
980
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000981 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000982 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000983 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
984 self.port = support.bind_port(sock, '')
985 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000986 self.listen(5)
987
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000988 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000989 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000990 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
991 self.ConnectionHandler(sock_obj, self.certfile)
992
993 def handle_error(self):
994 raise
995
Trent Nelson78520002008-04-10 20:54:35 +0000996 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000997 self.flag = None
998 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000999 self.server = self.EchoServer(certfile)
1000 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001001 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001002 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001003
1004 def __str__(self):
1005 return "<%s %s>" % (self.__class__.__name__, self.server)
1006
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001007 def __enter__(self):
1008 self.start(threading.Event())
1009 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001010 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001011
1012 def __exit__(self, *args):
1013 if support.verbose:
1014 sys.stdout.write(" cleanup: stopping server.\n")
1015 self.stop()
1016 if support.verbose:
1017 sys.stdout.write(" cleanup: joining server thread.\n")
1018 self.join()
1019 if support.verbose:
1020 sys.stdout.write(" cleanup: successfully joined.\n")
1021
Bill Janssen54cc54c2007-12-14 22:08:56 +00001022 def start (self, flag=None):
1023 self.flag = flag
1024 threading.Thread.start(self)
1025
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001027 self.active = True
1028 if self.flag:
1029 self.flag.set()
1030 while self.active:
1031 try:
1032 asyncore.loop(1)
1033 except:
1034 pass
1035
Antoine Pitrou480a1242010-04-28 21:37:09 +00001036 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001037 self.active = False
1038 self.server.close()
1039
Antoine Pitrou480a1242010-04-28 21:37:09 +00001040 def bad_cert_test(certfile):
1041 """
1042 Launch a server with CERT_REQUIRED, and check that trying to
1043 connect to it with the given client certificate fails.
1044 """
Trent Nelson78520002008-04-10 20:54:35 +00001045 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001046 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001047 cacerts=CERTFILE, chatty=False,
1048 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001049 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001050 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001051 with socket.socket() as sock:
1052 s = ssl.wrap_socket(sock,
1053 certfile=certfile,
1054 ssl_version=ssl.PROTOCOL_TLSv1)
1055 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001056 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001057 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001058 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001059 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001060 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001061 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001062 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001063 if x.errno != errno.ENOENT:
1064 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001065 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001066 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001067 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001068 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001069
Antoine Pitroub5218772010-05-21 09:56:06 +00001070 def server_params_test(client_context, server_context, indata=b"FOO\n",
1071 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001072 """
1073 Launch a server, connect a client to it and try various reads
1074 and writes.
1075 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001076 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001078 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001079 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001080 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001081 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001082 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001083 if connectionchatty:
1084 if support.verbose:
1085 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001086 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001087 s.write(arg)
1088 outdata = s.read()
1089 if connectionchatty:
1090 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001092 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001093 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001094 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1095 % (outdata[:20], len(outdata),
1096 indata[:20].lower(), len(indata)))
1097 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001098 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001099 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001100 sys.stdout.write(" client: closing connection.\n")
1101 s.close()
Thomas Woutersed03b412007-08-28 21:37:11 +00001102
Antoine Pitroub5218772010-05-21 09:56:06 +00001103 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1104 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001105 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001106 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001107 certtype = {
1108 ssl.CERT_NONE: "CERT_NONE",
1109 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1110 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1111 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001112 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001113 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001114 sys.stdout.write(formatstr %
1115 (ssl.get_protocol_name(client_protocol),
1116 ssl.get_protocol_name(server_protocol),
1117 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001118 client_context = ssl.SSLContext(client_protocol)
1119 client_context.options = ssl.OP_ALL | client_options
1120 server_context = ssl.SSLContext(server_protocol)
1121 server_context.options = ssl.OP_ALL | server_options
1122 for ctx in (client_context, server_context):
1123 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001124 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1125 # will send an SSLv3 hello (rather than SSLv2) starting from
1126 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001127 ctx.set_ciphers("ALL")
1128 ctx.load_cert_chain(CERTFILE)
1129 ctx.load_verify_locations(CERTFILE)
1130 try:
1131 server_params_test(client_context, server_context,
1132 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001133 # Protocol mismatch can result in either an SSLError, or a
1134 # "Connection reset by peer" error.
1135 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001136 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001137 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001138 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001140 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001141 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001142 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001143 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144 "Client protocol %s succeeded with server protocol %s!"
1145 % (ssl.get_protocol_name(client_protocol),
1146 ssl.get_protocol_name(server_protocol)))
1147
1148
Bill Janssen6e027db2007-11-15 22:23:56 +00001149 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150
Antoine Pitrou23df4832010-08-04 17:14:06 +00001151 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 def test_echo(self):
1153 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001154 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001155 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001156 for protocol in PROTOCOLS:
1157 context = ssl.SSLContext(protocol)
1158 context.load_cert_chain(CERTFILE)
1159 server_params_test(context, context,
1160 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001161
Antoine Pitrou480a1242010-04-28 21:37:09 +00001162 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001163 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001164 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001165 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1166 context.verify_mode = ssl.CERT_REQUIRED
1167 context.load_verify_locations(CERTFILE)
1168 context.load_cert_chain(CERTFILE)
1169 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001170 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001171 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001172 s.connect((HOST, server.port))
1173 cert = s.getpeercert()
1174 self.assertTrue(cert, "Can't get peer certificate.")
1175 cipher = s.cipher()
1176 if support.verbose:
1177 sys.stdout.write(pprint.pformat(cert) + '\n')
1178 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1179 if 'subject' not in cert:
1180 self.fail("No subject field in certificate: %s." %
1181 pprint.pformat(cert))
1182 if ((('organizationName', 'Python Software Foundation'),)
1183 not in cert['subject']):
1184 self.fail(
1185 "Missing or invalid 'organizationName' field in certificate subject; "
1186 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001187 self.assertIn('notBefore', cert)
1188 self.assertIn('notAfter', cert)
1189 before = ssl.cert_time_to_seconds(cert['notBefore'])
1190 after = ssl.cert_time_to_seconds(cert['notAfter'])
1191 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001192 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001193
Antoine Pitrou480a1242010-04-28 21:37:09 +00001194 def test_empty_cert(self):
1195 """Connecting with an empty cert file"""
1196 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1197 "nullcert.pem"))
1198 def test_malformed_cert(self):
1199 """Connecting with a badly formatted certificate (syntax error)"""
1200 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1201 "badcert.pem"))
1202 def test_nonexisting_cert(self):
1203 """Connecting with a non-existing cert file"""
1204 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1205 "wrongcert.pem"))
1206 def test_malformed_key(self):
1207 """Connecting with a badly formatted key (syntax error)"""
1208 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1209 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001210
Antoine Pitrou480a1242010-04-28 21:37:09 +00001211 def test_rude_shutdown(self):
1212 """A brutal shutdown of an SSL server should raise an IOError
1213 in the client when attempting handshake.
1214 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001215 listener_ready = threading.Event()
1216 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001217
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001218 s = socket.socket()
1219 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001220
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001221 # `listener` runs in a thread. It sits in an accept() until
1222 # the main thread connects. Then it rudely closes the socket,
1223 # and sets Event `listener_gone` to let the main thread know
1224 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001225 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001226 s.listen(5)
1227 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001228 newsock, addr = s.accept()
1229 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001230 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001231 listener_gone.set()
1232
1233 def connector():
1234 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001235 with socket.socket() as c:
1236 c.connect((HOST, port))
1237 listener_gone.wait()
1238 try:
1239 ssl_sock = ssl.wrap_socket(c)
1240 except IOError:
1241 pass
1242 else:
1243 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001244
1245 t = threading.Thread(target=listener)
1246 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001247 try:
1248 connector()
1249 finally:
1250 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001251
Antoine Pitrou23df4832010-08-04 17:14:06 +00001252 @skip_if_broken_ubuntu_ssl
Victor Stinneree18b6f2011-05-10 00:38:00 +02001253 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001254 def test_protocol_sslv2(self):
1255 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001256 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001257 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001258 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1259 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1260 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1261 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1262 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1263 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001264 # SSLv23 client with specific SSL options
1265 if no_sslv2_implies_sslv3_hello():
1266 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1267 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1268 client_options=ssl.OP_NO_SSLv2)
1269 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1270 client_options=ssl.OP_NO_SSLv3)
1271 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1272 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001273
Antoine Pitrou23df4832010-08-04 17:14:06 +00001274 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001275 def test_protocol_sslv23(self):
1276 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001277 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001278 sys.stdout.write("\n")
Victor Stinneree18b6f2011-05-10 00:38:00 +02001279 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1280 try:
1281 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1282 except (ssl.SSLError, socket.error) as x:
1283 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1284 if support.verbose:
1285 sys.stdout.write(
1286 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1287 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001288 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1289 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1290 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001291
Antoine Pitrou480a1242010-04-28 21:37:09 +00001292 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1293 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1294 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001295
Antoine Pitrou480a1242010-04-28 21:37:09 +00001296 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1297 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1298 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001299
Antoine Pitroub5218772010-05-21 09:56:06 +00001300 # Server with specific SSL options
1301 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1302 server_options=ssl.OP_NO_SSLv3)
1303 # Will choose TLSv1
1304 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1305 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1306 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1307 server_options=ssl.OP_NO_TLSv1)
1308
1309
Antoine Pitrou23df4832010-08-04 17:14:06 +00001310 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001311 def test_protocol_sslv3(self):
1312 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001313 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001314 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001315 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1316 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1317 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001318 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1319 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001320 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1321 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001322 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001323 if no_sslv2_implies_sslv3_hello():
1324 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1325 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1326 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001327
Antoine Pitrou23df4832010-08-04 17:14:06 +00001328 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001329 def test_protocol_tlsv1(self):
1330 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001331 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001332 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001333 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1334 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1335 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001336 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1337 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001338 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001339 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1340 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001341
Antoine Pitrou480a1242010-04-28 21:37:09 +00001342 def test_starttls(self):
1343 """Switching from clear text to encrypted and back again."""
1344 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 +00001345
Trent Nelson78520002008-04-10 20:54:35 +00001346 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001347 ssl_version=ssl.PROTOCOL_TLSv1,
1348 starttls_server=True,
1349 chatty=True,
1350 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001351 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001352 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001353 s = socket.socket()
1354 s.setblocking(1)
1355 s.connect((HOST, server.port))
1356 if support.verbose:
1357 sys.stdout.write("\n")
1358 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001359 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001360 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001361 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001362 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001363 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001364 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001365 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001366 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001367 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001368 msg = outdata.strip().lower()
1369 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1370 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001371 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001372 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001373 " client: read %r from server, starting TLS...\n"
1374 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001375 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1376 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001377 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1378 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001379 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001380 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001381 " client: read %r from server, ending TLS...\n"
1382 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001383 s = conn.unwrap()
1384 wrapped = False
1385 else:
1386 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001387 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001388 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001389 if support.verbose:
1390 sys.stdout.write(" client: closing connection.\n")
1391 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001392 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001393 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001394 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001395 if wrapped:
1396 conn.close()
1397 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001398 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001399
Antoine Pitrou480a1242010-04-28 21:37:09 +00001400 def test_socketserver(self):
1401 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001402 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001403 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001404 if support.verbose:
1405 sys.stdout.write('\n')
1406 with open(CERTFILE, 'rb') as f:
1407 d1 = f.read()
1408 d2 = ''
1409 # now fetch the same data from the HTTPS server
1410 url = 'https://%s:%d/%s' % (
1411 HOST, server.port, os.path.split(CERTFILE)[1])
1412 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001413 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001414 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001415 if dlen and (int(dlen) > 0):
1416 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001417 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001418 sys.stdout.write(
1419 " client: read %d bytes from remote server '%s'\n"
1420 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001421 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001422 f.close()
1423 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001424
Antoine Pitrou480a1242010-04-28 21:37:09 +00001425 def test_asyncore_server(self):
1426 """Check the example asyncore integration."""
1427 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001428
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001429 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001430 sys.stdout.write("\n")
1431
Antoine Pitrou480a1242010-04-28 21:37:09 +00001432 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001433 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001434 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001435 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001436 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001437 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001438 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001439 " client: sending %r...\n" % indata)
1440 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001441 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001442 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001443 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001444 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001445 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001446 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1447 % (outdata[:20], len(outdata),
1448 indata[:20].lower(), len(indata)))
1449 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001450 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001451 sys.stdout.write(" client: closing connection.\n")
1452 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001453 if support.verbose:
1454 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001455
Antoine Pitrou480a1242010-04-28 21:37:09 +00001456 def test_recv_send(self):
1457 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001458 if support.verbose:
1459 sys.stdout.write("\n")
1460
1461 server = ThreadedEchoServer(CERTFILE,
1462 certreqs=ssl.CERT_NONE,
1463 ssl_version=ssl.PROTOCOL_TLSv1,
1464 cacerts=CERTFILE,
1465 chatty=True,
1466 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001467 with server:
1468 s = ssl.wrap_socket(socket.socket(),
1469 server_side=False,
1470 certfile=CERTFILE,
1471 ca_certs=CERTFILE,
1472 cert_reqs=ssl.CERT_NONE,
1473 ssl_version=ssl.PROTOCOL_TLSv1)
1474 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001475 # helper methods for standardising recv* method signatures
1476 def _recv_into():
1477 b = bytearray(b"\0"*100)
1478 count = s.recv_into(b)
1479 return b[:count]
1480
1481 def _recvfrom_into():
1482 b = bytearray(b"\0"*100)
1483 count, addr = s.recvfrom_into(b)
1484 return b[:count]
1485
1486 # (name, method, whether to expect success, *args)
1487 send_methods = [
1488 ('send', s.send, True, []),
1489 ('sendto', s.sendto, False, ["some.address"]),
1490 ('sendall', s.sendall, True, []),
1491 ]
1492 recv_methods = [
1493 ('recv', s.recv, True, []),
1494 ('recvfrom', s.recvfrom, False, ["some.address"]),
1495 ('recv_into', _recv_into, True, []),
1496 ('recvfrom_into', _recvfrom_into, False, []),
1497 ]
1498 data_prefix = "PREFIX_"
1499
1500 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001501 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001502 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001503 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001504 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001505 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001506 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001507 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001508 "<<{outdata:r}>> ({nout:d}) received; "
1509 "expected <<{indata:r}>> ({nin:d})\n".format(
1510 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001511 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001512 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001513 )
1514 )
1515 except ValueError as e:
1516 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001517 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001518 "Failed to send with method <<{name:s}>>; "
1519 "expected to succeed.\n".format(name=meth_name)
1520 )
1521 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001522 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001523 "Method <<{name:s}>> failed with unexpected "
1524 "exception message: {exp:s}\n".format(
1525 name=meth_name, exp=e
1526 )
1527 )
1528
1529 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001530 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001531 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001532 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001533 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001534 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001535 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001536 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001537 "<<{outdata:r}>> ({nout:d}) received; "
1538 "expected <<{indata:r}>> ({nin:d})\n".format(
1539 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001540 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001541 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001542 )
1543 )
1544 except ValueError as e:
1545 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001546 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001547 "Failed to receive with method <<{name:s}>>; "
1548 "expected to succeed.\n".format(name=meth_name)
1549 )
1550 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001551 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001552 "Method <<{name:s}>> failed with unexpected "
1553 "exception message: {exp:s}\n".format(
1554 name=meth_name, exp=e
1555 )
1556 )
1557 # consume data
1558 s.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001559 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001560 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001561
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001562 def test_handshake_timeout(self):
1563 # Issue #5103: SSL handshake must respect the socket timeout
1564 server = socket.socket(socket.AF_INET)
1565 host = "127.0.0.1"
1566 port = support.bind_port(server)
1567 started = threading.Event()
1568 finish = False
1569
1570 def serve():
1571 server.listen(5)
1572 started.set()
1573 conns = []
1574 while not finish:
1575 r, w, e = select.select([server], [], [], 0.1)
1576 if server in r:
1577 # Let the socket hang around rather than having
1578 # it closed by garbage collection.
1579 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001580 for sock in conns:
1581 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001582
1583 t = threading.Thread(target=serve)
1584 t.start()
1585 started.wait()
1586
1587 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001588 try:
1589 c = socket.socket(socket.AF_INET)
1590 c.settimeout(0.2)
1591 c.connect((host, port))
1592 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001593 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001594 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001595 finally:
1596 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001597 try:
1598 c = socket.socket(socket.AF_INET)
1599 c = ssl.wrap_socket(c)
1600 c.settimeout(0.2)
1601 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001602 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001603 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001604 finally:
1605 c.close()
1606 finally:
1607 finish = True
1608 t.join()
1609 server.close()
1610
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001611 def test_default_ciphers(self):
1612 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1613 try:
1614 # Force a set of weak ciphers on our client context
1615 context.set_ciphers("DES")
1616 except ssl.SSLError:
1617 self.skipTest("no DES cipher available")
1618 with ThreadedEchoServer(CERTFILE,
1619 ssl_version=ssl.PROTOCOL_SSLv23,
1620 chatty=False) as server:
1621 with socket.socket() as sock:
1622 s = context.wrap_socket(sock)
1623 with self.assertRaises((OSError, ssl.SSLError)):
1624 s.connect((HOST, server.port))
1625 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1626
Bill Janssen58afe4c2008-09-08 16:45:19 +00001627
Thomas Woutersed03b412007-08-28 21:37:11 +00001628def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001629 if support.verbose:
1630 plats = {
1631 'Linux': platform.linux_distribution,
1632 'Mac': platform.mac_ver,
1633 'Windows': platform.win32_ver,
1634 }
1635 for name, func in plats.items():
1636 plat = func()
1637 if plat and plat[0]:
1638 plat = '%s %r' % (name, plat)
1639 break
1640 else:
1641 plat = repr(platform.platform())
1642 print("test_ssl: testing with %r %r" %
1643 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1644 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001645 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001646
Antoine Pitrou152efa22010-05-16 18:19:27 +00001647 for filename in [
1648 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1649 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1650 BADCERT, BADKEY, EMPTYCERT]:
1651 if not os.path.exists(filename):
1652 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001653
Antoine Pitrou152efa22010-05-16 18:19:27 +00001654 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001655
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001656 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001657 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001658
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001659 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001660 thread_info = support.threading_setup()
1661 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001662 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001663
Antoine Pitrou480a1242010-04-28 21:37:09 +00001664 try:
1665 support.run_unittest(*tests)
1666 finally:
1667 if _have_threads:
1668 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001669
1670if __name__ == "__main__":
1671 test_main()