blob: 91b8029d049520a5f56a0a0dbfa34dcc93eafa44 [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)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400178 # < 3.0
179 self.assertLess(n, 0x30000000)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000180 major, minor, fix, patch, status = t
181 self.assertGreaterEqual(major, 0)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400182 self.assertLess(major, 3)
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000183 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)
Antoine Pitrou4e64d872014-07-21 18:35:01 -0400191 # Version string as returned by {Open,Libre}SSL, the format might change
192 if "LibreSSL" in s:
193 self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
194 (s, t))
195 else:
196 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
197 (s, t))
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000198
Zachary Ware1f702212013-12-10 14:09:20 -0600199 @test_support.requires_resource('network')
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000200 def test_ciphers(self):
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000201 remote = ("svn.python.org", 443)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000202 with test_support.transient_internet(remote[0]):
203 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
204 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000205 s.connect(remote)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000206 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
207 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
208 s.connect(remote)
209 # Error checking occurs when connecting, because the SSL context
210 # isn't created before.
211 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
212 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
213 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
214 s.connect(remote)
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000215
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000216 @test_support.cpython_only
217 def test_refcycle(self):
218 # Issue #7943: an SSL object doesn't create reference cycles with
219 # itself.
220 s = socket.socket(socket.AF_INET)
221 ss = ssl.wrap_socket(s)
222 wr = weakref.ref(ss)
223 del ss
224 self.assertEqual(wr(), None)
225
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000226 def test_wrapped_unconnected(self):
227 # The _delegate_methods in socket.py are correctly delegated to by an
228 # unconnected SSLSocket, so they will raise a socket.error rather than
229 # something unexpected like TypeError.
230 s = socket.socket(socket.AF_INET)
231 ss = ssl.wrap_socket(s)
232 self.assertRaises(socket.error, ss.recv, 1)
233 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
234 self.assertRaises(socket.error, ss.recvfrom, 1)
235 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
236 self.assertRaises(socket.error, ss.send, b'x')
237 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
238
Antoine Pitrou63cc99d2013-12-28 17:26:33 +0100239 def test_unsupported_dtls(self):
240 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
241 self.addCleanup(s.close)
242 with self.assertRaises(NotImplementedError) as cx:
243 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
244 self.assertEqual(str(cx.exception), "only stream sockets are supported")
245
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000246
Bill Janssen934b16d2008-06-28 22:19:33 +0000247class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000248
Antoine Pitrou3945c862010-04-28 21:11:01 +0000249 def test_connect(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000250 with test_support.transient_internet("svn.python.org"):
251 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
252 cert_reqs=ssl.CERT_NONE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000253 s.connect(("svn.python.org", 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000254 c = s.getpeercert()
255 if c:
256 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000257 s.close()
258
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000259 # this should fail because we have no verification certs
260 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
261 cert_reqs=ssl.CERT_REQUIRED)
262 try:
263 s.connect(("svn.python.org", 443))
264 except ssl.SSLError:
265 pass
266 finally:
267 s.close()
268
269 # this should succeed because we specify the root cert
270 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
271 cert_reqs=ssl.CERT_REQUIRED,
272 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
273 try:
274 s.connect(("svn.python.org", 443))
275 finally:
276 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +0000277
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000278 def test_connect_ex(self):
279 # Issue #11326: check connect_ex() implementation
280 with test_support.transient_internet("svn.python.org"):
281 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
282 cert_reqs=ssl.CERT_REQUIRED,
283 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
284 try:
285 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
286 self.assertTrue(s.getpeercert())
287 finally:
288 s.close()
289
290 def test_non_blocking_connect_ex(self):
291 # Issue #11326: non-blocking connect_ex() should allow handshake
292 # to proceed after the socket gets ready.
293 with test_support.transient_internet("svn.python.org"):
294 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
295 cert_reqs=ssl.CERT_REQUIRED,
296 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
297 do_handshake_on_connect=False)
298 try:
299 s.setblocking(False)
300 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +0000301 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
302 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000303 # Wait for connect to finish
304 select.select([], [s], [], 5.0)
305 # Non-blocking handshake
306 while True:
307 try:
308 s.do_handshake()
309 break
310 except ssl.SSLError as err:
311 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
312 select.select([s], [], [], 5.0)
313 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
314 select.select([], [s], [], 5.0)
315 else:
316 raise
317 # SSL established
318 self.assertTrue(s.getpeercert())
319 finally:
320 s.close()
321
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100322 def test_timeout_connect_ex(self):
323 # Issue #12065: on a timeout, connect_ex() should return the original
324 # errno (mimicking the behaviour of non-SSL sockets).
325 with test_support.transient_internet("svn.python.org"):
326 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
327 cert_reqs=ssl.CERT_REQUIRED,
328 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
329 do_handshake_on_connect=False)
330 try:
331 s.settimeout(0.0000001)
332 rc = s.connect_ex(('svn.python.org', 443))
333 if rc == 0:
334 self.skipTest("svn.python.org responded too quickly")
335 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
336 finally:
337 s.close()
338
339 def test_connect_ex_error(self):
340 with test_support.transient_internet("svn.python.org"):
341 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
342 cert_reqs=ssl.CERT_REQUIRED,
343 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
344 try:
345 self.assertEqual(errno.ECONNREFUSED,
346 s.connect_ex(("svn.python.org", 444)))
347 finally:
348 s.close()
349
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000350 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
351 def test_makefile_close(self):
352 # Issue #5238: creating a file-like object with makefile() shouldn't
353 # delay closing the underlying "real socket" (here tested with its
354 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000355 with test_support.transient_internet("svn.python.org"):
356 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
357 ss.connect(("svn.python.org", 443))
358 fd = ss.fileno()
359 f = ss.makefile()
360 f.close()
361 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000362 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000363 # Closing the SSL socket should close the fd too
364 ss.close()
365 gc.collect()
366 with self.assertRaises(OSError) as e:
367 os.read(fd, 0)
368 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000369
Antoine Pitrou3945c862010-04-28 21:11:01 +0000370 def test_non_blocking_handshake(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000371 with test_support.transient_internet("svn.python.org"):
372 s = socket.socket(socket.AF_INET)
373 s.connect(("svn.python.org", 443))
374 s.setblocking(False)
375 s = ssl.wrap_socket(s,
376 cert_reqs=ssl.CERT_NONE,
377 do_handshake_on_connect=False)
378 count = 0
379 while True:
380 try:
381 count += 1
382 s.do_handshake()
383 break
384 except ssl.SSLError, err:
385 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
386 select.select([s], [], [])
387 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
388 select.select([], [s], [])
389 else:
390 raise
391 s.close()
392 if test_support.verbose:
393 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +0000394
Antoine Pitrou3945c862010-04-28 21:11:01 +0000395 def test_get_server_certificate(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000396 with test_support.transient_internet("svn.python.org"):
Benjamin Petersonae80f452014-03-12 18:05:53 -0500397 pem = ssl.get_server_certificate(("svn.python.org", 443),
398 ssl.PROTOCOL_SSLv23)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000399 if not pem:
400 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000401
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000402 try:
Benjamin Petersonae80f452014-03-12 18:05:53 -0500403 pem = ssl.get_server_certificate(("svn.python.org", 443),
404 ssl.PROTOCOL_SSLv23,
405 ca_certs=CERTFILE)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000406 except ssl.SSLError:
407 #should fail
408 pass
409 else:
410 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000411
Benjamin Petersonae80f452014-03-12 18:05:53 -0500412 pem = ssl.get_server_certificate(("svn.python.org", 443),
413 ssl.PROTOCOL_SSLv23,
414 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000415 if not pem:
416 self.fail("No server certificate on svn.python.org:443!")
417 if test_support.verbose:
418 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000419
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000420 def test_algorithms(self):
421 # Issue #8484: all algorithms should be available when verifying a
422 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000423 # SHA256 was added in OpenSSL 0.9.8
424 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
425 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc642f672012-05-04 16:33:30 +0200426 self.skipTest("remote host needs SNI, only available on Python 3.2+")
427 # NOTE: https://sha2.hboeck.de is another possible test host
Antoine Pitroud43245a2011-01-08 10:32:51 +0000428 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000429 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroud43245a2011-01-08 10:32:51 +0000430 with test_support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000431 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
432 cert_reqs=ssl.CERT_REQUIRED,
433 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000434 try:
435 s.connect(remote)
436 if test_support.verbose:
437 sys.stdout.write("\nCipher with %r is %r\n" %
438 (remote, s.cipher()))
439 sys.stdout.write("Certificate is:\n%s\n" %
440 pprint.pformat(s.getpeercert()))
441 finally:
442 s.close()
443
Bill Janssen296a59d2007-09-16 22:06:00 +0000444
Bill Janssen98d19da2007-09-10 21:51:02 +0000445try:
446 import threading
447except ImportError:
448 _have_threads = False
449else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000450 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000451
Bill Janssen98d19da2007-09-10 21:51:02 +0000452 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000453
Bill Janssen98d19da2007-09-10 21:51:02 +0000454 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000455
Bill Janssen98d19da2007-09-10 21:51:02 +0000456 """A mildly complicated class, because we want it to work both
457 with and without the SSL wrapper around the socket connection, so
458 that we can test the STARTTLS functionality."""
459
460 def __init__(self, server, connsock):
461 self.server = server
462 self.running = False
463 self.sock = connsock
464 self.sock.setblocking(1)
465 self.sslconn = None
466 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000467 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000468
Bill Janssen934b16d2008-06-28 22:19:33 +0000469 def show_conn_details(self):
470 if self.server.certreqs == ssl.CERT_REQUIRED:
471 cert = self.sslconn.getpeercert()
472 if test_support.verbose and self.server.chatty:
473 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
474 cert_binary = self.sslconn.getpeercert(True)
475 if test_support.verbose and self.server.chatty:
476 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
477 cipher = self.sslconn.cipher()
478 if test_support.verbose and self.server.chatty:
479 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
480
Antoine Pitrou3945c862010-04-28 21:11:01 +0000481 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000482 try:
483 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
484 certfile=self.server.certificate,
485 ssl_version=self.server.protocol,
486 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000487 cert_reqs=self.server.certreqs,
488 ciphers=self.server.ciphers)
Antoine Pitroud76088d2012-01-03 22:46:48 +0100489 except ssl.SSLError as e:
Antoine Pitroudb187842010-04-27 10:32:58 +0000490 # XXX Various errors can have happened here, for example
491 # a mismatching protocol version, an invalid certificate,
492 # or a low-level bug. This should be made more discriminating.
Antoine Pitroud76088d2012-01-03 22:46:48 +0100493 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +0000494 if self.server.chatty:
495 handle_error("\n server: bad connection attempt from " +
496 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000497 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000498 self.running = False
499 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000500 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000501 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000502 return True
503
504 def read(self):
505 if self.sslconn:
506 return self.sslconn.read()
507 else:
508 return self.sock.recv(1024)
509
510 def write(self, bytes):
511 if self.sslconn:
512 return self.sslconn.write(bytes)
513 else:
514 return self.sock.send(bytes)
515
516 def close(self):
517 if self.sslconn:
518 self.sslconn.close()
519 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000520 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000521
Antoine Pitrou3945c862010-04-28 21:11:01 +0000522 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000523 self.running = True
524 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000525 if isinstance(self.sock, ssl.SSLSocket):
526 self.sslconn = self.sock
527 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000528 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000529 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000530 while self.running:
531 try:
532 msg = self.read()
533 if not msg:
534 # eof, so quit this handler
535 self.running = False
536 self.close()
537 elif msg.strip() == 'over':
538 if test_support.verbose and self.server.connectionchatty:
539 sys.stdout.write(" server: client closed connection\n")
540 self.close()
541 return
542 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
543 if test_support.verbose and self.server.connectionchatty:
544 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
545 self.write("OK\n")
546 if not self.wrap_conn():
547 return
Bill Janssen39295c22008-08-12 16:31:21 +0000548 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
549 if test_support.verbose and self.server.connectionchatty:
550 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
551 self.write("OK\n")
552 self.sslconn.unwrap()
553 self.sslconn = None
554 if test_support.verbose and self.server.connectionchatty:
555 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000556 else:
557 if (test_support.verbose and
558 self.server.connectionchatty):
559 ctype = (self.sslconn and "encrypted") or "unencrypted"
560 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
561 % (repr(msg), ctype, repr(msg.lower()), ctype))
562 self.write(msg.lower())
563 except ssl.SSLError:
564 if self.server.chatty:
565 handle_error("Test server failure:\n")
566 self.close()
567 self.running = False
568 # normally, we'd just stop here, but for the test
569 # harness, we want to stop the server
570 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000571
Trent Nelsone41b0062008-04-08 23:47:30 +0000572 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000573 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000574 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000575 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000576
Bill Janssen98d19da2007-09-10 21:51:02 +0000577 if ssl_version is None:
578 ssl_version = ssl.PROTOCOL_TLSv1
579 if certreqs is None:
580 certreqs = ssl.CERT_NONE
581 self.certificate = certificate
582 self.protocol = ssl_version
583 self.certreqs = certreqs
584 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000585 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000586 self.chatty = chatty
587 self.connectionchatty = connectionchatty
588 self.starttls_server = starttls_server
589 self.sock = socket.socket()
590 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000591 if wrap_accepting_socket:
592 self.sock = ssl.wrap_socket(self.sock, server_side=True,
593 certfile=self.certificate,
594 cert_reqs = self.certreqs,
595 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000596 ssl_version = self.protocol,
597 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000598 if test_support.verbose and self.chatty:
599 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
600 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000601 self.active = False
Antoine Pitroud76088d2012-01-03 22:46:48 +0100602 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000603 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000604 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000605
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100606 def __enter__(self):
607 self.start(threading.Event())
608 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100609 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100610
611 def __exit__(self, *args):
612 self.stop()
613 self.join()
614
Antoine Pitrou3945c862010-04-28 21:11:01 +0000615 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000616 self.flag = flag
617 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000618
Antoine Pitrou3945c862010-04-28 21:11:01 +0000619 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000620 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000621 self.sock.listen(5)
622 self.active = True
623 if self.flag:
624 # signal an event
625 self.flag.set()
626 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000627 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000628 newconn, connaddr = self.sock.accept()
629 if test_support.verbose and self.chatty:
630 sys.stdout.write(' server: new connection from '
631 + str(connaddr) + '\n')
632 handler = self.ConnectionHandler(self, newconn)
633 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +0100634 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000635 except socket.timeout:
636 pass
637 except KeyboardInterrupt:
638 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000639 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000640
Antoine Pitrou3945c862010-04-28 21:11:01 +0000641 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000642 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000643
Bill Janssen934b16d2008-06-28 22:19:33 +0000644 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000645
Antoine Pitrou3945c862010-04-28 21:11:01 +0000646 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000647
Antoine Pitrou3945c862010-04-28 21:11:01 +0000648 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000649
650 def __init__(self, conn, certfile):
651 asyncore.dispatcher_with_send.__init__(self, conn)
652 self.socket = ssl.wrap_socket(conn, server_side=True,
653 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000654 do_handshake_on_connect=False)
655 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000656
657 def readable(self):
658 if isinstance(self.socket, ssl.SSLSocket):
659 while self.socket.pending() > 0:
660 self.handle_read_event()
661 return True
662
Antoine Pitroufc69af12010-04-24 20:04:58 +0000663 def _do_ssl_handshake(self):
664 try:
665 self.socket.do_handshake()
666 except ssl.SSLError, err:
667 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
668 ssl.SSL_ERROR_WANT_WRITE):
669 return
670 elif err.args[0] == ssl.SSL_ERROR_EOF:
671 return self.handle_close()
672 raise
673 except socket.error, err:
674 if err.args[0] == errno.ECONNABORTED:
675 return self.handle_close()
676 else:
677 self._ssl_accepting = False
678
Bill Janssen934b16d2008-06-28 22:19:33 +0000679 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000680 if self._ssl_accepting:
681 self._do_ssl_handshake()
682 else:
683 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000684 if data and data.strip() != 'over':
685 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000686
687 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000688 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000689 if test_support.verbose:
690 sys.stdout.write(" server: closed connection %s\n" % self.socket)
691
692 def handle_error(self):
693 raise
694
695 def __init__(self, certfile):
696 self.certfile = certfile
697 asyncore.dispatcher.__init__(self)
698 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
699 self.port = test_support.bind_port(self.socket)
700 self.listen(5)
701
702 def handle_accept(self):
703 sock_obj, addr = self.accept()
704 if test_support.verbose:
705 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
706 self.ConnectionHandler(sock_obj, self.certfile)
707
708 def handle_error(self):
709 raise
710
711 def __init__(self, certfile):
712 self.flag = None
713 self.active = False
714 self.server = self.EchoServer(certfile)
715 self.port = self.server.port
716 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000717 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000718
719 def __str__(self):
720 return "<%s %s>" % (self.__class__.__name__, self.server)
721
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100722 def __enter__(self):
723 self.start(threading.Event())
724 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100725 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100726
727 def __exit__(self, *args):
728 if test_support.verbose:
729 sys.stdout.write(" cleanup: stopping server.\n")
730 self.stop()
731 if test_support.verbose:
732 sys.stdout.write(" cleanup: joining server thread.\n")
733 self.join()
734 if test_support.verbose:
735 sys.stdout.write(" cleanup: successfully joined.\n")
736
Antoine Pitrou3945c862010-04-28 21:11:01 +0000737 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000738 self.flag = flag
739 threading.Thread.start(self)
740
Antoine Pitrou3945c862010-04-28 21:11:01 +0000741 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000742 self.active = True
743 if self.flag:
744 self.flag.set()
745 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000746 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000747
Antoine Pitrou3945c862010-04-28 21:11:01 +0000748 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000749 self.active = False
750 self.server.close()
751
752 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000753
754 class HTTPSServer(HTTPServer):
755
756 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000757 HTTPServer.__init__(self, server_address, RequestHandlerClass)
758 # we assume the certfile contains both private key and certificate
759 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000760 self.allow_reuse_address = True
761
Bill Janssen934b16d2008-06-28 22:19:33 +0000762 def __str__(self):
763 return ('<%s %s:%s>' %
764 (self.__class__.__name__,
765 self.server_name,
766 self.server_port))
767
Antoine Pitrou3945c862010-04-28 21:11:01 +0000768 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000769 # override this to wrap socket with SSL
770 sock, addr = self.socket.accept()
771 sslconn = ssl.wrap_socket(sock, server_side=True,
772 certfile=self.certfile)
773 return sslconn, addr
774
Bill Janssen296a59d2007-09-16 22:06:00 +0000775 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000776 # need to override translate_path to get a known root,
777 # instead of using os.curdir, since the test could be
778 # run from anywhere
779
780 server_version = "TestHTTPS/1.0"
781
782 root = None
783
784 def translate_path(self, path):
785 """Translate a /-separated PATH to the local filename syntax.
786
787 Components that mean special things to the local file system
788 (e.g. drive or directory names) are ignored. (XXX They should
789 probably be diagnosed.)
790
791 """
792 # abandon query parameters
793 path = urlparse.urlparse(path)[2]
794 path = os.path.normpath(urllib.unquote(path))
795 words = path.split('/')
796 words = filter(None, words)
797 path = self.root
798 for word in words:
799 drive, word = os.path.splitdrive(word)
800 head, word = os.path.split(word)
801 if word in self.root: continue
802 path = os.path.join(path, word)
803 return path
804
805 def log_message(self, format, *args):
806
807 # we override this to suppress logging unless "verbose"
808
809 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000810 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
811 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000812 self.server.server_port,
813 self.request.cipher(),
814 self.log_date_time_string(),
815 format%args))
816
817
Trent Nelsone41b0062008-04-08 23:47:30 +0000818 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000819 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000820 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
821 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000822 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
823 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000824 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000825 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000826
827 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000828 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000829
Antoine Pitrou3945c862010-04-28 21:11:01 +0000830 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000831 self.flag = flag
832 threading.Thread.start(self)
833
Antoine Pitrou3945c862010-04-28 21:11:01 +0000834 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000835 if self.flag:
836 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000837 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000838
Antoine Pitrou3945c862010-04-28 21:11:01 +0000839 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000840 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000841
842
Antoine Pitrou3945c862010-04-28 21:11:01 +0000843 def bad_cert_test(certfile):
844 """
845 Launch a server with CERT_REQUIRED, and check that trying to
846 connect to it with the given client certificate fails.
847 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000848 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000849 certreqs=ssl.CERT_REQUIRED,
850 cacerts=CERTFILE, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100851 with server:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000852 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000853 s = ssl.wrap_socket(socket.socket(),
854 certfile=certfile,
855 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000856 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000857 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000858 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000859 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000860 except socket.error, x:
861 if test_support.verbose:
862 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000863 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000864 raise AssertionError("Use of invalid cert should have failed!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000865
Antoine Pitrou3945c862010-04-28 21:11:01 +0000866 def server_params_test(certfile, protocol, certreqs, cacertsfile,
867 client_certfile, client_protocol=None, indata="FOO\n",
868 ciphers=None, chatty=True, connectionchatty=False,
869 wrap_accepting_socket=False):
870 """
871 Launch a server, connect a client to it and try various reads
872 and writes.
873 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000874 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000875 certreqs=certreqs,
876 ssl_version=protocol,
877 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000878 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000879 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000880 connectionchatty=connectionchatty,
881 wrap_accepting_socket=wrap_accepting_socket)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100882 with server:
883 # try to connect
884 if client_protocol is None:
885 client_protocol = protocol
Antoine Pitroudb187842010-04-27 10:32:58 +0000886 s = ssl.wrap_socket(socket.socket(),
887 certfile=client_certfile,
888 ca_certs=cacertsfile,
889 ciphers=ciphers,
890 cert_reqs=certreqs,
891 ssl_version=client_protocol)
892 s.connect((HOST, server.port))
893 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000894 if connectionchatty:
895 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000896 sys.stdout.write(
897 " client: sending %s...\n" % (repr(arg)))
898 s.write(arg)
899 outdata = s.read()
900 if connectionchatty:
901 if test_support.verbose:
902 sys.stdout.write(" client: read %s\n" % repr(outdata))
903 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000904 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000905 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
906 % (outdata[:min(len(outdata),20)], len(outdata),
907 indata[:min(len(indata),20)].lower(), len(indata)))
908 s.write("over\n")
909 if connectionchatty:
910 if test_support.verbose:
911 sys.stdout.write(" client: closing connection.\n")
912 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000913
Antoine Pitrou3945c862010-04-28 21:11:01 +0000914 def try_protocol_combo(server_protocol,
915 client_protocol,
916 expect_success,
917 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000918 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000919 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000920 certtype = {
921 ssl.CERT_NONE: "CERT_NONE",
922 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
923 ssl.CERT_REQUIRED: "CERT_REQUIRED",
924 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000925 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000926 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000927 sys.stdout.write(formatstr %
928 (ssl.get_protocol_name(client_protocol),
929 ssl.get_protocol_name(server_protocol),
930 certtype))
931 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000932 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
933 # will send an SSLv3 hello (rather than SSLv2) starting from
934 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000935 server_params_test(CERTFILE, server_protocol, certsreqs,
936 CERTFILE, CERTFILE, client_protocol,
937 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000938 # Protocol mismatch can result in either an SSLError, or a
939 # "Connection reset by peer" error.
940 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000941 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000942 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000943 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000944 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000945 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000946 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000947 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000948 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000949 "Client protocol %s succeeded with server protocol %s!"
950 % (ssl.get_protocol_name(client_protocol),
951 ssl.get_protocol_name(server_protocol)))
952
953
Bill Janssen934b16d2008-06-28 22:19:33 +0000954 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000955
Antoine Pitrou3945c862010-04-28 21:11:01 +0000956 def test_rude_shutdown(self):
957 """A brutal shutdown of an SSL server should raise an IOError
958 in the client when attempting handshake.
959 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000960 listener_ready = threading.Event()
961 listener_gone = threading.Event()
962
Antoine Pitrou150acda2010-04-27 08:40:51 +0000963 s = socket.socket()
964 port = test_support.bind_port(s, HOST)
965
966 # `listener` runs in a thread. It sits in an accept() until
967 # the main thread connects. Then it rudely closes the socket,
968 # and sets Event `listener_gone` to let the main thread know
969 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000970 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000971 s.listen(5)
972 listener_ready.set()
973 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000974 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000975 listener_gone.set()
976
977 def connector():
978 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000979 c = socket.socket()
980 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000981 listener_gone.wait()
982 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000983 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000984 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000985 pass
986 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000987 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000988
989 t = threading.Thread(target=listener)
990 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000991 try:
992 connector()
993 finally:
994 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000995
Antoine Pitroud75efd92010-08-04 17:38:33 +0000996 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000997 def test_echo(self):
998 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000999 if test_support.verbose:
1000 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001001 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
1002 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
1003 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001004
Antoine Pitrou3945c862010-04-28 21:11:01 +00001005 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +00001006 if test_support.verbose:
1007 sys.stdout.write("\n")
1008 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +00001009 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001010 certreqs=ssl.CERT_NONE,
1011 ssl_version=ssl.PROTOCOL_SSLv23,
1012 cacerts=CERTFILE,
1013 chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001014 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001015 s = ssl.wrap_socket(socket.socket(),
1016 certfile=CERTFILE,
1017 ca_certs=CERTFILE,
1018 cert_reqs=ssl.CERT_REQUIRED,
1019 ssl_version=ssl.PROTOCOL_SSLv23)
1020 s.connect((HOST, server.port))
1021 cert = s.getpeercert()
1022 self.assertTrue(cert, "Can't get peer certificate.")
1023 cipher = s.cipher()
1024 if test_support.verbose:
1025 sys.stdout.write(pprint.pformat(cert) + '\n')
1026 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1027 if 'subject' not in cert:
1028 self.fail("No subject field in certificate: %s." %
1029 pprint.pformat(cert))
1030 if ((('organizationName', 'Python Software Foundation'),)
1031 not in cert['subject']):
1032 self.fail(
1033 "Missing or invalid 'organizationName' field in certificate subject; "
1034 "should be 'Python Software Foundation'.")
1035 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001036
Antoine Pitrou3945c862010-04-28 21:11:01 +00001037 def test_empty_cert(self):
1038 """Connecting with an empty cert file"""
1039 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1040 "nullcert.pem"))
1041 def test_malformed_cert(self):
1042 """Connecting with a badly formatted certificate (syntax error)"""
1043 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1044 "badcert.pem"))
1045 def test_nonexisting_cert(self):
1046 """Connecting with a non-existing cert file"""
1047 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1048 "wrongcert.pem"))
1049 def test_malformed_key(self):
1050 """Connecting with a badly formatted key (syntax error)"""
1051 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1052 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +00001053
Antoine Pitroud75efd92010-08-04 17:38:33 +00001054 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001055 def test_protocol_sslv2(self):
1056 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001057 if test_support.verbose:
1058 sys.stdout.write("\n")
Antoine Pitrou6361ea22011-10-30 21:31:34 +01001059 if not hasattr(ssl, 'PROTOCOL_SSLv2'):
1060 self.skipTest("PROTOCOL_SSLv2 needed")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001061 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1062 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1063 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitrou3b2afbb2014-01-09 19:52:12 +01001064 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001065 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1066 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001067
Antoine Pitroud75efd92010-08-04 17:38:33 +00001068 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001069 def test_protocol_sslv23(self):
1070 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001071 if test_support.verbose:
1072 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001073 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1074 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1075 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
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_OPTIONAL)
1078 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1079 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00001080
Antoine Pitrou3945c862010-04-28 21:11:01 +00001081 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1082 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1083 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00001084
Antoine Pitroud75efd92010-08-04 17:38:33 +00001085 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001086 def test_protocol_sslv3(self):
1087 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001088 if test_support.verbose:
1089 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001090 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1091 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1092 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001093 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1094 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001095 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001096
Antoine Pitroud75efd92010-08-04 17:38:33 +00001097 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001098 def test_protocol_tlsv1(self):
1099 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001100 if test_support.verbose:
1101 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001102 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1103 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1104 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001105 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1106 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001107 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001108
Antoine Pitrou3945c862010-04-28 21:11:01 +00001109 def test_starttls(self):
1110 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +00001111 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00001112
Trent Nelsone41b0062008-04-08 23:47:30 +00001113 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001114 ssl_version=ssl.PROTOCOL_TLSv1,
1115 starttls_server=True,
1116 chatty=True,
1117 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001118 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001119 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001120 s = socket.socket()
1121 s.setblocking(1)
1122 s.connect((HOST, server.port))
1123 if test_support.verbose:
1124 sys.stdout.write("\n")
1125 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +00001126 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00001127 sys.stdout.write(
1128 " client: sending %s...\n" % repr(indata))
1129 if wrapped:
1130 conn.write(indata)
1131 outdata = conn.read()
1132 else:
1133 s.send(indata)
1134 outdata = s.recv(1024)
1135 if (indata == "STARTTLS" and
1136 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001137 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001138 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001139 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001140 " client: read %s from server, starting TLS...\n"
1141 % repr(outdata))
1142 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1143 wrapped = True
1144 elif (indata == "ENDTLS" and
1145 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001146 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001147 if test_support.verbose:
1148 sys.stdout.write(
1149 " client: read %s from server, ending TLS...\n"
1150 % repr(outdata))
1151 s = conn.unwrap()
1152 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001153 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001154 if test_support.verbose:
1155 sys.stdout.write(
1156 " client: read %s from server\n" % repr(outdata))
1157 if test_support.verbose:
1158 sys.stdout.write(" client: closing connection.\n")
1159 if wrapped:
1160 conn.write("over\n")
1161 else:
1162 s.send("over\n")
1163 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001164
Antoine Pitrou3945c862010-04-28 21:11:01 +00001165 def test_socketserver(self):
1166 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001167 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001168 flag = threading.Event()
1169 server.start(flag)
1170 # wait for it to start
1171 flag.wait()
1172 # try to connect
1173 try:
1174 if test_support.verbose:
1175 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001176 with open(CERTFILE, 'rb') as f:
1177 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001178 d2 = ''
1179 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001180 url = 'https://127.0.0.1:%d/%s' % (
1181 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001182 with test_support.check_py3k_warnings():
1183 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001184 dlen = f.info().getheader("content-length")
1185 if dlen and (int(dlen) > 0):
1186 d2 = f.read(int(dlen))
1187 if test_support.verbose:
1188 sys.stdout.write(
1189 " client: read %d bytes from remote server '%s'\n"
1190 % (len(d2), server))
1191 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001192 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001193 finally:
1194 server.stop()
1195 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001196
Antoine Pitrou3945c862010-04-28 21:11:01 +00001197 def test_wrapped_accept(self):
1198 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001199 if test_support.verbose:
1200 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001201 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1202 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1203 chatty=True, connectionchatty=True,
1204 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001205
Antoine Pitrou3945c862010-04-28 21:11:01 +00001206 def test_asyncore_server(self):
1207 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001208 indata = "TEST MESSAGE of mixed case\n"
1209
1210 if test_support.verbose:
1211 sys.stdout.write("\n")
1212 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001213 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001214 s = ssl.wrap_socket(socket.socket())
1215 s.connect(('127.0.0.1', server.port))
1216 if test_support.verbose:
1217 sys.stdout.write(
1218 " client: sending %s...\n" % (repr(indata)))
1219 s.write(indata)
1220 outdata = s.read()
1221 if test_support.verbose:
1222 sys.stdout.write(" client: read %s\n" % repr(outdata))
1223 if outdata != indata.lower():
1224 self.fail(
1225 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1226 % (outdata[:min(len(outdata),20)], len(outdata),
1227 indata[:min(len(indata),20)].lower(), len(indata)))
1228 s.write("over\n")
1229 if test_support.verbose:
1230 sys.stdout.write(" client: closing connection.\n")
1231 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001232
Antoine Pitrou3945c862010-04-28 21:11:01 +00001233 def test_recv_send(self):
1234 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001235 if test_support.verbose:
1236 sys.stdout.write("\n")
1237
1238 server = ThreadedEchoServer(CERTFILE,
1239 certreqs=ssl.CERT_NONE,
1240 ssl_version=ssl.PROTOCOL_TLSv1,
1241 cacerts=CERTFILE,
1242 chatty=True,
1243 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001244 with server:
1245 s = ssl.wrap_socket(socket.socket(),
1246 server_side=False,
1247 certfile=CERTFILE,
1248 ca_certs=CERTFILE,
1249 cert_reqs=ssl.CERT_NONE,
1250 ssl_version=ssl.PROTOCOL_TLSv1)
1251 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001252 # helper methods for standardising recv* method signatures
1253 def _recv_into():
1254 b = bytearray("\0"*100)
1255 count = s.recv_into(b)
1256 return b[:count]
1257
1258 def _recvfrom_into():
1259 b = bytearray("\0"*100)
1260 count, addr = s.recvfrom_into(b)
1261 return b[:count]
1262
1263 # (name, method, whether to expect success, *args)
1264 send_methods = [
1265 ('send', s.send, True, []),
1266 ('sendto', s.sendto, False, ["some.address"]),
1267 ('sendall', s.sendall, True, []),
1268 ]
1269 recv_methods = [
1270 ('recv', s.recv, True, []),
1271 ('recvfrom', s.recvfrom, False, ["some.address"]),
1272 ('recv_into', _recv_into, True, []),
1273 ('recvfrom_into', _recvfrom_into, False, []),
1274 ]
1275 data_prefix = u"PREFIX_"
1276
1277 for meth_name, send_meth, expect_success, args in send_methods:
1278 indata = data_prefix + meth_name
1279 try:
1280 send_meth(indata.encode('ASCII', 'strict'), *args)
1281 outdata = s.read()
1282 outdata = outdata.decode('ASCII', 'strict')
1283 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001284 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001285 "While sending with <<%s>> bad data "
1286 "<<%r>> (%d) received; "
1287 "expected <<%r>> (%d)\n" % (
1288 meth_name, outdata[:20], len(outdata),
1289 indata[:20], len(indata)
1290 )
1291 )
1292 except ValueError as e:
1293 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001294 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001295 "Failed to send with method <<%s>>; "
1296 "expected to succeed.\n" % (meth_name,)
1297 )
1298 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001299 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001300 "Method <<%s>> failed with unexpected "
1301 "exception message: %s\n" % (
1302 meth_name, e
1303 )
1304 )
1305
1306 for meth_name, recv_meth, expect_success, args in recv_methods:
1307 indata = data_prefix + meth_name
1308 try:
1309 s.send(indata.encode('ASCII', 'strict'))
1310 outdata = recv_meth(*args)
1311 outdata = outdata.decode('ASCII', 'strict')
1312 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001313 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001314 "While receiving with <<%s>> bad data "
1315 "<<%r>> (%d) received; "
1316 "expected <<%r>> (%d)\n" % (
1317 meth_name, outdata[:20], len(outdata),
1318 indata[:20], len(indata)
1319 )
1320 )
1321 except ValueError as e:
1322 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001323 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001324 "Failed to receive with method <<%s>>; "
1325 "expected to succeed.\n" % (meth_name,)
1326 )
1327 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001328 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001329 "Method <<%s>> failed with unexpected "
1330 "exception message: %s\n" % (
1331 meth_name, e
1332 )
1333 )
1334 # consume data
1335 s.read()
1336
1337 s.write("over\n".encode("ASCII", "strict"))
1338 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00001339
Antoine Pitroufc69af12010-04-24 20:04:58 +00001340 def test_handshake_timeout(self):
1341 # Issue #5103: SSL handshake must respect the socket timeout
1342 server = socket.socket(socket.AF_INET)
1343 host = "127.0.0.1"
1344 port = test_support.bind_port(server)
1345 started = threading.Event()
1346 finish = False
1347
1348 def serve():
1349 server.listen(5)
1350 started.set()
1351 conns = []
1352 while not finish:
1353 r, w, e = select.select([server], [], [], 0.1)
1354 if server in r:
1355 # Let the socket hang around rather than having
1356 # it closed by garbage collection.
1357 conns.append(server.accept()[0])
1358
1359 t = threading.Thread(target=serve)
1360 t.start()
1361 started.wait()
1362
1363 try:
1364 try:
1365 c = socket.socket(socket.AF_INET)
1366 c.settimeout(0.2)
1367 c.connect((host, port))
1368 # Will attempt handshake and time out
1369 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1370 ssl.wrap_socket, c)
1371 finally:
1372 c.close()
1373 try:
1374 c = socket.socket(socket.AF_INET)
1375 c.settimeout(0.2)
1376 c = ssl.wrap_socket(c)
1377 # Will attempt handshake and time out
1378 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1379 c.connect, (host, port))
1380 finally:
1381 c.close()
1382 finally:
1383 finish = True
1384 t.join()
1385 server.close()
1386
Antoine Pitroud76088d2012-01-03 22:46:48 +01001387 def test_default_ciphers(self):
1388 with ThreadedEchoServer(CERTFILE,
1389 ssl_version=ssl.PROTOCOL_SSLv23,
1390 chatty=False) as server:
1391 sock = socket.socket()
1392 try:
1393 # Force a set of weak ciphers on our client socket
1394 try:
1395 s = ssl.wrap_socket(sock,
1396 ssl_version=ssl.PROTOCOL_SSLv23,
1397 ciphers="DES")
1398 except ssl.SSLError:
1399 self.skipTest("no DES cipher available")
1400 with self.assertRaises((OSError, ssl.SSLError)):
1401 s.connect((HOST, server.port))
1402 finally:
1403 sock.close()
1404 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1405
Bill Janssen61c001a2008-09-08 16:37:24 +00001406
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001407def test_main(verbose=False):
Christian Heimes88b174c2013-08-17 00:54:47 +02001408 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT, NULLBYTECERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001409 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001410 "keycert.pem")
1411 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1412 os.path.dirname(__file__) or os.curdir,
1413 "https_svn_python_org_root.pem")
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001414 NOKIACERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1415 "nokia.pem")
Christian Heimes88b174c2013-08-17 00:54:47 +02001416 NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1417 "nullbytecert.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001418
1419 if (not os.path.exists(CERTFILE) or
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001420 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
Christian Heimes88b174c2013-08-17 00:54:47 +02001421 not os.path.exists(NOKIACERT) or
1422 not os.path.exists(NULLBYTECERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001423 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001424
Antoine Pitroude30f702010-09-14 12:54:08 +00001425 tests = [BasicTests, BasicSocketTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001426
Bill Janssen296a59d2007-09-16 22:06:00 +00001427 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001428 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001429
Bill Janssen98d19da2007-09-10 21:51:02 +00001430 if _have_threads:
1431 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001432 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001433 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001434
Antoine Pitrou3945c862010-04-28 21:11:01 +00001435 try:
1436 test_support.run_unittest(*tests)
1437 finally:
1438 if _have_threads:
1439 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001440
1441if __name__ == "__main__":
1442 test_main()