blob: 563f9293fef5493295abb02c3ce49b8517cb0727 [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)
140 self.assertEqual(p['subjectAltName'],
141 (('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 )
147
Antoine Pitrou3945c862010-04-28 21:11:01 +0000148 def test_DER_to_PEM(self):
149 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
150 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000151 d1 = ssl.PEM_cert_to_DER_cert(pem)
152 p2 = ssl.DER_cert_to_PEM_cert(d1)
153 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000154 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000155 if not p2.startswith(ssl.PEM_HEADER + '\n'):
156 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
157 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
158 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000159
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000160 def test_openssl_version(self):
161 n = ssl.OPENSSL_VERSION_NUMBER
162 t = ssl.OPENSSL_VERSION_INFO
163 s = ssl.OPENSSL_VERSION
164 self.assertIsInstance(n, (int, long))
165 self.assertIsInstance(t, tuple)
166 self.assertIsInstance(s, str)
167 # Some sanity checks follow
168 # >= 0.9
169 self.assertGreaterEqual(n, 0x900000)
170 # < 2.0
171 self.assertLess(n, 0x20000000)
172 major, minor, fix, patch, status = t
173 self.assertGreaterEqual(major, 0)
174 self.assertLess(major, 2)
175 self.assertGreaterEqual(minor, 0)
176 self.assertLess(minor, 256)
177 self.assertGreaterEqual(fix, 0)
178 self.assertLess(fix, 256)
179 self.assertGreaterEqual(patch, 0)
180 self.assertLessEqual(patch, 26)
181 self.assertGreaterEqual(status, 0)
182 self.assertLessEqual(status, 15)
183 # Version string as returned by OpenSSL, the format might change
184 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
185 (s, t))
186
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000187 def test_ciphers(self):
188 if not test_support.is_resource_enabled('network'):
189 return
190 remote = ("svn.python.org", 443)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000191 with test_support.transient_internet(remote[0]):
192 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
193 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000194 s.connect(remote)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000195 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
196 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
197 s.connect(remote)
198 # Error checking occurs when connecting, because the SSL context
199 # isn't created before.
200 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
201 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
202 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
203 s.connect(remote)
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000204
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000205 @test_support.cpython_only
206 def test_refcycle(self):
207 # Issue #7943: an SSL object doesn't create reference cycles with
208 # itself.
209 s = socket.socket(socket.AF_INET)
210 ss = ssl.wrap_socket(s)
211 wr = weakref.ref(ss)
212 del ss
213 self.assertEqual(wr(), None)
214
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000215 def test_wrapped_unconnected(self):
216 # The _delegate_methods in socket.py are correctly delegated to by an
217 # unconnected SSLSocket, so they will raise a socket.error rather than
218 # something unexpected like TypeError.
219 s = socket.socket(socket.AF_INET)
220 ss = ssl.wrap_socket(s)
221 self.assertRaises(socket.error, ss.recv, 1)
222 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
223 self.assertRaises(socket.error, ss.recvfrom, 1)
224 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
225 self.assertRaises(socket.error, ss.send, b'x')
226 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
227
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000228
Bill Janssen934b16d2008-06-28 22:19:33 +0000229class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000230
Antoine Pitrou3945c862010-04-28 21:11:01 +0000231 def test_connect(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000232 with test_support.transient_internet("svn.python.org"):
233 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
234 cert_reqs=ssl.CERT_NONE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000235 s.connect(("svn.python.org", 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000236 c = s.getpeercert()
237 if c:
238 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000239 s.close()
240
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000241 # this should fail because we have no verification certs
242 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
243 cert_reqs=ssl.CERT_REQUIRED)
244 try:
245 s.connect(("svn.python.org", 443))
246 except ssl.SSLError:
247 pass
248 finally:
249 s.close()
250
251 # this should succeed because we specify the root cert
252 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
253 cert_reqs=ssl.CERT_REQUIRED,
254 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
255 try:
256 s.connect(("svn.python.org", 443))
257 finally:
258 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +0000259
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000260 def test_connect_ex(self):
261 # Issue #11326: check connect_ex() implementation
262 with test_support.transient_internet("svn.python.org"):
263 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
264 cert_reqs=ssl.CERT_REQUIRED,
265 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
266 try:
267 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
268 self.assertTrue(s.getpeercert())
269 finally:
270 s.close()
271
272 def test_non_blocking_connect_ex(self):
273 # Issue #11326: non-blocking connect_ex() should allow handshake
274 # to proceed after the socket gets ready.
275 with test_support.transient_internet("svn.python.org"):
276 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
277 cert_reqs=ssl.CERT_REQUIRED,
278 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
279 do_handshake_on_connect=False)
280 try:
281 s.setblocking(False)
282 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +0000283 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
284 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000285 # Wait for connect to finish
286 select.select([], [s], [], 5.0)
287 # Non-blocking handshake
288 while True:
289 try:
290 s.do_handshake()
291 break
292 except ssl.SSLError as err:
293 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
294 select.select([s], [], [], 5.0)
295 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
296 select.select([], [s], [], 5.0)
297 else:
298 raise
299 # SSL established
300 self.assertTrue(s.getpeercert())
301 finally:
302 s.close()
303
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100304 def test_timeout_connect_ex(self):
305 # Issue #12065: on a timeout, connect_ex() should return the original
306 # errno (mimicking the behaviour of non-SSL sockets).
307 with test_support.transient_internet("svn.python.org"):
308 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
309 cert_reqs=ssl.CERT_REQUIRED,
310 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
311 do_handshake_on_connect=False)
312 try:
313 s.settimeout(0.0000001)
314 rc = s.connect_ex(('svn.python.org', 443))
315 if rc == 0:
316 self.skipTest("svn.python.org responded too quickly")
317 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
318 finally:
319 s.close()
320
321 def test_connect_ex_error(self):
322 with test_support.transient_internet("svn.python.org"):
323 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
324 cert_reqs=ssl.CERT_REQUIRED,
325 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
326 try:
327 self.assertEqual(errno.ECONNREFUSED,
328 s.connect_ex(("svn.python.org", 444)))
329 finally:
330 s.close()
331
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000332 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
333 def test_makefile_close(self):
334 # Issue #5238: creating a file-like object with makefile() shouldn't
335 # delay closing the underlying "real socket" (here tested with its
336 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000337 with test_support.transient_internet("svn.python.org"):
338 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
339 ss.connect(("svn.python.org", 443))
340 fd = ss.fileno()
341 f = ss.makefile()
342 f.close()
343 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000344 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000345 # Closing the SSL socket should close the fd too
346 ss.close()
347 gc.collect()
348 with self.assertRaises(OSError) as e:
349 os.read(fd, 0)
350 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000351
Antoine Pitrou3945c862010-04-28 21:11:01 +0000352 def test_non_blocking_handshake(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000353 with test_support.transient_internet("svn.python.org"):
354 s = socket.socket(socket.AF_INET)
355 s.connect(("svn.python.org", 443))
356 s.setblocking(False)
357 s = ssl.wrap_socket(s,
358 cert_reqs=ssl.CERT_NONE,
359 do_handshake_on_connect=False)
360 count = 0
361 while True:
362 try:
363 count += 1
364 s.do_handshake()
365 break
366 except ssl.SSLError, err:
367 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
368 select.select([s], [], [])
369 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
370 select.select([], [s], [])
371 else:
372 raise
373 s.close()
374 if test_support.verbose:
375 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +0000376
Antoine Pitrou3945c862010-04-28 21:11:01 +0000377 def test_get_server_certificate(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000378 with test_support.transient_internet("svn.python.org"):
379 pem = ssl.get_server_certificate(("svn.python.org", 443))
380 if not pem:
381 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000382
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000383 try:
384 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
385 except ssl.SSLError:
386 #should fail
387 pass
388 else:
389 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000390
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000391 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
392 if not pem:
393 self.fail("No server certificate on svn.python.org:443!")
394 if test_support.verbose:
395 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000396
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000397 def test_algorithms(self):
398 # Issue #8484: all algorithms should be available when verifying a
399 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000400 # SHA256 was added in OpenSSL 0.9.8
401 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
402 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc642f672012-05-04 16:33:30 +0200403 self.skipTest("remote host needs SNI, only available on Python 3.2+")
404 # NOTE: https://sha2.hboeck.de is another possible test host
Antoine Pitroud43245a2011-01-08 10:32:51 +0000405 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000406 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroud43245a2011-01-08 10:32:51 +0000407 with test_support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000408 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
409 cert_reqs=ssl.CERT_REQUIRED,
410 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000411 try:
412 s.connect(remote)
413 if test_support.verbose:
414 sys.stdout.write("\nCipher with %r is %r\n" %
415 (remote, s.cipher()))
416 sys.stdout.write("Certificate is:\n%s\n" %
417 pprint.pformat(s.getpeercert()))
418 finally:
419 s.close()
420
Bill Janssen296a59d2007-09-16 22:06:00 +0000421
Bill Janssen98d19da2007-09-10 21:51:02 +0000422try:
423 import threading
424except ImportError:
425 _have_threads = False
426else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000427 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000428
Bill Janssen98d19da2007-09-10 21:51:02 +0000429 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000430
Bill Janssen98d19da2007-09-10 21:51:02 +0000431 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000432
Bill Janssen98d19da2007-09-10 21:51:02 +0000433 """A mildly complicated class, because we want it to work both
434 with and without the SSL wrapper around the socket connection, so
435 that we can test the STARTTLS functionality."""
436
437 def __init__(self, server, connsock):
438 self.server = server
439 self.running = False
440 self.sock = connsock
441 self.sock.setblocking(1)
442 self.sslconn = None
443 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000444 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000445
Bill Janssen934b16d2008-06-28 22:19:33 +0000446 def show_conn_details(self):
447 if self.server.certreqs == ssl.CERT_REQUIRED:
448 cert = self.sslconn.getpeercert()
449 if test_support.verbose and self.server.chatty:
450 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
451 cert_binary = self.sslconn.getpeercert(True)
452 if test_support.verbose and self.server.chatty:
453 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
454 cipher = self.sslconn.cipher()
455 if test_support.verbose and self.server.chatty:
456 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
457
Antoine Pitrou3945c862010-04-28 21:11:01 +0000458 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000459 try:
460 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
461 certfile=self.server.certificate,
462 ssl_version=self.server.protocol,
463 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000464 cert_reqs=self.server.certreqs,
465 ciphers=self.server.ciphers)
Antoine Pitroud76088d2012-01-03 22:46:48 +0100466 except ssl.SSLError as e:
Antoine Pitroudb187842010-04-27 10:32:58 +0000467 # XXX Various errors can have happened here, for example
468 # a mismatching protocol version, an invalid certificate,
469 # or a low-level bug. This should be made more discriminating.
Antoine Pitroud76088d2012-01-03 22:46:48 +0100470 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +0000471 if self.server.chatty:
472 handle_error("\n server: bad connection attempt from " +
473 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000474 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000475 self.running = False
476 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000477 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000478 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000479 return True
480
481 def read(self):
482 if self.sslconn:
483 return self.sslconn.read()
484 else:
485 return self.sock.recv(1024)
486
487 def write(self, bytes):
488 if self.sslconn:
489 return self.sslconn.write(bytes)
490 else:
491 return self.sock.send(bytes)
492
493 def close(self):
494 if self.sslconn:
495 self.sslconn.close()
496 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000497 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000498
Antoine Pitrou3945c862010-04-28 21:11:01 +0000499 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000500 self.running = True
501 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000502 if isinstance(self.sock, ssl.SSLSocket):
503 self.sslconn = self.sock
504 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000505 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000506 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000507 while self.running:
508 try:
509 msg = self.read()
510 if not msg:
511 # eof, so quit this handler
512 self.running = False
513 self.close()
514 elif msg.strip() == 'over':
515 if test_support.verbose and self.server.connectionchatty:
516 sys.stdout.write(" server: client closed connection\n")
517 self.close()
518 return
519 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
520 if test_support.verbose and self.server.connectionchatty:
521 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
522 self.write("OK\n")
523 if not self.wrap_conn():
524 return
Bill Janssen39295c22008-08-12 16:31:21 +0000525 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
526 if test_support.verbose and self.server.connectionchatty:
527 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
528 self.write("OK\n")
529 self.sslconn.unwrap()
530 self.sslconn = None
531 if test_support.verbose and self.server.connectionchatty:
532 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000533 else:
534 if (test_support.verbose and
535 self.server.connectionchatty):
536 ctype = (self.sslconn and "encrypted") or "unencrypted"
537 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
538 % (repr(msg), ctype, repr(msg.lower()), ctype))
539 self.write(msg.lower())
540 except ssl.SSLError:
541 if self.server.chatty:
542 handle_error("Test server failure:\n")
543 self.close()
544 self.running = False
545 # normally, we'd just stop here, but for the test
546 # harness, we want to stop the server
547 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000548
Trent Nelsone41b0062008-04-08 23:47:30 +0000549 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000550 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000551 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000552 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000553
Bill Janssen98d19da2007-09-10 21:51:02 +0000554 if ssl_version is None:
555 ssl_version = ssl.PROTOCOL_TLSv1
556 if certreqs is None:
557 certreqs = ssl.CERT_NONE
558 self.certificate = certificate
559 self.protocol = ssl_version
560 self.certreqs = certreqs
561 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000562 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000563 self.chatty = chatty
564 self.connectionchatty = connectionchatty
565 self.starttls_server = starttls_server
566 self.sock = socket.socket()
567 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000568 if wrap_accepting_socket:
569 self.sock = ssl.wrap_socket(self.sock, server_side=True,
570 certfile=self.certificate,
571 cert_reqs = self.certreqs,
572 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000573 ssl_version = self.protocol,
574 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000575 if test_support.verbose and self.chatty:
576 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
577 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000578 self.active = False
Antoine Pitroud76088d2012-01-03 22:46:48 +0100579 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000580 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000581 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000582
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100583 def __enter__(self):
584 self.start(threading.Event())
585 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100586 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100587
588 def __exit__(self, *args):
589 self.stop()
590 self.join()
591
Antoine Pitrou3945c862010-04-28 21:11:01 +0000592 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000593 self.flag = flag
594 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000595
Antoine Pitrou3945c862010-04-28 21:11:01 +0000596 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000597 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000598 self.sock.listen(5)
599 self.active = True
600 if self.flag:
601 # signal an event
602 self.flag.set()
603 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000604 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000605 newconn, connaddr = self.sock.accept()
606 if test_support.verbose and self.chatty:
607 sys.stdout.write(' server: new connection from '
608 + str(connaddr) + '\n')
609 handler = self.ConnectionHandler(self, newconn)
610 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +0100611 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000612 except socket.timeout:
613 pass
614 except KeyboardInterrupt:
615 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000616 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000617
Antoine Pitrou3945c862010-04-28 21:11:01 +0000618 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000619 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000620
Bill Janssen934b16d2008-06-28 22:19:33 +0000621 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000622
Antoine Pitrou3945c862010-04-28 21:11:01 +0000623 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000624
Antoine Pitrou3945c862010-04-28 21:11:01 +0000625 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000626
627 def __init__(self, conn, certfile):
628 asyncore.dispatcher_with_send.__init__(self, conn)
629 self.socket = ssl.wrap_socket(conn, server_side=True,
630 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000631 do_handshake_on_connect=False)
632 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000633
634 def readable(self):
635 if isinstance(self.socket, ssl.SSLSocket):
636 while self.socket.pending() > 0:
637 self.handle_read_event()
638 return True
639
Antoine Pitroufc69af12010-04-24 20:04:58 +0000640 def _do_ssl_handshake(self):
641 try:
642 self.socket.do_handshake()
643 except ssl.SSLError, err:
644 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
645 ssl.SSL_ERROR_WANT_WRITE):
646 return
647 elif err.args[0] == ssl.SSL_ERROR_EOF:
648 return self.handle_close()
649 raise
650 except socket.error, err:
651 if err.args[0] == errno.ECONNABORTED:
652 return self.handle_close()
653 else:
654 self._ssl_accepting = False
655
Bill Janssen934b16d2008-06-28 22:19:33 +0000656 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000657 if self._ssl_accepting:
658 self._do_ssl_handshake()
659 else:
660 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000661 if data and data.strip() != 'over':
662 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000663
664 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000665 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000666 if test_support.verbose:
667 sys.stdout.write(" server: closed connection %s\n" % self.socket)
668
669 def handle_error(self):
670 raise
671
672 def __init__(self, certfile):
673 self.certfile = certfile
674 asyncore.dispatcher.__init__(self)
675 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
676 self.port = test_support.bind_port(self.socket)
677 self.listen(5)
678
679 def handle_accept(self):
680 sock_obj, addr = self.accept()
681 if test_support.verbose:
682 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
683 self.ConnectionHandler(sock_obj, self.certfile)
684
685 def handle_error(self):
686 raise
687
688 def __init__(self, certfile):
689 self.flag = None
690 self.active = False
691 self.server = self.EchoServer(certfile)
692 self.port = self.server.port
693 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000694 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000695
696 def __str__(self):
697 return "<%s %s>" % (self.__class__.__name__, self.server)
698
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100699 def __enter__(self):
700 self.start(threading.Event())
701 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100702 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100703
704 def __exit__(self, *args):
705 if test_support.verbose:
706 sys.stdout.write(" cleanup: stopping server.\n")
707 self.stop()
708 if test_support.verbose:
709 sys.stdout.write(" cleanup: joining server thread.\n")
710 self.join()
711 if test_support.verbose:
712 sys.stdout.write(" cleanup: successfully joined.\n")
713
Antoine Pitrou3945c862010-04-28 21:11:01 +0000714 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000715 self.flag = flag
716 threading.Thread.start(self)
717
Antoine Pitrou3945c862010-04-28 21:11:01 +0000718 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000719 self.active = True
720 if self.flag:
721 self.flag.set()
722 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000723 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000724
Antoine Pitrou3945c862010-04-28 21:11:01 +0000725 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000726 self.active = False
727 self.server.close()
728
729 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000730
731 class HTTPSServer(HTTPServer):
732
733 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000734 HTTPServer.__init__(self, server_address, RequestHandlerClass)
735 # we assume the certfile contains both private key and certificate
736 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000737 self.allow_reuse_address = True
738
Bill Janssen934b16d2008-06-28 22:19:33 +0000739 def __str__(self):
740 return ('<%s %s:%s>' %
741 (self.__class__.__name__,
742 self.server_name,
743 self.server_port))
744
Antoine Pitrou3945c862010-04-28 21:11:01 +0000745 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000746 # override this to wrap socket with SSL
747 sock, addr = self.socket.accept()
748 sslconn = ssl.wrap_socket(sock, server_side=True,
749 certfile=self.certfile)
750 return sslconn, addr
751
Bill Janssen296a59d2007-09-16 22:06:00 +0000752 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000753 # need to override translate_path to get a known root,
754 # instead of using os.curdir, since the test could be
755 # run from anywhere
756
757 server_version = "TestHTTPS/1.0"
758
759 root = None
760
761 def translate_path(self, path):
762 """Translate a /-separated PATH to the local filename syntax.
763
764 Components that mean special things to the local file system
765 (e.g. drive or directory names) are ignored. (XXX They should
766 probably be diagnosed.)
767
768 """
769 # abandon query parameters
770 path = urlparse.urlparse(path)[2]
771 path = os.path.normpath(urllib.unquote(path))
772 words = path.split('/')
773 words = filter(None, words)
774 path = self.root
775 for word in words:
776 drive, word = os.path.splitdrive(word)
777 head, word = os.path.split(word)
778 if word in self.root: continue
779 path = os.path.join(path, word)
780 return path
781
782 def log_message(self, format, *args):
783
784 # we override this to suppress logging unless "verbose"
785
786 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000787 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
788 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000789 self.server.server_port,
790 self.request.cipher(),
791 self.log_date_time_string(),
792 format%args))
793
794
Trent Nelsone41b0062008-04-08 23:47:30 +0000795 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000796 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000797 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
798 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000799 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
800 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000801 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000802 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000803
804 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000805 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000806
Antoine Pitrou3945c862010-04-28 21:11:01 +0000807 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000808 self.flag = flag
809 threading.Thread.start(self)
810
Antoine Pitrou3945c862010-04-28 21:11:01 +0000811 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000812 if self.flag:
813 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000814 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000815
Antoine Pitrou3945c862010-04-28 21:11:01 +0000816 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000817 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000818
819
Antoine Pitrou3945c862010-04-28 21:11:01 +0000820 def bad_cert_test(certfile):
821 """
822 Launch a server with CERT_REQUIRED, and check that trying to
823 connect to it with the given client certificate fails.
824 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000825 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000826 certreqs=ssl.CERT_REQUIRED,
827 cacerts=CERTFILE, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100828 with server:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000829 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000830 s = ssl.wrap_socket(socket.socket(),
831 certfile=certfile,
832 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000833 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000834 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000835 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000836 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000837 except socket.error, x:
838 if test_support.verbose:
839 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000840 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000841 raise AssertionError("Use of invalid cert should have failed!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000842
Antoine Pitrou3945c862010-04-28 21:11:01 +0000843 def server_params_test(certfile, protocol, certreqs, cacertsfile,
844 client_certfile, client_protocol=None, indata="FOO\n",
845 ciphers=None, chatty=True, connectionchatty=False,
846 wrap_accepting_socket=False):
847 """
848 Launch a server, connect a client to it and try various reads
849 and writes.
850 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000851 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000852 certreqs=certreqs,
853 ssl_version=protocol,
854 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000855 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000856 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000857 connectionchatty=connectionchatty,
858 wrap_accepting_socket=wrap_accepting_socket)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100859 with server:
860 # try to connect
861 if client_protocol is None:
862 client_protocol = protocol
Antoine Pitroudb187842010-04-27 10:32:58 +0000863 s = ssl.wrap_socket(socket.socket(),
864 certfile=client_certfile,
865 ca_certs=cacertsfile,
866 ciphers=ciphers,
867 cert_reqs=certreqs,
868 ssl_version=client_protocol)
869 s.connect((HOST, server.port))
870 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000871 if connectionchatty:
872 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000873 sys.stdout.write(
874 " client: sending %s...\n" % (repr(arg)))
875 s.write(arg)
876 outdata = s.read()
877 if connectionchatty:
878 if test_support.verbose:
879 sys.stdout.write(" client: read %s\n" % repr(outdata))
880 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000881 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000882 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
883 % (outdata[:min(len(outdata),20)], len(outdata),
884 indata[:min(len(indata),20)].lower(), len(indata)))
885 s.write("over\n")
886 if connectionchatty:
887 if test_support.verbose:
888 sys.stdout.write(" client: closing connection.\n")
889 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000890
Antoine Pitrou3945c862010-04-28 21:11:01 +0000891 def try_protocol_combo(server_protocol,
892 client_protocol,
893 expect_success,
894 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000895 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000896 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000897 certtype = {
898 ssl.CERT_NONE: "CERT_NONE",
899 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
900 ssl.CERT_REQUIRED: "CERT_REQUIRED",
901 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000902 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000903 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000904 sys.stdout.write(formatstr %
905 (ssl.get_protocol_name(client_protocol),
906 ssl.get_protocol_name(server_protocol),
907 certtype))
908 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000909 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
910 # will send an SSLv3 hello (rather than SSLv2) starting from
911 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000912 server_params_test(CERTFILE, server_protocol, certsreqs,
913 CERTFILE, CERTFILE, client_protocol,
914 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000915 # Protocol mismatch can result in either an SSLError, or a
916 # "Connection reset by peer" error.
917 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000918 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000919 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000920 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000921 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000922 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000923 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000924 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000925 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000926 "Client protocol %s succeeded with server protocol %s!"
927 % (ssl.get_protocol_name(client_protocol),
928 ssl.get_protocol_name(server_protocol)))
929
930
Bill Janssen934b16d2008-06-28 22:19:33 +0000931 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000932
Antoine Pitrou3945c862010-04-28 21:11:01 +0000933 def test_rude_shutdown(self):
934 """A brutal shutdown of an SSL server should raise an IOError
935 in the client when attempting handshake.
936 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000937 listener_ready = threading.Event()
938 listener_gone = threading.Event()
939
Antoine Pitrou150acda2010-04-27 08:40:51 +0000940 s = socket.socket()
941 port = test_support.bind_port(s, HOST)
942
943 # `listener` runs in a thread. It sits in an accept() until
944 # the main thread connects. Then it rudely closes the socket,
945 # and sets Event `listener_gone` to let the main thread know
946 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000947 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000948 s.listen(5)
949 listener_ready.set()
950 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000951 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000952 listener_gone.set()
953
954 def connector():
955 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000956 c = socket.socket()
957 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000958 listener_gone.wait()
959 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000960 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000961 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000962 pass
963 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000964 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000965
966 t = threading.Thread(target=listener)
967 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000968 try:
969 connector()
970 finally:
971 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000972
Antoine Pitroud75efd92010-08-04 17:38:33 +0000973 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000974 def test_echo(self):
975 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000976 if test_support.verbose:
977 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000978 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
979 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
980 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000981
Antoine Pitrou3945c862010-04-28 21:11:01 +0000982 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000983 if test_support.verbose:
984 sys.stdout.write("\n")
985 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000986 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000987 certreqs=ssl.CERT_NONE,
988 ssl_version=ssl.PROTOCOL_SSLv23,
989 cacerts=CERTFILE,
990 chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100991 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +0000992 s = ssl.wrap_socket(socket.socket(),
993 certfile=CERTFILE,
994 ca_certs=CERTFILE,
995 cert_reqs=ssl.CERT_REQUIRED,
996 ssl_version=ssl.PROTOCOL_SSLv23)
997 s.connect((HOST, server.port))
998 cert = s.getpeercert()
999 self.assertTrue(cert, "Can't get peer certificate.")
1000 cipher = s.cipher()
1001 if test_support.verbose:
1002 sys.stdout.write(pprint.pformat(cert) + '\n')
1003 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1004 if 'subject' not in cert:
1005 self.fail("No subject field in certificate: %s." %
1006 pprint.pformat(cert))
1007 if ((('organizationName', 'Python Software Foundation'),)
1008 not in cert['subject']):
1009 self.fail(
1010 "Missing or invalid 'organizationName' field in certificate subject; "
1011 "should be 'Python Software Foundation'.")
1012 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001013
Antoine Pitrou3945c862010-04-28 21:11:01 +00001014 def test_empty_cert(self):
1015 """Connecting with an empty cert file"""
1016 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1017 "nullcert.pem"))
1018 def test_malformed_cert(self):
1019 """Connecting with a badly formatted certificate (syntax error)"""
1020 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1021 "badcert.pem"))
1022 def test_nonexisting_cert(self):
1023 """Connecting with a non-existing cert file"""
1024 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1025 "wrongcert.pem"))
1026 def test_malformed_key(self):
1027 """Connecting with a badly formatted key (syntax error)"""
1028 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1029 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +00001030
Antoine Pitroud75efd92010-08-04 17:38:33 +00001031 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001032 def test_protocol_sslv2(self):
1033 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001034 if test_support.verbose:
1035 sys.stdout.write("\n")
Antoine Pitrou6361ea22011-10-30 21:31:34 +01001036 if not hasattr(ssl, 'PROTOCOL_SSLv2'):
1037 self.skipTest("PROTOCOL_SSLv2 needed")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001038 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1039 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1040 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1041 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1042 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1043 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
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_sslv23(self):
1047 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001048 if test_support.verbose:
1049 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001050 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1051 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1052 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001053
Antoine Pitrou3945c862010-04-28 21:11:01 +00001054 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1055 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1056 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00001057
Antoine Pitrou3945c862010-04-28 21:11:01 +00001058 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1059 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1060 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00001061
Antoine Pitroud75efd92010-08-04 17:38:33 +00001062 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001063 def test_protocol_sslv3(self):
1064 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001065 if test_support.verbose:
1066 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001067 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1068 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1069 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001070 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1071 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001072 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001073
Antoine Pitroud75efd92010-08-04 17:38:33 +00001074 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001075 def test_protocol_tlsv1(self):
1076 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001077 if test_support.verbose:
1078 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001079 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1080 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1081 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001082 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1083 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001084 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001085
Antoine Pitrou3945c862010-04-28 21:11:01 +00001086 def test_starttls(self):
1087 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +00001088 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00001089
Trent Nelsone41b0062008-04-08 23:47:30 +00001090 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001091 ssl_version=ssl.PROTOCOL_TLSv1,
1092 starttls_server=True,
1093 chatty=True,
1094 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001095 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001096 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001097 s = socket.socket()
1098 s.setblocking(1)
1099 s.connect((HOST, server.port))
1100 if test_support.verbose:
1101 sys.stdout.write("\n")
1102 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +00001103 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00001104 sys.stdout.write(
1105 " client: sending %s...\n" % repr(indata))
1106 if wrapped:
1107 conn.write(indata)
1108 outdata = conn.read()
1109 else:
1110 s.send(indata)
1111 outdata = s.recv(1024)
1112 if (indata == "STARTTLS" and
1113 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001114 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001115 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001116 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001117 " client: read %s from server, starting TLS...\n"
1118 % repr(outdata))
1119 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1120 wrapped = True
1121 elif (indata == "ENDTLS" and
1122 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001123 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001124 if test_support.verbose:
1125 sys.stdout.write(
1126 " client: read %s from server, ending TLS...\n"
1127 % repr(outdata))
1128 s = conn.unwrap()
1129 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001130 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001131 if test_support.verbose:
1132 sys.stdout.write(
1133 " client: read %s from server\n" % repr(outdata))
1134 if test_support.verbose:
1135 sys.stdout.write(" client: closing connection.\n")
1136 if wrapped:
1137 conn.write("over\n")
1138 else:
1139 s.send("over\n")
1140 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001141
Antoine Pitrou3945c862010-04-28 21:11:01 +00001142 def test_socketserver(self):
1143 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001144 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001145 flag = threading.Event()
1146 server.start(flag)
1147 # wait for it to start
1148 flag.wait()
1149 # try to connect
1150 try:
1151 if test_support.verbose:
1152 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001153 with open(CERTFILE, 'rb') as f:
1154 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001155 d2 = ''
1156 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001157 url = 'https://127.0.0.1:%d/%s' % (
1158 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001159 with test_support.check_py3k_warnings():
1160 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001161 dlen = f.info().getheader("content-length")
1162 if dlen and (int(dlen) > 0):
1163 d2 = f.read(int(dlen))
1164 if test_support.verbose:
1165 sys.stdout.write(
1166 " client: read %d bytes from remote server '%s'\n"
1167 % (len(d2), server))
1168 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001169 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001170 finally:
1171 server.stop()
1172 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001173
Antoine Pitrou3945c862010-04-28 21:11:01 +00001174 def test_wrapped_accept(self):
1175 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001176 if test_support.verbose:
1177 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001178 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1179 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1180 chatty=True, connectionchatty=True,
1181 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001182
Antoine Pitrou3945c862010-04-28 21:11:01 +00001183 def test_asyncore_server(self):
1184 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001185 indata = "TEST MESSAGE of mixed case\n"
1186
1187 if test_support.verbose:
1188 sys.stdout.write("\n")
1189 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001190 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001191 s = ssl.wrap_socket(socket.socket())
1192 s.connect(('127.0.0.1', server.port))
1193 if test_support.verbose:
1194 sys.stdout.write(
1195 " client: sending %s...\n" % (repr(indata)))
1196 s.write(indata)
1197 outdata = s.read()
1198 if test_support.verbose:
1199 sys.stdout.write(" client: read %s\n" % repr(outdata))
1200 if outdata != indata.lower():
1201 self.fail(
1202 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1203 % (outdata[:min(len(outdata),20)], len(outdata),
1204 indata[:min(len(indata),20)].lower(), len(indata)))
1205 s.write("over\n")
1206 if test_support.verbose:
1207 sys.stdout.write(" client: closing connection.\n")
1208 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001209
Antoine Pitrou3945c862010-04-28 21:11:01 +00001210 def test_recv_send(self):
1211 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001212 if test_support.verbose:
1213 sys.stdout.write("\n")
1214
1215 server = ThreadedEchoServer(CERTFILE,
1216 certreqs=ssl.CERT_NONE,
1217 ssl_version=ssl.PROTOCOL_TLSv1,
1218 cacerts=CERTFILE,
1219 chatty=True,
1220 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001221 with server:
1222 s = ssl.wrap_socket(socket.socket(),
1223 server_side=False,
1224 certfile=CERTFILE,
1225 ca_certs=CERTFILE,
1226 cert_reqs=ssl.CERT_NONE,
1227 ssl_version=ssl.PROTOCOL_TLSv1)
1228 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001229 # helper methods for standardising recv* method signatures
1230 def _recv_into():
1231 b = bytearray("\0"*100)
1232 count = s.recv_into(b)
1233 return b[:count]
1234
1235 def _recvfrom_into():
1236 b = bytearray("\0"*100)
1237 count, addr = s.recvfrom_into(b)
1238 return b[:count]
1239
1240 # (name, method, whether to expect success, *args)
1241 send_methods = [
1242 ('send', s.send, True, []),
1243 ('sendto', s.sendto, False, ["some.address"]),
1244 ('sendall', s.sendall, True, []),
1245 ]
1246 recv_methods = [
1247 ('recv', s.recv, True, []),
1248 ('recvfrom', s.recvfrom, False, ["some.address"]),
1249 ('recv_into', _recv_into, True, []),
1250 ('recvfrom_into', _recvfrom_into, False, []),
1251 ]
1252 data_prefix = u"PREFIX_"
1253
1254 for meth_name, send_meth, expect_success, args in send_methods:
1255 indata = data_prefix + meth_name
1256 try:
1257 send_meth(indata.encode('ASCII', 'strict'), *args)
1258 outdata = s.read()
1259 outdata = outdata.decode('ASCII', 'strict')
1260 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001261 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001262 "While sending with <<%s>> bad data "
1263 "<<%r>> (%d) received; "
1264 "expected <<%r>> (%d)\n" % (
1265 meth_name, outdata[:20], len(outdata),
1266 indata[:20], len(indata)
1267 )
1268 )
1269 except ValueError as e:
1270 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001271 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001272 "Failed to send with method <<%s>>; "
1273 "expected to succeed.\n" % (meth_name,)
1274 )
1275 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001276 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001277 "Method <<%s>> failed with unexpected "
1278 "exception message: %s\n" % (
1279 meth_name, e
1280 )
1281 )
1282
1283 for meth_name, recv_meth, expect_success, args in recv_methods:
1284 indata = data_prefix + meth_name
1285 try:
1286 s.send(indata.encode('ASCII', 'strict'))
1287 outdata = recv_meth(*args)
1288 outdata = outdata.decode('ASCII', 'strict')
1289 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001290 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001291 "While receiving with <<%s>> bad data "
1292 "<<%r>> (%d) received; "
1293 "expected <<%r>> (%d)\n" % (
1294 meth_name, outdata[:20], len(outdata),
1295 indata[:20], len(indata)
1296 )
1297 )
1298 except ValueError as e:
1299 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001300 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001301 "Failed to receive with method <<%s>>; "
1302 "expected to succeed.\n" % (meth_name,)
1303 )
1304 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001305 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001306 "Method <<%s>> failed with unexpected "
1307 "exception message: %s\n" % (
1308 meth_name, e
1309 )
1310 )
1311 # consume data
1312 s.read()
1313
1314 s.write("over\n".encode("ASCII", "strict"))
1315 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00001316
Antoine Pitroufc69af12010-04-24 20:04:58 +00001317 def test_handshake_timeout(self):
1318 # Issue #5103: SSL handshake must respect the socket timeout
1319 server = socket.socket(socket.AF_INET)
1320 host = "127.0.0.1"
1321 port = test_support.bind_port(server)
1322 started = threading.Event()
1323 finish = False
1324
1325 def serve():
1326 server.listen(5)
1327 started.set()
1328 conns = []
1329 while not finish:
1330 r, w, e = select.select([server], [], [], 0.1)
1331 if server in r:
1332 # Let the socket hang around rather than having
1333 # it closed by garbage collection.
1334 conns.append(server.accept()[0])
1335
1336 t = threading.Thread(target=serve)
1337 t.start()
1338 started.wait()
1339
1340 try:
1341 try:
1342 c = socket.socket(socket.AF_INET)
1343 c.settimeout(0.2)
1344 c.connect((host, port))
1345 # Will attempt handshake and time out
1346 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1347 ssl.wrap_socket, c)
1348 finally:
1349 c.close()
1350 try:
1351 c = socket.socket(socket.AF_INET)
1352 c.settimeout(0.2)
1353 c = ssl.wrap_socket(c)
1354 # Will attempt handshake and time out
1355 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1356 c.connect, (host, port))
1357 finally:
1358 c.close()
1359 finally:
1360 finish = True
1361 t.join()
1362 server.close()
1363
Antoine Pitroud76088d2012-01-03 22:46:48 +01001364 def test_default_ciphers(self):
1365 with ThreadedEchoServer(CERTFILE,
1366 ssl_version=ssl.PROTOCOL_SSLv23,
1367 chatty=False) as server:
1368 sock = socket.socket()
1369 try:
1370 # Force a set of weak ciphers on our client socket
1371 try:
1372 s = ssl.wrap_socket(sock,
1373 ssl_version=ssl.PROTOCOL_SSLv23,
1374 ciphers="DES")
1375 except ssl.SSLError:
1376 self.skipTest("no DES cipher available")
1377 with self.assertRaises((OSError, ssl.SSLError)):
1378 s.connect((HOST, server.port))
1379 finally:
1380 sock.close()
1381 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1382
Bill Janssen61c001a2008-09-08 16:37:24 +00001383
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001384def test_main(verbose=False):
Christian Heimes88b174c2013-08-17 00:54:47 +02001385 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT, NULLBYTECERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001386 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001387 "keycert.pem")
1388 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1389 os.path.dirname(__file__) or os.curdir,
1390 "https_svn_python_org_root.pem")
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001391 NOKIACERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1392 "nokia.pem")
Christian Heimes88b174c2013-08-17 00:54:47 +02001393 NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1394 "nullbytecert.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001395
1396 if (not os.path.exists(CERTFILE) or
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001397 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
Christian Heimes88b174c2013-08-17 00:54:47 +02001398 not os.path.exists(NOKIACERT) or
1399 not os.path.exists(NULLBYTECERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001400 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001401
Antoine Pitroude30f702010-09-14 12:54:08 +00001402 tests = [BasicTests, BasicSocketTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001403
Bill Janssen296a59d2007-09-16 22:06:00 +00001404 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001405 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001406
Bill Janssen98d19da2007-09-10 21:51:02 +00001407 if _have_threads:
1408 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001409 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001410 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001411
Antoine Pitrou3945c862010-04-28 21:11:01 +00001412 try:
1413 test_support.run_unittest(*tests)
1414 finally:
1415 if _have_threads:
1416 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001417
1418if __name__ == "__main__":
1419 test_main()