blob: c1c338449a4f6b80b0df5ac02566f5eb3627a063 [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"):
393 pem = ssl.get_server_certificate(("svn.python.org", 443))
394 if not pem:
395 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000396
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000397 try:
398 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
399 except ssl.SSLError:
400 #should fail
401 pass
402 else:
403 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000404
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000405 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
406 if not pem:
407 self.fail("No server certificate on svn.python.org:443!")
408 if test_support.verbose:
409 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000410
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000411 def test_algorithms(self):
412 # Issue #8484: all algorithms should be available when verifying a
413 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000414 # SHA256 was added in OpenSSL 0.9.8
415 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
416 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc642f672012-05-04 16:33:30 +0200417 self.skipTest("remote host needs SNI, only available on Python 3.2+")
418 # NOTE: https://sha2.hboeck.de is another possible test host
Antoine Pitroud43245a2011-01-08 10:32:51 +0000419 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000420 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroud43245a2011-01-08 10:32:51 +0000421 with test_support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000422 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
423 cert_reqs=ssl.CERT_REQUIRED,
424 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000425 try:
426 s.connect(remote)
427 if test_support.verbose:
428 sys.stdout.write("\nCipher with %r is %r\n" %
429 (remote, s.cipher()))
430 sys.stdout.write("Certificate is:\n%s\n" %
431 pprint.pformat(s.getpeercert()))
432 finally:
433 s.close()
434
Bill Janssen296a59d2007-09-16 22:06:00 +0000435
Bill Janssen98d19da2007-09-10 21:51:02 +0000436try:
437 import threading
438except ImportError:
439 _have_threads = False
440else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000441 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000442
Bill Janssen98d19da2007-09-10 21:51:02 +0000443 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000444
Bill Janssen98d19da2007-09-10 21:51:02 +0000445 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000446
Bill Janssen98d19da2007-09-10 21:51:02 +0000447 """A mildly complicated class, because we want it to work both
448 with and without the SSL wrapper around the socket connection, so
449 that we can test the STARTTLS functionality."""
450
451 def __init__(self, server, connsock):
452 self.server = server
453 self.running = False
454 self.sock = connsock
455 self.sock.setblocking(1)
456 self.sslconn = None
457 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000458 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000459
Bill Janssen934b16d2008-06-28 22:19:33 +0000460 def show_conn_details(self):
461 if self.server.certreqs == ssl.CERT_REQUIRED:
462 cert = self.sslconn.getpeercert()
463 if test_support.verbose and self.server.chatty:
464 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
465 cert_binary = self.sslconn.getpeercert(True)
466 if test_support.verbose and self.server.chatty:
467 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
468 cipher = self.sslconn.cipher()
469 if test_support.verbose and self.server.chatty:
470 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
471
Antoine Pitrou3945c862010-04-28 21:11:01 +0000472 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000473 try:
474 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
475 certfile=self.server.certificate,
476 ssl_version=self.server.protocol,
477 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000478 cert_reqs=self.server.certreqs,
479 ciphers=self.server.ciphers)
Antoine Pitroud76088d2012-01-03 22:46:48 +0100480 except ssl.SSLError as e:
Antoine Pitroudb187842010-04-27 10:32:58 +0000481 # XXX Various errors can have happened here, for example
482 # a mismatching protocol version, an invalid certificate,
483 # or a low-level bug. This should be made more discriminating.
Antoine Pitroud76088d2012-01-03 22:46:48 +0100484 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +0000485 if self.server.chatty:
486 handle_error("\n server: bad connection attempt from " +
487 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000488 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000489 self.running = False
490 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000491 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000492 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000493 return True
494
495 def read(self):
496 if self.sslconn:
497 return self.sslconn.read()
498 else:
499 return self.sock.recv(1024)
500
501 def write(self, bytes):
502 if self.sslconn:
503 return self.sslconn.write(bytes)
504 else:
505 return self.sock.send(bytes)
506
507 def close(self):
508 if self.sslconn:
509 self.sslconn.close()
510 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000511 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000512
Antoine Pitrou3945c862010-04-28 21:11:01 +0000513 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000514 self.running = True
515 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000516 if isinstance(self.sock, ssl.SSLSocket):
517 self.sslconn = self.sock
518 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000519 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000520 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000521 while self.running:
522 try:
523 msg = self.read()
524 if not msg:
525 # eof, so quit this handler
526 self.running = False
527 self.close()
528 elif msg.strip() == 'over':
529 if test_support.verbose and self.server.connectionchatty:
530 sys.stdout.write(" server: client closed connection\n")
531 self.close()
532 return
533 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
534 if test_support.verbose and self.server.connectionchatty:
535 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
536 self.write("OK\n")
537 if not self.wrap_conn():
538 return
Bill Janssen39295c22008-08-12 16:31:21 +0000539 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
540 if test_support.verbose and self.server.connectionchatty:
541 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
542 self.write("OK\n")
543 self.sslconn.unwrap()
544 self.sslconn = None
545 if test_support.verbose and self.server.connectionchatty:
546 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000547 else:
548 if (test_support.verbose and
549 self.server.connectionchatty):
550 ctype = (self.sslconn and "encrypted") or "unencrypted"
551 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
552 % (repr(msg), ctype, repr(msg.lower()), ctype))
553 self.write(msg.lower())
554 except ssl.SSLError:
555 if self.server.chatty:
556 handle_error("Test server failure:\n")
557 self.close()
558 self.running = False
559 # normally, we'd just stop here, but for the test
560 # harness, we want to stop the server
561 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000562
Trent Nelsone41b0062008-04-08 23:47:30 +0000563 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000564 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000565 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000566 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000567
Bill Janssen98d19da2007-09-10 21:51:02 +0000568 if ssl_version is None:
569 ssl_version = ssl.PROTOCOL_TLSv1
570 if certreqs is None:
571 certreqs = ssl.CERT_NONE
572 self.certificate = certificate
573 self.protocol = ssl_version
574 self.certreqs = certreqs
575 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000576 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000577 self.chatty = chatty
578 self.connectionchatty = connectionchatty
579 self.starttls_server = starttls_server
580 self.sock = socket.socket()
581 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000582 if wrap_accepting_socket:
583 self.sock = ssl.wrap_socket(self.sock, server_side=True,
584 certfile=self.certificate,
585 cert_reqs = self.certreqs,
586 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000587 ssl_version = self.protocol,
588 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000589 if test_support.verbose and self.chatty:
590 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
591 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000592 self.active = False
Antoine Pitroud76088d2012-01-03 22:46:48 +0100593 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000594 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000595 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000596
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100597 def __enter__(self):
598 self.start(threading.Event())
599 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100600 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100601
602 def __exit__(self, *args):
603 self.stop()
604 self.join()
605
Antoine Pitrou3945c862010-04-28 21:11:01 +0000606 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000607 self.flag = flag
608 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000609
Antoine Pitrou3945c862010-04-28 21:11:01 +0000610 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000611 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000612 self.sock.listen(5)
613 self.active = True
614 if self.flag:
615 # signal an event
616 self.flag.set()
617 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000618 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000619 newconn, connaddr = self.sock.accept()
620 if test_support.verbose and self.chatty:
621 sys.stdout.write(' server: new connection from '
622 + str(connaddr) + '\n')
623 handler = self.ConnectionHandler(self, newconn)
624 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +0100625 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000626 except socket.timeout:
627 pass
628 except KeyboardInterrupt:
629 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000630 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000631
Antoine Pitrou3945c862010-04-28 21:11:01 +0000632 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000633 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000634
Bill Janssen934b16d2008-06-28 22:19:33 +0000635 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000636
Antoine Pitrou3945c862010-04-28 21:11:01 +0000637 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000638
Antoine Pitrou3945c862010-04-28 21:11:01 +0000639 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000640
641 def __init__(self, conn, certfile):
642 asyncore.dispatcher_with_send.__init__(self, conn)
643 self.socket = ssl.wrap_socket(conn, server_side=True,
644 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000645 do_handshake_on_connect=False)
646 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000647
648 def readable(self):
649 if isinstance(self.socket, ssl.SSLSocket):
650 while self.socket.pending() > 0:
651 self.handle_read_event()
652 return True
653
Antoine Pitroufc69af12010-04-24 20:04:58 +0000654 def _do_ssl_handshake(self):
655 try:
656 self.socket.do_handshake()
657 except ssl.SSLError, err:
658 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
659 ssl.SSL_ERROR_WANT_WRITE):
660 return
661 elif err.args[0] == ssl.SSL_ERROR_EOF:
662 return self.handle_close()
663 raise
664 except socket.error, err:
665 if err.args[0] == errno.ECONNABORTED:
666 return self.handle_close()
667 else:
668 self._ssl_accepting = False
669
Bill Janssen934b16d2008-06-28 22:19:33 +0000670 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000671 if self._ssl_accepting:
672 self._do_ssl_handshake()
673 else:
674 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000675 if data and data.strip() != 'over':
676 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000677
678 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000679 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000680 if test_support.verbose:
681 sys.stdout.write(" server: closed connection %s\n" % self.socket)
682
683 def handle_error(self):
684 raise
685
686 def __init__(self, certfile):
687 self.certfile = certfile
688 asyncore.dispatcher.__init__(self)
689 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
690 self.port = test_support.bind_port(self.socket)
691 self.listen(5)
692
693 def handle_accept(self):
694 sock_obj, addr = self.accept()
695 if test_support.verbose:
696 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
697 self.ConnectionHandler(sock_obj, self.certfile)
698
699 def handle_error(self):
700 raise
701
702 def __init__(self, certfile):
703 self.flag = None
704 self.active = False
705 self.server = self.EchoServer(certfile)
706 self.port = self.server.port
707 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000708 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000709
710 def __str__(self):
711 return "<%s %s>" % (self.__class__.__name__, self.server)
712
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100713 def __enter__(self):
714 self.start(threading.Event())
715 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100716 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100717
718 def __exit__(self, *args):
719 if test_support.verbose:
720 sys.stdout.write(" cleanup: stopping server.\n")
721 self.stop()
722 if test_support.verbose:
723 sys.stdout.write(" cleanup: joining server thread.\n")
724 self.join()
725 if test_support.verbose:
726 sys.stdout.write(" cleanup: successfully joined.\n")
727
Antoine Pitrou3945c862010-04-28 21:11:01 +0000728 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000729 self.flag = flag
730 threading.Thread.start(self)
731
Antoine Pitrou3945c862010-04-28 21:11:01 +0000732 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000733 self.active = True
734 if self.flag:
735 self.flag.set()
736 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000737 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000738
Antoine Pitrou3945c862010-04-28 21:11:01 +0000739 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000740 self.active = False
741 self.server.close()
742
743 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000744
745 class HTTPSServer(HTTPServer):
746
747 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000748 HTTPServer.__init__(self, server_address, RequestHandlerClass)
749 # we assume the certfile contains both private key and certificate
750 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000751 self.allow_reuse_address = True
752
Bill Janssen934b16d2008-06-28 22:19:33 +0000753 def __str__(self):
754 return ('<%s %s:%s>' %
755 (self.__class__.__name__,
756 self.server_name,
757 self.server_port))
758
Antoine Pitrou3945c862010-04-28 21:11:01 +0000759 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000760 # override this to wrap socket with SSL
761 sock, addr = self.socket.accept()
762 sslconn = ssl.wrap_socket(sock, server_side=True,
763 certfile=self.certfile)
764 return sslconn, addr
765
Bill Janssen296a59d2007-09-16 22:06:00 +0000766 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000767 # need to override translate_path to get a known root,
768 # instead of using os.curdir, since the test could be
769 # run from anywhere
770
771 server_version = "TestHTTPS/1.0"
772
773 root = None
774
775 def translate_path(self, path):
776 """Translate a /-separated PATH to the local filename syntax.
777
778 Components that mean special things to the local file system
779 (e.g. drive or directory names) are ignored. (XXX They should
780 probably be diagnosed.)
781
782 """
783 # abandon query parameters
784 path = urlparse.urlparse(path)[2]
785 path = os.path.normpath(urllib.unquote(path))
786 words = path.split('/')
787 words = filter(None, words)
788 path = self.root
789 for word in words:
790 drive, word = os.path.splitdrive(word)
791 head, word = os.path.split(word)
792 if word in self.root: continue
793 path = os.path.join(path, word)
794 return path
795
796 def log_message(self, format, *args):
797
798 # we override this to suppress logging unless "verbose"
799
800 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000801 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
802 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000803 self.server.server_port,
804 self.request.cipher(),
805 self.log_date_time_string(),
806 format%args))
807
808
Trent Nelsone41b0062008-04-08 23:47:30 +0000809 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000810 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000811 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
812 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000813 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
814 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000815 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000816 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000817
818 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000819 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000820
Antoine Pitrou3945c862010-04-28 21:11:01 +0000821 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000822 self.flag = flag
823 threading.Thread.start(self)
824
Antoine Pitrou3945c862010-04-28 21:11:01 +0000825 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000826 if self.flag:
827 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000828 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000829
Antoine Pitrou3945c862010-04-28 21:11:01 +0000830 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000831 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000832
833
Antoine Pitrou3945c862010-04-28 21:11:01 +0000834 def bad_cert_test(certfile):
835 """
836 Launch a server with CERT_REQUIRED, and check that trying to
837 connect to it with the given client certificate fails.
838 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000839 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000840 certreqs=ssl.CERT_REQUIRED,
841 cacerts=CERTFILE, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100842 with server:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000843 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000844 s = ssl.wrap_socket(socket.socket(),
845 certfile=certfile,
846 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000847 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000848 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000849 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000850 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000851 except socket.error, x:
852 if test_support.verbose:
853 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000854 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000855 raise AssertionError("Use of invalid cert should have failed!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000856
Antoine Pitrou3945c862010-04-28 21:11:01 +0000857 def server_params_test(certfile, protocol, certreqs, cacertsfile,
858 client_certfile, client_protocol=None, indata="FOO\n",
859 ciphers=None, chatty=True, connectionchatty=False,
860 wrap_accepting_socket=False):
861 """
862 Launch a server, connect a client to it and try various reads
863 and writes.
864 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000865 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000866 certreqs=certreqs,
867 ssl_version=protocol,
868 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000869 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000870 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000871 connectionchatty=connectionchatty,
872 wrap_accepting_socket=wrap_accepting_socket)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100873 with server:
874 # try to connect
875 if client_protocol is None:
876 client_protocol = protocol
Antoine Pitroudb187842010-04-27 10:32:58 +0000877 s = ssl.wrap_socket(socket.socket(),
878 certfile=client_certfile,
879 ca_certs=cacertsfile,
880 ciphers=ciphers,
881 cert_reqs=certreqs,
882 ssl_version=client_protocol)
883 s.connect((HOST, server.port))
884 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000885 if connectionchatty:
886 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000887 sys.stdout.write(
888 " client: sending %s...\n" % (repr(arg)))
889 s.write(arg)
890 outdata = s.read()
891 if connectionchatty:
892 if test_support.verbose:
893 sys.stdout.write(" client: read %s\n" % repr(outdata))
894 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000895 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000896 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
897 % (outdata[:min(len(outdata),20)], len(outdata),
898 indata[:min(len(indata),20)].lower(), len(indata)))
899 s.write("over\n")
900 if connectionchatty:
901 if test_support.verbose:
902 sys.stdout.write(" client: closing connection.\n")
903 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000904
Antoine Pitrou3945c862010-04-28 21:11:01 +0000905 def try_protocol_combo(server_protocol,
906 client_protocol,
907 expect_success,
908 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000909 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000910 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000911 certtype = {
912 ssl.CERT_NONE: "CERT_NONE",
913 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
914 ssl.CERT_REQUIRED: "CERT_REQUIRED",
915 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000916 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000917 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000918 sys.stdout.write(formatstr %
919 (ssl.get_protocol_name(client_protocol),
920 ssl.get_protocol_name(server_protocol),
921 certtype))
922 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000923 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
924 # will send an SSLv3 hello (rather than SSLv2) starting from
925 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000926 server_params_test(CERTFILE, server_protocol, certsreqs,
927 CERTFILE, CERTFILE, client_protocol,
928 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000929 # Protocol mismatch can result in either an SSLError, or a
930 # "Connection reset by peer" error.
931 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000932 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000933 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000934 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000935 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000936 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000937 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000938 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000939 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000940 "Client protocol %s succeeded with server protocol %s!"
941 % (ssl.get_protocol_name(client_protocol),
942 ssl.get_protocol_name(server_protocol)))
943
944
Bill Janssen934b16d2008-06-28 22:19:33 +0000945 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000946
Antoine Pitrou3945c862010-04-28 21:11:01 +0000947 def test_rude_shutdown(self):
948 """A brutal shutdown of an SSL server should raise an IOError
949 in the client when attempting handshake.
950 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000951 listener_ready = threading.Event()
952 listener_gone = threading.Event()
953
Antoine Pitrou150acda2010-04-27 08:40:51 +0000954 s = socket.socket()
955 port = test_support.bind_port(s, HOST)
956
957 # `listener` runs in a thread. It sits in an accept() until
958 # the main thread connects. Then it rudely closes the socket,
959 # and sets Event `listener_gone` to let the main thread know
960 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000961 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000962 s.listen(5)
963 listener_ready.set()
964 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000965 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000966 listener_gone.set()
967
968 def connector():
969 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000970 c = socket.socket()
971 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000972 listener_gone.wait()
973 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000974 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000975 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000976 pass
977 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000978 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000979
980 t = threading.Thread(target=listener)
981 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000982 try:
983 connector()
984 finally:
985 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000986
Antoine Pitroud75efd92010-08-04 17:38:33 +0000987 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000988 def test_echo(self):
989 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000990 if test_support.verbose:
991 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000992 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
993 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
994 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000995
Antoine Pitrou3945c862010-04-28 21:11:01 +0000996 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000997 if test_support.verbose:
998 sys.stdout.write("\n")
999 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +00001000 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001001 certreqs=ssl.CERT_NONE,
1002 ssl_version=ssl.PROTOCOL_SSLv23,
1003 cacerts=CERTFILE,
1004 chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001005 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001006 s = ssl.wrap_socket(socket.socket(),
1007 certfile=CERTFILE,
1008 ca_certs=CERTFILE,
1009 cert_reqs=ssl.CERT_REQUIRED,
1010 ssl_version=ssl.PROTOCOL_SSLv23)
1011 s.connect((HOST, server.port))
1012 cert = s.getpeercert()
1013 self.assertTrue(cert, "Can't get peer certificate.")
1014 cipher = s.cipher()
1015 if test_support.verbose:
1016 sys.stdout.write(pprint.pformat(cert) + '\n')
1017 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1018 if 'subject' not in cert:
1019 self.fail("No subject field in certificate: %s." %
1020 pprint.pformat(cert))
1021 if ((('organizationName', 'Python Software Foundation'),)
1022 not in cert['subject']):
1023 self.fail(
1024 "Missing or invalid 'organizationName' field in certificate subject; "
1025 "should be 'Python Software Foundation'.")
1026 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001027
Antoine Pitrou3945c862010-04-28 21:11:01 +00001028 def test_empty_cert(self):
1029 """Connecting with an empty cert file"""
1030 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1031 "nullcert.pem"))
1032 def test_malformed_cert(self):
1033 """Connecting with a badly formatted certificate (syntax error)"""
1034 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1035 "badcert.pem"))
1036 def test_nonexisting_cert(self):
1037 """Connecting with a non-existing cert file"""
1038 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1039 "wrongcert.pem"))
1040 def test_malformed_key(self):
1041 """Connecting with a badly formatted key (syntax error)"""
1042 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1043 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +00001044
Antoine Pitroud75efd92010-08-04 17:38:33 +00001045 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001046 def test_protocol_sslv2(self):
1047 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001048 if test_support.verbose:
1049 sys.stdout.write("\n")
Antoine Pitrou6361ea22011-10-30 21:31:34 +01001050 if not hasattr(ssl, 'PROTOCOL_SSLv2'):
1051 self.skipTest("PROTOCOL_SSLv2 needed")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001052 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1053 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1054 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1055 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1056 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1057 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001058
Antoine Pitroud75efd92010-08-04 17:38:33 +00001059 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001060 def test_protocol_sslv23(self):
1061 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001062 if test_support.verbose:
1063 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001064 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1065 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1066 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001067
Antoine Pitrou3945c862010-04-28 21:11:01 +00001068 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1069 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1070 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00001071
Antoine Pitrou3945c862010-04-28 21:11:01 +00001072 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1073 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1074 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00001075
Antoine Pitroud75efd92010-08-04 17:38:33 +00001076 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001077 def test_protocol_sslv3(self):
1078 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001079 if test_support.verbose:
1080 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001081 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1082 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1083 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001084 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1085 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001086 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001087
Antoine Pitroud75efd92010-08-04 17:38:33 +00001088 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001089 def test_protocol_tlsv1(self):
1090 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001091 if test_support.verbose:
1092 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001093 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1094 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1095 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001096 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1097 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001098 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001099
Antoine Pitrou3945c862010-04-28 21:11:01 +00001100 def test_starttls(self):
1101 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +00001102 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00001103
Trent Nelsone41b0062008-04-08 23:47:30 +00001104 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001105 ssl_version=ssl.PROTOCOL_TLSv1,
1106 starttls_server=True,
1107 chatty=True,
1108 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001109 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001110 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001111 s = socket.socket()
1112 s.setblocking(1)
1113 s.connect((HOST, server.port))
1114 if test_support.verbose:
1115 sys.stdout.write("\n")
1116 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +00001117 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00001118 sys.stdout.write(
1119 " client: sending %s...\n" % repr(indata))
1120 if wrapped:
1121 conn.write(indata)
1122 outdata = conn.read()
1123 else:
1124 s.send(indata)
1125 outdata = s.recv(1024)
1126 if (indata == "STARTTLS" and
1127 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001128 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001129 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001130 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001131 " client: read %s from server, starting TLS...\n"
1132 % repr(outdata))
1133 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1134 wrapped = True
1135 elif (indata == "ENDTLS" and
1136 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001137 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001138 if test_support.verbose:
1139 sys.stdout.write(
1140 " client: read %s from server, ending TLS...\n"
1141 % repr(outdata))
1142 s = conn.unwrap()
1143 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001144 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001145 if test_support.verbose:
1146 sys.stdout.write(
1147 " client: read %s from server\n" % repr(outdata))
1148 if test_support.verbose:
1149 sys.stdout.write(" client: closing connection.\n")
1150 if wrapped:
1151 conn.write("over\n")
1152 else:
1153 s.send("over\n")
1154 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001155
Antoine Pitrou3945c862010-04-28 21:11:01 +00001156 def test_socketserver(self):
1157 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001158 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001159 flag = threading.Event()
1160 server.start(flag)
1161 # wait for it to start
1162 flag.wait()
1163 # try to connect
1164 try:
1165 if test_support.verbose:
1166 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001167 with open(CERTFILE, 'rb') as f:
1168 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001169 d2 = ''
1170 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001171 url = 'https://127.0.0.1:%d/%s' % (
1172 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001173 with test_support.check_py3k_warnings():
1174 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001175 dlen = f.info().getheader("content-length")
1176 if dlen and (int(dlen) > 0):
1177 d2 = f.read(int(dlen))
1178 if test_support.verbose:
1179 sys.stdout.write(
1180 " client: read %d bytes from remote server '%s'\n"
1181 % (len(d2), server))
1182 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001183 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001184 finally:
1185 server.stop()
1186 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001187
Antoine Pitrou3945c862010-04-28 21:11:01 +00001188 def test_wrapped_accept(self):
1189 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001190 if test_support.verbose:
1191 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001192 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1193 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1194 chatty=True, connectionchatty=True,
1195 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001196
Antoine Pitrou3945c862010-04-28 21:11:01 +00001197 def test_asyncore_server(self):
1198 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001199 indata = "TEST MESSAGE of mixed case\n"
1200
1201 if test_support.verbose:
1202 sys.stdout.write("\n")
1203 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001204 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001205 s = ssl.wrap_socket(socket.socket())
1206 s.connect(('127.0.0.1', server.port))
1207 if test_support.verbose:
1208 sys.stdout.write(
1209 " client: sending %s...\n" % (repr(indata)))
1210 s.write(indata)
1211 outdata = s.read()
1212 if test_support.verbose:
1213 sys.stdout.write(" client: read %s\n" % repr(outdata))
1214 if outdata != indata.lower():
1215 self.fail(
1216 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1217 % (outdata[:min(len(outdata),20)], len(outdata),
1218 indata[:min(len(indata),20)].lower(), len(indata)))
1219 s.write("over\n")
1220 if test_support.verbose:
1221 sys.stdout.write(" client: closing connection.\n")
1222 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001223
Antoine Pitrou3945c862010-04-28 21:11:01 +00001224 def test_recv_send(self):
1225 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001226 if test_support.verbose:
1227 sys.stdout.write("\n")
1228
1229 server = ThreadedEchoServer(CERTFILE,
1230 certreqs=ssl.CERT_NONE,
1231 ssl_version=ssl.PROTOCOL_TLSv1,
1232 cacerts=CERTFILE,
1233 chatty=True,
1234 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001235 with server:
1236 s = ssl.wrap_socket(socket.socket(),
1237 server_side=False,
1238 certfile=CERTFILE,
1239 ca_certs=CERTFILE,
1240 cert_reqs=ssl.CERT_NONE,
1241 ssl_version=ssl.PROTOCOL_TLSv1)
1242 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001243 # helper methods for standardising recv* method signatures
1244 def _recv_into():
1245 b = bytearray("\0"*100)
1246 count = s.recv_into(b)
1247 return b[:count]
1248
1249 def _recvfrom_into():
1250 b = bytearray("\0"*100)
1251 count, addr = s.recvfrom_into(b)
1252 return b[:count]
1253
1254 # (name, method, whether to expect success, *args)
1255 send_methods = [
1256 ('send', s.send, True, []),
1257 ('sendto', s.sendto, False, ["some.address"]),
1258 ('sendall', s.sendall, True, []),
1259 ]
1260 recv_methods = [
1261 ('recv', s.recv, True, []),
1262 ('recvfrom', s.recvfrom, False, ["some.address"]),
1263 ('recv_into', _recv_into, True, []),
1264 ('recvfrom_into', _recvfrom_into, False, []),
1265 ]
1266 data_prefix = u"PREFIX_"
1267
1268 for meth_name, send_meth, expect_success, args in send_methods:
1269 indata = data_prefix + meth_name
1270 try:
1271 send_meth(indata.encode('ASCII', 'strict'), *args)
1272 outdata = s.read()
1273 outdata = outdata.decode('ASCII', 'strict')
1274 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001275 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001276 "While sending with <<%s>> bad data "
1277 "<<%r>> (%d) received; "
1278 "expected <<%r>> (%d)\n" % (
1279 meth_name, outdata[:20], len(outdata),
1280 indata[:20], len(indata)
1281 )
1282 )
1283 except ValueError as e:
1284 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001285 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001286 "Failed to send with method <<%s>>; "
1287 "expected to succeed.\n" % (meth_name,)
1288 )
1289 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001290 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001291 "Method <<%s>> failed with unexpected "
1292 "exception message: %s\n" % (
1293 meth_name, e
1294 )
1295 )
1296
1297 for meth_name, recv_meth, expect_success, args in recv_methods:
1298 indata = data_prefix + meth_name
1299 try:
1300 s.send(indata.encode('ASCII', 'strict'))
1301 outdata = recv_meth(*args)
1302 outdata = outdata.decode('ASCII', 'strict')
1303 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001304 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001305 "While receiving with <<%s>> bad data "
1306 "<<%r>> (%d) received; "
1307 "expected <<%r>> (%d)\n" % (
1308 meth_name, outdata[:20], len(outdata),
1309 indata[:20], len(indata)
1310 )
1311 )
1312 except ValueError as e:
1313 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001314 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001315 "Failed to receive with method <<%s>>; "
1316 "expected to succeed.\n" % (meth_name,)
1317 )
1318 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001319 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001320 "Method <<%s>> failed with unexpected "
1321 "exception message: %s\n" % (
1322 meth_name, e
1323 )
1324 )
1325 # consume data
1326 s.read()
1327
1328 s.write("over\n".encode("ASCII", "strict"))
1329 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00001330
Antoine Pitroufc69af12010-04-24 20:04:58 +00001331 def test_handshake_timeout(self):
1332 # Issue #5103: SSL handshake must respect the socket timeout
1333 server = socket.socket(socket.AF_INET)
1334 host = "127.0.0.1"
1335 port = test_support.bind_port(server)
1336 started = threading.Event()
1337 finish = False
1338
1339 def serve():
1340 server.listen(5)
1341 started.set()
1342 conns = []
1343 while not finish:
1344 r, w, e = select.select([server], [], [], 0.1)
1345 if server in r:
1346 # Let the socket hang around rather than having
1347 # it closed by garbage collection.
1348 conns.append(server.accept()[0])
1349
1350 t = threading.Thread(target=serve)
1351 t.start()
1352 started.wait()
1353
1354 try:
1355 try:
1356 c = socket.socket(socket.AF_INET)
1357 c.settimeout(0.2)
1358 c.connect((host, port))
1359 # Will attempt handshake and time out
1360 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1361 ssl.wrap_socket, c)
1362 finally:
1363 c.close()
1364 try:
1365 c = socket.socket(socket.AF_INET)
1366 c.settimeout(0.2)
1367 c = ssl.wrap_socket(c)
1368 # Will attempt handshake and time out
1369 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1370 c.connect, (host, port))
1371 finally:
1372 c.close()
1373 finally:
1374 finish = True
1375 t.join()
1376 server.close()
1377
Antoine Pitroud76088d2012-01-03 22:46:48 +01001378 def test_default_ciphers(self):
1379 with ThreadedEchoServer(CERTFILE,
1380 ssl_version=ssl.PROTOCOL_SSLv23,
1381 chatty=False) as server:
1382 sock = socket.socket()
1383 try:
1384 # Force a set of weak ciphers on our client socket
1385 try:
1386 s = ssl.wrap_socket(sock,
1387 ssl_version=ssl.PROTOCOL_SSLv23,
1388 ciphers="DES")
1389 except ssl.SSLError:
1390 self.skipTest("no DES cipher available")
1391 with self.assertRaises((OSError, ssl.SSLError)):
1392 s.connect((HOST, server.port))
1393 finally:
1394 sock.close()
1395 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1396
Bill Janssen61c001a2008-09-08 16:37:24 +00001397
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001398def test_main(verbose=False):
Christian Heimes88b174c2013-08-17 00:54:47 +02001399 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT, NULLBYTECERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001400 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001401 "keycert.pem")
1402 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1403 os.path.dirname(__file__) or os.curdir,
1404 "https_svn_python_org_root.pem")
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001405 NOKIACERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1406 "nokia.pem")
Christian Heimes88b174c2013-08-17 00:54:47 +02001407 NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1408 "nullbytecert.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001409
1410 if (not os.path.exists(CERTFILE) or
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001411 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
Christian Heimes88b174c2013-08-17 00:54:47 +02001412 not os.path.exists(NOKIACERT) or
1413 not os.path.exists(NULLBYTECERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001414 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001415
Antoine Pitroude30f702010-09-14 12:54:08 +00001416 tests = [BasicTests, BasicSocketTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001417
Bill Janssen296a59d2007-09-16 22:06:00 +00001418 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001419 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001420
Bill Janssen98d19da2007-09-10 21:51:02 +00001421 if _have_threads:
1422 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001423 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001424 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001425
Antoine Pitrou3945c862010-04-28 21:11:01 +00001426 try:
1427 test_support.run_unittest(*tests)
1428 finally:
1429 if _have_threads:
1430 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001431
1432if __name__ == "__main__":
1433 test_main()