blob: ba1d868ccced8de8ed8551cc6605cfcabf67e4fe [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"))
Guido van Rossume4729332007-08-26 19:35:09 +000098 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000099 ssl.RAND_egd(1)
100 except TypeError:
101 pass
Guido van Rossume4729332007-08-26 19:35:09 +0000102 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000103 print "didn't raise TypeError"
104 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000105
Antoine Pitrou3945c862010-04-28 21:11:01 +0000106 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000107 # note that this uses an 'unofficial' function in _ssl.c,
108 # provided solely for this test, to exercise the certificate
109 # parsing code
110 p = ssl._ssl._test_decode_cert(CERTFILE, False)
111 if test_support.verbose:
112 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitrouf06eb462011-10-01 19:30:58 +0200113 self.assertEqual(p['subject'],
114 ((('countryName', u'US'),),
115 (('stateOrProvinceName', u'Delaware'),),
116 (('localityName', u'Wilmington'),),
117 (('organizationName', u'Python Software Foundation'),),
118 (('organizationalUnitName', u'SSL'),),
119 (('commonName', u'somemachine.python.org'),)),
120 )
121 # Issue #13034: the subjectAltName in some certificates
122 # (notably projects.developer.nokia.com:443) wasn't parsed
123 p = ssl._ssl._test_decode_cert(NOKIACERT)
124 if test_support.verbose:
125 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
126 self.assertEqual(p['subjectAltName'],
127 (('DNS', 'projects.developer.nokia.com'),
128 ('DNS', 'projects.forum.nokia.com'))
129 )
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000130
Antoine Pitrou3945c862010-04-28 21:11:01 +0000131 def test_DER_to_PEM(self):
132 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
133 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000134 d1 = ssl.PEM_cert_to_DER_cert(pem)
135 p2 = ssl.DER_cert_to_PEM_cert(d1)
136 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000137 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000138 if not p2.startswith(ssl.PEM_HEADER + '\n'):
139 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
140 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
141 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000142
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000143 def test_openssl_version(self):
144 n = ssl.OPENSSL_VERSION_NUMBER
145 t = ssl.OPENSSL_VERSION_INFO
146 s = ssl.OPENSSL_VERSION
147 self.assertIsInstance(n, (int, long))
148 self.assertIsInstance(t, tuple)
149 self.assertIsInstance(s, str)
150 # Some sanity checks follow
151 # >= 0.9
152 self.assertGreaterEqual(n, 0x900000)
153 # < 2.0
154 self.assertLess(n, 0x20000000)
155 major, minor, fix, patch, status = t
156 self.assertGreaterEqual(major, 0)
157 self.assertLess(major, 2)
158 self.assertGreaterEqual(minor, 0)
159 self.assertLess(minor, 256)
160 self.assertGreaterEqual(fix, 0)
161 self.assertLess(fix, 256)
162 self.assertGreaterEqual(patch, 0)
163 self.assertLessEqual(patch, 26)
164 self.assertGreaterEqual(status, 0)
165 self.assertLessEqual(status, 15)
166 # Version string as returned by OpenSSL, the format might change
167 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
168 (s, t))
169
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000170 def test_ciphers(self):
171 if not test_support.is_resource_enabled('network'):
172 return
173 remote = ("svn.python.org", 443)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000174 with test_support.transient_internet(remote[0]):
175 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
176 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000177 s.connect(remote)
Antoine Pitrou942d5542010-10-31 13:26:53 +0000178 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
179 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
180 s.connect(remote)
181 # Error checking occurs when connecting, because the SSL context
182 # isn't created before.
183 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
184 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
185 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
186 s.connect(remote)
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000187
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000188 @test_support.cpython_only
189 def test_refcycle(self):
190 # Issue #7943: an SSL object doesn't create reference cycles with
191 # itself.
192 s = socket.socket(socket.AF_INET)
193 ss = ssl.wrap_socket(s)
194 wr = weakref.ref(ss)
195 del ss
196 self.assertEqual(wr(), None)
197
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000198 def test_wrapped_unconnected(self):
199 # The _delegate_methods in socket.py are correctly delegated to by an
200 # unconnected SSLSocket, so they will raise a socket.error rather than
201 # something unexpected like TypeError.
202 s = socket.socket(socket.AF_INET)
203 ss = ssl.wrap_socket(s)
204 self.assertRaises(socket.error, ss.recv, 1)
205 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
206 self.assertRaises(socket.error, ss.recvfrom, 1)
207 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
208 self.assertRaises(socket.error, ss.send, b'x')
209 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
210
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000211
Bill Janssen934b16d2008-06-28 22:19:33 +0000212class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000213
Antoine Pitrou3945c862010-04-28 21:11:01 +0000214 def test_connect(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000215 with test_support.transient_internet("svn.python.org"):
216 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
217 cert_reqs=ssl.CERT_NONE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000218 s.connect(("svn.python.org", 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000219 c = s.getpeercert()
220 if c:
221 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000222 s.close()
223
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000224 # this should fail because we have no verification certs
225 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
226 cert_reqs=ssl.CERT_REQUIRED)
227 try:
228 s.connect(("svn.python.org", 443))
229 except ssl.SSLError:
230 pass
231 finally:
232 s.close()
233
234 # this should succeed because we specify the root cert
235 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
236 cert_reqs=ssl.CERT_REQUIRED,
237 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
238 try:
239 s.connect(("svn.python.org", 443))
240 finally:
241 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +0000242
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000243 def test_connect_ex(self):
244 # Issue #11326: check connect_ex() implementation
245 with test_support.transient_internet("svn.python.org"):
246 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
247 cert_reqs=ssl.CERT_REQUIRED,
248 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
249 try:
250 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
251 self.assertTrue(s.getpeercert())
252 finally:
253 s.close()
254
255 def test_non_blocking_connect_ex(self):
256 # Issue #11326: non-blocking connect_ex() should allow handshake
257 # to proceed after the socket gets ready.
258 with test_support.transient_internet("svn.python.org"):
259 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
260 cert_reqs=ssl.CERT_REQUIRED,
261 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
262 do_handshake_on_connect=False)
263 try:
264 s.setblocking(False)
265 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8ef39072011-02-27 15:45:22 +0000266 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
267 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroud3f6ea12011-02-26 23:35:27 +0000268 # Wait for connect to finish
269 select.select([], [s], [], 5.0)
270 # Non-blocking handshake
271 while True:
272 try:
273 s.do_handshake()
274 break
275 except ssl.SSLError as err:
276 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
277 select.select([s], [], [], 5.0)
278 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
279 select.select([], [s], [], 5.0)
280 else:
281 raise
282 # SSL established
283 self.assertTrue(s.getpeercert())
284 finally:
285 s.close()
286
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000287 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
288 def test_makefile_close(self):
289 # Issue #5238: creating a file-like object with makefile() shouldn't
290 # delay closing the underlying "real socket" (here tested with its
291 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000292 with test_support.transient_internet("svn.python.org"):
293 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
294 ss.connect(("svn.python.org", 443))
295 fd = ss.fileno()
296 f = ss.makefile()
297 f.close()
298 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000299 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000300 # Closing the SSL socket should close the fd too
301 ss.close()
302 gc.collect()
303 with self.assertRaises(OSError) as e:
304 os.read(fd, 0)
305 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000306
Antoine Pitrou3945c862010-04-28 21:11:01 +0000307 def test_non_blocking_handshake(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000308 with test_support.transient_internet("svn.python.org"):
309 s = socket.socket(socket.AF_INET)
310 s.connect(("svn.python.org", 443))
311 s.setblocking(False)
312 s = ssl.wrap_socket(s,
313 cert_reqs=ssl.CERT_NONE,
314 do_handshake_on_connect=False)
315 count = 0
316 while True:
317 try:
318 count += 1
319 s.do_handshake()
320 break
321 except ssl.SSLError, err:
322 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
323 select.select([s], [], [])
324 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
325 select.select([], [s], [])
326 else:
327 raise
328 s.close()
329 if test_support.verbose:
330 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +0000331
Antoine Pitrou3945c862010-04-28 21:11:01 +0000332 def test_get_server_certificate(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000333 with test_support.transient_internet("svn.python.org"):
334 pem = ssl.get_server_certificate(("svn.python.org", 443))
335 if not pem:
336 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000337
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000338 try:
339 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
340 except ssl.SSLError:
341 #should fail
342 pass
343 else:
344 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000345
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000346 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
347 if not pem:
348 self.fail("No server certificate on svn.python.org:443!")
349 if test_support.verbose:
350 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000351
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000352 def test_algorithms(self):
353 # Issue #8484: all algorithms should be available when verifying a
354 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000355 # SHA256 was added in OpenSSL 0.9.8
356 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
357 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000358 # NOTE: https://sha256.tbs-internet.com is another possible test host
Antoine Pitroud43245a2011-01-08 10:32:51 +0000359 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000360 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroud43245a2011-01-08 10:32:51 +0000361 with test_support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000362 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
363 cert_reqs=ssl.CERT_REQUIRED,
364 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000365 try:
366 s.connect(remote)
367 if test_support.verbose:
368 sys.stdout.write("\nCipher with %r is %r\n" %
369 (remote, s.cipher()))
370 sys.stdout.write("Certificate is:\n%s\n" %
371 pprint.pformat(s.getpeercert()))
372 finally:
373 s.close()
374
Bill Janssen296a59d2007-09-16 22:06:00 +0000375
Bill Janssen98d19da2007-09-10 21:51:02 +0000376try:
377 import threading
378except ImportError:
379 _have_threads = False
380else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000381 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000382
Bill Janssen98d19da2007-09-10 21:51:02 +0000383 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000384
Bill Janssen98d19da2007-09-10 21:51:02 +0000385 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000386
Bill Janssen98d19da2007-09-10 21:51:02 +0000387 """A mildly complicated class, because we want it to work both
388 with and without the SSL wrapper around the socket connection, so
389 that we can test the STARTTLS functionality."""
390
391 def __init__(self, server, connsock):
392 self.server = server
393 self.running = False
394 self.sock = connsock
395 self.sock.setblocking(1)
396 self.sslconn = None
397 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000398 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000399
Bill Janssen934b16d2008-06-28 22:19:33 +0000400 def show_conn_details(self):
401 if self.server.certreqs == ssl.CERT_REQUIRED:
402 cert = self.sslconn.getpeercert()
403 if test_support.verbose and self.server.chatty:
404 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
405 cert_binary = self.sslconn.getpeercert(True)
406 if test_support.verbose and self.server.chatty:
407 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
408 cipher = self.sslconn.cipher()
409 if test_support.verbose and self.server.chatty:
410 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
411
Antoine Pitrou3945c862010-04-28 21:11:01 +0000412 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000413 try:
414 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
415 certfile=self.server.certificate,
416 ssl_version=self.server.protocol,
417 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000418 cert_reqs=self.server.certreqs,
419 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000420 except ssl.SSLError:
421 # XXX Various errors can have happened here, for example
422 # a mismatching protocol version, an invalid certificate,
423 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000424 if self.server.chatty:
425 handle_error("\n server: bad connection attempt from " +
426 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000427 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000428 self.running = False
429 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000430 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000431 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000432 return True
433
434 def read(self):
435 if self.sslconn:
436 return self.sslconn.read()
437 else:
438 return self.sock.recv(1024)
439
440 def write(self, bytes):
441 if self.sslconn:
442 return self.sslconn.write(bytes)
443 else:
444 return self.sock.send(bytes)
445
446 def close(self):
447 if self.sslconn:
448 self.sslconn.close()
449 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000450 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000451
Antoine Pitrou3945c862010-04-28 21:11:01 +0000452 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000453 self.running = True
454 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000455 if isinstance(self.sock, ssl.SSLSocket):
456 self.sslconn = self.sock
457 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000458 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000459 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000460 while self.running:
461 try:
462 msg = self.read()
463 if not msg:
464 # eof, so quit this handler
465 self.running = False
466 self.close()
467 elif msg.strip() == 'over':
468 if test_support.verbose and self.server.connectionchatty:
469 sys.stdout.write(" server: client closed connection\n")
470 self.close()
471 return
472 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
473 if test_support.verbose and self.server.connectionchatty:
474 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
475 self.write("OK\n")
476 if not self.wrap_conn():
477 return
Bill Janssen39295c22008-08-12 16:31:21 +0000478 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
479 if test_support.verbose and self.server.connectionchatty:
480 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
481 self.write("OK\n")
482 self.sslconn.unwrap()
483 self.sslconn = None
484 if test_support.verbose and self.server.connectionchatty:
485 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000486 else:
487 if (test_support.verbose and
488 self.server.connectionchatty):
489 ctype = (self.sslconn and "encrypted") or "unencrypted"
490 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
491 % (repr(msg), ctype, repr(msg.lower()), ctype))
492 self.write(msg.lower())
493 except ssl.SSLError:
494 if self.server.chatty:
495 handle_error("Test server failure:\n")
496 self.close()
497 self.running = False
498 # normally, we'd just stop here, but for the test
499 # harness, we want to stop the server
500 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000501
Trent Nelsone41b0062008-04-08 23:47:30 +0000502 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000503 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000504 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000505 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000506
Bill Janssen98d19da2007-09-10 21:51:02 +0000507 if ssl_version is None:
508 ssl_version = ssl.PROTOCOL_TLSv1
509 if certreqs is None:
510 certreqs = ssl.CERT_NONE
511 self.certificate = certificate
512 self.protocol = ssl_version
513 self.certreqs = certreqs
514 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000515 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000516 self.chatty = chatty
517 self.connectionchatty = connectionchatty
518 self.starttls_server = starttls_server
519 self.sock = socket.socket()
520 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000521 if wrap_accepting_socket:
522 self.sock = ssl.wrap_socket(self.sock, server_side=True,
523 certfile=self.certificate,
524 cert_reqs = self.certreqs,
525 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000526 ssl_version = self.protocol,
527 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000528 if test_support.verbose and self.chatty:
529 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
530 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000531 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000532 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000533 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000534
Antoine Pitrou3945c862010-04-28 21:11:01 +0000535 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000536 self.flag = flag
537 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000538
Antoine Pitrou3945c862010-04-28 21:11:01 +0000539 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000540 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000541 self.sock.listen(5)
542 self.active = True
543 if self.flag:
544 # signal an event
545 self.flag.set()
546 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000547 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000548 newconn, connaddr = self.sock.accept()
549 if test_support.verbose and self.chatty:
550 sys.stdout.write(' server: new connection from '
551 + str(connaddr) + '\n')
552 handler = self.ConnectionHandler(self, newconn)
553 handler.start()
554 except socket.timeout:
555 pass
556 except KeyboardInterrupt:
557 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000558 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000559
Antoine Pitrou3945c862010-04-28 21:11:01 +0000560 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000561 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000562
Bill Janssen934b16d2008-06-28 22:19:33 +0000563 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000564
Antoine Pitrou3945c862010-04-28 21:11:01 +0000565 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000566
Antoine Pitrou3945c862010-04-28 21:11:01 +0000567 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000568
569 def __init__(self, conn, certfile):
570 asyncore.dispatcher_with_send.__init__(self, conn)
571 self.socket = ssl.wrap_socket(conn, server_side=True,
572 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000573 do_handshake_on_connect=False)
574 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000575
576 def readable(self):
577 if isinstance(self.socket, ssl.SSLSocket):
578 while self.socket.pending() > 0:
579 self.handle_read_event()
580 return True
581
Antoine Pitroufc69af12010-04-24 20:04:58 +0000582 def _do_ssl_handshake(self):
583 try:
584 self.socket.do_handshake()
585 except ssl.SSLError, err:
586 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
587 ssl.SSL_ERROR_WANT_WRITE):
588 return
589 elif err.args[0] == ssl.SSL_ERROR_EOF:
590 return self.handle_close()
591 raise
592 except socket.error, err:
593 if err.args[0] == errno.ECONNABORTED:
594 return self.handle_close()
595 else:
596 self._ssl_accepting = False
597
Bill Janssen934b16d2008-06-28 22:19:33 +0000598 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000599 if self._ssl_accepting:
600 self._do_ssl_handshake()
601 else:
602 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000603 if data and data.strip() != 'over':
604 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000605
606 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000607 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000608 if test_support.verbose:
609 sys.stdout.write(" server: closed connection %s\n" % self.socket)
610
611 def handle_error(self):
612 raise
613
614 def __init__(self, certfile):
615 self.certfile = certfile
616 asyncore.dispatcher.__init__(self)
617 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
618 self.port = test_support.bind_port(self.socket)
619 self.listen(5)
620
621 def handle_accept(self):
622 sock_obj, addr = self.accept()
623 if test_support.verbose:
624 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
625 self.ConnectionHandler(sock_obj, self.certfile)
626
627 def handle_error(self):
628 raise
629
630 def __init__(self, certfile):
631 self.flag = None
632 self.active = False
633 self.server = self.EchoServer(certfile)
634 self.port = self.server.port
635 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000636 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000637
638 def __str__(self):
639 return "<%s %s>" % (self.__class__.__name__, self.server)
640
Antoine Pitrou3945c862010-04-28 21:11:01 +0000641 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000642 self.flag = flag
643 threading.Thread.start(self)
644
Antoine Pitrou3945c862010-04-28 21:11:01 +0000645 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000646 self.active = True
647 if self.flag:
648 self.flag.set()
649 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000650 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000651
Antoine Pitrou3945c862010-04-28 21:11:01 +0000652 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000653 self.active = False
654 self.server.close()
655
656 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000657
658 class HTTPSServer(HTTPServer):
659
660 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000661 HTTPServer.__init__(self, server_address, RequestHandlerClass)
662 # we assume the certfile contains both private key and certificate
663 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000664 self.allow_reuse_address = True
665
Bill Janssen934b16d2008-06-28 22:19:33 +0000666 def __str__(self):
667 return ('<%s %s:%s>' %
668 (self.__class__.__name__,
669 self.server_name,
670 self.server_port))
671
Antoine Pitrou3945c862010-04-28 21:11:01 +0000672 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000673 # override this to wrap socket with SSL
674 sock, addr = self.socket.accept()
675 sslconn = ssl.wrap_socket(sock, server_side=True,
676 certfile=self.certfile)
677 return sslconn, addr
678
Bill Janssen296a59d2007-09-16 22:06:00 +0000679 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000680 # need to override translate_path to get a known root,
681 # instead of using os.curdir, since the test could be
682 # run from anywhere
683
684 server_version = "TestHTTPS/1.0"
685
686 root = None
687
688 def translate_path(self, path):
689 """Translate a /-separated PATH to the local filename syntax.
690
691 Components that mean special things to the local file system
692 (e.g. drive or directory names) are ignored. (XXX They should
693 probably be diagnosed.)
694
695 """
696 # abandon query parameters
697 path = urlparse.urlparse(path)[2]
698 path = os.path.normpath(urllib.unquote(path))
699 words = path.split('/')
700 words = filter(None, words)
701 path = self.root
702 for word in words:
703 drive, word = os.path.splitdrive(word)
704 head, word = os.path.split(word)
705 if word in self.root: continue
706 path = os.path.join(path, word)
707 return path
708
709 def log_message(self, format, *args):
710
711 # we override this to suppress logging unless "verbose"
712
713 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000714 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
715 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000716 self.server.server_port,
717 self.request.cipher(),
718 self.log_date_time_string(),
719 format%args))
720
721
Trent Nelsone41b0062008-04-08 23:47:30 +0000722 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000723 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000724 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
725 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000726 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
727 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000728 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000729 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000730
731 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000732 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000733
Antoine Pitrou3945c862010-04-28 21:11:01 +0000734 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000735 self.flag = flag
736 threading.Thread.start(self)
737
Antoine Pitrou3945c862010-04-28 21:11:01 +0000738 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000739 if self.flag:
740 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000741 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000742
Antoine Pitrou3945c862010-04-28 21:11:01 +0000743 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000744 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000745
746
Antoine Pitrou3945c862010-04-28 21:11:01 +0000747 def bad_cert_test(certfile):
748 """
749 Launch a server with CERT_REQUIRED, and check that trying to
750 connect to it with the given client certificate fails.
751 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000752 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000753 certreqs=ssl.CERT_REQUIRED,
754 cacerts=CERTFILE, chatty=False)
755 flag = threading.Event()
756 server.start(flag)
757 # wait for it to start
758 flag.wait()
759 # try to connect
760 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000761 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000762 s = ssl.wrap_socket(socket.socket(),
763 certfile=certfile,
764 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000765 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000766 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000767 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000768 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000769 except socket.error, x:
770 if test_support.verbose:
771 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000772 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000773 raise AssertionError("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000774 finally:
775 server.stop()
776 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000777
Antoine Pitrou3945c862010-04-28 21:11:01 +0000778 def server_params_test(certfile, protocol, certreqs, cacertsfile,
779 client_certfile, client_protocol=None, indata="FOO\n",
780 ciphers=None, chatty=True, connectionchatty=False,
781 wrap_accepting_socket=False):
782 """
783 Launch a server, connect a client to it and try various reads
784 and writes.
785 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000786 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000787 certreqs=certreqs,
788 ssl_version=protocol,
789 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000790 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000791 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000792 connectionchatty=connectionchatty,
793 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000794 flag = threading.Event()
795 server.start(flag)
796 # wait for it to start
797 flag.wait()
798 # try to connect
799 if client_protocol is None:
800 client_protocol = protocol
801 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000802 s = ssl.wrap_socket(socket.socket(),
803 certfile=client_certfile,
804 ca_certs=cacertsfile,
805 ciphers=ciphers,
806 cert_reqs=certreqs,
807 ssl_version=client_protocol)
808 s.connect((HOST, server.port))
809 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000810 if connectionchatty:
811 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000812 sys.stdout.write(
813 " client: sending %s...\n" % (repr(arg)))
814 s.write(arg)
815 outdata = s.read()
816 if connectionchatty:
817 if test_support.verbose:
818 sys.stdout.write(" client: read %s\n" % repr(outdata))
819 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000820 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000821 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
822 % (outdata[:min(len(outdata),20)], len(outdata),
823 indata[:min(len(indata),20)].lower(), len(indata)))
824 s.write("over\n")
825 if connectionchatty:
826 if test_support.verbose:
827 sys.stdout.write(" client: closing connection.\n")
828 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000829 finally:
830 server.stop()
831 server.join()
832
Antoine Pitrou3945c862010-04-28 21:11:01 +0000833 def try_protocol_combo(server_protocol,
834 client_protocol,
835 expect_success,
836 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000837 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000838 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000839 certtype = {
840 ssl.CERT_NONE: "CERT_NONE",
841 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
842 ssl.CERT_REQUIRED: "CERT_REQUIRED",
843 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000844 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000845 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000846 sys.stdout.write(formatstr %
847 (ssl.get_protocol_name(client_protocol),
848 ssl.get_protocol_name(server_protocol),
849 certtype))
850 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000851 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
852 # will send an SSLv3 hello (rather than SSLv2) starting from
853 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000854 server_params_test(CERTFILE, server_protocol, certsreqs,
855 CERTFILE, CERTFILE, client_protocol,
856 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000857 # Protocol mismatch can result in either an SSLError, or a
858 # "Connection reset by peer" error.
859 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000860 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000861 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000862 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000863 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000864 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000865 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000866 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000867 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000868 "Client protocol %s succeeded with server protocol %s!"
869 % (ssl.get_protocol_name(client_protocol),
870 ssl.get_protocol_name(server_protocol)))
871
872
Bill Janssen934b16d2008-06-28 22:19:33 +0000873 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000874
Antoine Pitrou3945c862010-04-28 21:11:01 +0000875 def test_rude_shutdown(self):
876 """A brutal shutdown of an SSL server should raise an IOError
877 in the client when attempting handshake.
878 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000879 listener_ready = threading.Event()
880 listener_gone = threading.Event()
881
Antoine Pitrou150acda2010-04-27 08:40:51 +0000882 s = socket.socket()
883 port = test_support.bind_port(s, HOST)
884
885 # `listener` runs in a thread. It sits in an accept() until
886 # the main thread connects. Then it rudely closes the socket,
887 # and sets Event `listener_gone` to let the main thread know
888 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000889 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000890 s.listen(5)
891 listener_ready.set()
892 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000893 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000894 listener_gone.set()
895
896 def connector():
897 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000898 c = socket.socket()
899 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000900 listener_gone.wait()
901 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000902 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000903 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000904 pass
905 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000906 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000907
908 t = threading.Thread(target=listener)
909 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000910 try:
911 connector()
912 finally:
913 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000914
Antoine Pitroud75efd92010-08-04 17:38:33 +0000915 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000916 def test_echo(self):
917 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000918 if test_support.verbose:
919 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000920 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
921 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
922 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000923
Antoine Pitrou3945c862010-04-28 21:11:01 +0000924 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000925 if test_support.verbose:
926 sys.stdout.write("\n")
927 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000928 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000929 certreqs=ssl.CERT_NONE,
930 ssl_version=ssl.PROTOCOL_SSLv23,
931 cacerts=CERTFILE,
932 chatty=False)
933 flag = threading.Event()
934 server.start(flag)
935 # wait for it to start
936 flag.wait()
937 # try to connect
938 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000939 s = ssl.wrap_socket(socket.socket(),
940 certfile=CERTFILE,
941 ca_certs=CERTFILE,
942 cert_reqs=ssl.CERT_REQUIRED,
943 ssl_version=ssl.PROTOCOL_SSLv23)
944 s.connect((HOST, server.port))
945 cert = s.getpeercert()
946 self.assertTrue(cert, "Can't get peer certificate.")
947 cipher = s.cipher()
948 if test_support.verbose:
949 sys.stdout.write(pprint.pformat(cert) + '\n')
950 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
951 if 'subject' not in cert:
952 self.fail("No subject field in certificate: %s." %
953 pprint.pformat(cert))
954 if ((('organizationName', 'Python Software Foundation'),)
955 not in cert['subject']):
956 self.fail(
957 "Missing or invalid 'organizationName' field in certificate subject; "
958 "should be 'Python Software Foundation'.")
959 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000960 finally:
961 server.stop()
962 server.join()
963
Antoine Pitrou3945c862010-04-28 21:11:01 +0000964 def test_empty_cert(self):
965 """Connecting with an empty cert file"""
966 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
967 "nullcert.pem"))
968 def test_malformed_cert(self):
969 """Connecting with a badly formatted certificate (syntax error)"""
970 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
971 "badcert.pem"))
972 def test_nonexisting_cert(self):
973 """Connecting with a non-existing cert file"""
974 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
975 "wrongcert.pem"))
976 def test_malformed_key(self):
977 """Connecting with a badly formatted key (syntax error)"""
978 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
979 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000980
Antoine Pitroud75efd92010-08-04 17:38:33 +0000981 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000982 def test_protocol_sslv2(self):
983 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000984 if test_support.verbose:
985 sys.stdout.write("\n")
Antoine Pitrou6361ea22011-10-30 21:31:34 +0100986 if not hasattr(ssl, 'PROTOCOL_SSLv2'):
987 self.skipTest("PROTOCOL_SSLv2 needed")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000988 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
989 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
990 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
991 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
992 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
993 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000994
Antoine Pitroud75efd92010-08-04 17:38:33 +0000995 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000996 def test_protocol_sslv23(self):
997 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000998 if test_support.verbose:
999 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001000 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1001 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1002 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +00001003
Antoine Pitrou3945c862010-04-28 21:11:01 +00001004 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1005 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1006 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +00001007
Antoine Pitrou3945c862010-04-28 21:11:01 +00001008 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1009 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1010 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +00001011
Antoine Pitroud75efd92010-08-04 17:38:33 +00001012 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +00001013 def test_protocol_sslv3(self):
1014 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +00001015 if test_support.verbose:
1016 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001017 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1018 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1019 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001020 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1021 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001022 try_protocol_combo(ssl.PROTOCOL_SSLv3, 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_tlsv1(self):
1026 """Connecting to a TLSv1 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_TLSv1, ssl.PROTOCOL_TLSv1, True)
1030 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1031 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinnerb1241f92011-05-10 01:52:03 +02001032 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1033 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou3945c862010-04-28 21:11:01 +00001034 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Bill Janssen98d19da2007-09-10 21:51:02 +00001035
Antoine Pitrou3945c862010-04-28 21:11:01 +00001036 def test_starttls(self):
1037 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +00001038 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00001039
Trent Nelsone41b0062008-04-08 23:47:30 +00001040 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001041 ssl_version=ssl.PROTOCOL_TLSv1,
1042 starttls_server=True,
1043 chatty=True,
1044 connectionchatty=True)
1045 flag = threading.Event()
1046 server.start(flag)
1047 # wait for it to start
1048 flag.wait()
1049 # try to connect
1050 wrapped = False
1051 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001052 s = socket.socket()
1053 s.setblocking(1)
1054 s.connect((HOST, server.port))
1055 if test_support.verbose:
1056 sys.stdout.write("\n")
1057 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +00001058 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00001059 sys.stdout.write(
1060 " client: sending %s...\n" % repr(indata))
1061 if wrapped:
1062 conn.write(indata)
1063 outdata = conn.read()
1064 else:
1065 s.send(indata)
1066 outdata = s.recv(1024)
1067 if (indata == "STARTTLS" and
1068 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001069 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001070 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001071 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001072 " client: read %s from server, starting TLS...\n"
1073 % repr(outdata))
1074 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1075 wrapped = True
1076 elif (indata == "ENDTLS" and
1077 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001078 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001079 if test_support.verbose:
1080 sys.stdout.write(
1081 " client: read %s from server, ending TLS...\n"
1082 % repr(outdata))
1083 s = conn.unwrap()
1084 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001085 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001086 if test_support.verbose:
1087 sys.stdout.write(
1088 " client: read %s from server\n" % repr(outdata))
1089 if test_support.verbose:
1090 sys.stdout.write(" client: closing connection.\n")
1091 if wrapped:
1092 conn.write("over\n")
1093 else:
1094 s.send("over\n")
1095 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001096 finally:
1097 server.stop()
1098 server.join()
1099
Antoine Pitrou3945c862010-04-28 21:11:01 +00001100 def test_socketserver(self):
1101 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001102 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001103 flag = threading.Event()
1104 server.start(flag)
1105 # wait for it to start
1106 flag.wait()
1107 # try to connect
1108 try:
1109 if test_support.verbose:
1110 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001111 with open(CERTFILE, 'rb') as f:
1112 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001113 d2 = ''
1114 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001115 url = 'https://127.0.0.1:%d/%s' % (
1116 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001117 with test_support.check_py3k_warnings():
1118 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001119 dlen = f.info().getheader("content-length")
1120 if dlen and (int(dlen) > 0):
1121 d2 = f.read(int(dlen))
1122 if test_support.verbose:
1123 sys.stdout.write(
1124 " client: read %d bytes from remote server '%s'\n"
1125 % (len(d2), server))
1126 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001127 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001128 finally:
1129 server.stop()
1130 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001131
Antoine Pitrou3945c862010-04-28 21:11:01 +00001132 def test_wrapped_accept(self):
1133 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001134 if test_support.verbose:
1135 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001136 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1137 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1138 chatty=True, connectionchatty=True,
1139 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001140
Antoine Pitrou3945c862010-04-28 21:11:01 +00001141 def test_asyncore_server(self):
1142 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001143 indata = "TEST MESSAGE of mixed case\n"
1144
1145 if test_support.verbose:
1146 sys.stdout.write("\n")
1147 server = AsyncoreEchoServer(CERTFILE)
1148 flag = threading.Event()
1149 server.start(flag)
1150 # wait for it to start
1151 flag.wait()
1152 # try to connect
1153 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001154 s = ssl.wrap_socket(socket.socket())
1155 s.connect(('127.0.0.1', server.port))
1156 if test_support.verbose:
1157 sys.stdout.write(
1158 " client: sending %s...\n" % (repr(indata)))
1159 s.write(indata)
1160 outdata = s.read()
1161 if test_support.verbose:
1162 sys.stdout.write(" client: read %s\n" % repr(outdata))
1163 if outdata != indata.lower():
1164 self.fail(
1165 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1166 % (outdata[:min(len(outdata),20)], len(outdata),
1167 indata[:min(len(indata),20)].lower(), len(indata)))
1168 s.write("over\n")
1169 if test_support.verbose:
1170 sys.stdout.write(" client: closing connection.\n")
1171 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001172 finally:
1173 server.stop()
1174 # wait for server thread to end
1175 server.join()
1176
Antoine Pitrou3945c862010-04-28 21:11:01 +00001177 def test_recv_send(self):
1178 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001179 if test_support.verbose:
1180 sys.stdout.write("\n")
1181
1182 server = ThreadedEchoServer(CERTFILE,
1183 certreqs=ssl.CERT_NONE,
1184 ssl_version=ssl.PROTOCOL_TLSv1,
1185 cacerts=CERTFILE,
1186 chatty=True,
1187 connectionchatty=False)
1188 flag = threading.Event()
1189 server.start(flag)
1190 # wait for it to start
1191 flag.wait()
1192 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001193 s = ssl.wrap_socket(socket.socket(),
1194 server_side=False,
1195 certfile=CERTFILE,
1196 ca_certs=CERTFILE,
1197 cert_reqs=ssl.CERT_NONE,
1198 ssl_version=ssl.PROTOCOL_TLSv1)
1199 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001200 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001201 # helper methods for standardising recv* method signatures
1202 def _recv_into():
1203 b = bytearray("\0"*100)
1204 count = s.recv_into(b)
1205 return b[:count]
1206
1207 def _recvfrom_into():
1208 b = bytearray("\0"*100)
1209 count, addr = s.recvfrom_into(b)
1210 return b[:count]
1211
1212 # (name, method, whether to expect success, *args)
1213 send_methods = [
1214 ('send', s.send, True, []),
1215 ('sendto', s.sendto, False, ["some.address"]),
1216 ('sendall', s.sendall, True, []),
1217 ]
1218 recv_methods = [
1219 ('recv', s.recv, True, []),
1220 ('recvfrom', s.recvfrom, False, ["some.address"]),
1221 ('recv_into', _recv_into, True, []),
1222 ('recvfrom_into', _recvfrom_into, False, []),
1223 ]
1224 data_prefix = u"PREFIX_"
1225
1226 for meth_name, send_meth, expect_success, args in send_methods:
1227 indata = data_prefix + meth_name
1228 try:
1229 send_meth(indata.encode('ASCII', 'strict'), *args)
1230 outdata = s.read()
1231 outdata = outdata.decode('ASCII', 'strict')
1232 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001233 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001234 "While sending with <<%s>> bad data "
1235 "<<%r>> (%d) received; "
1236 "expected <<%r>> (%d)\n" % (
1237 meth_name, outdata[:20], len(outdata),
1238 indata[:20], len(indata)
1239 )
1240 )
1241 except ValueError as e:
1242 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001243 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001244 "Failed to send with method <<%s>>; "
1245 "expected to succeed.\n" % (meth_name,)
1246 )
1247 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001248 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001249 "Method <<%s>> failed with unexpected "
1250 "exception message: %s\n" % (
1251 meth_name, e
1252 )
1253 )
1254
1255 for meth_name, recv_meth, expect_success, args in recv_methods:
1256 indata = data_prefix + meth_name
1257 try:
1258 s.send(indata.encode('ASCII', 'strict'))
1259 outdata = recv_meth(*args)
1260 outdata = outdata.decode('ASCII', 'strict')
1261 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001262 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001263 "While receiving with <<%s>> bad data "
1264 "<<%r>> (%d) received; "
1265 "expected <<%r>> (%d)\n" % (
1266 meth_name, outdata[:20], len(outdata),
1267 indata[:20], len(indata)
1268 )
1269 )
1270 except ValueError as e:
1271 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001272 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001273 "Failed to receive with method <<%s>>; "
1274 "expected to succeed.\n" % (meth_name,)
1275 )
1276 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001277 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001278 "Method <<%s>> failed with unexpected "
1279 "exception message: %s\n" % (
1280 meth_name, e
1281 )
1282 )
1283 # consume data
1284 s.read()
1285
1286 s.write("over\n".encode("ASCII", "strict"))
1287 s.close()
1288 finally:
1289 server.stop()
1290 server.join()
1291
Antoine Pitroufc69af12010-04-24 20:04:58 +00001292 def test_handshake_timeout(self):
1293 # Issue #5103: SSL handshake must respect the socket timeout
1294 server = socket.socket(socket.AF_INET)
1295 host = "127.0.0.1"
1296 port = test_support.bind_port(server)
1297 started = threading.Event()
1298 finish = False
1299
1300 def serve():
1301 server.listen(5)
1302 started.set()
1303 conns = []
1304 while not finish:
1305 r, w, e = select.select([server], [], [], 0.1)
1306 if server in r:
1307 # Let the socket hang around rather than having
1308 # it closed by garbage collection.
1309 conns.append(server.accept()[0])
1310
1311 t = threading.Thread(target=serve)
1312 t.start()
1313 started.wait()
1314
1315 try:
1316 try:
1317 c = socket.socket(socket.AF_INET)
1318 c.settimeout(0.2)
1319 c.connect((host, port))
1320 # Will attempt handshake and time out
1321 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1322 ssl.wrap_socket, c)
1323 finally:
1324 c.close()
1325 try:
1326 c = socket.socket(socket.AF_INET)
1327 c.settimeout(0.2)
1328 c = ssl.wrap_socket(c)
1329 # Will attempt handshake and time out
1330 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1331 c.connect, (host, port))
1332 finally:
1333 c.close()
1334 finally:
1335 finish = True
1336 t.join()
1337 server.close()
1338
Bill Janssen61c001a2008-09-08 16:37:24 +00001339
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001340def test_main(verbose=False):
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001341 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001342 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001343 "keycert.pem")
1344 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1345 os.path.dirname(__file__) or os.curdir,
1346 "https_svn_python_org_root.pem")
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001347 NOKIACERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1348 "nokia.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001349
1350 if (not os.path.exists(CERTFILE) or
Antoine Pitrouf06eb462011-10-01 19:30:58 +02001351 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
1352 not os.path.exists(NOKIACERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001353 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001354
Antoine Pitroude30f702010-09-14 12:54:08 +00001355 tests = [BasicTests, BasicSocketTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001356
Bill Janssen296a59d2007-09-16 22:06:00 +00001357 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001358 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001359
Bill Janssen98d19da2007-09-10 21:51:02 +00001360 if _have_threads:
1361 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001362 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001363 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001364
Antoine Pitrou3945c862010-04-28 21:11:01 +00001365 try:
1366 test_support.run_unittest(*tests)
1367 finally:
1368 if _have_threads:
1369 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001370
1371if __name__ == "__main__":
1372 test_main()