blob: 7c32c1b09f12f72548d79d51e00eee707682ebe5 [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])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000687 except socket.error, x:
688 if test_support.verbose:
689 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000690 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000691 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000692 finally:
693 server.stop()
694 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000695
Bill Janssen98d19da2007-09-10 21:51:02 +0000696 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
697 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000698 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000699 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000700
Trent Nelsone41b0062008-04-08 23:47:30 +0000701 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000702 certreqs=certreqs,
703 ssl_version=protocol,
704 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000705 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000706 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000707 connectionchatty=connectionchatty,
708 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000709 flag = threading.Event()
710 server.start(flag)
711 # wait for it to start
712 flag.wait()
713 # try to connect
714 if client_protocol is None:
715 client_protocol = protocol
716 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000717 s = ssl.wrap_socket(socket.socket(),
718 certfile=client_certfile,
719 ca_certs=cacertsfile,
720 ciphers=ciphers,
721 cert_reqs=certreqs,
722 ssl_version=client_protocol)
723 s.connect((HOST, server.port))
724 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000725 if connectionchatty:
726 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000727 sys.stdout.write(
728 " client: sending %s...\n" % (repr(arg)))
729 s.write(arg)
730 outdata = s.read()
731 if connectionchatty:
732 if test_support.verbose:
733 sys.stdout.write(" client: read %s\n" % repr(outdata))
734 if outdata != indata.lower():
735 self.fail(
736 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
737 % (outdata[:min(len(outdata),20)], len(outdata),
738 indata[:min(len(indata),20)].lower(), len(indata)))
739 s.write("over\n")
740 if connectionchatty:
741 if test_support.verbose:
742 sys.stdout.write(" client: closing connection.\n")
743 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000744 finally:
745 server.stop()
746 server.join()
747
748 def tryProtocolCombo (server_protocol,
749 client_protocol,
750 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000751 certsreqs=None):
752
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000753 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000754 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000755
756 if certsreqs == ssl.CERT_NONE:
757 certtype = "CERT_NONE"
758 elif certsreqs == ssl.CERT_OPTIONAL:
759 certtype = "CERT_OPTIONAL"
760 elif certsreqs == ssl.CERT_REQUIRED:
761 certtype = "CERT_REQUIRED"
762 if test_support.verbose:
763 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
764 sys.stdout.write(formatstr %
765 (ssl.get_protocol_name(client_protocol),
766 ssl.get_protocol_name(server_protocol),
767 certtype))
768 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000769 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
770 # will send an SSLv3 hello (rather than SSLv2) starting from
771 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000772 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000773 CERTFILE, CERTFILE, client_protocol,
774 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000775 # Protocol mismatch can result in either an SSLError, or a
776 # "Connection reset by peer" error.
777 except ssl.SSLError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000778 if expectedToWork:
779 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000780 except socket.error as e:
781 if expectedToWork or e.errno != errno.ECONNRESET:
782 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000783 else:
784 if not expectedToWork:
Antoine Pitroudb187842010-04-27 10:32:58 +0000785 self.fail(
Bill Janssen98d19da2007-09-10 21:51:02 +0000786 "Client protocol %s succeeded with server protocol %s!"
787 % (ssl.get_protocol_name(client_protocol),
788 ssl.get_protocol_name(server_protocol)))
789
790
Bill Janssen934b16d2008-06-28 22:19:33 +0000791 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000792
793 def testRudeShutdown(self):
794
795 listener_ready = threading.Event()
796 listener_gone = threading.Event()
797
Antoine Pitrou150acda2010-04-27 08:40:51 +0000798 s = socket.socket()
799 port = test_support.bind_port(s, HOST)
800
801 # `listener` runs in a thread. It sits in an accept() until
802 # the main thread connects. Then it rudely closes the socket,
803 # and sets Event `listener_gone` to let the main thread know
804 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000805 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000806 s.listen(5)
807 listener_ready.set()
808 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000809 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000810 listener_gone.set()
811
812 def connector():
813 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000814 c = socket.socket()
815 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000816 listener_gone.wait()
817 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000818 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000819 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000820 pass
821 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000822 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000823
824 t = threading.Thread(target=listener)
825 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000826 try:
827 connector()
828 finally:
829 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000830
831 def testEcho (self):
832
833 if test_support.verbose:
834 sys.stdout.write("\n")
835 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
836 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
837 chatty=True, connectionchatty=True)
838
839 def testReadCert(self):
840
841 if test_support.verbose:
842 sys.stdout.write("\n")
843 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000844 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000845 certreqs=ssl.CERT_NONE,
846 ssl_version=ssl.PROTOCOL_SSLv23,
847 cacerts=CERTFILE,
848 chatty=False)
849 flag = threading.Event()
850 server.start(flag)
851 # wait for it to start
852 flag.wait()
853 # try to connect
854 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000855 s = ssl.wrap_socket(socket.socket(),
856 certfile=CERTFILE,
857 ca_certs=CERTFILE,
858 cert_reqs=ssl.CERT_REQUIRED,
859 ssl_version=ssl.PROTOCOL_SSLv23)
860 s.connect((HOST, server.port))
861 cert = s.getpeercert()
862 self.assertTrue(cert, "Can't get peer certificate.")
863 cipher = s.cipher()
864 if test_support.verbose:
865 sys.stdout.write(pprint.pformat(cert) + '\n')
866 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
867 if 'subject' not in cert:
868 self.fail("No subject field in certificate: %s." %
869 pprint.pformat(cert))
870 if ((('organizationName', 'Python Software Foundation'),)
871 not in cert['subject']):
872 self.fail(
873 "Missing or invalid 'organizationName' field in certificate subject; "
874 "should be 'Python Software Foundation'.")
875 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000876 finally:
877 server.stop()
878 server.join()
879
880 def testNULLcert(self):
881 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
882 "nullcert.pem"))
883 def testMalformedCert(self):
884 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
885 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000886 def testWrongCert(self):
887 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
888 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000889 def testMalformedKey(self):
890 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
891 "badkey.pem"))
892
893 def testProtocolSSL2(self):
894 if test_support.verbose:
895 sys.stdout.write("\n")
896 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
897 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
898 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
899 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
900 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
901 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
902
903 def testProtocolSSL23(self):
904 if test_support.verbose:
905 sys.stdout.write("\n")
906 try:
907 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000908 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000909 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
910 if test_support.verbose:
911 sys.stdout.write(
912 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
913 % str(x))
914 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
915 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
916 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
917
918 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
919 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
920 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
921
922 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
923 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
924 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
925
926 def testProtocolSSL3(self):
927 if test_support.verbose:
928 sys.stdout.write("\n")
929 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
930 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
931 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
932 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
933 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
934 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
935
936 def testProtocolTLS1(self):
937 if test_support.verbose:
938 sys.stdout.write("\n")
939 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
940 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
941 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
942 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
943 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
944 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
945
946 def testSTARTTLS (self):
947
Bill Janssen39295c22008-08-12 16:31:21 +0000948 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000949
Trent Nelsone41b0062008-04-08 23:47:30 +0000950 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000951 ssl_version=ssl.PROTOCOL_TLSv1,
952 starttls_server=True,
953 chatty=True,
954 connectionchatty=True)
955 flag = threading.Event()
956 server.start(flag)
957 # wait for it to start
958 flag.wait()
959 # try to connect
960 wrapped = False
961 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000962 s = socket.socket()
963 s.setblocking(1)
964 s.connect((HOST, server.port))
965 if test_support.verbose:
966 sys.stdout.write("\n")
967 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000968 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000969 sys.stdout.write(
970 " client: sending %s...\n" % repr(indata))
971 if wrapped:
972 conn.write(indata)
973 outdata = conn.read()
974 else:
975 s.send(indata)
976 outdata = s.recv(1024)
977 if (indata == "STARTTLS" and
978 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000979 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000980 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +0000981 " client: read %s from server, starting TLS...\n"
982 % repr(outdata))
983 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
984 wrapped = True
985 elif (indata == "ENDTLS" and
986 outdata.strip().lower().startswith("ok")):
987 if test_support.verbose:
988 sys.stdout.write(
989 " client: read %s from server, ending TLS...\n"
990 % repr(outdata))
991 s = conn.unwrap()
992 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000993 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000994 if test_support.verbose:
995 sys.stdout.write(
996 " client: read %s from server\n" % repr(outdata))
997 if test_support.verbose:
998 sys.stdout.write(" client: closing connection.\n")
999 if wrapped:
1000 conn.write("over\n")
1001 else:
1002 s.send("over\n")
1003 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001004 finally:
1005 server.stop()
1006 server.join()
1007
Bill Janssen934b16d2008-06-28 22:19:33 +00001008 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001009
Bill Janssen934b16d2008-06-28 22:19:33 +00001010 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001011 flag = threading.Event()
1012 server.start(flag)
1013 # wait for it to start
1014 flag.wait()
1015 # try to connect
1016 try:
1017 if test_support.verbose:
1018 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001019 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001020 d2 = ''
1021 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001022 url = 'https://127.0.0.1:%d/%s' % (
1023 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001024 with test_support.check_py3k_warnings():
1025 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001026 dlen = f.info().getheader("content-length")
1027 if dlen and (int(dlen) > 0):
1028 d2 = f.read(int(dlen))
1029 if test_support.verbose:
1030 sys.stdout.write(
1031 " client: read %d bytes from remote server '%s'\n"
1032 % (len(d2), server))
1033 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001034 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001035 finally:
1036 server.stop()
1037 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001038
Bill Janssen934b16d2008-06-28 22:19:33 +00001039 def testWrappedAccept (self):
1040
1041 if test_support.verbose:
1042 sys.stdout.write("\n")
1043 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1044 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1045 chatty=True, connectionchatty=True,
1046 wrap_accepting_socket=True)
1047
1048
1049 def testAsyncoreServer (self):
1050
1051 indata = "TEST MESSAGE of mixed case\n"
1052
1053 if test_support.verbose:
1054 sys.stdout.write("\n")
1055 server = AsyncoreEchoServer(CERTFILE)
1056 flag = threading.Event()
1057 server.start(flag)
1058 # wait for it to start
1059 flag.wait()
1060 # try to connect
1061 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001062 s = ssl.wrap_socket(socket.socket())
1063 s.connect(('127.0.0.1', server.port))
1064 if test_support.verbose:
1065 sys.stdout.write(
1066 " client: sending %s...\n" % (repr(indata)))
1067 s.write(indata)
1068 outdata = s.read()
1069 if test_support.verbose:
1070 sys.stdout.write(" client: read %s\n" % repr(outdata))
1071 if outdata != indata.lower():
1072 self.fail(
1073 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1074 % (outdata[:min(len(outdata),20)], len(outdata),
1075 indata[:min(len(indata),20)].lower(), len(indata)))
1076 s.write("over\n")
1077 if test_support.verbose:
1078 sys.stdout.write(" client: closing connection.\n")
1079 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001080 finally:
1081 server.stop()
1082 # wait for server thread to end
1083 server.join()
1084
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001085
Bill Janssen61c001a2008-09-08 16:37:24 +00001086 def testAllRecvAndSendMethods(self):
1087
1088 if test_support.verbose:
1089 sys.stdout.write("\n")
1090
1091 server = ThreadedEchoServer(CERTFILE,
1092 certreqs=ssl.CERT_NONE,
1093 ssl_version=ssl.PROTOCOL_TLSv1,
1094 cacerts=CERTFILE,
1095 chatty=True,
1096 connectionchatty=False)
1097 flag = threading.Event()
1098 server.start(flag)
1099 # wait for it to start
1100 flag.wait()
1101 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001102 s = ssl.wrap_socket(socket.socket(),
1103 server_side=False,
1104 certfile=CERTFILE,
1105 ca_certs=CERTFILE,
1106 cert_reqs=ssl.CERT_NONE,
1107 ssl_version=ssl.PROTOCOL_TLSv1)
1108 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001109 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001110 # helper methods for standardising recv* method signatures
1111 def _recv_into():
1112 b = bytearray("\0"*100)
1113 count = s.recv_into(b)
1114 return b[:count]
1115
1116 def _recvfrom_into():
1117 b = bytearray("\0"*100)
1118 count, addr = s.recvfrom_into(b)
1119 return b[:count]
1120
1121 # (name, method, whether to expect success, *args)
1122 send_methods = [
1123 ('send', s.send, True, []),
1124 ('sendto', s.sendto, False, ["some.address"]),
1125 ('sendall', s.sendall, True, []),
1126 ]
1127 recv_methods = [
1128 ('recv', s.recv, True, []),
1129 ('recvfrom', s.recvfrom, False, ["some.address"]),
1130 ('recv_into', _recv_into, True, []),
1131 ('recvfrom_into', _recvfrom_into, False, []),
1132 ]
1133 data_prefix = u"PREFIX_"
1134
1135 for meth_name, send_meth, expect_success, args in send_methods:
1136 indata = data_prefix + meth_name
1137 try:
1138 send_meth(indata.encode('ASCII', 'strict'), *args)
1139 outdata = s.read()
1140 outdata = outdata.decode('ASCII', 'strict')
1141 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001142 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001143 "While sending with <<%s>> bad data "
1144 "<<%r>> (%d) received; "
1145 "expected <<%r>> (%d)\n" % (
1146 meth_name, outdata[:20], len(outdata),
1147 indata[:20], len(indata)
1148 )
1149 )
1150 except ValueError as e:
1151 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001152 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001153 "Failed to send with method <<%s>>; "
1154 "expected to succeed.\n" % (meth_name,)
1155 )
1156 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001157 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001158 "Method <<%s>> failed with unexpected "
1159 "exception message: %s\n" % (
1160 meth_name, e
1161 )
1162 )
1163
1164 for meth_name, recv_meth, expect_success, args in recv_methods:
1165 indata = data_prefix + meth_name
1166 try:
1167 s.send(indata.encode('ASCII', 'strict'))
1168 outdata = recv_meth(*args)
1169 outdata = outdata.decode('ASCII', 'strict')
1170 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001171 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001172 "While receiving with <<%s>> bad data "
1173 "<<%r>> (%d) received; "
1174 "expected <<%r>> (%d)\n" % (
1175 meth_name, outdata[:20], len(outdata),
1176 indata[:20], len(indata)
1177 )
1178 )
1179 except ValueError as e:
1180 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001181 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001182 "Failed to receive with method <<%s>>; "
1183 "expected to succeed.\n" % (meth_name,)
1184 )
1185 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001186 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001187 "Method <<%s>> failed with unexpected "
1188 "exception message: %s\n" % (
1189 meth_name, e
1190 )
1191 )
1192 # consume data
1193 s.read()
1194
1195 s.write("over\n".encode("ASCII", "strict"))
1196 s.close()
1197 finally:
1198 server.stop()
1199 server.join()
1200
Antoine Pitroufc69af12010-04-24 20:04:58 +00001201 def test_handshake_timeout(self):
1202 # Issue #5103: SSL handshake must respect the socket timeout
1203 server = socket.socket(socket.AF_INET)
1204 host = "127.0.0.1"
1205 port = test_support.bind_port(server)
1206 started = threading.Event()
1207 finish = False
1208
1209 def serve():
1210 server.listen(5)
1211 started.set()
1212 conns = []
1213 while not finish:
1214 r, w, e = select.select([server], [], [], 0.1)
1215 if server in r:
1216 # Let the socket hang around rather than having
1217 # it closed by garbage collection.
1218 conns.append(server.accept()[0])
1219
1220 t = threading.Thread(target=serve)
1221 t.start()
1222 started.wait()
1223
1224 try:
1225 try:
1226 c = socket.socket(socket.AF_INET)
1227 c.settimeout(0.2)
1228 c.connect((host, port))
1229 # Will attempt handshake and time out
1230 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1231 ssl.wrap_socket, c)
1232 finally:
1233 c.close()
1234 try:
1235 c = socket.socket(socket.AF_INET)
1236 c.settimeout(0.2)
1237 c = ssl.wrap_socket(c)
1238 # Will attempt handshake and time out
1239 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1240 c.connect, (host, port))
1241 finally:
1242 c.close()
1243 finally:
1244 finish = True
1245 t.join()
1246 server.close()
1247
Bill Janssen61c001a2008-09-08 16:37:24 +00001248
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001249def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001250 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001251 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001252
Trent Nelsone41b0062008-04-08 23:47:30 +00001253 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001254 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001255 "keycert.pem")
1256 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1257 os.path.dirname(__file__) or os.curdir,
1258 "https_svn_python_org_root.pem")
1259
1260 if (not os.path.exists(CERTFILE) or
1261 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001262 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001263
1264 tests = [BasicTests]
1265
Bill Janssen296a59d2007-09-16 22:06:00 +00001266 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001267 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001268
Bill Janssen98d19da2007-09-10 21:51:02 +00001269 if _have_threads:
1270 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001271 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001272 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001273
Bill Janssen98d19da2007-09-10 21:51:02 +00001274 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001275
Bill Janssen98d19da2007-09-10 21:51:02 +00001276 if _have_threads:
1277 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001278
1279if __name__ == "__main__":
1280 test_main()