blob: 9f5138719e89fc87dad390173453eeed673e97e4 [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
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000028
Neal Norwitz3e533c22007-08-27 01:03:18 +000029def handle_error(prefix):
30 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000031 if test_support.verbose:
32 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000033
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000034
35class BasicTests(unittest.TestCase):
36
Antoine Pitrou3945c862010-04-28 21:11:01 +000037 def test_sslwrap_simple(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000038 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000039 try:
40 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
41 except IOError, e:
42 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
43 pass
44 else:
45 raise
46 try:
47 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
48 except IOError, e:
49 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
50 pass
51 else:
52 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000053
Antoine Pitroud75efd92010-08-04 17:38:33 +000054# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
55def skip_if_broken_ubuntu_ssl(func):
Victor Stinnerb1241f92011-05-10 01:52:03 +020056 if hasattr(ssl, 'PROTOCOL_SSLv2'):
57 # We need to access the lower-level wrapper in order to create an
58 # implicit SSL context without trying to connect or listen.
Antoine Pitroud75efd92010-08-04 17:38:33 +000059 try:
Victor Stinnerb1241f92011-05-10 01:52:03 +020060 import _ssl
61 except ImportError:
62 # The returned function won't get executed, just ignore the error
63 pass
64 @functools.wraps(func)
65 def f(*args, **kwargs):
66 try:
67 s = socket.socket(socket.AF_INET)
68 _ssl.sslwrap(s._sock, 0, None, None,
69 ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None)
70 except ssl.SSLError as e:
71 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
72 platform.linux_distribution() == ('debian', 'squeeze/sid', '')
73 and 'Invalid SSL protocol variant specified' in str(e)):
74 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
75 return func(*args, **kwargs)
76 return f
77 else:
78 return func
Antoine Pitroud75efd92010-08-04 17:38:33 +000079
80
81class BasicSocketTests(unittest.TestCase):
82
Antoine Pitrou3945c862010-04-28 21:11:01 +000083 def test_constants(self):
Victor Stinnerb1241f92011-05-10 01:52:03 +020084 #ssl.PROTOCOL_SSLv2
Bill Janssen98d19da2007-09-10 21:51:02 +000085 ssl.PROTOCOL_SSLv23
86 ssl.PROTOCOL_SSLv3
87 ssl.PROTOCOL_TLSv1
88 ssl.CERT_NONE
89 ssl.CERT_OPTIONAL
90 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000091
Antoine Pitrou3945c862010-04-28 21:11:01 +000092 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000093 v = ssl.RAND_status()
94 if test_support.verbose:
95 sys.stdout.write("\n RAND_status is %d (%s)\n"
96 % (v, (v and "sufficient randomness") or
97 "insufficient randomness"))
Jesus Ceaa8a5b392012-09-11 01:55:04 +020098 self.assertRaises(TypeError, ssl.RAND_egd, 1)
99 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000100 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000101
Antoine Pitrou3945c862010-04-28 21:11:01 +0000102 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000103 # note that this uses an 'unofficial' function in _ssl.c,
104 # provided solely for this test, to exercise the certificate
105 # parsing code
106 p = ssl._ssl._test_decode_cert(CERTFILE, False)
107 if test_support.verbose:
108 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200109 self.assertEqual(p['subject'],
110 ((('countryName', u'US'),),
111 (('stateOrProvinceName', u'Delaware'),),
112 (('localityName', u'Wilmington'),),
113 (('organizationName', u'Python Software Foundation'),),
114 (('organizationalUnitName', u'SSL'),),
115 (('commonName', u'somemachine.python.org'),)),
116 )
117 # 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
Antoine Pitrou3945c862010-04-28 21:11:01 +0000127 def test_DER_to_PEM(self):
128 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
129 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000130 d1 = ssl.PEM_cert_to_DER_cert(pem)
131 p2 = ssl.DER_cert_to_PEM_cert(d1)
132 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000133 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000134 if not p2.startswith(ssl.PEM_HEADER + '\n'):
135 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
136 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
137 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000138
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000139 def test_openssl_version(self):
140 n = ssl.OPENSSL_VERSION_NUMBER
141 t = ssl.OPENSSL_VERSION_INFO
142 s = ssl.OPENSSL_VERSION
143 self.assertIsInstance(n, (int, long))
144 self.assertIsInstance(t, tuple)
145 self.assertIsInstance(s, str)
146 # Some sanity checks follow
147 # >= 0.9
148 self.assertGreaterEqual(n, 0x900000)
149 # < 2.0
150 self.assertLess(n, 0x20000000)
151 major, minor, fix, patch, status = t
152 self.assertGreaterEqual(major, 0)
153 self.assertLess(major, 2)
154 self.assertGreaterEqual(minor, 0)
155 self.assertLess(minor, 256)
156 self.assertGreaterEqual(fix, 0)
157 self.assertLess(fix, 256)
158 self.assertGreaterEqual(patch, 0)
159 self.assertLessEqual(patch, 26)
160 self.assertGreaterEqual(status, 0)
161 self.assertLessEqual(status, 15)
162 # Version string as returned by OpenSSL, the format might change
163 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
164 (s, t))
165
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000166 def test_ciphers(self):
167 if not test_support.is_resource_enabled('network'):
168 return
169 remote = ("svn.python.org", 443)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000170 with test_support.transient_internet(remote[0]):
171 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
172 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000173 s.connect(remote)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000174 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
175 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
176 s.connect(remote)
177 # Error checking occurs when connecting, because the SSL context
178 # isn't created before.
179 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
180 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
181 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
182 s.connect(remote)
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000183
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000184 @test_support.cpython_only
185 def test_refcycle(self):
186 # Issue #7943: an SSL object doesn't create reference cycles with
187 # itself.
188 s = socket.socket(socket.AF_INET)
189 ss = ssl.wrap_socket(s)
190 wr = weakref.ref(ss)
191 del ss
192 self.assertEqual(wr(), None)
193
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000194 def test_wrapped_unconnected(self):
195 # The _delegate_methods in socket.py are correctly delegated to by an
196 # unconnected SSLSocket, so they will raise a socket.error rather than
197 # something unexpected like TypeError.
198 s = socket.socket(socket.AF_INET)
199 ss = ssl.wrap_socket(s)
200 self.assertRaises(socket.error, ss.recv, 1)
201 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
202 self.assertRaises(socket.error, ss.recvfrom, 1)
203 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
204 self.assertRaises(socket.error, ss.send, b'x')
205 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
206
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000207
Bill Janssen934b16d2008-06-28 22:19:33 +0000208class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000209
Antoine Pitrou3945c862010-04-28 21:11:01 +0000210 def test_connect(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000211 with test_support.transient_internet("svn.python.org"):
212 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
213 cert_reqs=ssl.CERT_NONE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000214 s.connect(("svn.python.org", 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000215 c = s.getpeercert()
216 if c:
217 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000218 s.close()
219
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000220 # this should fail because we have no verification certs
221 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
222 cert_reqs=ssl.CERT_REQUIRED)
223 try:
224 s.connect(("svn.python.org", 443))
225 except ssl.SSLError:
226 pass
227 finally:
228 s.close()
229
230 # this should succeed because we specify the root cert
231 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
232 cert_reqs=ssl.CERT_REQUIRED,
233 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
234 try:
235 s.connect(("svn.python.org", 443))
236 finally:
237 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +0000238
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000239 def test_connect_ex(self):
240 # Issue #11326: check connect_ex() implementation
241 with test_support.transient_internet("svn.python.org"):
242 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
243 cert_reqs=ssl.CERT_REQUIRED,
244 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
245 try:
246 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
247 self.assertTrue(s.getpeercert())
248 finally:
249 s.close()
250
251 def test_non_blocking_connect_ex(self):
252 # Issue #11326: non-blocking connect_ex() should allow handshake
253 # to proceed after the socket gets ready.
254 with test_support.transient_internet("svn.python.org"):
255 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
256 cert_reqs=ssl.CERT_REQUIRED,
257 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
258 do_handshake_on_connect=False)
259 try:
260 s.setblocking(False)
261 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +0000262 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
263 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000264 # Wait for connect to finish
265 select.select([], [s], [], 5.0)
266 # Non-blocking handshake
267 while True:
268 try:
269 s.do_handshake()
270 break
271 except ssl.SSLError as err:
272 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
273 select.select([s], [], [], 5.0)
274 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
275 select.select([], [s], [], 5.0)
276 else:
277 raise
278 # SSL established
279 self.assertTrue(s.getpeercert())
280 finally:
281 s.close()
282
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100283 def test_timeout_connect_ex(self):
284 # Issue #12065: on a timeout, connect_ex() should return the original
285 # errno (mimicking the behaviour of non-SSL sockets).
286 with test_support.transient_internet("svn.python.org"):
287 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
288 cert_reqs=ssl.CERT_REQUIRED,
289 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
290 do_handshake_on_connect=False)
291 try:
292 s.settimeout(0.0000001)
293 rc = s.connect_ex(('svn.python.org', 443))
294 if rc == 0:
295 self.skipTest("svn.python.org responded too quickly")
296 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
297 finally:
298 s.close()
299
300 def test_connect_ex_error(self):
301 with test_support.transient_internet("svn.python.org"):
302 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
303 cert_reqs=ssl.CERT_REQUIRED,
304 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
305 try:
306 self.assertEqual(errno.ECONNREFUSED,
307 s.connect_ex(("svn.python.org", 444)))
308 finally:
309 s.close()
310
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000311 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
312 def test_makefile_close(self):
313 # Issue #5238: creating a file-like object with makefile() shouldn't
314 # delay closing the underlying "real socket" (here tested with its
315 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000316 with test_support.transient_internet("svn.python.org"):
317 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
318 ss.connect(("svn.python.org", 443))
319 fd = ss.fileno()
320 f = ss.makefile()
321 f.close()
322 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000323 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000324 # Closing the SSL socket should close the fd too
325 ss.close()
326 gc.collect()
327 with self.assertRaises(OSError) as e:
328 os.read(fd, 0)
329 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000330
Antoine Pitrou3945c862010-04-28 21:11:01 +0000331 def test_non_blocking_handshake(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000332 with test_support.transient_internet("svn.python.org"):
333 s = socket.socket(socket.AF_INET)
334 s.connect(("svn.python.org", 443))
335 s.setblocking(False)
336 s = ssl.wrap_socket(s,
337 cert_reqs=ssl.CERT_NONE,
338 do_handshake_on_connect=False)
339 count = 0
340 while True:
341 try:
342 count += 1
343 s.do_handshake()
344 break
345 except ssl.SSLError, err:
346 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
347 select.select([s], [], [])
348 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
349 select.select([], [s], [])
350 else:
351 raise
352 s.close()
353 if test_support.verbose:
354 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +0000355
Antoine Pitrou3945c862010-04-28 21:11:01 +0000356 def test_get_server_certificate(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000357 with test_support.transient_internet("svn.python.org"):
358 pem = ssl.get_server_certificate(("svn.python.org", 443))
359 if not pem:
360 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000361
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000362 try:
363 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
364 except ssl.SSLError:
365 #should fail
366 pass
367 else:
368 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000369
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000370 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
371 if not pem:
372 self.fail("No server certificate on svn.python.org:443!")
373 if test_support.verbose:
374 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000375
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000376 def test_algorithms(self):
377 # Issue #8484: all algorithms should be available when verifying a
378 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000379 # SHA256 was added in OpenSSL 0.9.8
380 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
381 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc642f672012-05-04 16:33:30 +0200382 self.skipTest("remote host needs SNI, only available on Python 3.2+")
383 # NOTE: https://sha2.hboeck.de is another possible test host
Antoine Pitroud43245a2011-01-08 10:32:51 +0000384 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000385 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroud43245a2011-01-08 10:32:51 +0000386 with test_support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000387 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
388 cert_reqs=ssl.CERT_REQUIRED,
389 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000390 try:
391 s.connect(remote)
392 if test_support.verbose:
393 sys.stdout.write("\nCipher with %r is %r\n" %
394 (remote, s.cipher()))
395 sys.stdout.write("Certificate is:\n%s\n" %
396 pprint.pformat(s.getpeercert()))
397 finally:
398 s.close()
399
Bill Janssen296a59d2007-09-16 22:06:00 +0000400
Bill Janssen98d19da2007-09-10 21:51:02 +0000401try:
402 import threading
403except ImportError:
404 _have_threads = False
405else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000406 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000407
Bill Janssen98d19da2007-09-10 21:51:02 +0000408 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000409
Bill Janssen98d19da2007-09-10 21:51:02 +0000410 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000411
Bill Janssen98d19da2007-09-10 21:51:02 +0000412 """A mildly complicated class, because we want it to work both
413 with and without the SSL wrapper around the socket connection, so
414 that we can test the STARTTLS functionality."""
415
416 def __init__(self, server, connsock):
417 self.server = server
418 self.running = False
419 self.sock = connsock
420 self.sock.setblocking(1)
421 self.sslconn = None
422 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000423 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000424
Bill Janssen934b16d2008-06-28 22:19:33 +0000425 def show_conn_details(self):
426 if self.server.certreqs == ssl.CERT_REQUIRED:
427 cert = self.sslconn.getpeercert()
428 if test_support.verbose and self.server.chatty:
429 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
430 cert_binary = self.sslconn.getpeercert(True)
431 if test_support.verbose and self.server.chatty:
432 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
433 cipher = self.sslconn.cipher()
434 if test_support.verbose and self.server.chatty:
435 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
436
Antoine Pitrou3945c862010-04-28 21:11:01 +0000437 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000438 try:
439 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
440 certfile=self.server.certificate,
441 ssl_version=self.server.protocol,
442 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000443 cert_reqs=self.server.certreqs,
444 ciphers=self.server.ciphers)
Antoine Pitroud76088d2012-01-03 22:46:48 +0100445 except ssl.SSLError as e:
Antoine Pitroudb187842010-04-27 10:32:58 +0000446 # XXX Various errors can have happened here, for example
447 # a mismatching protocol version, an invalid certificate,
448 # or a low-level bug. This should be made more discriminating.
Antoine Pitroud76088d2012-01-03 22:46:48 +0100449 self.server.conn_errors.append(e)
Bill Janssen98d19da2007-09-10 21:51:02 +0000450 if self.server.chatty:
451 handle_error("\n server: bad connection attempt from " +
452 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000453 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000454 self.running = False
455 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000456 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000457 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000458 return True
459
460 def read(self):
461 if self.sslconn:
462 return self.sslconn.read()
463 else:
464 return self.sock.recv(1024)
465
466 def write(self, bytes):
467 if self.sslconn:
468 return self.sslconn.write(bytes)
469 else:
470 return self.sock.send(bytes)
471
472 def close(self):
473 if self.sslconn:
474 self.sslconn.close()
475 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000476 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000477
Antoine Pitrou3945c862010-04-28 21:11:01 +0000478 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000479 self.running = True
480 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000481 if isinstance(self.sock, ssl.SSLSocket):
482 self.sslconn = self.sock
483 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000484 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000485 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000486 while self.running:
487 try:
488 msg = self.read()
489 if not msg:
490 # eof, so quit this handler
491 self.running = False
492 self.close()
493 elif msg.strip() == 'over':
494 if test_support.verbose and self.server.connectionchatty:
495 sys.stdout.write(" server: client closed connection\n")
496 self.close()
497 return
498 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
499 if test_support.verbose and self.server.connectionchatty:
500 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
501 self.write("OK\n")
502 if not self.wrap_conn():
503 return
Bill Janssen39295c22008-08-12 16:31:21 +0000504 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
505 if test_support.verbose and self.server.connectionchatty:
506 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
507 self.write("OK\n")
508 self.sslconn.unwrap()
509 self.sslconn = None
510 if test_support.verbose and self.server.connectionchatty:
511 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000512 else:
513 if (test_support.verbose and
514 self.server.connectionchatty):
515 ctype = (self.sslconn and "encrypted") or "unencrypted"
516 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
517 % (repr(msg), ctype, repr(msg.lower()), ctype))
518 self.write(msg.lower())
519 except ssl.SSLError:
520 if self.server.chatty:
521 handle_error("Test server failure:\n")
522 self.close()
523 self.running = False
524 # normally, we'd just stop here, but for the test
525 # harness, we want to stop the server
526 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000527
Trent Nelsone41b0062008-04-08 23:47:30 +0000528 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000529 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000530 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000531 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000532
Bill Janssen98d19da2007-09-10 21:51:02 +0000533 if ssl_version is None:
534 ssl_version = ssl.PROTOCOL_TLSv1
535 if certreqs is None:
536 certreqs = ssl.CERT_NONE
537 self.certificate = certificate
538 self.protocol = ssl_version
539 self.certreqs = certreqs
540 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000541 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000542 self.chatty = chatty
543 self.connectionchatty = connectionchatty
544 self.starttls_server = starttls_server
545 self.sock = socket.socket()
546 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000547 if wrap_accepting_socket:
548 self.sock = ssl.wrap_socket(self.sock, server_side=True,
549 certfile=self.certificate,
550 cert_reqs = self.certreqs,
551 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000552 ssl_version = self.protocol,
553 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000554 if test_support.verbose and self.chatty:
555 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
556 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000557 self.active = False
Antoine Pitroud76088d2012-01-03 22:46:48 +0100558 self.conn_errors = []
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000559 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000560 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000561
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100562 def __enter__(self):
563 self.start(threading.Event())
564 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100565 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100566
567 def __exit__(self, *args):
568 self.stop()
569 self.join()
570
Antoine Pitrou3945c862010-04-28 21:11:01 +0000571 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000572 self.flag = flag
573 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000574
Antoine Pitrou3945c862010-04-28 21:11:01 +0000575 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000576 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000577 self.sock.listen(5)
578 self.active = True
579 if self.flag:
580 # signal an event
581 self.flag.set()
582 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000583 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000584 newconn, connaddr = self.sock.accept()
585 if test_support.verbose and self.chatty:
586 sys.stdout.write(' server: new connection from '
587 + str(connaddr) + '\n')
588 handler = self.ConnectionHandler(self, newconn)
589 handler.start()
Antoine Pitrou7a556842012-01-27 17:33:01 +0100590 handler.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000591 except socket.timeout:
592 pass
593 except KeyboardInterrupt:
594 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000595 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000596
Antoine Pitrou3945c862010-04-28 21:11:01 +0000597 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000598 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000599
Bill Janssen934b16d2008-06-28 22:19:33 +0000600 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000601
Antoine Pitrou3945c862010-04-28 21:11:01 +0000602 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000603
Antoine Pitrou3945c862010-04-28 21:11:01 +0000604 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000605
606 def __init__(self, conn, certfile):
607 asyncore.dispatcher_with_send.__init__(self, conn)
608 self.socket = ssl.wrap_socket(conn, server_side=True,
609 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000610 do_handshake_on_connect=False)
611 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000612
613 def readable(self):
614 if isinstance(self.socket, ssl.SSLSocket):
615 while self.socket.pending() > 0:
616 self.handle_read_event()
617 return True
618
Antoine Pitroufc69af12010-04-24 20:04:58 +0000619 def _do_ssl_handshake(self):
620 try:
621 self.socket.do_handshake()
622 except ssl.SSLError, err:
623 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
624 ssl.SSL_ERROR_WANT_WRITE):
625 return
626 elif err.args[0] == ssl.SSL_ERROR_EOF:
627 return self.handle_close()
628 raise
629 except socket.error, err:
630 if err.args[0] == errno.ECONNABORTED:
631 return self.handle_close()
632 else:
633 self._ssl_accepting = False
634
Bill Janssen934b16d2008-06-28 22:19:33 +0000635 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000636 if self._ssl_accepting:
637 self._do_ssl_handshake()
638 else:
639 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000640 if data and data.strip() != 'over':
641 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000642
643 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000644 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000645 if test_support.verbose:
646 sys.stdout.write(" server: closed connection %s\n" % self.socket)
647
648 def handle_error(self):
649 raise
650
651 def __init__(self, certfile):
652 self.certfile = certfile
653 asyncore.dispatcher.__init__(self)
654 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
655 self.port = test_support.bind_port(self.socket)
656 self.listen(5)
657
658 def handle_accept(self):
659 sock_obj, addr = self.accept()
660 if test_support.verbose:
661 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
662 self.ConnectionHandler(sock_obj, self.certfile)
663
664 def handle_error(self):
665 raise
666
667 def __init__(self, certfile):
668 self.flag = None
669 self.active = False
670 self.server = self.EchoServer(certfile)
671 self.port = self.server.port
672 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000673 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000674
675 def __str__(self):
676 return "<%s %s>" % (self.__class__.__name__, self.server)
677
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100678 def __enter__(self):
679 self.start(threading.Event())
680 self.flag.wait()
Antoine Pitroud76088d2012-01-03 22:46:48 +0100681 return self
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100682
683 def __exit__(self, *args):
684 if test_support.verbose:
685 sys.stdout.write(" cleanup: stopping server.\n")
686 self.stop()
687 if test_support.verbose:
688 sys.stdout.write(" cleanup: joining server thread.\n")
689 self.join()
690 if test_support.verbose:
691 sys.stdout.write(" cleanup: successfully joined.\n")
692
Antoine Pitrou3945c862010-04-28 21:11:01 +0000693 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000694 self.flag = flag
695 threading.Thread.start(self)
696
Antoine Pitrou3945c862010-04-28 21:11:01 +0000697 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000698 self.active = True
699 if self.flag:
700 self.flag.set()
701 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000702 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000703
Antoine Pitrou3945c862010-04-28 21:11:01 +0000704 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000705 self.active = False
706 self.server.close()
707
708 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000709
710 class HTTPSServer(HTTPServer):
711
712 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000713 HTTPServer.__init__(self, server_address, RequestHandlerClass)
714 # we assume the certfile contains both private key and certificate
715 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000716 self.allow_reuse_address = True
717
Bill Janssen934b16d2008-06-28 22:19:33 +0000718 def __str__(self):
719 return ('<%s %s:%s>' %
720 (self.__class__.__name__,
721 self.server_name,
722 self.server_port))
723
Antoine Pitrou3945c862010-04-28 21:11:01 +0000724 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000725 # override this to wrap socket with SSL
726 sock, addr = self.socket.accept()
727 sslconn = ssl.wrap_socket(sock, server_side=True,
728 certfile=self.certfile)
729 return sslconn, addr
730
Bill Janssen296a59d2007-09-16 22:06:00 +0000731 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000732 # need to override translate_path to get a known root,
733 # instead of using os.curdir, since the test could be
734 # run from anywhere
735
736 server_version = "TestHTTPS/1.0"
737
738 root = None
739
740 def translate_path(self, path):
741 """Translate a /-separated PATH to the local filename syntax.
742
743 Components that mean special things to the local file system
744 (e.g. drive or directory names) are ignored. (XXX They should
745 probably be diagnosed.)
746
747 """
748 # abandon query parameters
749 path = urlparse.urlparse(path)[2]
750 path = os.path.normpath(urllib.unquote(path))
751 words = path.split('/')
752 words = filter(None, words)
753 path = self.root
754 for word in words:
755 drive, word = os.path.splitdrive(word)
756 head, word = os.path.split(word)
757 if word in self.root: continue
758 path = os.path.join(path, word)
759 return path
760
761 def log_message(self, format, *args):
762
763 # we override this to suppress logging unless "verbose"
764
765 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000766 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
767 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000768 self.server.server_port,
769 self.request.cipher(),
770 self.log_date_time_string(),
771 format%args))
772
773
Trent Nelsone41b0062008-04-08 23:47:30 +0000774 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000775 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000776 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
777 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000778 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
779 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000780 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000781 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000782
783 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000784 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000785
Antoine Pitrou3945c862010-04-28 21:11:01 +0000786 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000787 self.flag = flag
788 threading.Thread.start(self)
789
Antoine Pitrou3945c862010-04-28 21:11:01 +0000790 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000791 if self.flag:
792 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000793 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000794
Antoine Pitrou3945c862010-04-28 21:11:01 +0000795 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000796 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000797
798
Antoine Pitrou3945c862010-04-28 21:11:01 +0000799 def bad_cert_test(certfile):
800 """
801 Launch a server with CERT_REQUIRED, and check that trying to
802 connect to it with the given client certificate fails.
803 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000804 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000805 certreqs=ssl.CERT_REQUIRED,
806 cacerts=CERTFILE, chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100807 with server:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000808 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000809 s = ssl.wrap_socket(socket.socket(),
810 certfile=certfile,
811 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000812 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000813 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000814 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000815 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000816 except socket.error, x:
817 if test_support.verbose:
818 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000819 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000820 raise AssertionError("Use of invalid cert should have failed!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000821
Antoine Pitrou3945c862010-04-28 21:11:01 +0000822 def server_params_test(certfile, protocol, certreqs, cacertsfile,
823 client_certfile, client_protocol=None, indata="FOO\n",
824 ciphers=None, chatty=True, connectionchatty=False,
825 wrap_accepting_socket=False):
826 """
827 Launch a server, connect a client to it and try various reads
828 and writes.
829 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000830 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000831 certreqs=certreqs,
832 ssl_version=protocol,
833 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000834 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000835 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000836 connectionchatty=connectionchatty,
837 wrap_accepting_socket=wrap_accepting_socket)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100838 with server:
839 # try to connect
840 if client_protocol is None:
841 client_protocol = protocol
Antoine Pitroudb187842010-04-27 10:32:58 +0000842 s = ssl.wrap_socket(socket.socket(),
843 certfile=client_certfile,
844 ca_certs=cacertsfile,
845 ciphers=ciphers,
846 cert_reqs=certreqs,
847 ssl_version=client_protocol)
848 s.connect((HOST, server.port))
849 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000850 if connectionchatty:
851 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000852 sys.stdout.write(
853 " client: sending %s...\n" % (repr(arg)))
854 s.write(arg)
855 outdata = s.read()
856 if connectionchatty:
857 if test_support.verbose:
858 sys.stdout.write(" client: read %s\n" % repr(outdata))
859 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000860 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000861 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
862 % (outdata[:min(len(outdata),20)], len(outdata),
863 indata[:min(len(indata),20)].lower(), len(indata)))
864 s.write("over\n")
865 if connectionchatty:
866 if test_support.verbose:
867 sys.stdout.write(" client: closing connection.\n")
868 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000869
Antoine Pitrou3945c862010-04-28 21:11:01 +0000870 def try_protocol_combo(server_protocol,
871 client_protocol,
872 expect_success,
873 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000874 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000875 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000876 certtype = {
877 ssl.CERT_NONE: "CERT_NONE",
878 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
879 ssl.CERT_REQUIRED: "CERT_REQUIRED",
880 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000881 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000882 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000883 sys.stdout.write(formatstr %
884 (ssl.get_protocol_name(client_protocol),
885 ssl.get_protocol_name(server_protocol),
886 certtype))
887 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000888 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
889 # will send an SSLv3 hello (rather than SSLv2) starting from
890 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000891 server_params_test(CERTFILE, server_protocol, certsreqs,
892 CERTFILE, CERTFILE, client_protocol,
893 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000894 # Protocol mismatch can result in either an SSLError, or a
895 # "Connection reset by peer" error.
896 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000897 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000898 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000899 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000900 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000901 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000902 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000903 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000904 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000905 "Client protocol %s succeeded with server protocol %s!"
906 % (ssl.get_protocol_name(client_protocol),
907 ssl.get_protocol_name(server_protocol)))
908
909
Bill Janssen934b16d2008-06-28 22:19:33 +0000910 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000911
Antoine Pitrou3945c862010-04-28 21:11:01 +0000912 def test_rude_shutdown(self):
913 """A brutal shutdown of an SSL server should raise an IOError
914 in the client when attempting handshake.
915 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000916 listener_ready = threading.Event()
917 listener_gone = threading.Event()
918
Antoine Pitrou150acda2010-04-27 08:40:51 +0000919 s = socket.socket()
920 port = test_support.bind_port(s, HOST)
921
922 # `listener` runs in a thread. It sits in an accept() until
923 # the main thread connects. Then it rudely closes the socket,
924 # and sets Event `listener_gone` to let the main thread know
925 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000926 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000927 s.listen(5)
928 listener_ready.set()
929 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000930 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000931 listener_gone.set()
932
933 def connector():
934 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000935 c = socket.socket()
936 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000937 listener_gone.wait()
938 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000939 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000940 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000941 pass
942 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000943 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000944
945 t = threading.Thread(target=listener)
946 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000947 try:
948 connector()
949 finally:
950 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000951
Antoine Pitroud75efd92010-08-04 17:38:33 +0000952 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000953 def test_echo(self):
954 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000955 if test_support.verbose:
956 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000957 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
958 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
959 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000960
Antoine Pitrou3945c862010-04-28 21:11:01 +0000961 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000962 if test_support.verbose:
963 sys.stdout.write("\n")
964 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000965 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000966 certreqs=ssl.CERT_NONE,
967 ssl_version=ssl.PROTOCOL_SSLv23,
968 cacerts=CERTFILE,
969 chatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +0100970 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +0000971 s = ssl.wrap_socket(socket.socket(),
972 certfile=CERTFILE,
973 ca_certs=CERTFILE,
974 cert_reqs=ssl.CERT_REQUIRED,
975 ssl_version=ssl.PROTOCOL_SSLv23)
976 s.connect((HOST, server.port))
977 cert = s.getpeercert()
978 self.assertTrue(cert, "Can't get peer certificate.")
979 cipher = s.cipher()
980 if test_support.verbose:
981 sys.stdout.write(pprint.pformat(cert) + '\n')
982 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
983 if 'subject' not in cert:
984 self.fail("No subject field in certificate: %s." %
985 pprint.pformat(cert))
986 if ((('organizationName', 'Python Software Foundation'),)
987 not in cert['subject']):
988 self.fail(
989 "Missing or invalid 'organizationName' field in certificate subject; "
990 "should be 'Python Software Foundation'.")
991 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000992
Antoine Pitrou3945c862010-04-28 21:11:01 +0000993 def test_empty_cert(self):
994 """Connecting with an empty cert file"""
995 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
996 "nullcert.pem"))
997 def test_malformed_cert(self):
998 """Connecting with a badly formatted certificate (syntax error)"""
999 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1000 "badcert.pem"))
1001 def test_nonexisting_cert(self):
1002 """Connecting with a non-existing cert file"""
1003 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1004 "wrongcert.pem"))
1005 def test_malformed_key(self):
1006 """Connecting with a badly formatted key (syntax error)"""
1007 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1008 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +00001009
Antoine Pitroud75efd92010-08-04 17:38:33 +00001010 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001011 def test_protocol_sslv2(self):
1012 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001013 if test_support.verbose:
1014 sys.stdout.write("\n")
Antoine Pitrou6361ea22011-10-30 21:31:34 +01001015 if not hasattr(ssl, 'PROTOCOL_SSLv2'):
1016 self.skipTest("PROTOCOL_SSLv2 needed")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001017 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1018 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1019 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1020 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1021 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1022 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001023
Antoine Pitroud75efd92010-08-04 17:38:33 +00001024 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001025 def test_protocol_sslv23(self):
1026 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001027 if test_support.verbose:
1028 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001029 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1030 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1031 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001032
Antoine Pitrou3945c862010-04-28 21:11:01 +00001033 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1034 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1035 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00001036
Antoine Pitrou3945c862010-04-28 21:11:01 +00001037 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1038 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1039 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00001040
Antoine Pitroud75efd92010-08-04 17:38:33 +00001041 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001042 def test_protocol_sslv3(self):
1043 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001044 if test_support.verbose:
1045 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001046 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1047 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1048 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001049 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1050 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001051 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001052
Antoine Pitroud75efd92010-08-04 17:38:33 +00001053 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001054 def test_protocol_tlsv1(self):
1055 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001056 if test_support.verbose:
1057 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001058 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1059 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1060 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001061 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1062 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001063 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001064
Antoine Pitrou3945c862010-04-28 21:11:01 +00001065 def test_starttls(self):
1066 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +00001067 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00001068
Trent Nelsone41b0062008-04-08 23:47:30 +00001069 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001070 ssl_version=ssl.PROTOCOL_TLSv1,
1071 starttls_server=True,
1072 chatty=True,
1073 connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001074 wrapped = False
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001075 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001076 s = socket.socket()
1077 s.setblocking(1)
1078 s.connect((HOST, server.port))
1079 if test_support.verbose:
1080 sys.stdout.write("\n")
1081 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +00001082 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00001083 sys.stdout.write(
1084 " client: sending %s...\n" % repr(indata))
1085 if wrapped:
1086 conn.write(indata)
1087 outdata = conn.read()
1088 else:
1089 s.send(indata)
1090 outdata = s.recv(1024)
1091 if (indata == "STARTTLS" and
1092 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001093 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001094 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001095 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001096 " client: read %s from server, starting TLS...\n"
1097 % repr(outdata))
1098 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1099 wrapped = True
1100 elif (indata == "ENDTLS" and
1101 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001102 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001103 if test_support.verbose:
1104 sys.stdout.write(
1105 " client: read %s from server, ending TLS...\n"
1106 % repr(outdata))
1107 s = conn.unwrap()
1108 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001109 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001110 if test_support.verbose:
1111 sys.stdout.write(
1112 " client: read %s from server\n" % repr(outdata))
1113 if test_support.verbose:
1114 sys.stdout.write(" client: closing connection.\n")
1115 if wrapped:
1116 conn.write("over\n")
1117 else:
1118 s.send("over\n")
1119 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001120
Antoine Pitrou3945c862010-04-28 21:11:01 +00001121 def test_socketserver(self):
1122 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001123 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001124 flag = threading.Event()
1125 server.start(flag)
1126 # wait for it to start
1127 flag.wait()
1128 # try to connect
1129 try:
1130 if test_support.verbose:
1131 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001132 with open(CERTFILE, 'rb') as f:
1133 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001134 d2 = ''
1135 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001136 url = 'https://127.0.0.1:%d/%s' % (
1137 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001138 with test_support.check_py3k_warnings():
1139 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001140 dlen = f.info().getheader("content-length")
1141 if dlen and (int(dlen) > 0):
1142 d2 = f.read(int(dlen))
1143 if test_support.verbose:
1144 sys.stdout.write(
1145 " client: read %d bytes from remote server '%s'\n"
1146 % (len(d2), server))
1147 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001148 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001149 finally:
1150 server.stop()
1151 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001152
Antoine Pitrou3945c862010-04-28 21:11:01 +00001153 def test_wrapped_accept(self):
1154 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001155 if test_support.verbose:
1156 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001157 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1158 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1159 chatty=True, connectionchatty=True,
1160 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001161
Antoine Pitrou3945c862010-04-28 21:11:01 +00001162 def test_asyncore_server(self):
1163 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001164 indata = "TEST MESSAGE of mixed case\n"
1165
1166 if test_support.verbose:
1167 sys.stdout.write("\n")
1168 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001169 with server:
Antoine Pitroudb187842010-04-27 10:32:58 +00001170 s = ssl.wrap_socket(socket.socket())
1171 s.connect(('127.0.0.1', server.port))
1172 if test_support.verbose:
1173 sys.stdout.write(
1174 " client: sending %s...\n" % (repr(indata)))
1175 s.write(indata)
1176 outdata = s.read()
1177 if test_support.verbose:
1178 sys.stdout.write(" client: read %s\n" % repr(outdata))
1179 if outdata != indata.lower():
1180 self.fail(
1181 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1182 % (outdata[:min(len(outdata),20)], len(outdata),
1183 indata[:min(len(indata),20)].lower(), len(indata)))
1184 s.write("over\n")
1185 if test_support.verbose:
1186 sys.stdout.write(" client: closing connection.\n")
1187 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001188
Antoine Pitrou3945c862010-04-28 21:11:01 +00001189 def test_recv_send(self):
1190 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001191 if test_support.verbose:
1192 sys.stdout.write("\n")
1193
1194 server = ThreadedEchoServer(CERTFILE,
1195 certreqs=ssl.CERT_NONE,
1196 ssl_version=ssl.PROTOCOL_TLSv1,
1197 cacerts=CERTFILE,
1198 chatty=True,
1199 connectionchatty=False)
Antoine Pitrou5b95eb92011-12-21 16:52:40 +01001200 with server:
1201 s = ssl.wrap_socket(socket.socket(),
1202 server_side=False,
1203 certfile=CERTFILE,
1204 ca_certs=CERTFILE,
1205 cert_reqs=ssl.CERT_NONE,
1206 ssl_version=ssl.PROTOCOL_TLSv1)
1207 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001208 # helper methods for standardising recv* method signatures
1209 def _recv_into():
1210 b = bytearray("\0"*100)
1211 count = s.recv_into(b)
1212 return b[:count]
1213
1214 def _recvfrom_into():
1215 b = bytearray("\0"*100)
1216 count, addr = s.recvfrom_into(b)
1217 return b[:count]
1218
1219 # (name, method, whether to expect success, *args)
1220 send_methods = [
1221 ('send', s.send, True, []),
1222 ('sendto', s.sendto, False, ["some.address"]),
1223 ('sendall', s.sendall, True, []),
1224 ]
1225 recv_methods = [
1226 ('recv', s.recv, True, []),
1227 ('recvfrom', s.recvfrom, False, ["some.address"]),
1228 ('recv_into', _recv_into, True, []),
1229 ('recvfrom_into', _recvfrom_into, False, []),
1230 ]
1231 data_prefix = u"PREFIX_"
1232
1233 for meth_name, send_meth, expect_success, args in send_methods:
1234 indata = data_prefix + meth_name
1235 try:
1236 send_meth(indata.encode('ASCII', 'strict'), *args)
1237 outdata = s.read()
1238 outdata = outdata.decode('ASCII', 'strict')
1239 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001240 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001241 "While sending with <<%s>> bad data "
1242 "<<%r>> (%d) received; "
1243 "expected <<%r>> (%d)\n" % (
1244 meth_name, outdata[:20], len(outdata),
1245 indata[:20], len(indata)
1246 )
1247 )
1248 except ValueError as e:
1249 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001250 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001251 "Failed to send with method <<%s>>; "
1252 "expected to succeed.\n" % (meth_name,)
1253 )
1254 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001255 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001256 "Method <<%s>> failed with unexpected "
1257 "exception message: %s\n" % (
1258 meth_name, e
1259 )
1260 )
1261
1262 for meth_name, recv_meth, expect_success, args in recv_methods:
1263 indata = data_prefix + meth_name
1264 try:
1265 s.send(indata.encode('ASCII', 'strict'))
1266 outdata = recv_meth(*args)
1267 outdata = outdata.decode('ASCII', 'strict')
1268 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001269 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001270 "While receiving with <<%s>> bad data "
1271 "<<%r>> (%d) received; "
1272 "expected <<%r>> (%d)\n" % (
1273 meth_name, outdata[:20], len(outdata),
1274 indata[:20], len(indata)
1275 )
1276 )
1277 except ValueError as e:
1278 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001279 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001280 "Failed to receive with method <<%s>>; "
1281 "expected to succeed.\n" % (meth_name,)
1282 )
1283 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001284 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001285 "Method <<%s>> failed with unexpected "
1286 "exception message: %s\n" % (
1287 meth_name, e
1288 )
1289 )
1290 # consume data
1291 s.read()
1292
1293 s.write("over\n".encode("ASCII", "strict"))
1294 s.close()
Bill Janssen61c001a2008-09-08 16:37:24 +00001295
Antoine Pitroufc69af12010-04-24 20:04:58 +00001296 def test_handshake_timeout(self):
1297 # Issue #5103: SSL handshake must respect the socket timeout
1298 server = socket.socket(socket.AF_INET)
1299 host = "127.0.0.1"
1300 port = test_support.bind_port(server)
1301 started = threading.Event()
1302 finish = False
1303
1304 def serve():
1305 server.listen(5)
1306 started.set()
1307 conns = []
1308 while not finish:
1309 r, w, e = select.select([server], [], [], 0.1)
1310 if server in r:
1311 # Let the socket hang around rather than having
1312 # it closed by garbage collection.
1313 conns.append(server.accept()[0])
1314
1315 t = threading.Thread(target=serve)
1316 t.start()
1317 started.wait()
1318
1319 try:
1320 try:
1321 c = socket.socket(socket.AF_INET)
1322 c.settimeout(0.2)
1323 c.connect((host, port))
1324 # Will attempt handshake and time out
1325 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1326 ssl.wrap_socket, c)
1327 finally:
1328 c.close()
1329 try:
1330 c = socket.socket(socket.AF_INET)
1331 c.settimeout(0.2)
1332 c = ssl.wrap_socket(c)
1333 # Will attempt handshake and time out
1334 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1335 c.connect, (host, port))
1336 finally:
1337 c.close()
1338 finally:
1339 finish = True
1340 t.join()
1341 server.close()
1342
Antoine Pitroud76088d2012-01-03 22:46:48 +01001343 def test_default_ciphers(self):
1344 with ThreadedEchoServer(CERTFILE,
1345 ssl_version=ssl.PROTOCOL_SSLv23,
1346 chatty=False) as server:
1347 sock = socket.socket()
1348 try:
1349 # Force a set of weak ciphers on our client socket
1350 try:
1351 s = ssl.wrap_socket(sock,
1352 ssl_version=ssl.PROTOCOL_SSLv23,
1353 ciphers="DES")
1354 except ssl.SSLError:
1355 self.skipTest("no DES cipher available")
1356 with self.assertRaises((OSError, ssl.SSLError)):
1357 s.connect((HOST, server.port))
1358 finally:
1359 sock.close()
1360 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1361
Bill Janssen61c001a2008-09-08 16:37:24 +00001362
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001363def test_main(verbose=False):
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001364 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001365 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001366 "keycert.pem")
1367 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1368 os.path.dirname(__file__) or os.curdir,
1369 "https_svn_python_org_root.pem")
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001370 NOKIACERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1371 "nokia.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001372
1373 if (not os.path.exists(CERTFILE) or
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001374 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
1375 not os.path.exists(NOKIACERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001376 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001377
Antoine Pitroude30f702010-09-14 12:54:08 +00001378 tests = [BasicTests, BasicSocketTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001379
Bill Janssen296a59d2007-09-16 22:06:00 +00001380 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001381 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001382
Bill Janssen98d19da2007-09-10 21:51:02 +00001383 if _have_threads:
1384 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001385 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001386 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001387
Antoine Pitrou3945c862010-04-28 21:11:01 +00001388 try:
1389 test_support.run_unittest(*tests)
1390 finally:
1391 if _have_threads:
1392 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001393
1394if __name__ == "__main__":
1395 test_main()