blob: 7c13db42cf7258fc4dcb854cece033e53222defe [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
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000017
Bill Janssen296a59d2007-09-16 22:06:00 +000018from BaseHTTPServer import HTTPServer
19from SimpleHTTPServer import SimpleHTTPRequestHandler
20
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000021# Optionally test SSL support, if we have it in the tested platform
22skip_expected = False
23try:
24 import ssl
25except ImportError:
26 skip_expected = True
27
Trent Nelsone41b0062008-04-08 23:47:30 +000028HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000029CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000030SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000031
Neal Norwitz3e533c22007-08-27 01:03:18 +000032def handle_error(prefix):
33 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000034 if test_support.verbose:
35 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000036
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000037
38class BasicTests(unittest.TestCase):
39
Bill Jansseneb257ac2008-09-29 18:56:38 +000040 def testSimpleSSLwrap(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000041 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000042 try:
43 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
44 except IOError, e:
45 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
46 pass
47 else:
48 raise
49 try:
50 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
51 except IOError, e:
52 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
53 pass
54 else:
55 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000056
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000057 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000058 if not test_support.is_resource_enabled('network'):
59 return
Bill Janssen296a59d2007-09-16 22:06:00 +000060 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
61 cert_reqs=ssl.CERT_NONE)
62 s.connect(("svn.python.org", 443))
63 c = s.getpeercert()
64 if c:
Antoine Pitroudb187842010-04-27 10:32:58 +000065 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +000066 s.close()
67
68 # this should fail because we have no verification certs
69 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
70 cert_reqs=ssl.CERT_REQUIRED)
71 try:
72 s.connect(("svn.python.org", 443))
73 except ssl.SSLError:
74 pass
75 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000076 s.close()
77
Bill Janssen98d19da2007-09-10 21:51:02 +000078 def testCrucialConstants(self):
79 ssl.PROTOCOL_SSLv2
80 ssl.PROTOCOL_SSLv23
81 ssl.PROTOCOL_SSLv3
82 ssl.PROTOCOL_TLSv1
83 ssl.CERT_NONE
84 ssl.CERT_OPTIONAL
85 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000086
Bill Janssen98d19da2007-09-10 21:51:02 +000087 def testRAND(self):
88 v = ssl.RAND_status()
89 if test_support.verbose:
90 sys.stdout.write("\n RAND_status is %d (%s)\n"
91 % (v, (v and "sufficient randomness") or
92 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000093 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000094 ssl.RAND_egd(1)
95 except TypeError:
96 pass
Guido van Rossume4729332007-08-26 19:35:09 +000097 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000098 print "didn't raise TypeError"
99 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000100
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 def testParseCert(self):
102 # note that this uses an 'unofficial' function in _ssl.c,
103 # provided solely for this test, to exercise the certificate
104 # parsing code
105 p = ssl._ssl._test_decode_cert(CERTFILE, False)
106 if test_support.verbose:
107 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000108
Bill Janssen296a59d2007-09-16 22:06:00 +0000109 def testDERtoPEM(self):
110
111 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
112 d1 = ssl.PEM_cert_to_DER_cert(pem)
113 p2 = ssl.DER_cert_to_PEM_cert(d1)
114 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000115 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000116
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000117 def test_openssl_version(self):
118 n = ssl.OPENSSL_VERSION_NUMBER
119 t = ssl.OPENSSL_VERSION_INFO
120 s = ssl.OPENSSL_VERSION
121 self.assertIsInstance(n, (int, long))
122 self.assertIsInstance(t, tuple)
123 self.assertIsInstance(s, str)
124 # Some sanity checks follow
125 # >= 0.9
126 self.assertGreaterEqual(n, 0x900000)
127 # < 2.0
128 self.assertLess(n, 0x20000000)
129 major, minor, fix, patch, status = t
130 self.assertGreaterEqual(major, 0)
131 self.assertLess(major, 2)
132 self.assertGreaterEqual(minor, 0)
133 self.assertLess(minor, 256)
134 self.assertGreaterEqual(fix, 0)
135 self.assertLess(fix, 256)
136 self.assertGreaterEqual(patch, 0)
137 self.assertLessEqual(patch, 26)
138 self.assertGreaterEqual(status, 0)
139 self.assertLessEqual(status, 15)
140 # Version string as returned by OpenSSL, the format might change
141 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
142 (s, t))
143
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000144 def test_ciphers(self):
145 if not test_support.is_resource_enabled('network'):
146 return
147 remote = ("svn.python.org", 443)
148 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
149 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
150 s.connect(remote)
151 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
152 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
153 s.connect(remote)
154 # Error checking occurs when connecting, because the SSL context
155 # isn't created before.
156 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
157 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
158 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
159 s.connect(remote)
160
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000161 @test_support.cpython_only
162 def test_refcycle(self):
163 # Issue #7943: an SSL object doesn't create reference cycles with
164 # itself.
165 s = socket.socket(socket.AF_INET)
166 ss = ssl.wrap_socket(s)
167 wr = weakref.ref(ss)
168 del ss
169 self.assertEqual(wr(), None)
170
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000171
Bill Janssen934b16d2008-06-28 22:19:33 +0000172class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000173
174 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000175 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
176 cert_reqs=ssl.CERT_NONE)
177 s.connect(("svn.python.org", 443))
178 c = s.getpeercert()
179 if c:
Antoine Pitroudb187842010-04-27 10:32:58 +0000180 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000181 s.close()
182
183 # this should fail because we have no verification certs
184 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
185 cert_reqs=ssl.CERT_REQUIRED)
186 try:
187 s.connect(("svn.python.org", 443))
188 except ssl.SSLError:
189 pass
190 finally:
191 s.close()
192
193 # this should succeed because we specify the root cert
194 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
195 cert_reqs=ssl.CERT_REQUIRED,
196 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
197 try:
198 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000199 finally:
200 s.close()
201
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000202 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
203 def test_makefile_close(self):
204 # Issue #5238: creating a file-like object with makefile() shouldn't
205 # delay closing the underlying "real socket" (here tested with its
206 # file descriptor, hence skipping the test under Windows).
207 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
208 ss.connect(("svn.python.org", 443))
209 fd = ss.fileno()
210 f = ss.makefile()
211 f.close()
212 # The fd is still open
213 os.read(fd, 0)
214 # Closing the SSL socket should close the fd too
215 ss.close()
216 gc.collect()
217 with self.assertRaises(OSError) as e:
218 os.read(fd, 0)
219 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000220
221 def testNonBlockingHandshake(self):
222 s = socket.socket(socket.AF_INET)
223 s.connect(("svn.python.org", 443))
224 s.setblocking(False)
225 s = ssl.wrap_socket(s,
226 cert_reqs=ssl.CERT_NONE,
227 do_handshake_on_connect=False)
228 count = 0
229 while True:
230 try:
231 count += 1
232 s.do_handshake()
233 break
234 except ssl.SSLError, err:
235 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
236 select.select([s], [], [])
237 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
238 select.select([], [s], [])
239 else:
240 raise
241 s.close()
242 if test_support.verbose:
243 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
244
Bill Janssen296a59d2007-09-16 22:06:00 +0000245 def testFetchServerCert(self):
246
247 pem = ssl.get_server_certificate(("svn.python.org", 443))
248 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000249 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000250
251 try:
252 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
253 except ssl.SSLError:
254 #should fail
255 pass
256 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000257 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000258
259 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
260 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000261 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000262 if test_support.verbose:
263 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
264
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000265 def test_algorithms(self):
266 # Issue #8484: all algorithms should be available when verifying a
267 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000268 # SHA256 was added in OpenSSL 0.9.8
269 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
270 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000271 # NOTE: https://sha256.tbs-internet.com is another possible test host
272 remote = ("sha2.hboeck.de", 443)
273 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
274 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
275 cert_reqs=ssl.CERT_REQUIRED,
276 ca_certs=sha256_cert,)
277 with test_support.transient_internet():
278 try:
279 s.connect(remote)
280 if test_support.verbose:
281 sys.stdout.write("\nCipher with %r is %r\n" %
282 (remote, s.cipher()))
283 sys.stdout.write("Certificate is:\n%s\n" %
284 pprint.pformat(s.getpeercert()))
285 finally:
286 s.close()
287
Bill Janssen296a59d2007-09-16 22:06:00 +0000288
Bill Janssen98d19da2007-09-10 21:51:02 +0000289try:
290 import threading
291except ImportError:
292 _have_threads = False
293else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000294
Bill Janssen98d19da2007-09-10 21:51:02 +0000295 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000296
Bill Janssen98d19da2007-09-10 21:51:02 +0000297 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000298
Bill Janssen98d19da2007-09-10 21:51:02 +0000299 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000300
Bill Janssen98d19da2007-09-10 21:51:02 +0000301 """A mildly complicated class, because we want it to work both
302 with and without the SSL wrapper around the socket connection, so
303 that we can test the STARTTLS functionality."""
304
305 def __init__(self, server, connsock):
306 self.server = server
307 self.running = False
308 self.sock = connsock
309 self.sock.setblocking(1)
310 self.sslconn = None
311 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000312 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000313
Bill Janssen934b16d2008-06-28 22:19:33 +0000314 def show_conn_details(self):
315 if self.server.certreqs == ssl.CERT_REQUIRED:
316 cert = self.sslconn.getpeercert()
317 if test_support.verbose and self.server.chatty:
318 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
319 cert_binary = self.sslconn.getpeercert(True)
320 if test_support.verbose and self.server.chatty:
321 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
322 cipher = self.sslconn.cipher()
323 if test_support.verbose and self.server.chatty:
324 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
325
Bill Janssen98d19da2007-09-10 21:51:02 +0000326 def wrap_conn (self):
327 try:
328 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
329 certfile=self.server.certificate,
330 ssl_version=self.server.protocol,
331 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000332 cert_reqs=self.server.certreqs,
333 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000334 except ssl.SSLError:
335 # XXX Various errors can have happened here, for example
336 # a mismatching protocol version, an invalid certificate,
337 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000338 if self.server.chatty:
339 handle_error("\n server: bad connection attempt from " +
340 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000341 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000342 self.running = False
343 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000344 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000345 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000346 return True
347
348 def read(self):
349 if self.sslconn:
350 return self.sslconn.read()
351 else:
352 return self.sock.recv(1024)
353
354 def write(self, bytes):
355 if self.sslconn:
356 return self.sslconn.write(bytes)
357 else:
358 return self.sock.send(bytes)
359
360 def close(self):
361 if self.sslconn:
362 self.sslconn.close()
363 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000364 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000365
366 def run (self):
367 self.running = True
368 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000369 if isinstance(self.sock, ssl.SSLSocket):
370 self.sslconn = self.sock
371 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000372 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000373 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000374 while self.running:
375 try:
376 msg = self.read()
377 if not msg:
378 # eof, so quit this handler
379 self.running = False
380 self.close()
381 elif msg.strip() == 'over':
382 if test_support.verbose and self.server.connectionchatty:
383 sys.stdout.write(" server: client closed connection\n")
384 self.close()
385 return
386 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
387 if test_support.verbose and self.server.connectionchatty:
388 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
389 self.write("OK\n")
390 if not self.wrap_conn():
391 return
Bill Janssen39295c22008-08-12 16:31:21 +0000392 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
393 if test_support.verbose and self.server.connectionchatty:
394 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
395 self.write("OK\n")
396 self.sslconn.unwrap()
397 self.sslconn = None
398 if test_support.verbose and self.server.connectionchatty:
399 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000400 else:
401 if (test_support.verbose and
402 self.server.connectionchatty):
403 ctype = (self.sslconn and "encrypted") or "unencrypted"
404 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
405 % (repr(msg), ctype, repr(msg.lower()), ctype))
406 self.write(msg.lower())
407 except ssl.SSLError:
408 if self.server.chatty:
409 handle_error("Test server failure:\n")
410 self.close()
411 self.running = False
412 # normally, we'd just stop here, but for the test
413 # harness, we want to stop the server
414 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000415
Trent Nelsone41b0062008-04-08 23:47:30 +0000416 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000417 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000418 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000419 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000420
Bill Janssen98d19da2007-09-10 21:51:02 +0000421 if ssl_version is None:
422 ssl_version = ssl.PROTOCOL_TLSv1
423 if certreqs is None:
424 certreqs = ssl.CERT_NONE
425 self.certificate = certificate
426 self.protocol = ssl_version
427 self.certreqs = certreqs
428 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000429 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000430 self.chatty = chatty
431 self.connectionchatty = connectionchatty
432 self.starttls_server = starttls_server
433 self.sock = socket.socket()
434 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000435 if wrap_accepting_socket:
436 self.sock = ssl.wrap_socket(self.sock, server_side=True,
437 certfile=self.certificate,
438 cert_reqs = self.certreqs,
439 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000440 ssl_version = self.protocol,
441 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000442 if test_support.verbose and self.chatty:
443 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
444 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000445 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000446 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000447 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000448
449 def start (self, flag=None):
450 self.flag = flag
451 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000452
453 def run (self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000454 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000455 self.sock.listen(5)
456 self.active = True
457 if self.flag:
458 # signal an event
459 self.flag.set()
460 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000461 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000462 newconn, connaddr = self.sock.accept()
463 if test_support.verbose and self.chatty:
464 sys.stdout.write(' server: new connection from '
465 + str(connaddr) + '\n')
466 handler = self.ConnectionHandler(self, newconn)
467 handler.start()
468 except socket.timeout:
469 pass
470 except KeyboardInterrupt:
471 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000472 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000473
Bill Janssen98d19da2007-09-10 21:51:02 +0000474 def stop (self):
475 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000476
Bill Janssen934b16d2008-06-28 22:19:33 +0000477 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000478
Bill Janssen934b16d2008-06-28 22:19:33 +0000479 class EchoServer (asyncore.dispatcher):
480
481 class ConnectionHandler (asyncore.dispatcher_with_send):
482
483 def __init__(self, conn, certfile):
484 asyncore.dispatcher_with_send.__init__(self, conn)
485 self.socket = ssl.wrap_socket(conn, server_side=True,
486 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000487 do_handshake_on_connect=False)
488 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000489
490 def readable(self):
491 if isinstance(self.socket, ssl.SSLSocket):
492 while self.socket.pending() > 0:
493 self.handle_read_event()
494 return True
495
Antoine Pitroufc69af12010-04-24 20:04:58 +0000496 def _do_ssl_handshake(self):
497 try:
498 self.socket.do_handshake()
499 except ssl.SSLError, err:
500 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
501 ssl.SSL_ERROR_WANT_WRITE):
502 return
503 elif err.args[0] == ssl.SSL_ERROR_EOF:
504 return self.handle_close()
505 raise
506 except socket.error, err:
507 if err.args[0] == errno.ECONNABORTED:
508 return self.handle_close()
509 else:
510 self._ssl_accepting = False
511
Bill Janssen934b16d2008-06-28 22:19:33 +0000512 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000513 if self._ssl_accepting:
514 self._do_ssl_handshake()
515 else:
516 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000517 if data and data.strip() != 'over':
518 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000519
520 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000521 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000522 if test_support.verbose:
523 sys.stdout.write(" server: closed connection %s\n" % self.socket)
524
525 def handle_error(self):
526 raise
527
528 def __init__(self, certfile):
529 self.certfile = certfile
530 asyncore.dispatcher.__init__(self)
531 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
532 self.port = test_support.bind_port(self.socket)
533 self.listen(5)
534
535 def handle_accept(self):
536 sock_obj, addr = self.accept()
537 if test_support.verbose:
538 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
539 self.ConnectionHandler(sock_obj, self.certfile)
540
541 def handle_error(self):
542 raise
543
544 def __init__(self, certfile):
545 self.flag = None
546 self.active = False
547 self.server = self.EchoServer(certfile)
548 self.port = self.server.port
549 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000550 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000551
552 def __str__(self):
553 return "<%s %s>" % (self.__class__.__name__, self.server)
554
555 def start (self, flag=None):
556 self.flag = flag
557 threading.Thread.start(self)
558
559 def run (self):
560 self.active = True
561 if self.flag:
562 self.flag.set()
563 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000564 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000565
566 def stop (self):
567 self.active = False
568 self.server.close()
569
570 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000571
572 class HTTPSServer(HTTPServer):
573
574 def __init__(self, server_address, RequestHandlerClass, certfile):
575
576 HTTPServer.__init__(self, server_address, RequestHandlerClass)
577 # we assume the certfile contains both private key and certificate
578 self.certfile = certfile
579 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000580 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000581 self.allow_reuse_address = True
582
Bill Janssen934b16d2008-06-28 22:19:33 +0000583 def __str__(self):
584 return ('<%s %s:%s>' %
585 (self.__class__.__name__,
586 self.server_name,
587 self.server_port))
588
Bill Janssen296a59d2007-09-16 22:06:00 +0000589 def get_request (self):
590 # override this to wrap socket with SSL
591 sock, addr = self.socket.accept()
592 sslconn = ssl.wrap_socket(sock, server_side=True,
593 certfile=self.certfile)
594 return sslconn, addr
595
Bill Janssen296a59d2007-09-16 22:06:00 +0000596 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
597
598 # need to override translate_path to get a known root,
599 # instead of using os.curdir, since the test could be
600 # run from anywhere
601
602 server_version = "TestHTTPS/1.0"
603
604 root = None
605
606 def translate_path(self, path):
607 """Translate a /-separated PATH to the local filename syntax.
608
609 Components that mean special things to the local file system
610 (e.g. drive or directory names) are ignored. (XXX They should
611 probably be diagnosed.)
612
613 """
614 # abandon query parameters
615 path = urlparse.urlparse(path)[2]
616 path = os.path.normpath(urllib.unquote(path))
617 words = path.split('/')
618 words = filter(None, words)
619 path = self.root
620 for word in words:
621 drive, word = os.path.splitdrive(word)
622 head, word = os.path.split(word)
623 if word in self.root: continue
624 path = os.path.join(path, word)
625 return path
626
627 def log_message(self, format, *args):
628
629 # we override this to suppress logging unless "verbose"
630
631 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000632 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
633 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000634 self.server.server_port,
635 self.request.cipher(),
636 self.log_date_time_string(),
637 format%args))
638
639
Trent Nelsone41b0062008-04-08 23:47:30 +0000640 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000641 self.flag = None
642 self.active = False
643 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
644 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000645 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
646 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000647 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000648 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000649
650 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000651 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000652
653 def start (self, flag=None):
654 self.flag = flag
655 threading.Thread.start(self)
656
657 def run (self):
658 self.active = True
659 if self.flag:
660 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000661 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000662 self.active = False
663
664 def stop (self):
665 self.active = False
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000666 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000667
668
Bill Janssen98d19da2007-09-10 21:51:02 +0000669 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000670 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000671 certreqs=ssl.CERT_REQUIRED,
672 cacerts=CERTFILE, chatty=False)
673 flag = threading.Event()
674 server.start(flag)
675 # wait for it to start
676 flag.wait()
677 # try to connect
678 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000679 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000680 s = ssl.wrap_socket(socket.socket(),
681 certfile=certfile,
682 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000683 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000684 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000685 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000686 sys.stdout.write("\nSSLError is %s\n" % x[1])
687 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000688 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000689 finally:
690 server.stop()
691 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000692
Bill Janssen98d19da2007-09-10 21:51:02 +0000693 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
694 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000695 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000696 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000697
Trent Nelsone41b0062008-04-08 23:47:30 +0000698 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000699 certreqs=certreqs,
700 ssl_version=protocol,
701 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000702 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000703 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000704 connectionchatty=connectionchatty,
705 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000706 flag = threading.Event()
707 server.start(flag)
708 # wait for it to start
709 flag.wait()
710 # try to connect
711 if client_protocol is None:
712 client_protocol = protocol
713 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000714 s = ssl.wrap_socket(socket.socket(),
715 certfile=client_certfile,
716 ca_certs=cacertsfile,
717 ciphers=ciphers,
718 cert_reqs=certreqs,
719 ssl_version=client_protocol)
720 s.connect((HOST, server.port))
721 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000722 if connectionchatty:
723 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000724 sys.stdout.write(
725 " client: sending %s...\n" % (repr(arg)))
726 s.write(arg)
727 outdata = s.read()
728 if connectionchatty:
729 if test_support.verbose:
730 sys.stdout.write(" client: read %s\n" % repr(outdata))
731 if outdata != indata.lower():
732 self.fail(
733 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
734 % (outdata[:min(len(outdata),20)], len(outdata),
735 indata[:min(len(indata),20)].lower(), len(indata)))
736 s.write("over\n")
737 if connectionchatty:
738 if test_support.verbose:
739 sys.stdout.write(" client: closing connection.\n")
740 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000741 finally:
742 server.stop()
743 server.join()
744
745 def tryProtocolCombo (server_protocol,
746 client_protocol,
747 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000748 certsreqs=None):
749
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000750 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000751 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000752
753 if certsreqs == ssl.CERT_NONE:
754 certtype = "CERT_NONE"
755 elif certsreqs == ssl.CERT_OPTIONAL:
756 certtype = "CERT_OPTIONAL"
757 elif certsreqs == ssl.CERT_REQUIRED:
758 certtype = "CERT_REQUIRED"
759 if test_support.verbose:
760 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
761 sys.stdout.write(formatstr %
762 (ssl.get_protocol_name(client_protocol),
763 ssl.get_protocol_name(server_protocol),
764 certtype))
765 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000766 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
767 # will send an SSLv3 hello (rather than SSLv2) starting from
768 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000769 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000770 CERTFILE, CERTFILE, client_protocol,
771 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000772 # Protocol mismatch can result in either an SSLError, or a
773 # "Connection reset by peer" error.
774 except ssl.SSLError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000775 if expectedToWork:
776 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000777 except socket.error as e:
778 if expectedToWork or e.errno != errno.ECONNRESET:
779 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000780 else:
781 if not expectedToWork:
Antoine Pitroudb187842010-04-27 10:32:58 +0000782 self.fail(
Bill Janssen98d19da2007-09-10 21:51:02 +0000783 "Client protocol %s succeeded with server protocol %s!"
784 % (ssl.get_protocol_name(client_protocol),
785 ssl.get_protocol_name(server_protocol)))
786
787
Bill Janssen934b16d2008-06-28 22:19:33 +0000788 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000789
790 def testRudeShutdown(self):
791
792 listener_ready = threading.Event()
793 listener_gone = threading.Event()
794
Antoine Pitrou150acda2010-04-27 08:40:51 +0000795 s = socket.socket()
796 port = test_support.bind_port(s, HOST)
797
798 # `listener` runs in a thread. It sits in an accept() until
799 # the main thread connects. Then it rudely closes the socket,
800 # and sets Event `listener_gone` to let the main thread know
801 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000802 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000803 s.listen(5)
804 listener_ready.set()
805 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000806 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000807 listener_gone.set()
808
809 def connector():
810 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000811 c = socket.socket()
812 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000813 listener_gone.wait()
814 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000815 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000816 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000817 pass
818 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000819 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000820
821 t = threading.Thread(target=listener)
822 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000823 try:
824 connector()
825 finally:
826 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000827
828 def testEcho (self):
829
830 if test_support.verbose:
831 sys.stdout.write("\n")
832 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
833 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
834 chatty=True, connectionchatty=True)
835
836 def testReadCert(self):
837
838 if test_support.verbose:
839 sys.stdout.write("\n")
840 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000841 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000842 certreqs=ssl.CERT_NONE,
843 ssl_version=ssl.PROTOCOL_SSLv23,
844 cacerts=CERTFILE,
845 chatty=False)
846 flag = threading.Event()
847 server.start(flag)
848 # wait for it to start
849 flag.wait()
850 # try to connect
851 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000852 s = ssl.wrap_socket(socket.socket(),
853 certfile=CERTFILE,
854 ca_certs=CERTFILE,
855 cert_reqs=ssl.CERT_REQUIRED,
856 ssl_version=ssl.PROTOCOL_SSLv23)
857 s.connect((HOST, server.port))
858 cert = s.getpeercert()
859 self.assertTrue(cert, "Can't get peer certificate.")
860 cipher = s.cipher()
861 if test_support.verbose:
862 sys.stdout.write(pprint.pformat(cert) + '\n')
863 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
864 if 'subject' not in cert:
865 self.fail("No subject field in certificate: %s." %
866 pprint.pformat(cert))
867 if ((('organizationName', 'Python Software Foundation'),)
868 not in cert['subject']):
869 self.fail(
870 "Missing or invalid 'organizationName' field in certificate subject; "
871 "should be 'Python Software Foundation'.")
872 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000873 finally:
874 server.stop()
875 server.join()
876
877 def testNULLcert(self):
878 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
879 "nullcert.pem"))
880 def testMalformedCert(self):
881 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
882 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000883 def testWrongCert(self):
884 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
885 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000886 def testMalformedKey(self):
887 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
888 "badkey.pem"))
889
890 def testProtocolSSL2(self):
891 if test_support.verbose:
892 sys.stdout.write("\n")
893 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
894 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
895 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
896 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
897 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
898 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
899
900 def testProtocolSSL23(self):
901 if test_support.verbose:
902 sys.stdout.write("\n")
903 try:
904 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroudb187842010-04-27 10:32:58 +0000905 except (SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000906 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
907 if test_support.verbose:
908 sys.stdout.write(
909 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
910 % str(x))
911 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
912 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
913 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
914
915 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
916 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
917 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
918
919 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
920 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
921 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
922
923 def testProtocolSSL3(self):
924 if test_support.verbose:
925 sys.stdout.write("\n")
926 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
927 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
928 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
929 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
930 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
931 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
932
933 def testProtocolTLS1(self):
934 if test_support.verbose:
935 sys.stdout.write("\n")
936 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
937 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
938 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
939 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
940 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
941 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
942
943 def testSTARTTLS (self):
944
Bill Janssen39295c22008-08-12 16:31:21 +0000945 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000946
Trent Nelsone41b0062008-04-08 23:47:30 +0000947 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000948 ssl_version=ssl.PROTOCOL_TLSv1,
949 starttls_server=True,
950 chatty=True,
951 connectionchatty=True)
952 flag = threading.Event()
953 server.start(flag)
954 # wait for it to start
955 flag.wait()
956 # try to connect
957 wrapped = False
958 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000959 s = socket.socket()
960 s.setblocking(1)
961 s.connect((HOST, server.port))
962 if test_support.verbose:
963 sys.stdout.write("\n")
964 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000965 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000966 sys.stdout.write(
967 " client: sending %s...\n" % repr(indata))
968 if wrapped:
969 conn.write(indata)
970 outdata = conn.read()
971 else:
972 s.send(indata)
973 outdata = s.recv(1024)
974 if (indata == "STARTTLS" and
975 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000976 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000977 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +0000978 " client: read %s from server, starting TLS...\n"
979 % repr(outdata))
980 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
981 wrapped = True
982 elif (indata == "ENDTLS" and
983 outdata.strip().lower().startswith("ok")):
984 if test_support.verbose:
985 sys.stdout.write(
986 " client: read %s from server, ending TLS...\n"
987 % repr(outdata))
988 s = conn.unwrap()
989 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000990 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000991 if test_support.verbose:
992 sys.stdout.write(
993 " client: read %s from server\n" % repr(outdata))
994 if test_support.verbose:
995 sys.stdout.write(" client: closing connection.\n")
996 if wrapped:
997 conn.write("over\n")
998 else:
999 s.send("over\n")
1000 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001001 finally:
1002 server.stop()
1003 server.join()
1004
Bill Janssen934b16d2008-06-28 22:19:33 +00001005 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001006
Bill Janssen934b16d2008-06-28 22:19:33 +00001007 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001008 flag = threading.Event()
1009 server.start(flag)
1010 # wait for it to start
1011 flag.wait()
1012 # try to connect
1013 try:
1014 if test_support.verbose:
1015 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001016 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001017 d2 = ''
1018 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001019 url = 'https://127.0.0.1:%d/%s' % (
1020 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001021 with test_support.check_py3k_warnings():
1022 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001023 dlen = f.info().getheader("content-length")
1024 if dlen and (int(dlen) > 0):
1025 d2 = f.read(int(dlen))
1026 if test_support.verbose:
1027 sys.stdout.write(
1028 " client: read %d bytes from remote server '%s'\n"
1029 % (len(d2), server))
1030 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001031 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001032 finally:
1033 server.stop()
1034 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001035
Bill Janssen934b16d2008-06-28 22:19:33 +00001036 def testWrappedAccept (self):
1037
1038 if test_support.verbose:
1039 sys.stdout.write("\n")
1040 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1041 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1042 chatty=True, connectionchatty=True,
1043 wrap_accepting_socket=True)
1044
1045
1046 def testAsyncoreServer (self):
1047
1048 indata = "TEST MESSAGE of mixed case\n"
1049
1050 if test_support.verbose:
1051 sys.stdout.write("\n")
1052 server = AsyncoreEchoServer(CERTFILE)
1053 flag = threading.Event()
1054 server.start(flag)
1055 # wait for it to start
1056 flag.wait()
1057 # try to connect
1058 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001059 s = ssl.wrap_socket(socket.socket())
1060 s.connect(('127.0.0.1', server.port))
1061 if test_support.verbose:
1062 sys.stdout.write(
1063 " client: sending %s...\n" % (repr(indata)))
1064 s.write(indata)
1065 outdata = s.read()
1066 if test_support.verbose:
1067 sys.stdout.write(" client: read %s\n" % repr(outdata))
1068 if outdata != indata.lower():
1069 self.fail(
1070 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1071 % (outdata[:min(len(outdata),20)], len(outdata),
1072 indata[:min(len(indata),20)].lower(), len(indata)))
1073 s.write("over\n")
1074 if test_support.verbose:
1075 sys.stdout.write(" client: closing connection.\n")
1076 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001077 finally:
1078 server.stop()
1079 # wait for server thread to end
1080 server.join()
1081
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001082
Bill Janssen61c001a2008-09-08 16:37:24 +00001083 def testAllRecvAndSendMethods(self):
1084
1085 if test_support.verbose:
1086 sys.stdout.write("\n")
1087
1088 server = ThreadedEchoServer(CERTFILE,
1089 certreqs=ssl.CERT_NONE,
1090 ssl_version=ssl.PROTOCOL_TLSv1,
1091 cacerts=CERTFILE,
1092 chatty=True,
1093 connectionchatty=False)
1094 flag = threading.Event()
1095 server.start(flag)
1096 # wait for it to start
1097 flag.wait()
1098 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001099 s = ssl.wrap_socket(socket.socket(),
1100 server_side=False,
1101 certfile=CERTFILE,
1102 ca_certs=CERTFILE,
1103 cert_reqs=ssl.CERT_NONE,
1104 ssl_version=ssl.PROTOCOL_TLSv1)
1105 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001106 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001107 # helper methods for standardising recv* method signatures
1108 def _recv_into():
1109 b = bytearray("\0"*100)
1110 count = s.recv_into(b)
1111 return b[:count]
1112
1113 def _recvfrom_into():
1114 b = bytearray("\0"*100)
1115 count, addr = s.recvfrom_into(b)
1116 return b[:count]
1117
1118 # (name, method, whether to expect success, *args)
1119 send_methods = [
1120 ('send', s.send, True, []),
1121 ('sendto', s.sendto, False, ["some.address"]),
1122 ('sendall', s.sendall, True, []),
1123 ]
1124 recv_methods = [
1125 ('recv', s.recv, True, []),
1126 ('recvfrom', s.recvfrom, False, ["some.address"]),
1127 ('recv_into', _recv_into, True, []),
1128 ('recvfrom_into', _recvfrom_into, False, []),
1129 ]
1130 data_prefix = u"PREFIX_"
1131
1132 for meth_name, send_meth, expect_success, args in send_methods:
1133 indata = data_prefix + meth_name
1134 try:
1135 send_meth(indata.encode('ASCII', 'strict'), *args)
1136 outdata = s.read()
1137 outdata = outdata.decode('ASCII', 'strict')
1138 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001139 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001140 "While sending with <<%s>> bad data "
1141 "<<%r>> (%d) received; "
1142 "expected <<%r>> (%d)\n" % (
1143 meth_name, outdata[:20], len(outdata),
1144 indata[:20], len(indata)
1145 )
1146 )
1147 except ValueError as e:
1148 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001149 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001150 "Failed to send with method <<%s>>; "
1151 "expected to succeed.\n" % (meth_name,)
1152 )
1153 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001154 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001155 "Method <<%s>> failed with unexpected "
1156 "exception message: %s\n" % (
1157 meth_name, e
1158 )
1159 )
1160
1161 for meth_name, recv_meth, expect_success, args in recv_methods:
1162 indata = data_prefix + meth_name
1163 try:
1164 s.send(indata.encode('ASCII', 'strict'))
1165 outdata = recv_meth(*args)
1166 outdata = outdata.decode('ASCII', 'strict')
1167 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001168 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001169 "While receiving with <<%s>> bad data "
1170 "<<%r>> (%d) received; "
1171 "expected <<%r>> (%d)\n" % (
1172 meth_name, outdata[:20], len(outdata),
1173 indata[:20], len(indata)
1174 )
1175 )
1176 except ValueError as e:
1177 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001178 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001179 "Failed to receive with method <<%s>>; "
1180 "expected to succeed.\n" % (meth_name,)
1181 )
1182 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001183 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001184 "Method <<%s>> failed with unexpected "
1185 "exception message: %s\n" % (
1186 meth_name, e
1187 )
1188 )
1189 # consume data
1190 s.read()
1191
1192 s.write("over\n".encode("ASCII", "strict"))
1193 s.close()
1194 finally:
1195 server.stop()
1196 server.join()
1197
Antoine Pitroufc69af12010-04-24 20:04:58 +00001198 def test_handshake_timeout(self):
1199 # Issue #5103: SSL handshake must respect the socket timeout
1200 server = socket.socket(socket.AF_INET)
1201 host = "127.0.0.1"
1202 port = test_support.bind_port(server)
1203 started = threading.Event()
1204 finish = False
1205
1206 def serve():
1207 server.listen(5)
1208 started.set()
1209 conns = []
1210 while not finish:
1211 r, w, e = select.select([server], [], [], 0.1)
1212 if server in r:
1213 # Let the socket hang around rather than having
1214 # it closed by garbage collection.
1215 conns.append(server.accept()[0])
1216
1217 t = threading.Thread(target=serve)
1218 t.start()
1219 started.wait()
1220
1221 try:
1222 try:
1223 c = socket.socket(socket.AF_INET)
1224 c.settimeout(0.2)
1225 c.connect((host, port))
1226 # Will attempt handshake and time out
1227 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1228 ssl.wrap_socket, c)
1229 finally:
1230 c.close()
1231 try:
1232 c = socket.socket(socket.AF_INET)
1233 c.settimeout(0.2)
1234 c = ssl.wrap_socket(c)
1235 # Will attempt handshake and time out
1236 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1237 c.connect, (host, port))
1238 finally:
1239 c.close()
1240 finally:
1241 finish = True
1242 t.join()
1243 server.close()
1244
Bill Janssen61c001a2008-09-08 16:37:24 +00001245
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001246def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001247 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001248 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001249
Trent Nelsone41b0062008-04-08 23:47:30 +00001250 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001251 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001252 "keycert.pem")
1253 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1254 os.path.dirname(__file__) or os.curdir,
1255 "https_svn_python_org_root.pem")
1256
1257 if (not os.path.exists(CERTFILE) or
1258 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001259 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001260
1261 tests = [BasicTests]
1262
Bill Janssen296a59d2007-09-16 22:06:00 +00001263 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001264 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001265
Bill Janssen98d19da2007-09-10 21:51:02 +00001266 if _have_threads:
1267 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001268 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001269 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001270
Bill Janssen98d19da2007-09-10 21:51:02 +00001271 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001272
Bill Janssen98d19da2007-09-10 21:51:02 +00001273 if _have_threads:
1274 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001275
1276if __name__ == "__main__":
1277 test_main()