blob: 37a0cdb7c28c06c5a26b08c5ceae82fd07e8c251 [file] [log] [blame]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
5from test import test_support
Bill Janssen934b16d2008-06-28 22:19:33 +00006import asyncore
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00007import socket
Bill Janssen934b16d2008-06-28 22:19:33 +00008import select
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00009import time
Antoine Pitroub558f172010-04-23 23:25:45 +000010import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000011import os
Antoine Pitroub558f172010-04-23 23:25:45 +000012import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000014import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import traceback
Antoine Pitroudfb299b2010-04-23 22:54:59 +000016import weakref
Antoine Pitroud75efd92010-08-04 17:38:33 +000017import functools
18import platform
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000019
Bill Janssen296a59d2007-09-16 22:06:00 +000020from BaseHTTPServer import HTTPServer
21from SimpleHTTPServer import SimpleHTTPRequestHandler
22
Victor Stinner2e7f39e2011-05-22 13:22:28 +020023ssl = test_support.import_module("ssl")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000024
Trent Nelsone41b0062008-04-08 23:47:30 +000025HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000026CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000027SVN_PYTHON_ORG_ROOT_CERT = None
Christian Heimes88b174c2013-08-17 00:54:47 +020028NULLBYTECERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000029
Neal Norwitz3e533c22007-08-27 01:03:18 +000030def handle_error(prefix):
31 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000032 if test_support.verbose:
33 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000034
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000035
36class BasicTests(unittest.TestCase):
37
Antoine Pitrou3945c862010-04-28 21:11:01 +000038 def test_sslwrap_simple(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000039 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000040 try:
41 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
42 except IOError, e:
43 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
44 pass
45 else:
46 raise
47 try:
48 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
49 except IOError, e:
50 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
51 pass
52 else:
53 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000054
Antoine Pitroud75efd92010-08-04 17:38:33 +000055# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
56def skip_if_broken_ubuntu_ssl(func):
Victor Stinnerb1241f92011-05-10 01:52:03 +020057 if hasattr(ssl, 'PROTOCOL_SSLv2'):
58 # We need to access the lower-level wrapper in order to create an
59 # implicit SSL context without trying to connect or listen.
Antoine Pitroud75efd92010-08-04 17:38:33 +000060 try:
Victor Stinnerb1241f92011-05-10 01:52:03 +020061 import _ssl
62 except ImportError:
63 # The returned function won't get executed, just ignore the error
64 pass
65 @functools.wraps(func)
66 def f(*args, **kwargs):
67 try:
68 s = socket.socket(socket.AF_INET)
69 _ssl.sslwrap(s._sock, 0, None, None,
70 ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None)
71 except ssl.SSLError as e:
72 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
73 platform.linux_distribution() == ('debian', 'squeeze/sid', '')
74 and 'Invalid SSL protocol variant specified' in str(e)):
75 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
76 return func(*args, **kwargs)
77 return f
78 else:
79 return func
Antoine Pitroud75efd92010-08-04 17:38:33 +000080
81
82class BasicSocketTests(unittest.TestCase):
83
Antoine Pitrou3945c862010-04-28 21:11:01 +000084 def test_constants(self):
Victor Stinnerb1241f92011-05-10 01:52:03 +020085 #ssl.PROTOCOL_SSLv2
Bill Janssen98d19da2007-09-10 21:51:02 +000086 ssl.PROTOCOL_SSLv23
87 ssl.PROTOCOL_SSLv3
88 ssl.PROTOCOL_TLSv1
89 ssl.CERT_NONE
90 ssl.CERT_OPTIONAL
91 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000092
Antoine Pitrou3945c862010-04-28 21:11:01 +000093 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000094 v = ssl.RAND_status()
95 if test_support.verbose:
96 sys.stdout.write("\n RAND_status is %d (%s)\n"
97 % (v, (v and "sufficient randomness") or
98 "insufficient randomness"))
Jesus Ceaa8a5b392012-09-11 01:55:04 +020099 self.assertRaises(TypeError, ssl.RAND_egd, 1)
100 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000102
Antoine Pitrou3945c862010-04-28 21:11:01 +0000103 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000104 # note that this uses an 'unofficial' function in _ssl.c,
105 # provided solely for this test, to exercise the certificate
106 # parsing code
107 p = ssl._ssl._test_decode_cert(CERTFILE, False)
108 if test_support.verbose:
109 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200110 self.assertEqual(p['subject'],
Antoine Pitrou60982912013-02-16 21:39:28 +0100111 ((('countryName', 'XY'),),
112 (('localityName', 'Castle Anthrax'),),
113 (('organizationName', 'Python Software Foundation'),),
114 (('commonName', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200115 )
Antoine Pitrou60982912013-02-16 21:39:28 +0100116 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200117 # Issue #13034: the subjectAltName in some certificates
118 # (notably projects.developer.nokia.com:443) wasn't parsed
119 p = ssl._ssl._test_decode_cert(NOKIACERT)
120 if test_support.verbose:
121 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
122 self.assertEqual(p['subjectAltName'],
123 (('DNS', 'projects.developer.nokia.com'),
124 ('DNS', 'projects.forum.nokia.com'))
125 )
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000126
Christian Heimes88b174c2013-08-17 00:54:47 +0200127 def test_parse_cert_CVE_2013_4238(self):
128 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
129 if test_support.verbose:
130 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
131 subject = ((('countryName', 'US'),),
132 (('stateOrProvinceName', 'Oregon'),),
133 (('localityName', 'Beaverton'),),
134 (('organizationName', 'Python Software Foundation'),),
135 (('organizationalUnitName', 'Python Core Development'),),
136 (('commonName', 'null.python.org\x00example.org'),),
137 (('emailAddress', 'python-dev@python.org'),))
138 self.assertEqual(p['subject'], subject)
139 self.assertEqual(p['issuer'], subject)
Christian Heimesa0c83732013-08-25 14:44:27 +0200140 if ssl.OPENSSL_VERSION_INFO >= (0, 9, 8):
Christian Heimesf869a942013-08-25 14:12:41 +0200141 san = (('DNS', 'altnull.python.org\x00example.com'),
142 ('email', 'null@python.org\x00user@example.org'),
143 ('URI', 'http://null.python.org\x00http://example.org'),
144 ('IP Address', '192.0.2.1'),
145 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
146 else:
147 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
148 san = (('DNS', 'altnull.python.org\x00example.com'),
149 ('email', 'null@python.org\x00user@example.org'),
150 ('URI', 'http://null.python.org\x00http://example.org'),
151 ('IP Address', '192.0.2.1'),
152 ('IP Address', '<invalid>'))
153
154 self.assertEqual(p['subjectAltName'], san)
Christian Heimes88b174c2013-08-17 00:54:47 +0200155
Antoine Pitrou3945c862010-04-28 21:11:01 +0000156 def test_DER_to_PEM(self):
157 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
158 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000159 d1 = ssl.PEM_cert_to_DER_cert(pem)
160 p2 = ssl.DER_cert_to_PEM_cert(d1)
161 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000162 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000163 if not p2.startswith(ssl.PEM_HEADER + '\n'):
164 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
165 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
166 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000167
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000168 def test_openssl_version(self):
169 n = ssl.OPENSSL_VERSION_NUMBER
170 t = ssl.OPENSSL_VERSION_INFO
171 s = ssl.OPENSSL_VERSION
172 self.assertIsInstance(n, (int, long))
173 self.assertIsInstance(t, tuple)
174 self.assertIsInstance(s, str)
175 # Some sanity checks follow
176 # >= 0.9
177 self.assertGreaterEqual(n, 0x900000)
178 # < 2.0
179 self.assertLess(n, 0x20000000)
180 major, minor, fix, patch, status = t
181 self.assertGreaterEqual(major, 0)
182 self.assertLess(major, 2)
183 self.assertGreaterEqual(minor, 0)
184 self.assertLess(minor, 256)
185 self.assertGreaterEqual(fix, 0)
186 self.assertLess(fix, 256)
187 self.assertGreaterEqual(patch, 0)
188 self.assertLessEqual(patch, 26)
189 self.assertGreaterEqual(status, 0)
190 self.assertLessEqual(status, 15)
191 # Version string as returned by OpenSSL, the format might change
192 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
193 (s, t))
194
Zachary Ware1f702212013-12-10 14:09:20 -0600195 @test_support.requires_resource('network')
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000196 def test_ciphers(self):
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000197 remote = ("svn.python.org", 443)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000198 with test_support.transient_internet(remote[0]):
199 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
200 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000201 s.connect(remote)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000202 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
203 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
204 s.connect(remote)
205 # Error checking occurs when connecting, because the SSL context
206 # isn't created before.
207 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
208 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
209 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
210 s.connect(remote)
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000211
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000212 @test_support.cpython_only
213 def test_refcycle(self):
214 # Issue #7943: an SSL object doesn't create reference cycles with
215 # itself.
216 s = socket.socket(socket.AF_INET)
217 ss = ssl.wrap_socket(s)
218 wr = weakref.ref(ss)
219 del ss
220 self.assertEqual(wr(), None)
221
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000222 def test_wrapped_unconnected(self):
223 # The _delegate_methods in socket.py are correctly delegated to by an
224 # unconnected SSLSocket, so they will raise a socket.error rather than
225 # something unexpected like TypeError.
226 s = socket.socket(socket.AF_INET)
227 ss = ssl.wrap_socket(s)
228 self.assertRaises(socket.error, ss.recv, 1)
229 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
230 self.assertRaises(socket.error, ss.recvfrom, 1)
231 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
232 self.assertRaises(socket.error, ss.send, b'x')
233 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
234
Antoine Pitrou63cc99d2013-12-28 17:26:33 +0100235 def test_unsupported_dtls(self):
236 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
237 self.addCleanup(s.close)
238 with self.assertRaises(NotImplementedError) as cx:
239 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
240 self.assertEqual(str(cx.exception), "only stream sockets are supported")
241
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000242
Bill Janssen934b16d2008-06-28 22:19:33 +0000243class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000244
Antoine Pitrou3945c862010-04-28 21:11:01 +0000245 def test_connect(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000246 with test_support.transient_internet("svn.python.org"):
247 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
248 cert_reqs=ssl.CERT_NONE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000249 s.connect(("svn.python.org", 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000250 c = s.getpeercert()
251 if c:
252 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000253 s.close()
254
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000255 # this should fail because we have no verification certs
256 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
257 cert_reqs=ssl.CERT_REQUIRED)
258 try:
259 s.connect(("svn.python.org", 443))
260 except ssl.SSLError:
261 pass
262 finally:
263 s.close()
264
265 # this should succeed because we specify the root cert
266 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
267 cert_reqs=ssl.CERT_REQUIRED,
268 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
269 try:
270 s.connect(("svn.python.org", 443))
271 finally:
272 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +0000273
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000274 def test_connect_ex(self):
275 # Issue #11326: check connect_ex() implementation
276 with test_support.transient_internet("svn.python.org"):
277 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
278 cert_reqs=ssl.CERT_REQUIRED,
279 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
280 try:
281 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
282 self.assertTrue(s.getpeercert())
283 finally:
284 s.close()
285
286 def test_non_blocking_connect_ex(self):
287 # Issue #11326: non-blocking connect_ex() should allow handshake
288 # to proceed after the socket gets ready.
289 with test_support.transient_internet("svn.python.org"):
290 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
291 cert_reqs=ssl.CERT_REQUIRED,
292 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
293 do_handshake_on_connect=False)
294 try:
295 s.setblocking(False)
296 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +0000297 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
298 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000299 # Wait for connect to finish
300 select.select([], [s], [], 5.0)
301 # Non-blocking handshake
302 while True:
303 try:
304 s.do_handshake()
305 break
306 except ssl.SSLError as err:
307 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
308 select.select([s], [], [], 5.0)
309 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
310 select.select([], [s], [], 5.0)
311 else:
312 raise
313 # SSL established
314 self.assertTrue(s.getpeercert())
315 finally:
316 s.close()
317
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100318 def test_timeout_connect_ex(self):
319 # Issue #12065: on a timeout, connect_ex() should return the original
320 # errno (mimicking the behaviour of non-SSL sockets).
321 with test_support.transient_internet("svn.python.org"):
322 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
323 cert_reqs=ssl.CERT_REQUIRED,
324 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
325 do_handshake_on_connect=False)
326 try:
327 s.settimeout(0.0000001)
328 rc = s.connect_ex(('svn.python.org', 443))
329 if rc == 0:
330 self.skipTest("svn.python.org responded too quickly")
331 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
332 finally:
333 s.close()
334
335 def test_connect_ex_error(self):
336 with test_support.transient_internet("svn.python.org"):
337 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
338 cert_reqs=ssl.CERT_REQUIRED,
339 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
340 try:
341 self.assertEqual(errno.ECONNREFUSED,
342 s.connect_ex(("svn.python.org", 444)))
343 finally:
344 s.close()
345
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000346 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
347 def test_makefile_close(self):
348 # Issue #5238: creating a file-like object with makefile() shouldn't
349 # delay closing the underlying "real socket" (here tested with its
350 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000351 with test_support.transient_internet("svn.python.org"):
352 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
353 ss.connect(("svn.python.org", 443))
354 fd = ss.fileno()
355 f = ss.makefile()
356 f.close()
357 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000358 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000359 # Closing the SSL socket should close the fd too
360 ss.close()
361 gc.collect()
362 with self.assertRaises(OSError) as e:
363 os.read(fd, 0)
364 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000365
Antoine Pitrou3945c862010-04-28 21:11:01 +0000366 def test_non_blocking_handshake(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000367 with test_support.transient_internet("svn.python.org"):
368 s = socket.socket(socket.AF_INET)
369 s.connect(("svn.python.org", 443))
370 s.setblocking(False)
371 s = ssl.wrap_socket(s,
372 cert_reqs=ssl.CERT_NONE,
373 do_handshake_on_connect=False)
374 count = 0
375 while True:
376 try:
377 count += 1
378 s.do_handshake()
379 break
380 except ssl.SSLError, err:
381 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
382 select.select([s], [], [])
383 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
384 select.select([], [s], [])
385 else:
386 raise
387 s.close()
388 if test_support.verbose:
389 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +0000390
Antoine Pitrou3945c862010-04-28 21:11:01 +0000391 def test_get_server_certificate(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000392 with test_support.transient_internet("svn.python.org"):
Benjamin Petersonae80f452014-03-12 18:05:53 -0500393 pem = ssl.get_server_certificate(("svn.python.org", 443),
394 ssl.PROTOCOL_SSLv23)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000395 if not pem:
396 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000397
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000398 try:
Benjamin Petersonae80f452014-03-12 18:05:53 -0500399 pem = ssl.get_server_certificate(("svn.python.org", 443),
400 ssl.PROTOCOL_SSLv23,
401 ca_certs=CERTFILE)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000402 except ssl.SSLError:
403 #should fail
404 pass
405 else:
406 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000407
Benjamin Petersonae80f452014-03-12 18:05:53 -0500408 pem = ssl.get_server_certificate(("svn.python.org", 443),
409 ssl.PROTOCOL_SSLv23,
410 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000411 if not pem:
412 self.fail("No server certificate on svn.python.org:443!")
413 if test_support.verbose:
414 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000415
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000416 def test_algorithms(self):
417 # Issue #8484: all algorithms should be available when verifying a
418 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000419 # SHA256 was added in OpenSSL 0.9.8
420 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
421 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc642f672012-05-04 16:33:30 +0200422 self.skipTest("remote host needs SNI, only available on Python 3.2+")
423 # NOTE: https://sha2.hboeck.de is another possible test host
Antoine Pitroud43245a2011-01-08 10:32:51 +0000424 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000425 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroud43245a2011-01-08 10:32:51 +0000426 with test_support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000427 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
428 cert_reqs=ssl.CERT_REQUIRED,
429 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000430 try:
431 s.connect(remote)
432 if test_support.verbose:
433 sys.stdout.write("\nCipher with %r is %r\n" %
434 (remote, s.cipher()))
435 sys.stdout.write("Certificate is:\n%s\n" %
436 pprint.pformat(s.getpeercert()))
437 finally:
438 s.close()
439
Bill Janssen296a59d2007-09-16 22:06:00 +0000440
Bill Janssen98d19da2007-09-10 21:51:02 +0000441try:
442 import threading
443except ImportError:
444 _have_threads = False
445else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000446 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000447
Bill Janssen98d19da2007-09-10 21:51:02 +0000448 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000449
Bill Janssen98d19da2007-09-10 21:51:02 +0000450 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000451
Bill Janssen98d19da2007-09-10 21:51:02 +0000452 """A mildly complicated class, because we want it to work both
453 with and without the SSL wrapper around the socket connection, so
454 that we can test the STARTTLS functionality."""
455
456 def __init__(self, server, connsock):
457 self.server = server
458 self.running = False
459 self.sock = connsock
460 self.sock.setblocking(1)
461 self.sslconn = None
462 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000463 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000464
Bill Janssen934b16d2008-06-28 22:19:33 +0000465 def show_conn_details(self):
466 if self.server.certreqs == ssl.CERT_REQUIRED:
467 cert = self.sslconn.getpeercert()
468 if test_support.verbose and self.server.chatty:
469 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
470 cert_binary = self.sslconn.getpeercert(True)
471 if test_support.verbose and self.server.chatty:
472 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
473 cipher = self.sslconn.cipher()
474 if test_support.verbose and self.server.chatty:
475 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
476
Antoine Pitrou3945c862010-04-28 21:11:01 +0000477 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000478 try:
479 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
480 certfile=self.server.certificate,
481 ssl_version=self.server.protocol,
482 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000483 cert_reqs=self.server.certreqs,
484 ciphers=self.server.ciphers)
Antoine Pitroud76088d2012-01-03 22:46:48 +0100485 except ssl.SSLError as e:
Antoine Pitroudb187842010-04-27 10:32:58 +0000486 # XXX Various errors can have happened here, for example
487 # a mismatching protocol version, an invalid certificate,
488 # or a low-level bug. This should be made more discriminating.
Antoine Pitroud76088d2012-01-03 22:46:48 +0100489 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +0000490 if self.server.chatty:
491 handle_error("\n server: bad connection attempt from " +
492 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000493 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000494 self.running = False
495 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000496 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000497 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000498 return True
499
500 def read(self):
501 if self.sslconn:
502 return self.sslconn.read()
503 else:
504 return self.sock.recv(1024)
505
506 def write(self, bytes):
507 if self.sslconn:
508 return self.sslconn.write(bytes)
509 else:
510 return self.sock.send(bytes)
511
512 def close(self):
513 if self.sslconn:
514 self.sslconn.close()
515 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000516 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000517
Antoine Pitrou3945c862010-04-28 21:11:01 +0000518 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000519 self.running = True
520 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000521 if isinstance(self.sock, ssl.SSLSocket):
522 self.sslconn = self.sock
523 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000524 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000525 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000526 while self.running:
527 try:
528 msg = self.read()
529 if not msg:
530 # eof, so quit this handler
531 self.running = False
532 self.close()
533 elif msg.strip() == 'over':
534 if test_support.verbose and self.server.connectionchatty:
535 sys.stdout.write(" server: client closed connection\n")
536 self.close()
537 return
538 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
539 if test_support.verbose and self.server.connectionchatty:
540 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
541 self.write("OK\n")
542 if not self.wrap_conn():
543 return
Bill Janssen39295c22008-08-12 16:31:21 +0000544 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
545 if test_support.verbose and self.server.connectionchatty:
546 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
547 self.write("OK\n")
548 self.sslconn.unwrap()
549 self.sslconn = None
550 if test_support.verbose and self.server.connectionchatty:
551 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000552 else:
553 if (test_support.verbose and
554 self.server.connectionchatty):
555 ctype = (self.sslconn and "encrypted") or "unencrypted"
556 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
557 % (repr(msg), ctype, repr(msg.lower()), ctype))
558 self.write(msg.lower())
559 except ssl.SSLError:
560 if self.server.chatty:
561 handle_error("Test server failure:\n")
562 self.close()
563 self.running = False
564 # normally, we'd just stop here, but for the test
565 # harness, we want to stop the server
566 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000567
Trent Nelsone41b0062008-04-08 23:47:30 +0000568 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000569 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000570 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000571 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000572
Bill Janssen98d19da2007-09-10 21:51:02 +0000573 if ssl_version is None:
574 ssl_version = ssl.PROTOCOL_TLSv1
575 if certreqs is None:
576 certreqs = ssl.CERT_NONE
577 self.certificate = certificate
578 self.protocol = ssl_version
579 self.certreqs = certreqs
580 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000581 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000582 self.chatty = chatty
583 self.connectionchatty = connectionchatty
584 self.starttls_server = starttls_server
585 self.sock = socket.socket()
586 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000587 if wrap_accepting_socket:
588 self.sock = ssl.wrap_socket(self.sock, server_side=True,
589 certfile=self.certificate,
590 cert_reqs = self.certreqs,
591 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000592 ssl_version = self.protocol,
593 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000594 if test_support.verbose and self.chatty:
595 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
596 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000597 self.active = False
Antoine Pitroud76088d2012-01-03 22:46:48 +0100598 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000599 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000600 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000601
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100602 def __enter__(self):
603 self.start(threading.Event())
604 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100605 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100606
607 def __exit__(self, *args):
608 self.stop()
609 self.join()
610
Antoine Pitrou3945c862010-04-28 21:11:01 +0000611 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000612 self.flag = flag
613 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000614
Antoine Pitrou3945c862010-04-28 21:11:01 +0000615 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000616 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000617 self.sock.listen(5)
618 self.active = True
619 if self.flag:
620 # signal an event
621 self.flag.set()
622 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000623 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000624 newconn, connaddr = self.sock.accept()
625 if test_support.verbose and self.chatty:
626 sys.stdout.write(' server: new connection from '
627 + str(connaddr) + '\n')
628 handler = self.ConnectionHandler(self, newconn)
629 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +0100630 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000631 except socket.timeout:
632 pass
633 except KeyboardInterrupt:
634 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000635 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000636
Antoine Pitrou3945c862010-04-28 21:11:01 +0000637 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000638 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000639
Bill Janssen934b16d2008-06-28 22:19:33 +0000640 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000641
Antoine Pitrou3945c862010-04-28 21:11:01 +0000642 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000643
Antoine Pitrou3945c862010-04-28 21:11:01 +0000644 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000645
646 def __init__(self, conn, certfile):
647 asyncore.dispatcher_with_send.__init__(self, conn)
648 self.socket = ssl.wrap_socket(conn, server_side=True,
649 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000650 do_handshake_on_connect=False)
651 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000652
653 def readable(self):
654 if isinstance(self.socket, ssl.SSLSocket):
655 while self.socket.pending() > 0:
656 self.handle_read_event()
657 return True
658
Antoine Pitroufc69af12010-04-24 20:04:58 +0000659 def _do_ssl_handshake(self):
660 try:
661 self.socket.do_handshake()
662 except ssl.SSLError, err:
663 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
664 ssl.SSL_ERROR_WANT_WRITE):
665 return
666 elif err.args[0] == ssl.SSL_ERROR_EOF:
667 return self.handle_close()
668 raise
669 except socket.error, err:
670 if err.args[0] == errno.ECONNABORTED:
671 return self.handle_close()
672 else:
673 self._ssl_accepting = False
674
Bill Janssen934b16d2008-06-28 22:19:33 +0000675 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000676 if self._ssl_accepting:
677 self._do_ssl_handshake()
678 else:
679 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000680 if data and data.strip() != 'over':
681 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000682
683 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000684 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000685 if test_support.verbose:
686 sys.stdout.write(" server: closed connection %s\n" % self.socket)
687
688 def handle_error(self):
689 raise
690
691 def __init__(self, certfile):
692 self.certfile = certfile
693 asyncore.dispatcher.__init__(self)
694 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
695 self.port = test_support.bind_port(self.socket)
696 self.listen(5)
697
698 def handle_accept(self):
699 sock_obj, addr = self.accept()
700 if test_support.verbose:
701 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
702 self.ConnectionHandler(sock_obj, self.certfile)
703
704 def handle_error(self):
705 raise
706
707 def __init__(self, certfile):
708 self.flag = None
709 self.active = False
710 self.server = self.EchoServer(certfile)
711 self.port = self.server.port
712 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000713 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000714
715 def __str__(self):
716 return "<%s %s>" % (self.__class__.__name__, self.server)
717
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100718 def __enter__(self):
719 self.start(threading.Event())
720 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100721 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100722
723 def __exit__(self, *args):
724 if test_support.verbose:
725 sys.stdout.write(" cleanup: stopping server.\n")
726 self.stop()
727 if test_support.verbose:
728 sys.stdout.write(" cleanup: joining server thread.\n")
729 self.join()
730 if test_support.verbose:
731 sys.stdout.write(" cleanup: successfully joined.\n")
732
Antoine Pitrou3945c862010-04-28 21:11:01 +0000733 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000734 self.flag = flag
735 threading.Thread.start(self)
736
Antoine Pitrou3945c862010-04-28 21:11:01 +0000737 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000738 self.active = True
739 if self.flag:
740 self.flag.set()
741 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000742 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000743
Antoine Pitrou3945c862010-04-28 21:11:01 +0000744 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000745 self.active = False
746 self.server.close()
747
748 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000749
750 class HTTPSServer(HTTPServer):
751
752 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000753 HTTPServer.__init__(self, server_address, RequestHandlerClass)
754 # we assume the certfile contains both private key and certificate
755 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000756 self.allow_reuse_address = True
757
Bill Janssen934b16d2008-06-28 22:19:33 +0000758 def __str__(self):
759 return ('<%s %s:%s>' %
760 (self.__class__.__name__,
761 self.server_name,
762 self.server_port))
763
Antoine Pitrou3945c862010-04-28 21:11:01 +0000764 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000765 # override this to wrap socket with SSL
766 sock, addr = self.socket.accept()
767 sslconn = ssl.wrap_socket(sock, server_side=True,
768 certfile=self.certfile)
769 return sslconn, addr
770
Bill Janssen296a59d2007-09-16 22:06:00 +0000771 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000772 # need to override translate_path to get a known root,
773 # instead of using os.curdir, since the test could be
774 # run from anywhere
775
776 server_version = "TestHTTPS/1.0"
777
778 root = None
779
780 def translate_path(self, path):
781 """Translate a /-separated PATH to the local filename syntax.
782
783 Components that mean special things to the local file system
784 (e.g. drive or directory names) are ignored. (XXX They should
785 probably be diagnosed.)
786
787 """
788 # abandon query parameters
789 path = urlparse.urlparse(path)[2]
790 path = os.path.normpath(urllib.unquote(path))
791 words = path.split('/')
792 words = filter(None, words)
793 path = self.root
794 for word in words:
795 drive, word = os.path.splitdrive(word)
796 head, word = os.path.split(word)
797 if word in self.root: continue
798 path = os.path.join(path, word)
799 return path
800
801 def log_message(self, format, *args):
802
803 # we override this to suppress logging unless "verbose"
804
805 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000806 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
807 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000808 self.server.server_port,
809 self.request.cipher(),
810 self.log_date_time_string(),
811 format%args))
812
813
Trent Nelsone41b0062008-04-08 23:47:30 +0000814 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000815 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000816 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
817 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000818 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
819 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000820 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000821 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000822
823 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000824 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000825
Antoine Pitrou3945c862010-04-28 21:11:01 +0000826 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000827 self.flag = flag
828 threading.Thread.start(self)
829
Antoine Pitrou3945c862010-04-28 21:11:01 +0000830 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000831 if self.flag:
832 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000833 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000834
Antoine Pitrou3945c862010-04-28 21:11:01 +0000835 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000836 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000837
838
Antoine Pitrou3945c862010-04-28 21:11:01 +0000839 def bad_cert_test(certfile):
840 """
841 Launch a server with CERT_REQUIRED, and check that trying to
842 connect to it with the given client certificate fails.
843 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000844 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000845 certreqs=ssl.CERT_REQUIRED,
846 cacerts=CERTFILE, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100847 with server:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000848 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000849 s = ssl.wrap_socket(socket.socket(),
850 certfile=certfile,
851 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000852 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000853 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000854 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000855 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000856 except socket.error, x:
857 if test_support.verbose:
858 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000859 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000860 raise AssertionError("Use of invalid cert should have failed!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000861
Antoine Pitrou3945c862010-04-28 21:11:01 +0000862 def server_params_test(certfile, protocol, certreqs, cacertsfile,
863 client_certfile, client_protocol=None, indata="FOO\n",
864 ciphers=None, chatty=True, connectionchatty=False,
865 wrap_accepting_socket=False):
866 """
867 Launch a server, connect a client to it and try various reads
868 and writes.
869 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000870 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000871 certreqs=certreqs,
872 ssl_version=protocol,
873 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000874 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000875 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000876 connectionchatty=connectionchatty,
877 wrap_accepting_socket=wrap_accepting_socket)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100878 with server:
879 # try to connect
880 if client_protocol is None:
881 client_protocol = protocol
Antoine Pitroudb187842010-04-27 10:32:58 +0000882 s = ssl.wrap_socket(socket.socket(),
883 certfile=client_certfile,
884 ca_certs=cacertsfile,
885 ciphers=ciphers,
886 cert_reqs=certreqs,
887 ssl_version=client_protocol)
888 s.connect((HOST, server.port))
889 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000890 if connectionchatty:
891 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000892 sys.stdout.write(
893 " client: sending %s...\n" % (repr(arg)))
894 s.write(arg)
895 outdata = s.read()
896 if connectionchatty:
897 if test_support.verbose:
898 sys.stdout.write(" client: read %s\n" % repr(outdata))
899 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000900 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000901 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
902 % (outdata[:min(len(outdata),20)], len(outdata),
903 indata[:min(len(indata),20)].lower(), len(indata)))
904 s.write("over\n")
905 if connectionchatty:
906 if test_support.verbose:
907 sys.stdout.write(" client: closing connection.\n")
908 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000909
Antoine Pitrou3945c862010-04-28 21:11:01 +0000910 def try_protocol_combo(server_protocol,
911 client_protocol,
912 expect_success,
913 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000914 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000915 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000916 certtype = {
917 ssl.CERT_NONE: "CERT_NONE",
918 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
919 ssl.CERT_REQUIRED: "CERT_REQUIRED",
920 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000921 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000922 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000923 sys.stdout.write(formatstr %
924 (ssl.get_protocol_name(client_protocol),
925 ssl.get_protocol_name(server_protocol),
926 certtype))
927 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000928 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
929 # will send an SSLv3 hello (rather than SSLv2) starting from
930 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000931 server_params_test(CERTFILE, server_protocol, certsreqs,
932 CERTFILE, CERTFILE, client_protocol,
933 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000934 # Protocol mismatch can result in either an SSLError, or a
935 # "Connection reset by peer" error.
936 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000937 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000938 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000939 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000940 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000941 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000942 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000943 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000944 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000945 "Client protocol %s succeeded with server protocol %s!"
946 % (ssl.get_protocol_name(client_protocol),
947 ssl.get_protocol_name(server_protocol)))
948
949
Bill Janssen934b16d2008-06-28 22:19:33 +0000950 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000951
Antoine Pitrou3945c862010-04-28 21:11:01 +0000952 def test_rude_shutdown(self):
953 """A brutal shutdown of an SSL server should raise an IOError
954 in the client when attempting handshake.
955 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000956 listener_ready = threading.Event()
957 listener_gone = threading.Event()
958
Antoine Pitrou150acda2010-04-27 08:40:51 +0000959 s = socket.socket()
960 port = test_support.bind_port(s, HOST)
961
962 # `listener` runs in a thread. It sits in an accept() until
963 # the main thread connects. Then it rudely closes the socket,
964 # and sets Event `listener_gone` to let the main thread know
965 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000966 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000967 s.listen(5)
968 listener_ready.set()
969 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000970 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000971 listener_gone.set()
972
973 def connector():
974 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000975 c = socket.socket()
976 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000977 listener_gone.wait()
978 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000979 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000980 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000981 pass
982 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000983 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000984
985 t = threading.Thread(target=listener)
986 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000987 try:
988 connector()
989 finally:
990 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000991
Antoine Pitroud75efd92010-08-04 17:38:33 +0000992 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000993 def test_echo(self):
994 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000995 if test_support.verbose:
996 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000997 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
998 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
999 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001000
Antoine Pitrou3945c862010-04-28 21:11:01 +00001001 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001002 if test_support.verbose:
1003 sys.stdout.write("\n")
1004 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +00001005 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001006 certreqs=ssl.CERT_NONE,
1007 ssl_version=ssl.PROTOCOL_SSLv23,
1008 cacerts=CERTFILE,
1009 chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001010 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001011 s = ssl.wrap_socket(socket.socket(),
1012 certfile=CERTFILE,
1013 ca_certs=CERTFILE,
1014 cert_reqs=ssl.CERT_REQUIRED,
1015 ssl_version=ssl.PROTOCOL_SSLv23)
1016 s.connect((HOST, server.port))
1017 cert = s.getpeercert()
1018 self.assertTrue(cert, "Can't get peer certificate.")
1019 cipher = s.cipher()
1020 if test_support.verbose:
1021 sys.stdout.write(pprint.pformat(cert) + '\n')
1022 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1023 if 'subject' not in cert:
1024 self.fail("No subject field in certificate: %s." %
1025 pprint.pformat(cert))
1026 if ((('organizationName', 'Python Software Foundation'),)
1027 not in cert['subject']):
1028 self.fail(
1029 "Missing or invalid 'organizationName' field in certificate subject; "
1030 "should be 'Python Software Foundation'.")
1031 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001032
Antoine Pitrou3945c862010-04-28 21:11:01 +00001033 def test_empty_cert(self):
1034 """Connecting with an empty cert file"""
1035 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1036 "nullcert.pem"))
1037 def test_malformed_cert(self):
1038 """Connecting with a badly formatted certificate (syntax error)"""
1039 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1040 "badcert.pem"))
1041 def test_nonexisting_cert(self):
1042 """Connecting with a non-existing cert file"""
1043 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1044 "wrongcert.pem"))
1045 def test_malformed_key(self):
1046 """Connecting with a badly formatted key (syntax error)"""
1047 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1048 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +00001049
Antoine Pitroud75efd92010-08-04 17:38:33 +00001050 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001051 def test_protocol_sslv2(self):
1052 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001053 if test_support.verbose:
1054 sys.stdout.write("\n")
Antoine Pitrou6361ea22011-10-30 21:31:34 +01001055 if not hasattr(ssl, 'PROTOCOL_SSLv2'):
1056 self.skipTest("PROTOCOL_SSLv2 needed")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001057 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1058 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1059 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01001060 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001061 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1062 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001063
Antoine Pitroud75efd92010-08-04 17:38:33 +00001064 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001065 def test_protocol_sslv23(self):
1066 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001067 if test_support.verbose:
1068 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001069 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1070 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1071 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001072
Antoine Pitrou3945c862010-04-28 21:11:01 +00001073 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1074 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1075 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00001076
Antoine Pitrou3945c862010-04-28 21:11:01 +00001077 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1078 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1079 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00001080
Antoine Pitroud75efd92010-08-04 17:38:33 +00001081 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001082 def test_protocol_sslv3(self):
1083 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001084 if test_support.verbose:
1085 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001086 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1087 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1088 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001089 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1090 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001091 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001092
Antoine Pitroud75efd92010-08-04 17:38:33 +00001093 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001094 def test_protocol_tlsv1(self):
1095 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001096 if test_support.verbose:
1097 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001098 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1099 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1100 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001101 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1102 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001103 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001104
Antoine Pitrou3945c862010-04-28 21:11:01 +00001105 def test_starttls(self):
1106 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +00001107 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00001108
Trent Nelsone41b0062008-04-08 23:47:30 +00001109 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001110 ssl_version=ssl.PROTOCOL_TLSv1,
1111 starttls_server=True,
1112 chatty=True,
1113 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001114 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001115 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001116 s = socket.socket()
1117 s.setblocking(1)
1118 s.connect((HOST, server.port))
1119 if test_support.verbose:
1120 sys.stdout.write("\n")
1121 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +00001122 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00001123 sys.stdout.write(
1124 " client: sending %s...\n" % repr(indata))
1125 if wrapped:
1126 conn.write(indata)
1127 outdata = conn.read()
1128 else:
1129 s.send(indata)
1130 outdata = s.recv(1024)
1131 if (indata == "STARTTLS" and
1132 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001133 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001134 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001135 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001136 " client: read %s from server, starting TLS...\n"
1137 % repr(outdata))
1138 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1139 wrapped = True
1140 elif (indata == "ENDTLS" and
1141 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001142 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001143 if test_support.verbose:
1144 sys.stdout.write(
1145 " client: read %s from server, ending TLS...\n"
1146 % repr(outdata))
1147 s = conn.unwrap()
1148 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001149 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001150 if test_support.verbose:
1151 sys.stdout.write(
1152 " client: read %s from server\n" % repr(outdata))
1153 if test_support.verbose:
1154 sys.stdout.write(" client: closing connection.\n")
1155 if wrapped:
1156 conn.write("over\n")
1157 else:
1158 s.send("over\n")
1159 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001160
Antoine Pitrou3945c862010-04-28 21:11:01 +00001161 def test_socketserver(self):
1162 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001163 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001164 flag = threading.Event()
1165 server.start(flag)
1166 # wait for it to start
1167 flag.wait()
1168 # try to connect
1169 try:
1170 if test_support.verbose:
1171 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001172 with open(CERTFILE, 'rb') as f:
1173 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001174 d2 = ''
1175 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001176 url = 'https://127.0.0.1:%d/%s' % (
1177 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001178 with test_support.check_py3k_warnings():
1179 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001180 dlen = f.info().getheader("content-length")
1181 if dlen and (int(dlen) > 0):
1182 d2 = f.read(int(dlen))
1183 if test_support.verbose:
1184 sys.stdout.write(
1185 " client: read %d bytes from remote server '%s'\n"
1186 % (len(d2), server))
1187 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001188 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001189 finally:
1190 server.stop()
1191 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001192
Antoine Pitrou3945c862010-04-28 21:11:01 +00001193 def test_wrapped_accept(self):
1194 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001195 if test_support.verbose:
1196 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001197 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1198 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1199 chatty=True, connectionchatty=True,
1200 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001201
Antoine Pitrou3945c862010-04-28 21:11:01 +00001202 def test_asyncore_server(self):
1203 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001204 indata = "TEST MESSAGE of mixed case\n"
1205
1206 if test_support.verbose:
1207 sys.stdout.write("\n")
1208 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001209 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001210 s = ssl.wrap_socket(socket.socket())
1211 s.connect(('127.0.0.1', server.port))
1212 if test_support.verbose:
1213 sys.stdout.write(
1214 " client: sending %s...\n" % (repr(indata)))
1215 s.write(indata)
1216 outdata = s.read()
1217 if test_support.verbose:
1218 sys.stdout.write(" client: read %s\n" % repr(outdata))
1219 if outdata != indata.lower():
1220 self.fail(
1221 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1222 % (outdata[:min(len(outdata),20)], len(outdata),
1223 indata[:min(len(indata),20)].lower(), len(indata)))
1224 s.write("over\n")
1225 if test_support.verbose:
1226 sys.stdout.write(" client: closing connection.\n")
1227 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001228
Antoine Pitrou3945c862010-04-28 21:11:01 +00001229 def test_recv_send(self):
1230 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001231 if test_support.verbose:
1232 sys.stdout.write("\n")
1233
1234 server = ThreadedEchoServer(CERTFILE,
1235 certreqs=ssl.CERT_NONE,
1236 ssl_version=ssl.PROTOCOL_TLSv1,
1237 cacerts=CERTFILE,
1238 chatty=True,
1239 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001240 with server:
1241 s = ssl.wrap_socket(socket.socket(),
1242 server_side=False,
1243 certfile=CERTFILE,
1244 ca_certs=CERTFILE,
1245 cert_reqs=ssl.CERT_NONE,
1246 ssl_version=ssl.PROTOCOL_TLSv1)
1247 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001248 # helper methods for standardising recv* method signatures
1249 def _recv_into():
1250 b = bytearray("\0"*100)
1251 count = s.recv_into(b)
1252 return b[:count]
1253
1254 def _recvfrom_into():
1255 b = bytearray("\0"*100)
1256 count, addr = s.recvfrom_into(b)
1257 return b[:count]
1258
1259 # (name, method, whether to expect success, *args)
1260 send_methods = [
1261 ('send', s.send, True, []),
1262 ('sendto', s.sendto, False, ["some.address"]),
1263 ('sendall', s.sendall, True, []),
1264 ]
1265 recv_methods = [
1266 ('recv', s.recv, True, []),
1267 ('recvfrom', s.recvfrom, False, ["some.address"]),
1268 ('recv_into', _recv_into, True, []),
1269 ('recvfrom_into', _recvfrom_into, False, []),
1270 ]
1271 data_prefix = u"PREFIX_"
1272
1273 for meth_name, send_meth, expect_success, args in send_methods:
1274 indata = data_prefix + meth_name
1275 try:
1276 send_meth(indata.encode('ASCII', 'strict'), *args)
1277 outdata = s.read()
1278 outdata = outdata.decode('ASCII', 'strict')
1279 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001280 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001281 "While sending with <<%s>> bad data "
1282 "<<%r>> (%d) received; "
1283 "expected <<%r>> (%d)\n" % (
1284 meth_name, outdata[:20], len(outdata),
1285 indata[:20], len(indata)
1286 )
1287 )
1288 except ValueError as e:
1289 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001290 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001291 "Failed to send with method <<%s>>; "
1292 "expected to succeed.\n" % (meth_name,)
1293 )
1294 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001295 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001296 "Method <<%s>> failed with unexpected "
1297 "exception message: %s\n" % (
1298 meth_name, e
1299 )
1300 )
1301
1302 for meth_name, recv_meth, expect_success, args in recv_methods:
1303 indata = data_prefix + meth_name
1304 try:
1305 s.send(indata.encode('ASCII', 'strict'))
1306 outdata = recv_meth(*args)
1307 outdata = outdata.decode('ASCII', 'strict')
1308 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001309 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001310 "While receiving with <<%s>> bad data "
1311 "<<%r>> (%d) received; "
1312 "expected <<%r>> (%d)\n" % (
1313 meth_name, outdata[:20], len(outdata),
1314 indata[:20], len(indata)
1315 )
1316 )
1317 except ValueError as e:
1318 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001319 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001320 "Failed to receive with method <<%s>>; "
1321 "expected to succeed.\n" % (meth_name,)
1322 )
1323 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001324 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001325 "Method <<%s>> failed with unexpected "
1326 "exception message: %s\n" % (
1327 meth_name, e
1328 )
1329 )
1330 # consume data
1331 s.read()
1332
1333 s.write("over\n".encode("ASCII", "strict"))
1334 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00001335
Antoine Pitroufc69af12010-04-24 20:04:58 +00001336 def test_handshake_timeout(self):
1337 # Issue #5103: SSL handshake must respect the socket timeout
1338 server = socket.socket(socket.AF_INET)
1339 host = "127.0.0.1"
1340 port = test_support.bind_port(server)
1341 started = threading.Event()
1342 finish = False
1343
1344 def serve():
1345 server.listen(5)
1346 started.set()
1347 conns = []
1348 while not finish:
1349 r, w, e = select.select([server], [], [], 0.1)
1350 if server in r:
1351 # Let the socket hang around rather than having
1352 # it closed by garbage collection.
1353 conns.append(server.accept()[0])
1354
1355 t = threading.Thread(target=serve)
1356 t.start()
1357 started.wait()
1358
1359 try:
1360 try:
1361 c = socket.socket(socket.AF_INET)
1362 c.settimeout(0.2)
1363 c.connect((host, port))
1364 # Will attempt handshake and time out
1365 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1366 ssl.wrap_socket, c)
1367 finally:
1368 c.close()
1369 try:
1370 c = socket.socket(socket.AF_INET)
1371 c.settimeout(0.2)
1372 c = ssl.wrap_socket(c)
1373 # Will attempt handshake and time out
1374 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1375 c.connect, (host, port))
1376 finally:
1377 c.close()
1378 finally:
1379 finish = True
1380 t.join()
1381 server.close()
1382
Antoine Pitroud76088d2012-01-03 22:46:48 +01001383 def test_default_ciphers(self):
1384 with ThreadedEchoServer(CERTFILE,
1385 ssl_version=ssl.PROTOCOL_SSLv23,
1386 chatty=False) as server:
1387 sock = socket.socket()
1388 try:
1389 # Force a set of weak ciphers on our client socket
1390 try:
1391 s = ssl.wrap_socket(sock,
1392 ssl_version=ssl.PROTOCOL_SSLv23,
1393 ciphers="DES")
1394 except ssl.SSLError:
1395 self.skipTest("no DES cipher available")
1396 with self.assertRaises((OSError, ssl.SSLError)):
1397 s.connect((HOST, server.port))
1398 finally:
1399 sock.close()
1400 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1401
Bill Janssen61c001a2008-09-08 16:37:24 +00001402
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001403def test_main(verbose=False):
Christian Heimes88b174c2013-08-17 00:54:47 +02001404 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT, NULLBYTECERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001405 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001406 "keycert.pem")
1407 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1408 os.path.dirname(__file__) or os.curdir,
1409 "https_svn_python_org_root.pem")
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001410 NOKIACERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1411 "nokia.pem")
Christian Heimes88b174c2013-08-17 00:54:47 +02001412 NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1413 "nullbytecert.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001414
1415 if (not os.path.exists(CERTFILE) or
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001416 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
Christian Heimes88b174c2013-08-17 00:54:47 +02001417 not os.path.exists(NOKIACERT) or
1418 not os.path.exists(NULLBYTECERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001419 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001420
Antoine Pitroude30f702010-09-14 12:54:08 +00001421 tests = [BasicTests, BasicSocketTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001422
Bill Janssen296a59d2007-09-16 22:06:00 +00001423 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001424 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001425
Bill Janssen98d19da2007-09-10 21:51:02 +00001426 if _have_threads:
1427 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001428 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001429 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001430
Antoine Pitrou3945c862010-04-28 21:11:01 +00001431 try:
1432 test_support.run_unittest(*tests)
1433 finally:
1434 if _have_threads:
1435 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001436
1437if __name__ == "__main__":
1438 test_main()