blob: 435c198170fa3ff11d4f8722e90b6d14593a1237 [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:
65 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
66 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)
115 if (d1 != d2):
116 raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
117
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000118 def test_openssl_version(self):
119 n = ssl.OPENSSL_VERSION_NUMBER
120 t = ssl.OPENSSL_VERSION_INFO
121 s = ssl.OPENSSL_VERSION
122 self.assertIsInstance(n, (int, long))
123 self.assertIsInstance(t, tuple)
124 self.assertIsInstance(s, str)
125 # Some sanity checks follow
126 # >= 0.9
127 self.assertGreaterEqual(n, 0x900000)
128 # < 2.0
129 self.assertLess(n, 0x20000000)
130 major, minor, fix, patch, status = t
131 self.assertGreaterEqual(major, 0)
132 self.assertLess(major, 2)
133 self.assertGreaterEqual(minor, 0)
134 self.assertLess(minor, 256)
135 self.assertGreaterEqual(fix, 0)
136 self.assertLess(fix, 256)
137 self.assertGreaterEqual(patch, 0)
138 self.assertLessEqual(patch, 26)
139 self.assertGreaterEqual(status, 0)
140 self.assertLessEqual(status, 15)
141 # Version string as returned by OpenSSL, the format might change
142 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
143 (s, t))
144
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000145 def test_ciphers(self):
146 if not test_support.is_resource_enabled('network'):
147 return
148 remote = ("svn.python.org", 443)
149 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
150 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
151 s.connect(remote)
152 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
153 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
154 s.connect(remote)
155 # Error checking occurs when connecting, because the SSL context
156 # isn't created before.
157 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
158 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
159 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
160 s.connect(remote)
161
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000162 @test_support.cpython_only
163 def test_refcycle(self):
164 # Issue #7943: an SSL object doesn't create reference cycles with
165 # itself.
166 s = socket.socket(socket.AF_INET)
167 ss = ssl.wrap_socket(s)
168 wr = weakref.ref(ss)
169 del ss
170 self.assertEqual(wr(), None)
171
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000172
Bill Janssen934b16d2008-06-28 22:19:33 +0000173class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000174
175 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000176 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
177 cert_reqs=ssl.CERT_NONE)
178 s.connect(("svn.python.org", 443))
179 c = s.getpeercert()
180 if c:
181 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
182 s.close()
183
184 # this should fail because we have no verification certs
185 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
186 cert_reqs=ssl.CERT_REQUIRED)
187 try:
188 s.connect(("svn.python.org", 443))
189 except ssl.SSLError:
190 pass
191 finally:
192 s.close()
193
194 # this should succeed because we specify the root cert
195 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
196 cert_reqs=ssl.CERT_REQUIRED,
197 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
198 try:
199 s.connect(("svn.python.org", 443))
200 except ssl.SSLError, x:
201 raise test_support.TestFailed("Unexpected exception %s" % x)
202 finally:
203 s.close()
204
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000205 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
206 def test_makefile_close(self):
207 # Issue #5238: creating a file-like object with makefile() shouldn't
208 # delay closing the underlying "real socket" (here tested with its
209 # file descriptor, hence skipping the test under Windows).
210 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
211 ss.connect(("svn.python.org", 443))
212 fd = ss.fileno()
213 f = ss.makefile()
214 f.close()
215 # The fd is still open
216 os.read(fd, 0)
217 # Closing the SSL socket should close the fd too
218 ss.close()
219 gc.collect()
220 with self.assertRaises(OSError) as e:
221 os.read(fd, 0)
222 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000223
224 def testNonBlockingHandshake(self):
225 s = socket.socket(socket.AF_INET)
226 s.connect(("svn.python.org", 443))
227 s.setblocking(False)
228 s = ssl.wrap_socket(s,
229 cert_reqs=ssl.CERT_NONE,
230 do_handshake_on_connect=False)
231 count = 0
232 while True:
233 try:
234 count += 1
235 s.do_handshake()
236 break
237 except ssl.SSLError, err:
238 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
239 select.select([s], [], [])
240 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
241 select.select([], [s], [])
242 else:
243 raise
244 s.close()
245 if test_support.verbose:
246 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
247
Bill Janssen296a59d2007-09-16 22:06:00 +0000248 def testFetchServerCert(self):
249
250 pem = ssl.get_server_certificate(("svn.python.org", 443))
251 if not pem:
252 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
253
254 try:
255 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
256 except ssl.SSLError:
257 #should fail
258 pass
259 else:
260 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
261
262 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
263 if not pem:
264 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
265 if test_support.verbose:
266 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
267
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000268 def test_algorithms(self):
269 # Issue #8484: all algorithms should be available when verifying a
270 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000271 # SHA256 was added in OpenSSL 0.9.8
272 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
273 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000274 # NOTE: https://sha256.tbs-internet.com is another possible test host
275 remote = ("sha2.hboeck.de", 443)
276 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
277 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
278 cert_reqs=ssl.CERT_REQUIRED,
279 ca_certs=sha256_cert,)
280 with test_support.transient_internet():
281 try:
282 s.connect(remote)
283 if test_support.verbose:
284 sys.stdout.write("\nCipher with %r is %r\n" %
285 (remote, s.cipher()))
286 sys.stdout.write("Certificate is:\n%s\n" %
287 pprint.pformat(s.getpeercert()))
288 finally:
289 s.close()
290
Bill Janssen296a59d2007-09-16 22:06:00 +0000291
Bill Janssen98d19da2007-09-10 21:51:02 +0000292try:
293 import threading
294except ImportError:
295 _have_threads = False
296else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000297
Bill Janssen98d19da2007-09-10 21:51:02 +0000298 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000299
Bill Janssen98d19da2007-09-10 21:51:02 +0000300 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000301
Bill Janssen98d19da2007-09-10 21:51:02 +0000302 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000303
Bill Janssen98d19da2007-09-10 21:51:02 +0000304 """A mildly complicated class, because we want it to work both
305 with and without the SSL wrapper around the socket connection, so
306 that we can test the STARTTLS functionality."""
307
308 def __init__(self, server, connsock):
309 self.server = server
310 self.running = False
311 self.sock = connsock
312 self.sock.setblocking(1)
313 self.sslconn = None
314 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000315 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000316
Bill Janssen934b16d2008-06-28 22:19:33 +0000317 def show_conn_details(self):
318 if self.server.certreqs == ssl.CERT_REQUIRED:
319 cert = self.sslconn.getpeercert()
320 if test_support.verbose and self.server.chatty:
321 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
322 cert_binary = self.sslconn.getpeercert(True)
323 if test_support.verbose and self.server.chatty:
324 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
325 cipher = self.sslconn.cipher()
326 if test_support.verbose and self.server.chatty:
327 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
328
Bill Janssen98d19da2007-09-10 21:51:02 +0000329 def wrap_conn (self):
330 try:
331 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
332 certfile=self.server.certificate,
333 ssl_version=self.server.protocol,
334 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000335 cert_reqs=self.server.certreqs,
336 ciphers=self.server.ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +0000337 except:
338 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()
Bill Janssen98d19da2007-09-10 21:51:02 +0000342 if not self.server.expect_bad_connects:
343 # here, we want to stop the server, because this shouldn't
344 # happen in the context of our test case
345 self.running = False
346 # normally, we'd just stop here, but for the test
347 # harness, we want to stop the server
348 self.server.stop()
349 return False
350
351 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000352 return True
353
354 def read(self):
355 if self.sslconn:
356 return self.sslconn.read()
357 else:
358 return self.sock.recv(1024)
359
360 def write(self, bytes):
361 if self.sslconn:
362 return self.sslconn.write(bytes)
363 else:
364 return self.sock.send(bytes)
365
366 def close(self):
367 if self.sslconn:
368 self.sslconn.close()
369 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000370 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000371
372 def run (self):
373 self.running = True
374 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000375 if isinstance(self.sock, ssl.SSLSocket):
376 self.sslconn = self.sock
377 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000378 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000379 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000380 while self.running:
381 try:
382 msg = self.read()
383 if not msg:
384 # eof, so quit this handler
385 self.running = False
386 self.close()
387 elif msg.strip() == 'over':
388 if test_support.verbose and self.server.connectionchatty:
389 sys.stdout.write(" server: client closed connection\n")
390 self.close()
391 return
392 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
393 if test_support.verbose and self.server.connectionchatty:
394 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
395 self.write("OK\n")
396 if not self.wrap_conn():
397 return
Bill Janssen39295c22008-08-12 16:31:21 +0000398 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
399 if test_support.verbose and self.server.connectionchatty:
400 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
401 self.write("OK\n")
402 self.sslconn.unwrap()
403 self.sslconn = None
404 if test_support.verbose and self.server.connectionchatty:
405 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000406 else:
407 if (test_support.verbose and
408 self.server.connectionchatty):
409 ctype = (self.sslconn and "encrypted") or "unencrypted"
410 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
411 % (repr(msg), ctype, repr(msg.lower()), ctype))
412 self.write(msg.lower())
413 except ssl.SSLError:
414 if self.server.chatty:
415 handle_error("Test server failure:\n")
416 self.close()
417 self.running = False
418 # normally, we'd just stop here, but for the test
419 # harness, we want to stop the server
420 self.server.stop()
421 except:
422 handle_error('')
423
Trent Nelsone41b0062008-04-08 23:47:30 +0000424 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000425 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000426 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000427 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000428
Bill Janssen98d19da2007-09-10 21:51:02 +0000429 if ssl_version is None:
430 ssl_version = ssl.PROTOCOL_TLSv1
431 if certreqs is None:
432 certreqs = ssl.CERT_NONE
433 self.certificate = certificate
434 self.protocol = ssl_version
435 self.certreqs = certreqs
436 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000437 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000438 self.expect_bad_connects = expect_bad_connects
439 self.chatty = chatty
440 self.connectionchatty = connectionchatty
441 self.starttls_server = starttls_server
442 self.sock = socket.socket()
443 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000444 if wrap_accepting_socket:
445 self.sock = ssl.wrap_socket(self.sock, server_side=True,
446 certfile=self.certificate,
447 cert_reqs = self.certreqs,
448 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000449 ssl_version = self.protocol,
450 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000451 if test_support.verbose and self.chatty:
452 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
453 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000454 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000455 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000456 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000457
458 def start (self, flag=None):
459 self.flag = flag
460 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000461
462 def run (self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000463 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000464 self.sock.listen(5)
465 self.active = True
466 if self.flag:
467 # signal an event
468 self.flag.set()
469 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000470 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000471 newconn, connaddr = self.sock.accept()
472 if test_support.verbose and self.chatty:
473 sys.stdout.write(' server: new connection from '
474 + str(connaddr) + '\n')
475 handler = self.ConnectionHandler(self, newconn)
476 handler.start()
477 except socket.timeout:
478 pass
479 except KeyboardInterrupt:
480 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000481 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000482 if self.chatty:
483 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000484 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000485
Bill Janssen98d19da2007-09-10 21:51:02 +0000486 def stop (self):
487 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000488
Bill Janssen934b16d2008-06-28 22:19:33 +0000489 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000490
Bill Janssen934b16d2008-06-28 22:19:33 +0000491 class EchoServer (asyncore.dispatcher):
492
493 class ConnectionHandler (asyncore.dispatcher_with_send):
494
495 def __init__(self, conn, certfile):
496 asyncore.dispatcher_with_send.__init__(self, conn)
497 self.socket = ssl.wrap_socket(conn, server_side=True,
498 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000499 do_handshake_on_connect=False)
500 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000501
502 def readable(self):
503 if isinstance(self.socket, ssl.SSLSocket):
504 while self.socket.pending() > 0:
505 self.handle_read_event()
506 return True
507
Antoine Pitroufc69af12010-04-24 20:04:58 +0000508 def _do_ssl_handshake(self):
509 try:
510 self.socket.do_handshake()
511 except ssl.SSLError, err:
512 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
513 ssl.SSL_ERROR_WANT_WRITE):
514 return
515 elif err.args[0] == ssl.SSL_ERROR_EOF:
516 return self.handle_close()
517 raise
518 except socket.error, err:
519 if err.args[0] == errno.ECONNABORTED:
520 return self.handle_close()
521 else:
522 self._ssl_accepting = False
523
Bill Janssen934b16d2008-06-28 22:19:33 +0000524 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000525 if self._ssl_accepting:
526 self._do_ssl_handshake()
527 else:
528 data = self.recv(1024)
529 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000530
531 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000532 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000533 if test_support.verbose:
534 sys.stdout.write(" server: closed connection %s\n" % self.socket)
535
536 def handle_error(self):
537 raise
538
539 def __init__(self, certfile):
540 self.certfile = certfile
541 asyncore.dispatcher.__init__(self)
542 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
543 self.port = test_support.bind_port(self.socket)
544 self.listen(5)
545
546 def handle_accept(self):
547 sock_obj, addr = self.accept()
548 if test_support.verbose:
549 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
550 self.ConnectionHandler(sock_obj, self.certfile)
551
552 def handle_error(self):
553 raise
554
555 def __init__(self, certfile):
556 self.flag = None
557 self.active = False
558 self.server = self.EchoServer(certfile)
559 self.port = self.server.port
560 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000561 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000562
563 def __str__(self):
564 return "<%s %s>" % (self.__class__.__name__, self.server)
565
566 def start (self, flag=None):
567 self.flag = flag
568 threading.Thread.start(self)
569
570 def run (self):
571 self.active = True
572 if self.flag:
573 self.flag.set()
574 while self.active:
575 try:
576 asyncore.loop(1)
577 except:
578 pass
579
580 def stop (self):
581 self.active = False
582 self.server.close()
583
584 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000585
586 class HTTPSServer(HTTPServer):
587
588 def __init__(self, server_address, RequestHandlerClass, certfile):
589
590 HTTPServer.__init__(self, server_address, RequestHandlerClass)
591 # we assume the certfile contains both private key and certificate
592 self.certfile = certfile
593 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000594 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000595 self.allow_reuse_address = True
596
Bill Janssen934b16d2008-06-28 22:19:33 +0000597 def __str__(self):
598 return ('<%s %s:%s>' %
599 (self.__class__.__name__,
600 self.server_name,
601 self.server_port))
602
Bill Janssen296a59d2007-09-16 22:06:00 +0000603 def get_request (self):
604 # override this to wrap socket with SSL
605 sock, addr = self.socket.accept()
606 sslconn = ssl.wrap_socket(sock, server_side=True,
607 certfile=self.certfile)
608 return sslconn, addr
609
Bill Janssen296a59d2007-09-16 22:06:00 +0000610 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
611
612 # need to override translate_path to get a known root,
613 # instead of using os.curdir, since the test could be
614 # run from anywhere
615
616 server_version = "TestHTTPS/1.0"
617
618 root = None
619
620 def translate_path(self, path):
621 """Translate a /-separated PATH to the local filename syntax.
622
623 Components that mean special things to the local file system
624 (e.g. drive or directory names) are ignored. (XXX They should
625 probably be diagnosed.)
626
627 """
628 # abandon query parameters
629 path = urlparse.urlparse(path)[2]
630 path = os.path.normpath(urllib.unquote(path))
631 words = path.split('/')
632 words = filter(None, words)
633 path = self.root
634 for word in words:
635 drive, word = os.path.splitdrive(word)
636 head, word = os.path.split(word)
637 if word in self.root: continue
638 path = os.path.join(path, word)
639 return path
640
641 def log_message(self, format, *args):
642
643 # we override this to suppress logging unless "verbose"
644
645 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000646 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
647 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000648 self.server.server_port,
649 self.request.cipher(),
650 self.log_date_time_string(),
651 format%args))
652
653
Trent Nelsone41b0062008-04-08 23:47:30 +0000654 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000655 self.flag = None
656 self.active = False
657 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
658 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000659 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
660 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000661 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000662 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000663
664 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000665 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000666
667 def start (self, flag=None):
668 self.flag = flag
669 threading.Thread.start(self)
670
671 def run (self):
672 self.active = True
673 if self.flag:
674 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000675 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000676 self.active = False
677
678 def stop (self):
679 self.active = False
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000680 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000681
682
Bill Janssen98d19da2007-09-10 21:51:02 +0000683 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000684 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000685 certreqs=ssl.CERT_REQUIRED,
686 cacerts=CERTFILE, chatty=False)
687 flag = threading.Event()
688 server.start(flag)
689 # wait for it to start
690 flag.wait()
691 # try to connect
692 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000693 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000694 s = ssl.wrap_socket(socket.socket(),
695 certfile=certfile,
696 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000697 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000698 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000699 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000700 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000701 except socket.error, x:
702 if test_support.verbose:
703 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000704 else:
705 raise test_support.TestFailed(
706 "Use of invalid cert should have failed!")
707 finally:
708 server.stop()
709 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000710
Bill Janssen98d19da2007-09-10 21:51:02 +0000711 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
712 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000713 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000714 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000715
Trent Nelsone41b0062008-04-08 23:47:30 +0000716 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000717 certreqs=certreqs,
718 ssl_version=protocol,
719 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000720 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000721 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000722 connectionchatty=connectionchatty,
723 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000724 flag = threading.Event()
725 server.start(flag)
726 # wait for it to start
727 flag.wait()
728 # try to connect
729 if client_protocol is None:
730 client_protocol = protocol
731 try:
732 try:
733 s = ssl.wrap_socket(socket.socket(),
734 certfile=client_certfile,
735 ca_certs=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000736 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000737 cert_reqs=certreqs,
738 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000739 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000740 except ssl.SSLError, x:
741 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
742 except Exception, x:
743 raise test_support.TestFailed("Unexpected exception: " + str(x))
744 else:
Antoine Pitrou5ba84912009-10-19 17:59:07 +0000745 for arg in [indata, bytearray(indata), memoryview(indata)]:
746 if connectionchatty:
747 if test_support.verbose:
748 sys.stdout.write(
749 " client: sending %s...\n" % (repr(arg)))
750 s.write(arg)
751 outdata = s.read()
752 if connectionchatty:
753 if test_support.verbose:
754 sys.stdout.write(" client: read %s\n" % repr(outdata))
755 if outdata != indata.lower():
756 raise test_support.TestFailed(
757 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
758 % (outdata[:min(len(outdata),20)], len(outdata),
759 indata[:min(len(indata),20)].lower(), len(indata)))
Bill Janssen98d19da2007-09-10 21:51:02 +0000760 s.write("over\n")
761 if connectionchatty:
762 if test_support.verbose:
763 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000764 s.close()
765 finally:
766 server.stop()
767 server.join()
768
769 def tryProtocolCombo (server_protocol,
770 client_protocol,
771 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000772 certsreqs=None):
773
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000774 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000775 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000776
777 if certsreqs == ssl.CERT_NONE:
778 certtype = "CERT_NONE"
779 elif certsreqs == ssl.CERT_OPTIONAL:
780 certtype = "CERT_OPTIONAL"
781 elif certsreqs == ssl.CERT_REQUIRED:
782 certtype = "CERT_REQUIRED"
783 if test_support.verbose:
784 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
785 sys.stdout.write(formatstr %
786 (ssl.get_protocol_name(client_protocol),
787 ssl.get_protocol_name(server_protocol),
788 certtype))
789 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000790 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
791 # will send an SSLv3 hello (rather than SSLv2) starting from
792 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000793 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000794 CERTFILE, CERTFILE, client_protocol,
795 ciphers="ALL", chatty=False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000796 except test_support.TestFailed:
797 if expectedToWork:
798 raise
799 else:
800 if not expectedToWork:
801 raise test_support.TestFailed(
802 "Client protocol %s succeeded with server protocol %s!"
803 % (ssl.get_protocol_name(client_protocol),
804 ssl.get_protocol_name(server_protocol)))
805
806
Bill Janssen934b16d2008-06-28 22:19:33 +0000807 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000808
809 def testRudeShutdown(self):
810
811 listener_ready = threading.Event()
812 listener_gone = threading.Event()
813
Antoine Pitrou150acda2010-04-27 08:40:51 +0000814 s = socket.socket()
815 port = test_support.bind_port(s, HOST)
816
817 # `listener` runs in a thread. It sits in an accept() until
818 # the main thread connects. Then it rudely closes the socket,
819 # and sets Event `listener_gone` to let the main thread know
820 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000821 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000822 s.listen(5)
823 listener_ready.set()
824 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000825 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000826 listener_gone.set()
827
828 def connector():
829 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000830 c = socket.socket()
831 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000832 listener_gone.wait()
833 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000834 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000835 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000836 pass
837 else:
838 raise test_support.TestFailed(
839 'connecting to closed SSL socket should have failed')
840
841 t = threading.Thread(target=listener)
842 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000843 try:
844 connector()
845 finally:
846 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000847
848 def testEcho (self):
849
850 if test_support.verbose:
851 sys.stdout.write("\n")
852 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
853 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
854 chatty=True, connectionchatty=True)
855
856 def testReadCert(self):
857
858 if test_support.verbose:
859 sys.stdout.write("\n")
860 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000861 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000862 certreqs=ssl.CERT_NONE,
863 ssl_version=ssl.PROTOCOL_SSLv23,
864 cacerts=CERTFILE,
865 chatty=False)
866 flag = threading.Event()
867 server.start(flag)
868 # wait for it to start
869 flag.wait()
870 # try to connect
871 try:
872 try:
873 s = ssl.wrap_socket(socket.socket(),
874 certfile=CERTFILE,
875 ca_certs=CERTFILE,
876 cert_reqs=ssl.CERT_REQUIRED,
877 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000878 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000879 except ssl.SSLError, x:
880 raise test_support.TestFailed(
881 "Unexpected SSL error: " + str(x))
882 except Exception, x:
883 raise test_support.TestFailed(
884 "Unexpected exception: " + str(x))
885 else:
886 if not s:
887 raise test_support.TestFailed(
888 "Can't SSL-handshake with test server")
889 cert = s.getpeercert()
890 if not cert:
891 raise test_support.TestFailed(
892 "Can't get peer certificate.")
893 cipher = s.cipher()
894 if test_support.verbose:
895 sys.stdout.write(pprint.pformat(cert) + '\n')
896 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000897 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000898 raise test_support.TestFailed(
899 "No subject field in certificate: %s." %
900 pprint.pformat(cert))
901 if ((('organizationName', 'Python Software Foundation'),)
902 not in cert['subject']):
903 raise test_support.TestFailed(
904 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000905 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000906 s.close()
907 finally:
908 server.stop()
909 server.join()
910
911 def testNULLcert(self):
912 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
913 "nullcert.pem"))
914 def testMalformedCert(self):
915 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
916 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000917 def testWrongCert(self):
918 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
919 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000920 def testMalformedKey(self):
921 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
922 "badkey.pem"))
923
924 def testProtocolSSL2(self):
925 if test_support.verbose:
926 sys.stdout.write("\n")
927 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
928 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
929 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
930 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
931 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
932 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
933
934 def testProtocolSSL23(self):
935 if test_support.verbose:
936 sys.stdout.write("\n")
937 try:
938 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
939 except test_support.TestFailed, x:
940 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
941 if test_support.verbose:
942 sys.stdout.write(
943 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
944 % str(x))
945 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
946 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
947 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
948
949 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
950 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
951 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
952
953 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
954 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
955 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
956
957 def testProtocolSSL3(self):
958 if test_support.verbose:
959 sys.stdout.write("\n")
960 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
961 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
962 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
963 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
964 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
965 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
966
967 def testProtocolTLS1(self):
968 if test_support.verbose:
969 sys.stdout.write("\n")
970 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
971 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
972 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
973 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
974 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
975 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
976
977 def testSTARTTLS (self):
978
Bill Janssen39295c22008-08-12 16:31:21 +0000979 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000980
Trent Nelsone41b0062008-04-08 23:47:30 +0000981 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000982 ssl_version=ssl.PROTOCOL_TLSv1,
983 starttls_server=True,
984 chatty=True,
985 connectionchatty=True)
986 flag = threading.Event()
987 server.start(flag)
988 # wait for it to start
989 flag.wait()
990 # try to connect
991 wrapped = False
992 try:
993 try:
994 s = socket.socket()
995 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000996 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000997 except Exception, x:
998 raise test_support.TestFailed("Unexpected exception: " + str(x))
999 else:
1000 if test_support.verbose:
1001 sys.stdout.write("\n")
1002 for indata in msgs:
1003 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001004 sys.stdout.write(
1005 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001006 if wrapped:
1007 conn.write(indata)
1008 outdata = conn.read()
1009 else:
1010 s.send(indata)
1011 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001012 if (indata == "STARTTLS" and
1013 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001014 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001015 sys.stdout.write(
1016 " client: read %s from server, starting TLS...\n"
1017 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001018 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001019 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001020 elif (indata == "ENDTLS" and
1021 outdata.strip().lower().startswith("ok")):
1022 if test_support.verbose:
1023 sys.stdout.write(
1024 " client: read %s from server, ending TLS...\n"
1025 % repr(outdata))
1026 s = conn.unwrap()
1027 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001028 else:
1029 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001030 sys.stdout.write(
1031 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001032 if test_support.verbose:
1033 sys.stdout.write(" client: closing connection.\n")
1034 if wrapped:
1035 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001036 else:
1037 s.send("over\n")
1038 s.close()
1039 finally:
1040 server.stop()
1041 server.join()
1042
Bill Janssen934b16d2008-06-28 22:19:33 +00001043 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001044
Bill Janssen934b16d2008-06-28 22:19:33 +00001045 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001046 flag = threading.Event()
1047 server.start(flag)
1048 # wait for it to start
1049 flag.wait()
1050 # try to connect
1051 try:
1052 if test_support.verbose:
1053 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001054 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001055 d2 = ''
1056 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001057 url = 'https://127.0.0.1:%d/%s' % (
1058 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001059 with test_support.check_py3k_warnings():
1060 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001061 dlen = f.info().getheader("content-length")
1062 if dlen and (int(dlen) > 0):
1063 d2 = f.read(int(dlen))
1064 if test_support.verbose:
1065 sys.stdout.write(
1066 " client: read %d bytes from remote server '%s'\n"
1067 % (len(d2), server))
1068 f.close()
1069 except:
1070 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1071 if test_support.verbose:
1072 sys.stdout.write('\n' + msg)
1073 raise test_support.TestFailed(msg)
1074 else:
1075 if not (d1 == d2):
1076 raise test_support.TestFailed(
1077 "Couldn't fetch data from HTTPS server")
1078 finally:
1079 server.stop()
1080 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001081
Bill Janssen934b16d2008-06-28 22:19:33 +00001082 def testWrappedAccept (self):
1083
1084 if test_support.verbose:
1085 sys.stdout.write("\n")
1086 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1087 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1088 chatty=True, connectionchatty=True,
1089 wrap_accepting_socket=True)
1090
1091
1092 def testAsyncoreServer (self):
1093
1094 indata = "TEST MESSAGE of mixed case\n"
1095
1096 if test_support.verbose:
1097 sys.stdout.write("\n")
1098 server = AsyncoreEchoServer(CERTFILE)
1099 flag = threading.Event()
1100 server.start(flag)
1101 # wait for it to start
1102 flag.wait()
1103 # try to connect
1104 try:
1105 try:
1106 s = ssl.wrap_socket(socket.socket())
1107 s.connect(('127.0.0.1', server.port))
1108 except ssl.SSLError, x:
1109 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1110 except Exception, x:
1111 raise test_support.TestFailed("Unexpected exception: " + str(x))
1112 else:
1113 if test_support.verbose:
1114 sys.stdout.write(
1115 " client: sending %s...\n" % (repr(indata)))
1116 s.write(indata)
1117 outdata = s.read()
1118 if test_support.verbose:
1119 sys.stdout.write(" client: read %s\n" % repr(outdata))
1120 if outdata != indata.lower():
1121 raise test_support.TestFailed(
1122 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1123 % (outdata[:min(len(outdata),20)], len(outdata),
1124 indata[:min(len(indata),20)].lower(), len(indata)))
1125 s.write("over\n")
1126 if test_support.verbose:
1127 sys.stdout.write(" client: closing connection.\n")
1128 s.close()
1129 finally:
1130 server.stop()
1131 # wait for server thread to end
1132 server.join()
1133
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001134
Bill Janssen61c001a2008-09-08 16:37:24 +00001135 def testAllRecvAndSendMethods(self):
1136
1137 if test_support.verbose:
1138 sys.stdout.write("\n")
1139
1140 server = ThreadedEchoServer(CERTFILE,
1141 certreqs=ssl.CERT_NONE,
1142 ssl_version=ssl.PROTOCOL_TLSv1,
1143 cacerts=CERTFILE,
1144 chatty=True,
1145 connectionchatty=False)
1146 flag = threading.Event()
1147 server.start(flag)
1148 # wait for it to start
1149 flag.wait()
1150 # try to connect
1151 try:
1152 s = ssl.wrap_socket(socket.socket(),
1153 server_side=False,
1154 certfile=CERTFILE,
1155 ca_certs=CERTFILE,
1156 cert_reqs=ssl.CERT_NONE,
1157 ssl_version=ssl.PROTOCOL_TLSv1)
1158 s.connect((HOST, server.port))
1159 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001160 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001161 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001162 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001163 else:
1164 # helper methods for standardising recv* method signatures
1165 def _recv_into():
1166 b = bytearray("\0"*100)
1167 count = s.recv_into(b)
1168 return b[:count]
1169
1170 def _recvfrom_into():
1171 b = bytearray("\0"*100)
1172 count, addr = s.recvfrom_into(b)
1173 return b[:count]
1174
1175 # (name, method, whether to expect success, *args)
1176 send_methods = [
1177 ('send', s.send, True, []),
1178 ('sendto', s.sendto, False, ["some.address"]),
1179 ('sendall', s.sendall, True, []),
1180 ]
1181 recv_methods = [
1182 ('recv', s.recv, True, []),
1183 ('recvfrom', s.recvfrom, False, ["some.address"]),
1184 ('recv_into', _recv_into, True, []),
1185 ('recvfrom_into', _recvfrom_into, False, []),
1186 ]
1187 data_prefix = u"PREFIX_"
1188
1189 for meth_name, send_meth, expect_success, args in send_methods:
1190 indata = data_prefix + meth_name
1191 try:
1192 send_meth(indata.encode('ASCII', 'strict'), *args)
1193 outdata = s.read()
1194 outdata = outdata.decode('ASCII', 'strict')
1195 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001196 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001197 "While sending with <<%s>> bad data "
1198 "<<%r>> (%d) received; "
1199 "expected <<%r>> (%d)\n" % (
1200 meth_name, outdata[:20], len(outdata),
1201 indata[:20], len(indata)
1202 )
1203 )
1204 except ValueError as e:
1205 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001206 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001207 "Failed to send with method <<%s>>; "
1208 "expected to succeed.\n" % (meth_name,)
1209 )
1210 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001211 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001212 "Method <<%s>> failed with unexpected "
1213 "exception message: %s\n" % (
1214 meth_name, e
1215 )
1216 )
1217
1218 for meth_name, recv_meth, expect_success, args in recv_methods:
1219 indata = data_prefix + meth_name
1220 try:
1221 s.send(indata.encode('ASCII', 'strict'))
1222 outdata = recv_meth(*args)
1223 outdata = outdata.decode('ASCII', 'strict')
1224 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001225 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001226 "While receiving with <<%s>> bad data "
1227 "<<%r>> (%d) received; "
1228 "expected <<%r>> (%d)\n" % (
1229 meth_name, outdata[:20], len(outdata),
1230 indata[:20], len(indata)
1231 )
1232 )
1233 except ValueError as e:
1234 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001235 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001236 "Failed to receive with method <<%s>>; "
1237 "expected to succeed.\n" % (meth_name,)
1238 )
1239 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001240 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001241 "Method <<%s>> failed with unexpected "
1242 "exception message: %s\n" % (
1243 meth_name, e
1244 )
1245 )
1246 # consume data
1247 s.read()
1248
1249 s.write("over\n".encode("ASCII", "strict"))
1250 s.close()
1251 finally:
1252 server.stop()
1253 server.join()
1254
Antoine Pitroufc69af12010-04-24 20:04:58 +00001255 def test_handshake_timeout(self):
1256 # Issue #5103: SSL handshake must respect the socket timeout
1257 server = socket.socket(socket.AF_INET)
1258 host = "127.0.0.1"
1259 port = test_support.bind_port(server)
1260 started = threading.Event()
1261 finish = False
1262
1263 def serve():
1264 server.listen(5)
1265 started.set()
1266 conns = []
1267 while not finish:
1268 r, w, e = select.select([server], [], [], 0.1)
1269 if server in r:
1270 # Let the socket hang around rather than having
1271 # it closed by garbage collection.
1272 conns.append(server.accept()[0])
1273
1274 t = threading.Thread(target=serve)
1275 t.start()
1276 started.wait()
1277
1278 try:
1279 try:
1280 c = socket.socket(socket.AF_INET)
1281 c.settimeout(0.2)
1282 c.connect((host, port))
1283 # Will attempt handshake and time out
1284 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1285 ssl.wrap_socket, c)
1286 finally:
1287 c.close()
1288 try:
1289 c = socket.socket(socket.AF_INET)
1290 c.settimeout(0.2)
1291 c = ssl.wrap_socket(c)
1292 # Will attempt handshake and time out
1293 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1294 c.connect, (host, port))
1295 finally:
1296 c.close()
1297 finally:
1298 finish = True
1299 t.join()
1300 server.close()
1301
Bill Janssen61c001a2008-09-08 16:37:24 +00001302
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001303def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001304 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001305 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001306
Trent Nelsone41b0062008-04-08 23:47:30 +00001307 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001308 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001309 "keycert.pem")
1310 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1311 os.path.dirname(__file__) or os.curdir,
1312 "https_svn_python_org_root.pem")
1313
1314 if (not os.path.exists(CERTFILE) or
1315 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001316 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001317
1318 tests = [BasicTests]
1319
Bill Janssen296a59d2007-09-16 22:06:00 +00001320 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001321 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001322
Bill Janssen98d19da2007-09-10 21:51:02 +00001323 if _have_threads:
1324 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001325 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001326 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001327
Bill Janssen98d19da2007-09-10 21:51:02 +00001328 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001329
Bill Janssen98d19da2007-09-10 21:51:02 +00001330 if _have_threads:
1331 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001332
1333if __name__ == "__main__":
1334 test_main()