blob: d4c5e6351a30c4dd933a7ddb8025b11a6e977213 [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 Pitrou152efa22010-05-16 18:19:27 +0000561 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000562 with support.transient_internet("svn.python.org"):
563 # Same as test_connect, but with a separately created context
564 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
565 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
566 s.connect(("svn.python.org", 443))
567 try:
568 self.assertEqual({}, s.getpeercert())
569 finally:
570 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000571 # Same with a server hostname
572 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
573 server_hostname="svn.python.org")
574 if ssl.HAS_SNI:
575 s.connect(("svn.python.org", 443))
576 s.close()
577 else:
578 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000579 # This should fail because we have no verification certs
580 ctx.verify_mode = ssl.CERT_REQUIRED
581 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000582 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000583 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000584 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000585 # This should succeed because we specify the root cert
586 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
587 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
588 s.connect(("svn.python.org", 443))
589 try:
590 cert = s.getpeercert()
591 self.assertTrue(cert)
592 finally:
593 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000594
595 def test_connect_capath(self):
596 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000597 # NOTE: the subject hashing algorithm has been changed between
598 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
599 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000600 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000601 with support.transient_internet("svn.python.org"):
602 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
603 ctx.verify_mode = ssl.CERT_REQUIRED
604 ctx.load_verify_locations(capath=CAPATH)
605 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
606 s.connect(("svn.python.org", 443))
607 try:
608 cert = s.getpeercert()
609 self.assertTrue(cert)
610 finally:
611 s.close()
612 # Same with a bytes `capath` argument
613 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
614 ctx.verify_mode = ssl.CERT_REQUIRED
615 ctx.load_verify_locations(capath=BYTES_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()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000623
Antoine Pitroue3220242010-04-24 11:13:53 +0000624 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
625 def test_makefile_close(self):
626 # Issue #5238: creating a file-like object with makefile() shouldn't
627 # delay closing the underlying "real socket" (here tested with its
628 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000629 with support.transient_internet("svn.python.org"):
630 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
631 ss.connect(("svn.python.org", 443))
632 fd = ss.fileno()
633 f = ss.makefile()
634 f.close()
635 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000636 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000637 # Closing the SSL socket should close the fd too
638 ss.close()
639 gc.collect()
640 with self.assertRaises(OSError) as e:
641 os.read(fd, 0)
642 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000643
Antoine Pitrou480a1242010-04-28 21:37:09 +0000644 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000645 with support.transient_internet("svn.python.org"):
646 s = socket.socket(socket.AF_INET)
647 s.connect(("svn.python.org", 443))
648 s.setblocking(False)
649 s = ssl.wrap_socket(s,
650 cert_reqs=ssl.CERT_NONE,
651 do_handshake_on_connect=False)
652 count = 0
653 while True:
654 try:
655 count += 1
656 s.do_handshake()
657 break
658 except ssl.SSLError as err:
659 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
660 select.select([s], [], [])
661 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
662 select.select([], [s], [])
663 else:
664 raise
665 s.close()
666 if support.verbose:
667 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000668
Antoine Pitrou480a1242010-04-28 21:37:09 +0000669 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000670 with support.transient_internet("svn.python.org"):
671 pem = ssl.get_server_certificate(("svn.python.org", 443))
672 if not pem:
673 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000674
Antoine Pitrou350c7222010-09-09 13:31:46 +0000675 try:
676 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
677 except ssl.SSLError as x:
678 #should fail
679 if support.verbose:
680 sys.stdout.write("%s\n" % x)
681 else:
682 self.fail("Got server certificate %s for svn.python.org!" % pem)
683
684 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
685 if not pem:
686 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000687 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000688 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000689
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000690 def test_ciphers(self):
691 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000692 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000693 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000694 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000695 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000696 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
697 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
698 s.connect(remote)
699 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000700 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000701 with socket.socket(socket.AF_INET) as sock:
702 s = ssl.wrap_socket(sock,
703 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
704 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000705
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000706 def test_algorithms(self):
707 # Issue #8484: all algorithms should be available when verifying a
708 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000709 # SHA256 was added in OpenSSL 0.9.8
710 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
711 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200712 # sha256.tbs-internet.com needs SNI to use the correct certificate
713 if not ssl.HAS_SNI:
714 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000715 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
716 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000717 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000718 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200719 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
720 ctx.verify_mode = ssl.CERT_REQUIRED
721 ctx.load_verify_locations(sha256_cert)
722 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
723 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000724 try:
725 s.connect(remote)
726 if support.verbose:
727 sys.stdout.write("\nCipher with %r is %r\n" %
728 (remote, s.cipher()))
729 sys.stdout.write("Certificate is:\n%s\n" %
730 pprint.pformat(s.getpeercert()))
731 finally:
732 s.close()
733
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000734
735try:
736 import threading
737except ImportError:
738 _have_threads = False
739else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000740 _have_threads = True
741
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000742 from test.ssl_servers import make_https_server
743
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000744 class ThreadedEchoServer(threading.Thread):
745
746 class ConnectionHandler(threading.Thread):
747
748 """A mildly complicated class, because we want it to work both
749 with and without the SSL wrapper around the socket connection, so
750 that we can test the STARTTLS functionality."""
751
Bill Janssen6e027db2007-11-15 22:23:56 +0000752 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000753 self.server = server
754 self.running = False
755 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000756 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000757 self.sock.setblocking(1)
758 self.sslconn = None
759 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000760 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000761
Antoine Pitrou480a1242010-04-28 21:37:09 +0000762 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000764 self.sslconn = self.server.context.wrap_socket(
765 self.sock, server_side=True)
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100766 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000767 # XXX Various errors can have happened here, for example
768 # a mismatching protocol version, an invalid certificate,
769 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100770 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000771 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000772 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000773 self.running = False
774 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000775 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000776 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000777 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000778 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000779 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000780 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000781 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
782 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000783 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000784 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
785 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000786 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
788 return True
789
790 def read(self):
791 if self.sslconn:
792 return self.sslconn.read()
793 else:
794 return self.sock.recv(1024)
795
796 def write(self, bytes):
797 if self.sslconn:
798 return self.sslconn.write(bytes)
799 else:
800 return self.sock.send(bytes)
801
802 def close(self):
803 if self.sslconn:
804 self.sslconn.close()
805 else:
806 self.sock.close()
807
Antoine Pitrou480a1242010-04-28 21:37:09 +0000808 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000809 self.running = True
810 if not self.server.starttls_server:
811 if not self.wrap_conn():
812 return
813 while self.running:
814 try:
815 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000816 stripped = msg.strip()
817 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000818 # eof, so quit this handler
819 self.running = False
820 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000821 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000822 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000823 sys.stdout.write(" server: client closed connection\n")
824 self.close()
825 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000826 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000827 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000828 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000829 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000830 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000831 if not self.wrap_conn():
832 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000833 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000834 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000835 if support.verbose and self.server.connectionchatty:
836 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000837 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000838 self.sock = self.sslconn.unwrap()
839 self.sslconn = None
840 if support.verbose and self.server.connectionchatty:
841 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000842 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000843 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000844 self.server.connectionchatty):
845 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000846 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
847 % (msg, ctype, msg.lower(), ctype))
848 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000849 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850 if self.server.chatty:
851 handle_error("Test server failure:\n")
852 self.close()
853 self.running = False
854 # normally, we'd just stop here, but for the test
855 # harness, we want to stop the server
856 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000857
Antoine Pitroub5218772010-05-21 09:56:06 +0000858 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000859 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000860 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000861 ciphers=None, context=None):
862 if context:
863 self.context = context
864 else:
865 self.context = ssl.SSLContext(ssl_version
866 if ssl_version is not None
867 else ssl.PROTOCOL_TLSv1)
868 self.context.verify_mode = (certreqs if certreqs is not None
869 else ssl.CERT_NONE)
870 if cacerts:
871 self.context.load_verify_locations(cacerts)
872 if certificate:
873 self.context.load_cert_chain(certificate)
874 if ciphers:
875 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000876 self.chatty = chatty
877 self.connectionchatty = connectionchatty
878 self.starttls_server = starttls_server
879 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000880 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000882 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100883 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000884 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000885 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100887 def __enter__(self):
888 self.start(threading.Event())
889 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100890 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +0100891
892 def __exit__(self, *args):
893 self.stop()
894 self.join()
895
Antoine Pitrou480a1242010-04-28 21:37:09 +0000896 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000897 self.flag = flag
898 threading.Thread.start(self)
899
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000901 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000902 self.sock.listen(5)
903 self.active = True
904 if self.flag:
905 # signal an event
906 self.flag.set()
907 while self.active:
908 try:
909 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000910 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000912 + repr(connaddr) + '\n')
913 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000914 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +0100915 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000916 except socket.timeout:
917 pass
918 except KeyboardInterrupt:
919 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000920 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921
Antoine Pitrou480a1242010-04-28 21:37:09 +0000922 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924
Bill Janssen54cc54c2007-12-14 22:08:56 +0000925 class AsyncoreEchoServer(threading.Thread):
926
927 # this one's based on asyncore.dispatcher
928
929 class EchoServer (asyncore.dispatcher):
930
931 class ConnectionHandler (asyncore.dispatcher_with_send):
932
933 def __init__(self, conn, certfile):
934 self.socket = ssl.wrap_socket(conn, server_side=True,
935 certfile=certfile,
936 do_handshake_on_connect=False)
937 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000938 self._ssl_accepting = True
939 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000940
941 def readable(self):
942 if isinstance(self.socket, ssl.SSLSocket):
943 while self.socket.pending() > 0:
944 self.handle_read_event()
945 return True
946
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000947 def _do_ssl_handshake(self):
948 try:
949 self.socket.do_handshake()
950 except ssl.SSLError as err:
951 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
952 ssl.SSL_ERROR_WANT_WRITE):
953 return
954 elif err.args[0] == ssl.SSL_ERROR_EOF:
955 return self.handle_close()
956 raise
957 except socket.error as err:
958 if err.args[0] == errno.ECONNABORTED:
959 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000960 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000961 self._ssl_accepting = False
962
963 def handle_read(self):
964 if self._ssl_accepting:
965 self._do_ssl_handshake()
966 else:
967 data = self.recv(1024)
968 if support.verbose:
969 sys.stdout.write(" server: read %s from client\n" % repr(data))
970 if not data:
971 self.close()
972 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000973 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000974
975 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000976 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000977 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000978 sys.stdout.write(" server: closed connection %s\n" % self.socket)
979
980 def handle_error(self):
981 raise
982
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000983 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000984 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000985 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
986 self.port = support.bind_port(sock, '')
987 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000988 self.listen(5)
989
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000990 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000991 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000992 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
993 self.ConnectionHandler(sock_obj, self.certfile)
994
995 def handle_error(self):
996 raise
997
Trent Nelson78520002008-04-10 20:54:35 +0000998 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000999 self.flag = None
1000 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001001 self.server = self.EchoServer(certfile)
1002 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001003 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001004 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001005
1006 def __str__(self):
1007 return "<%s %s>" % (self.__class__.__name__, self.server)
1008
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001009 def __enter__(self):
1010 self.start(threading.Event())
1011 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001012 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001013
1014 def __exit__(self, *args):
1015 if support.verbose:
1016 sys.stdout.write(" cleanup: stopping server.\n")
1017 self.stop()
1018 if support.verbose:
1019 sys.stdout.write(" cleanup: joining server thread.\n")
1020 self.join()
1021 if support.verbose:
1022 sys.stdout.write(" cleanup: successfully joined.\n")
1023
Bill Janssen54cc54c2007-12-14 22:08:56 +00001024 def start (self, flag=None):
1025 self.flag = flag
1026 threading.Thread.start(self)
1027
Antoine Pitrou480a1242010-04-28 21:37:09 +00001028 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001029 self.active = True
1030 if self.flag:
1031 self.flag.set()
1032 while self.active:
1033 try:
1034 asyncore.loop(1)
1035 except:
1036 pass
1037
Antoine Pitrou480a1242010-04-28 21:37:09 +00001038 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001039 self.active = False
1040 self.server.close()
1041
Antoine Pitrou480a1242010-04-28 21:37:09 +00001042 def bad_cert_test(certfile):
1043 """
1044 Launch a server with CERT_REQUIRED, and check that trying to
1045 connect to it with the given client certificate fails.
1046 """
Trent Nelson78520002008-04-10 20:54:35 +00001047 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001048 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001049 cacerts=CERTFILE, chatty=False,
1050 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001051 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001052 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001053 with socket.socket() as sock:
1054 s = ssl.wrap_socket(sock,
1055 certfile=certfile,
1056 ssl_version=ssl.PROTOCOL_TLSv1)
1057 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001058 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001059 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001060 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001061 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001062 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001063 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001064 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001065 if x.errno != errno.ENOENT:
1066 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001067 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001068 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001069 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001070 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001071
Antoine Pitroub5218772010-05-21 09:56:06 +00001072 def server_params_test(client_context, server_context, indata=b"FOO\n",
1073 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001074 """
1075 Launch a server, connect a client to it and try various reads
1076 and writes.
1077 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001078 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001079 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001080 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001081 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001082 with client_context.wrap_socket(socket.socket()) as s:
1083 s.connect((HOST, server.port))
1084 for arg in [indata, bytearray(indata), memoryview(indata)]:
1085 if connectionchatty:
1086 if support.verbose:
1087 sys.stdout.write(
1088 " client: sending %r...\n" % indata)
1089 s.write(arg)
1090 outdata = s.read()
1091 if connectionchatty:
1092 if support.verbose:
1093 sys.stdout.write(" client: read %r\n" % outdata)
1094 if outdata != indata.lower():
1095 raise AssertionError(
1096 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1097 % (outdata[:20], len(outdata),
1098 indata[:20].lower(), len(indata)))
1099 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001100 if connectionchatty:
1101 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001102 sys.stdout.write(" client: closing connection.\n")
1103 s.close()
Thomas Woutersed03b412007-08-28 21:37:11 +00001104
Antoine Pitroub5218772010-05-21 09:56:06 +00001105 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1106 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001107 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001108 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001109 certtype = {
1110 ssl.CERT_NONE: "CERT_NONE",
1111 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1112 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1113 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001114 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001115 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001116 sys.stdout.write(formatstr %
1117 (ssl.get_protocol_name(client_protocol),
1118 ssl.get_protocol_name(server_protocol),
1119 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001120 client_context = ssl.SSLContext(client_protocol)
1121 client_context.options = ssl.OP_ALL | client_options
1122 server_context = ssl.SSLContext(server_protocol)
1123 server_context.options = ssl.OP_ALL | server_options
1124 for ctx in (client_context, server_context):
1125 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001126 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1127 # will send an SSLv3 hello (rather than SSLv2) starting from
1128 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001129 ctx.set_ciphers("ALL")
1130 ctx.load_cert_chain(CERTFILE)
1131 ctx.load_verify_locations(CERTFILE)
1132 try:
1133 server_params_test(client_context, server_context,
1134 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001135 # Protocol mismatch can result in either an SSLError, or a
1136 # "Connection reset by peer" error.
1137 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001138 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001139 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001140 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001142 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001143 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001144 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001145 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001146 "Client protocol %s succeeded with server protocol %s!"
1147 % (ssl.get_protocol_name(client_protocol),
1148 ssl.get_protocol_name(server_protocol)))
1149
1150
Bill Janssen6e027db2007-11-15 22:23:56 +00001151 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001152
Antoine Pitrou23df4832010-08-04 17:14:06 +00001153 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001154 def test_echo(self):
1155 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001156 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001157 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001158 for protocol in PROTOCOLS:
1159 context = ssl.SSLContext(protocol)
1160 context.load_cert_chain(CERTFILE)
1161 server_params_test(context, context,
1162 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001163
Antoine Pitrou480a1242010-04-28 21:37:09 +00001164 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001165 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001167 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1168 context.verify_mode = ssl.CERT_REQUIRED
1169 context.load_verify_locations(CERTFILE)
1170 context.load_cert_chain(CERTFILE)
1171 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001172 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001173 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001174 s.connect((HOST, server.port))
1175 cert = s.getpeercert()
1176 self.assertTrue(cert, "Can't get peer certificate.")
1177 cipher = s.cipher()
1178 if support.verbose:
1179 sys.stdout.write(pprint.pformat(cert) + '\n')
1180 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1181 if 'subject' not in cert:
1182 self.fail("No subject field in certificate: %s." %
1183 pprint.pformat(cert))
1184 if ((('organizationName', 'Python Software Foundation'),)
1185 not in cert['subject']):
1186 self.fail(
1187 "Missing or invalid 'organizationName' field in certificate subject; "
1188 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001189 self.assertIn('notBefore', cert)
1190 self.assertIn('notAfter', cert)
1191 before = ssl.cert_time_to_seconds(cert['notBefore'])
1192 after = ssl.cert_time_to_seconds(cert['notAfter'])
1193 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001194 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001195
Antoine Pitrou480a1242010-04-28 21:37:09 +00001196 def test_empty_cert(self):
1197 """Connecting with an empty cert file"""
1198 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1199 "nullcert.pem"))
1200 def test_malformed_cert(self):
1201 """Connecting with a badly formatted certificate (syntax error)"""
1202 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1203 "badcert.pem"))
1204 def test_nonexisting_cert(self):
1205 """Connecting with a non-existing cert file"""
1206 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1207 "wrongcert.pem"))
1208 def test_malformed_key(self):
1209 """Connecting with a badly formatted key (syntax error)"""
1210 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1211 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001212
Antoine Pitrou480a1242010-04-28 21:37:09 +00001213 def test_rude_shutdown(self):
1214 """A brutal shutdown of an SSL server should raise an IOError
1215 in the client when attempting handshake.
1216 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001217 listener_ready = threading.Event()
1218 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001219
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001220 s = socket.socket()
1221 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001222
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001223 # `listener` runs in a thread. It sits in an accept() until
1224 # the main thread connects. Then it rudely closes the socket,
1225 # and sets Event `listener_gone` to let the main thread know
1226 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001227 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001228 s.listen(5)
1229 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001230 newsock, addr = s.accept()
1231 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001232 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001233 listener_gone.set()
1234
1235 def connector():
1236 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001237 with socket.socket() as c:
1238 c.connect((HOST, port))
1239 listener_gone.wait()
1240 try:
1241 ssl_sock = ssl.wrap_socket(c)
1242 except IOError:
1243 pass
1244 else:
1245 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001246
1247 t = threading.Thread(target=listener)
1248 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001249 try:
1250 connector()
1251 finally:
1252 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001253
Antoine Pitrou23df4832010-08-04 17:14:06 +00001254 @skip_if_broken_ubuntu_ssl
Victor Stinneree18b6f2011-05-10 00:38:00 +02001255 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001256 def test_protocol_sslv2(self):
1257 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001258 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001259 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001260 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1261 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1262 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1263 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1264 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1265 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001266 # SSLv23 client with specific SSL options
1267 if no_sslv2_implies_sslv3_hello():
1268 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1269 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1270 client_options=ssl.OP_NO_SSLv2)
1271 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1272 client_options=ssl.OP_NO_SSLv3)
1273 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1274 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001275
Antoine Pitrou23df4832010-08-04 17:14:06 +00001276 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001277 def test_protocol_sslv23(self):
1278 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001279 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001280 sys.stdout.write("\n")
Victor Stinneree18b6f2011-05-10 00:38:00 +02001281 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1282 try:
1283 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1284 except (ssl.SSLError, socket.error) as x:
1285 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1286 if support.verbose:
1287 sys.stdout.write(
1288 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1289 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001290 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1291 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1292 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001293
Antoine Pitrou480a1242010-04-28 21:37:09 +00001294 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1295 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1296 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001297
Antoine Pitrou480a1242010-04-28 21:37:09 +00001298 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1299 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1300 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001301
Antoine Pitroub5218772010-05-21 09:56:06 +00001302 # Server with specific SSL options
1303 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1304 server_options=ssl.OP_NO_SSLv3)
1305 # Will choose TLSv1
1306 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1307 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1308 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1309 server_options=ssl.OP_NO_TLSv1)
1310
1311
Antoine Pitrou23df4832010-08-04 17:14:06 +00001312 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001313 def test_protocol_sslv3(self):
1314 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001315 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001316 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001317 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1318 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1319 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001320 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1321 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001322 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1323 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001324 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001325 if no_sslv2_implies_sslv3_hello():
1326 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1327 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1328 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001329
Antoine Pitrou23df4832010-08-04 17:14:06 +00001330 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001331 def test_protocol_tlsv1(self):
1332 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001333 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001334 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001335 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1336 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1337 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +02001338 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1339 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001340 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001341 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1342 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001343
Antoine Pitrou480a1242010-04-28 21:37:09 +00001344 def test_starttls(self):
1345 """Switching from clear text to encrypted and back again."""
1346 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 +00001347
Trent Nelson78520002008-04-10 20:54:35 +00001348 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001349 ssl_version=ssl.PROTOCOL_TLSv1,
1350 starttls_server=True,
1351 chatty=True,
1352 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001353 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001354 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001355 s = socket.socket()
1356 s.setblocking(1)
1357 s.connect((HOST, server.port))
1358 if support.verbose:
1359 sys.stdout.write("\n")
1360 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001361 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001362 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001363 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001364 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001365 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001366 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001367 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001368 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001369 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001370 msg = outdata.strip().lower()
1371 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1372 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001373 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001374 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001375 " client: read %r from server, starting TLS...\n"
1376 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001377 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1378 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001379 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1380 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001381 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001382 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 " client: read %r from server, ending TLS...\n"
1384 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001385 s = conn.unwrap()
1386 wrapped = False
1387 else:
1388 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001389 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001390 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001391 if support.verbose:
1392 sys.stdout.write(" client: closing connection.\n")
1393 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001394 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001395 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001397 if wrapped:
1398 conn.close()
1399 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001400 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001401
Antoine Pitrou480a1242010-04-28 21:37:09 +00001402 def test_socketserver(self):
1403 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001404 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001405 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001406 if support.verbose:
1407 sys.stdout.write('\n')
1408 with open(CERTFILE, 'rb') as f:
1409 d1 = f.read()
1410 d2 = ''
1411 # now fetch the same data from the HTTPS server
1412 url = 'https://%s:%d/%s' % (
1413 HOST, server.port, os.path.split(CERTFILE)[1])
1414 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001415 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001416 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001417 if dlen and (int(dlen) > 0):
1418 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001419 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001420 sys.stdout.write(
1421 " client: read %d bytes from remote server '%s'\n"
1422 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001423 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001424 f.close()
1425 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001426
Antoine Pitrou480a1242010-04-28 21:37:09 +00001427 def test_asyncore_server(self):
1428 """Check the example asyncore integration."""
1429 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001430
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001431 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001432 sys.stdout.write("\n")
1433
Antoine Pitrou480a1242010-04-28 21:37:09 +00001434 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001435 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001436 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001437 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001438 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001439 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001440 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001441 " client: sending %r...\n" % indata)
1442 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001443 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001444 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001445 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001446 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001447 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1449 % (outdata[:20], len(outdata),
1450 indata[:20].lower(), len(indata)))
1451 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001452 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001453 sys.stdout.write(" client: closing connection.\n")
1454 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001455 if support.verbose:
1456 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001457
Antoine Pitrou480a1242010-04-28 21:37:09 +00001458 def test_recv_send(self):
1459 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001460 if support.verbose:
1461 sys.stdout.write("\n")
1462
1463 server = ThreadedEchoServer(CERTFILE,
1464 certreqs=ssl.CERT_NONE,
1465 ssl_version=ssl.PROTOCOL_TLSv1,
1466 cacerts=CERTFILE,
1467 chatty=True,
1468 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001469 with server:
1470 s = ssl.wrap_socket(socket.socket(),
1471 server_side=False,
1472 certfile=CERTFILE,
1473 ca_certs=CERTFILE,
1474 cert_reqs=ssl.CERT_NONE,
1475 ssl_version=ssl.PROTOCOL_TLSv1)
1476 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001477 # helper methods for standardising recv* method signatures
1478 def _recv_into():
1479 b = bytearray(b"\0"*100)
1480 count = s.recv_into(b)
1481 return b[:count]
1482
1483 def _recvfrom_into():
1484 b = bytearray(b"\0"*100)
1485 count, addr = s.recvfrom_into(b)
1486 return b[:count]
1487
1488 # (name, method, whether to expect success, *args)
1489 send_methods = [
1490 ('send', s.send, True, []),
1491 ('sendto', s.sendto, False, ["some.address"]),
1492 ('sendall', s.sendall, True, []),
1493 ]
1494 recv_methods = [
1495 ('recv', s.recv, True, []),
1496 ('recvfrom', s.recvfrom, False, ["some.address"]),
1497 ('recv_into', _recv_into, True, []),
1498 ('recvfrom_into', _recvfrom_into, False, []),
1499 ]
1500 data_prefix = "PREFIX_"
1501
1502 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001503 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001504 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001505 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001506 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001507 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001508 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001509 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001510 "<<{outdata:r}>> ({nout:d}) received; "
1511 "expected <<{indata:r}>> ({nin:d})\n".format(
1512 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001513 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001514 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001515 )
1516 )
1517 except ValueError as e:
1518 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001519 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001520 "Failed to send with method <<{name:s}>>; "
1521 "expected to succeed.\n".format(name=meth_name)
1522 )
1523 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001524 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001525 "Method <<{name:s}>> failed with unexpected "
1526 "exception message: {exp:s}\n".format(
1527 name=meth_name, exp=e
1528 )
1529 )
1530
1531 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001532 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001533 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001534 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001535 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001536 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001537 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001538 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001539 "<<{outdata:r}>> ({nout:d}) received; "
1540 "expected <<{indata:r}>> ({nin:d})\n".format(
1541 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001542 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001543 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001544 )
1545 )
1546 except ValueError as e:
1547 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001548 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001549 "Failed to receive with method <<{name:s}>>; "
1550 "expected to succeed.\n".format(name=meth_name)
1551 )
1552 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001553 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001554 "Method <<{name:s}>> failed with unexpected "
1555 "exception message: {exp:s}\n".format(
1556 name=meth_name, exp=e
1557 )
1558 )
1559 # consume data
1560 s.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001561 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001562 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001563
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001564 def test_handshake_timeout(self):
1565 # Issue #5103: SSL handshake must respect the socket timeout
1566 server = socket.socket(socket.AF_INET)
1567 host = "127.0.0.1"
1568 port = support.bind_port(server)
1569 started = threading.Event()
1570 finish = False
1571
1572 def serve():
1573 server.listen(5)
1574 started.set()
1575 conns = []
1576 while not finish:
1577 r, w, e = select.select([server], [], [], 0.1)
1578 if server in r:
1579 # Let the socket hang around rather than having
1580 # it closed by garbage collection.
1581 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001582 for sock in conns:
1583 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001584
1585 t = threading.Thread(target=serve)
1586 t.start()
1587 started.wait()
1588
1589 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001590 try:
1591 c = socket.socket(socket.AF_INET)
1592 c.settimeout(0.2)
1593 c.connect((host, port))
1594 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001595 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001596 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001597 finally:
1598 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001599 try:
1600 c = socket.socket(socket.AF_INET)
1601 c = ssl.wrap_socket(c)
1602 c.settimeout(0.2)
1603 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001604 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001605 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001606 finally:
1607 c.close()
1608 finally:
1609 finish = True
1610 t.join()
1611 server.close()
1612
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001613 def test_default_ciphers(self):
1614 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1615 try:
1616 # Force a set of weak ciphers on our client context
1617 context.set_ciphers("DES")
1618 except ssl.SSLError:
1619 self.skipTest("no DES cipher available")
1620 with ThreadedEchoServer(CERTFILE,
1621 ssl_version=ssl.PROTOCOL_SSLv23,
1622 chatty=False) as server:
1623 with socket.socket() as sock:
1624 s = context.wrap_socket(sock)
1625 with self.assertRaises((OSError, ssl.SSLError)):
1626 s.connect((HOST, server.port))
1627 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1628
Bill Janssen58afe4c2008-09-08 16:45:19 +00001629
Thomas Woutersed03b412007-08-28 21:37:11 +00001630def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001631 if support.verbose:
1632 plats = {
1633 'Linux': platform.linux_distribution,
1634 'Mac': platform.mac_ver,
1635 'Windows': platform.win32_ver,
1636 }
1637 for name, func in plats.items():
1638 plat = func()
1639 if plat and plat[0]:
1640 plat = '%s %r' % (name, plat)
1641 break
1642 else:
1643 plat = repr(platform.platform())
1644 print("test_ssl: testing with %r %r" %
1645 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1646 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001647 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001648
Antoine Pitrou152efa22010-05-16 18:19:27 +00001649 for filename in [
1650 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1651 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1652 BADCERT, BADKEY, EMPTYCERT]:
1653 if not os.path.exists(filename):
1654 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001655
Antoine Pitrou152efa22010-05-16 18:19:27 +00001656 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001657
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001658 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001659 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001660
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001661 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001662 thread_info = support.threading_setup()
1663 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001664 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001665
Antoine Pitrou480a1242010-04-28 21:37:09 +00001666 try:
1667 support.run_unittest(*tests)
1668 finally:
1669 if _have_threads:
1670 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001671
1672if __name__ == "__main__":
1673 test_main()