blob: c7cd388b27e47848bb3c57bba5a70e795a0feca2 [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
Antoine Pitrou3945c862010-04-28 21:11:01 +000040 def test_sslwrap_simple(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
Antoine Pitrou3945c862010-04-28 21:11:01 +000057 def test_connect(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
Antoine Pitrou3945c862010-04-28 21:11:01 +000078 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000079 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
Antoine Pitrou3945c862010-04-28 21:11:01 +000087 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000088 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
Antoine Pitrou3945c862010-04-28 21:11:01 +0000101 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000102 # 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
Antoine Pitrou3945c862010-04-28 21:11:01 +0000109 def test_DER_to_PEM(self):
110 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
111 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000112 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)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000116 if not p2.startswith(ssl.PEM_HEADER + '\n'):
117 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
118 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
119 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000120
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000121 def test_openssl_version(self):
122 n = ssl.OPENSSL_VERSION_NUMBER
123 t = ssl.OPENSSL_VERSION_INFO
124 s = ssl.OPENSSL_VERSION
125 self.assertIsInstance(n, (int, long))
126 self.assertIsInstance(t, tuple)
127 self.assertIsInstance(s, str)
128 # Some sanity checks follow
129 # >= 0.9
130 self.assertGreaterEqual(n, 0x900000)
131 # < 2.0
132 self.assertLess(n, 0x20000000)
133 major, minor, fix, patch, status = t
134 self.assertGreaterEqual(major, 0)
135 self.assertLess(major, 2)
136 self.assertGreaterEqual(minor, 0)
137 self.assertLess(minor, 256)
138 self.assertGreaterEqual(fix, 0)
139 self.assertLess(fix, 256)
140 self.assertGreaterEqual(patch, 0)
141 self.assertLessEqual(patch, 26)
142 self.assertGreaterEqual(status, 0)
143 self.assertLessEqual(status, 15)
144 # Version string as returned by OpenSSL, the format might change
145 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
146 (s, t))
147
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000148 def test_ciphers(self):
149 if not test_support.is_resource_enabled('network'):
150 return
151 remote = ("svn.python.org", 443)
152 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
153 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
154 s.connect(remote)
155 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
156 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
157 s.connect(remote)
158 # Error checking occurs when connecting, because the SSL context
159 # isn't created before.
160 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
161 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
162 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
163 s.connect(remote)
164
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000165 @test_support.cpython_only
166 def test_refcycle(self):
167 # Issue #7943: an SSL object doesn't create reference cycles with
168 # itself.
169 s = socket.socket(socket.AF_INET)
170 ss = ssl.wrap_socket(s)
171 wr = weakref.ref(ss)
172 del ss
173 self.assertEqual(wr(), None)
174
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000175
Bill Janssen934b16d2008-06-28 22:19:33 +0000176class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000177
Antoine Pitrou3945c862010-04-28 21:11:01 +0000178 def test_connect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000179 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
180 cert_reqs=ssl.CERT_NONE)
181 s.connect(("svn.python.org", 443))
182 c = s.getpeercert()
183 if c:
Antoine Pitroudb187842010-04-27 10:32:58 +0000184 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000185 s.close()
186
187 # this should fail because we have no verification certs
188 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
189 cert_reqs=ssl.CERT_REQUIRED)
190 try:
191 s.connect(("svn.python.org", 443))
192 except ssl.SSLError:
193 pass
194 finally:
195 s.close()
196
197 # this should succeed because we specify the root cert
198 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
199 cert_reqs=ssl.CERT_REQUIRED,
200 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
201 try:
202 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000203 finally:
204 s.close()
205
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000206 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
207 def test_makefile_close(self):
208 # Issue #5238: creating a file-like object with makefile() shouldn't
209 # delay closing the underlying "real socket" (here tested with its
210 # file descriptor, hence skipping the test under Windows).
211 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
212 ss.connect(("svn.python.org", 443))
213 fd = ss.fileno()
214 f = ss.makefile()
215 f.close()
216 # The fd is still open
217 os.read(fd, 0)
218 # Closing the SSL socket should close the fd too
219 ss.close()
220 gc.collect()
221 with self.assertRaises(OSError) as e:
222 os.read(fd, 0)
223 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000224
Antoine Pitrou3945c862010-04-28 21:11:01 +0000225 def test_non_blocking_handshake(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000226 s = socket.socket(socket.AF_INET)
227 s.connect(("svn.python.org", 443))
228 s.setblocking(False)
229 s = ssl.wrap_socket(s,
230 cert_reqs=ssl.CERT_NONE,
231 do_handshake_on_connect=False)
232 count = 0
233 while True:
234 try:
235 count += 1
236 s.do_handshake()
237 break
238 except ssl.SSLError, err:
239 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
240 select.select([s], [], [])
241 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
242 select.select([], [s], [])
243 else:
244 raise
245 s.close()
246 if test_support.verbose:
247 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
248
Antoine Pitrou3945c862010-04-28 21:11:01 +0000249 def test_get_server_certificate(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000250 pem = ssl.get_server_certificate(("svn.python.org", 443))
251 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000252 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000253
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:
Antoine Pitroudb187842010-04-27 10:32:58 +0000260 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000261
262 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
263 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000264 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000265 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:
Bill Janssen98d19da2007-09-10 21:51:02 +0000297 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000298
Bill Janssen98d19da2007-09-10 21:51:02 +0000299 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000300
Bill Janssen98d19da2007-09-10 21:51:02 +0000301 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000302
Bill Janssen98d19da2007-09-10 21:51:02 +0000303 """A mildly complicated class, because we want it to work both
304 with and without the SSL wrapper around the socket connection, so
305 that we can test the STARTTLS functionality."""
306
307 def __init__(self, server, connsock):
308 self.server = server
309 self.running = False
310 self.sock = connsock
311 self.sock.setblocking(1)
312 self.sslconn = None
313 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000314 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000315
Bill Janssen934b16d2008-06-28 22:19:33 +0000316 def show_conn_details(self):
317 if self.server.certreqs == ssl.CERT_REQUIRED:
318 cert = self.sslconn.getpeercert()
319 if test_support.verbose and self.server.chatty:
320 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
321 cert_binary = self.sslconn.getpeercert(True)
322 if test_support.verbose and self.server.chatty:
323 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
324 cipher = self.sslconn.cipher()
325 if test_support.verbose and self.server.chatty:
326 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
327
Antoine Pitrou3945c862010-04-28 21:11:01 +0000328 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000329 try:
330 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
331 certfile=self.server.certificate,
332 ssl_version=self.server.protocol,
333 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000334 cert_reqs=self.server.certreqs,
335 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000336 except ssl.SSLError:
337 # XXX Various errors can have happened here, for example
338 # a mismatching protocol version, an invalid certificate,
339 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000340 if self.server.chatty:
341 handle_error("\n server: bad connection attempt from " +
342 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000343 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000344 self.running = False
345 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000346 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000347 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000348 return True
349
350 def read(self):
351 if self.sslconn:
352 return self.sslconn.read()
353 else:
354 return self.sock.recv(1024)
355
356 def write(self, bytes):
357 if self.sslconn:
358 return self.sslconn.write(bytes)
359 else:
360 return self.sock.send(bytes)
361
362 def close(self):
363 if self.sslconn:
364 self.sslconn.close()
365 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000366 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000367
Antoine Pitrou3945c862010-04-28 21:11:01 +0000368 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000369 self.running = True
370 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000371 if isinstance(self.sock, ssl.SSLSocket):
372 self.sslconn = self.sock
373 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000374 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000375 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000376 while self.running:
377 try:
378 msg = self.read()
379 if not msg:
380 # eof, so quit this handler
381 self.running = False
382 self.close()
383 elif msg.strip() == 'over':
384 if test_support.verbose and self.server.connectionchatty:
385 sys.stdout.write(" server: client closed connection\n")
386 self.close()
387 return
388 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
389 if test_support.verbose and self.server.connectionchatty:
390 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
391 self.write("OK\n")
392 if not self.wrap_conn():
393 return
Bill Janssen39295c22008-08-12 16:31:21 +0000394 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
395 if test_support.verbose and self.server.connectionchatty:
396 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
397 self.write("OK\n")
398 self.sslconn.unwrap()
399 self.sslconn = None
400 if test_support.verbose and self.server.connectionchatty:
401 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000402 else:
403 if (test_support.verbose and
404 self.server.connectionchatty):
405 ctype = (self.sslconn and "encrypted") or "unencrypted"
406 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
407 % (repr(msg), ctype, repr(msg.lower()), ctype))
408 self.write(msg.lower())
409 except ssl.SSLError:
410 if self.server.chatty:
411 handle_error("Test server failure:\n")
412 self.close()
413 self.running = False
414 # normally, we'd just stop here, but for the test
415 # harness, we want to stop the server
416 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000417
Trent Nelsone41b0062008-04-08 23:47:30 +0000418 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000419 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000420 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000421 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000422
Bill Janssen98d19da2007-09-10 21:51:02 +0000423 if ssl_version is None:
424 ssl_version = ssl.PROTOCOL_TLSv1
425 if certreqs is None:
426 certreqs = ssl.CERT_NONE
427 self.certificate = certificate
428 self.protocol = ssl_version
429 self.certreqs = certreqs
430 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000431 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000432 self.chatty = chatty
433 self.connectionchatty = connectionchatty
434 self.starttls_server = starttls_server
435 self.sock = socket.socket()
436 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000437 if wrap_accepting_socket:
438 self.sock = ssl.wrap_socket(self.sock, server_side=True,
439 certfile=self.certificate,
440 cert_reqs = self.certreqs,
441 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000442 ssl_version = self.protocol,
443 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000444 if test_support.verbose and self.chatty:
445 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
446 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000447 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000448 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000449 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000450
Antoine Pitrou3945c862010-04-28 21:11:01 +0000451 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000452 self.flag = flag
453 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000454
Antoine Pitrou3945c862010-04-28 21:11:01 +0000455 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000456 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000457 self.sock.listen(5)
458 self.active = True
459 if self.flag:
460 # signal an event
461 self.flag.set()
462 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000463 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000464 newconn, connaddr = self.sock.accept()
465 if test_support.verbose and self.chatty:
466 sys.stdout.write(' server: new connection from '
467 + str(connaddr) + '\n')
468 handler = self.ConnectionHandler(self, newconn)
469 handler.start()
470 except socket.timeout:
471 pass
472 except KeyboardInterrupt:
473 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000474 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000475
Antoine Pitrou3945c862010-04-28 21:11:01 +0000476 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000477 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000478
Bill Janssen934b16d2008-06-28 22:19:33 +0000479 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000480
Antoine Pitrou3945c862010-04-28 21:11:01 +0000481 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000482
Antoine Pitrou3945c862010-04-28 21:11:01 +0000483 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000484
485 def __init__(self, conn, certfile):
486 asyncore.dispatcher_with_send.__init__(self, conn)
487 self.socket = ssl.wrap_socket(conn, server_side=True,
488 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000489 do_handshake_on_connect=False)
490 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000491
492 def readable(self):
493 if isinstance(self.socket, ssl.SSLSocket):
494 while self.socket.pending() > 0:
495 self.handle_read_event()
496 return True
497
Antoine Pitroufc69af12010-04-24 20:04:58 +0000498 def _do_ssl_handshake(self):
499 try:
500 self.socket.do_handshake()
501 except ssl.SSLError, err:
502 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
503 ssl.SSL_ERROR_WANT_WRITE):
504 return
505 elif err.args[0] == ssl.SSL_ERROR_EOF:
506 return self.handle_close()
507 raise
508 except socket.error, err:
509 if err.args[0] == errno.ECONNABORTED:
510 return self.handle_close()
511 else:
512 self._ssl_accepting = False
513
Bill Janssen934b16d2008-06-28 22:19:33 +0000514 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000515 if self._ssl_accepting:
516 self._do_ssl_handshake()
517 else:
518 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000519 if data and data.strip() != 'over':
520 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000521
522 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000523 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000524 if test_support.verbose:
525 sys.stdout.write(" server: closed connection %s\n" % self.socket)
526
527 def handle_error(self):
528 raise
529
530 def __init__(self, certfile):
531 self.certfile = certfile
532 asyncore.dispatcher.__init__(self)
533 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
534 self.port = test_support.bind_port(self.socket)
535 self.listen(5)
536
537 def handle_accept(self):
538 sock_obj, addr = self.accept()
539 if test_support.verbose:
540 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
541 self.ConnectionHandler(sock_obj, self.certfile)
542
543 def handle_error(self):
544 raise
545
546 def __init__(self, certfile):
547 self.flag = None
548 self.active = False
549 self.server = self.EchoServer(certfile)
550 self.port = self.server.port
551 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000552 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000553
554 def __str__(self):
555 return "<%s %s>" % (self.__class__.__name__, self.server)
556
Antoine Pitrou3945c862010-04-28 21:11:01 +0000557 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000558 self.flag = flag
559 threading.Thread.start(self)
560
Antoine Pitrou3945c862010-04-28 21:11:01 +0000561 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000562 self.active = True
563 if self.flag:
564 self.flag.set()
565 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000566 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000567
Antoine Pitrou3945c862010-04-28 21:11:01 +0000568 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000569 self.active = False
570 self.server.close()
571
572 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000573
574 class HTTPSServer(HTTPServer):
575
576 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000577 HTTPServer.__init__(self, server_address, RequestHandlerClass)
578 # we assume the certfile contains both private key and certificate
579 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000580 self.allow_reuse_address = True
581
Bill Janssen934b16d2008-06-28 22:19:33 +0000582 def __str__(self):
583 return ('<%s %s:%s>' %
584 (self.__class__.__name__,
585 self.server_name,
586 self.server_port))
587
Antoine Pitrou3945c862010-04-28 21:11:01 +0000588 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000589 # override this to wrap socket with SSL
590 sock, addr = self.socket.accept()
591 sslconn = ssl.wrap_socket(sock, server_side=True,
592 certfile=self.certfile)
593 return sslconn, addr
594
Bill Janssen296a59d2007-09-16 22:06:00 +0000595 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000596 # need to override translate_path to get a known root,
597 # instead of using os.curdir, since the test could be
598 # run from anywhere
599
600 server_version = "TestHTTPS/1.0"
601
602 root = None
603
604 def translate_path(self, path):
605 """Translate a /-separated PATH to the local filename syntax.
606
607 Components that mean special things to the local file system
608 (e.g. drive or directory names) are ignored. (XXX They should
609 probably be diagnosed.)
610
611 """
612 # abandon query parameters
613 path = urlparse.urlparse(path)[2]
614 path = os.path.normpath(urllib.unquote(path))
615 words = path.split('/')
616 words = filter(None, words)
617 path = self.root
618 for word in words:
619 drive, word = os.path.splitdrive(word)
620 head, word = os.path.split(word)
621 if word in self.root: continue
622 path = os.path.join(path, word)
623 return path
624
625 def log_message(self, format, *args):
626
627 # we override this to suppress logging unless "verbose"
628
629 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000630 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
631 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000632 self.server.server_port,
633 self.request.cipher(),
634 self.log_date_time_string(),
635 format%args))
636
637
Trent Nelsone41b0062008-04-08 23:47:30 +0000638 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000639 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000640 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
641 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000642 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
643 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000644 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000645 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000646
647 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000648 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000649
Antoine Pitrou3945c862010-04-28 21:11:01 +0000650 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000651 self.flag = flag
652 threading.Thread.start(self)
653
Antoine Pitrou3945c862010-04-28 21:11:01 +0000654 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000655 if self.flag:
656 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000657 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000658
Antoine Pitrou3945c862010-04-28 21:11:01 +0000659 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000660 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000661
662
Antoine Pitrou3945c862010-04-28 21:11:01 +0000663 def bad_cert_test(certfile):
664 """
665 Launch a server with CERT_REQUIRED, and check that trying to
666 connect to it with the given client certificate fails.
667 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000668 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000669 certreqs=ssl.CERT_REQUIRED,
670 cacerts=CERTFILE, chatty=False)
671 flag = threading.Event()
672 server.start(flag)
673 # wait for it to start
674 flag.wait()
675 # try to connect
676 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000677 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000678 s = ssl.wrap_socket(socket.socket(),
679 certfile=certfile,
680 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000681 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000682 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000683 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000684 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000685 except socket.error, x:
686 if test_support.verbose:
687 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000688 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000689 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000690 finally:
691 server.stop()
692 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000693
Antoine Pitrou3945c862010-04-28 21:11:01 +0000694 def server_params_test(certfile, protocol, certreqs, cacertsfile,
695 client_certfile, client_protocol=None, indata="FOO\n",
696 ciphers=None, chatty=True, connectionchatty=False,
697 wrap_accepting_socket=False):
698 """
699 Launch a server, connect a client to it and try various reads
700 and writes.
701 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000702 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000703 certreqs=certreqs,
704 ssl_version=protocol,
705 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000706 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000707 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000708 connectionchatty=connectionchatty,
709 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000710 flag = threading.Event()
711 server.start(flag)
712 # wait for it to start
713 flag.wait()
714 # try to connect
715 if client_protocol is None:
716 client_protocol = protocol
717 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000718 s = ssl.wrap_socket(socket.socket(),
719 certfile=client_certfile,
720 ca_certs=cacertsfile,
721 ciphers=ciphers,
722 cert_reqs=certreqs,
723 ssl_version=client_protocol)
724 s.connect((HOST, server.port))
725 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000726 if connectionchatty:
727 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000728 sys.stdout.write(
729 " client: sending %s...\n" % (repr(arg)))
730 s.write(arg)
731 outdata = s.read()
732 if connectionchatty:
733 if test_support.verbose:
734 sys.stdout.write(" client: read %s\n" % repr(outdata))
735 if outdata != indata.lower():
736 self.fail(
737 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
738 % (outdata[:min(len(outdata),20)], len(outdata),
739 indata[:min(len(indata),20)].lower(), len(indata)))
740 s.write("over\n")
741 if connectionchatty:
742 if test_support.verbose:
743 sys.stdout.write(" client: closing connection.\n")
744 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000745 finally:
746 server.stop()
747 server.join()
748
Antoine Pitrou3945c862010-04-28 21:11:01 +0000749 def try_protocol_combo(server_protocol,
750 client_protocol,
751 expect_success,
752 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000753 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000754 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000755 certtype = {
756 ssl.CERT_NONE: "CERT_NONE",
757 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
758 ssl.CERT_REQUIRED: "CERT_REQUIRED",
759 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000760 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000761 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000762 sys.stdout.write(formatstr %
763 (ssl.get_protocol_name(client_protocol),
764 ssl.get_protocol_name(server_protocol),
765 certtype))
766 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000767 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
768 # will send an SSLv3 hello (rather than SSLv2) starting from
769 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000770 server_params_test(CERTFILE, server_protocol, certsreqs,
771 CERTFILE, CERTFILE, client_protocol,
772 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000773 # Protocol mismatch can result in either an SSLError, or a
774 # "Connection reset by peer" error.
775 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000776 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000777 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000778 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000779 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000780 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000781 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000782 if not expect_success:
Antoine Pitroudb187842010-04-27 10:32:58 +0000783 self.fail(
Bill Janssen98d19da2007-09-10 21:51:02 +0000784 "Client protocol %s succeeded with server protocol %s!"
785 % (ssl.get_protocol_name(client_protocol),
786 ssl.get_protocol_name(server_protocol)))
787
788
Bill Janssen934b16d2008-06-28 22:19:33 +0000789 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000790
Antoine Pitrou3945c862010-04-28 21:11:01 +0000791 def test_rude_shutdown(self):
792 """A brutal shutdown of an SSL server should raise an IOError
793 in the client when attempting handshake.
794 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000795 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
Antoine Pitrou3945c862010-04-28 21:11:01 +0000831 def test_echo(self):
832 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000833 if test_support.verbose:
834 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000835 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
836 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
837 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000838
Antoine Pitrou3945c862010-04-28 21:11:01 +0000839 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000840 if test_support.verbose:
841 sys.stdout.write("\n")
842 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000843 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000844 certreqs=ssl.CERT_NONE,
845 ssl_version=ssl.PROTOCOL_SSLv23,
846 cacerts=CERTFILE,
847 chatty=False)
848 flag = threading.Event()
849 server.start(flag)
850 # wait for it to start
851 flag.wait()
852 # try to connect
853 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000854 s = ssl.wrap_socket(socket.socket(),
855 certfile=CERTFILE,
856 ca_certs=CERTFILE,
857 cert_reqs=ssl.CERT_REQUIRED,
858 ssl_version=ssl.PROTOCOL_SSLv23)
859 s.connect((HOST, server.port))
860 cert = s.getpeercert()
861 self.assertTrue(cert, "Can't get peer certificate.")
862 cipher = s.cipher()
863 if test_support.verbose:
864 sys.stdout.write(pprint.pformat(cert) + '\n')
865 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
866 if 'subject' not in cert:
867 self.fail("No subject field in certificate: %s." %
868 pprint.pformat(cert))
869 if ((('organizationName', 'Python Software Foundation'),)
870 not in cert['subject']):
871 self.fail(
872 "Missing or invalid 'organizationName' field in certificate subject; "
873 "should be 'Python Software Foundation'.")
874 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000875 finally:
876 server.stop()
877 server.join()
878
Antoine Pitrou3945c862010-04-28 21:11:01 +0000879 def test_empty_cert(self):
880 """Connecting with an empty cert file"""
881 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
882 "nullcert.pem"))
883 def test_malformed_cert(self):
884 """Connecting with a badly formatted certificate (syntax error)"""
885 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
886 "badcert.pem"))
887 def test_nonexisting_cert(self):
888 """Connecting with a non-existing cert file"""
889 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
890 "wrongcert.pem"))
891 def test_malformed_key(self):
892 """Connecting with a badly formatted key (syntax error)"""
893 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
894 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000895
Antoine Pitrou3945c862010-04-28 21:11:01 +0000896 def test_protocol_sslv2(self):
897 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000898 if test_support.verbose:
899 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000900 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
901 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
902 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
903 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
904 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
905 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000906
Antoine Pitrou3945c862010-04-28 21:11:01 +0000907 def test_protocol_sslv23(self):
908 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000909 if test_support.verbose:
910 sys.stdout.write("\n")
911 try:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000912 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000913 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000914 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
915 if test_support.verbose:
916 sys.stdout.write(
917 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
918 % str(x))
Antoine Pitrou3945c862010-04-28 21:11:01 +0000919 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
920 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
921 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000922
Antoine Pitrou3945c862010-04-28 21:11:01 +0000923 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
924 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
925 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000926
Antoine Pitrou3945c862010-04-28 21:11:01 +0000927 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
928 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
929 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000930
Antoine Pitrou3945c862010-04-28 21:11:01 +0000931 def test_protocol_sslv3(self):
932 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000933 if test_support.verbose:
934 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000935 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
936 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
937 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
938 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
939 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
940 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000941
Antoine Pitrou3945c862010-04-28 21:11:01 +0000942 def test_protocol_tlsv1(self):
943 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000944 if test_support.verbose:
945 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000946 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
947 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
948 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
949 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
950 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
951 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000952
Antoine Pitrou3945c862010-04-28 21:11:01 +0000953 def test_starttls(self):
954 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000955 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000956
Trent Nelsone41b0062008-04-08 23:47:30 +0000957 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000958 ssl_version=ssl.PROTOCOL_TLSv1,
959 starttls_server=True,
960 chatty=True,
961 connectionchatty=True)
962 flag = threading.Event()
963 server.start(flag)
964 # wait for it to start
965 flag.wait()
966 # try to connect
967 wrapped = False
968 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000969 s = socket.socket()
970 s.setblocking(1)
971 s.connect((HOST, server.port))
972 if test_support.verbose:
973 sys.stdout.write("\n")
974 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000975 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000976 sys.stdout.write(
977 " client: sending %s...\n" % repr(indata))
978 if wrapped:
979 conn.write(indata)
980 outdata = conn.read()
981 else:
982 s.send(indata)
983 outdata = s.recv(1024)
984 if (indata == "STARTTLS" and
985 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +0000986 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +0000987 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000988 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +0000989 " client: read %s from server, starting TLS...\n"
990 % repr(outdata))
991 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
992 wrapped = True
993 elif (indata == "ENDTLS" and
994 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +0000995 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +0000996 if test_support.verbose:
997 sys.stdout.write(
998 " client: read %s from server, ending TLS...\n"
999 % repr(outdata))
1000 s = conn.unwrap()
1001 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001002 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001003 if test_support.verbose:
1004 sys.stdout.write(
1005 " client: read %s from server\n" % repr(outdata))
1006 if test_support.verbose:
1007 sys.stdout.write(" client: closing connection.\n")
1008 if wrapped:
1009 conn.write("over\n")
1010 else:
1011 s.send("over\n")
1012 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001013 finally:
1014 server.stop()
1015 server.join()
1016
Antoine Pitrou3945c862010-04-28 21:11:01 +00001017 def test_socketserver(self):
1018 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001019 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001020 flag = threading.Event()
1021 server.start(flag)
1022 # wait for it to start
1023 flag.wait()
1024 # try to connect
1025 try:
1026 if test_support.verbose:
1027 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001028 with open(CERTFILE, 'rb') as f:
1029 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001030 d2 = ''
1031 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001032 url = 'https://127.0.0.1:%d/%s' % (
1033 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001034 with test_support.check_py3k_warnings():
1035 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001036 dlen = f.info().getheader("content-length")
1037 if dlen and (int(dlen) > 0):
1038 d2 = f.read(int(dlen))
1039 if test_support.verbose:
1040 sys.stdout.write(
1041 " client: read %d bytes from remote server '%s'\n"
1042 % (len(d2), server))
1043 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001044 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001045 finally:
1046 server.stop()
1047 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001048
Antoine Pitrou3945c862010-04-28 21:11:01 +00001049 def test_wrapped_accept(self):
1050 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001051 if test_support.verbose:
1052 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001053 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1054 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1055 chatty=True, connectionchatty=True,
1056 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001057
Antoine Pitrou3945c862010-04-28 21:11:01 +00001058 def test_asyncore_server(self):
1059 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001060 indata = "TEST MESSAGE of mixed case\n"
1061
1062 if test_support.verbose:
1063 sys.stdout.write("\n")
1064 server = AsyncoreEchoServer(CERTFILE)
1065 flag = threading.Event()
1066 server.start(flag)
1067 # wait for it to start
1068 flag.wait()
1069 # try to connect
1070 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001071 s = ssl.wrap_socket(socket.socket())
1072 s.connect(('127.0.0.1', server.port))
1073 if test_support.verbose:
1074 sys.stdout.write(
1075 " client: sending %s...\n" % (repr(indata)))
1076 s.write(indata)
1077 outdata = s.read()
1078 if test_support.verbose:
1079 sys.stdout.write(" client: read %s\n" % repr(outdata))
1080 if outdata != indata.lower():
1081 self.fail(
1082 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1083 % (outdata[:min(len(outdata),20)], len(outdata),
1084 indata[:min(len(indata),20)].lower(), len(indata)))
1085 s.write("over\n")
1086 if test_support.verbose:
1087 sys.stdout.write(" client: closing connection.\n")
1088 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001089 finally:
1090 server.stop()
1091 # wait for server thread to end
1092 server.join()
1093
Antoine Pitrou3945c862010-04-28 21:11:01 +00001094 def test_recv_send(self):
1095 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001096 if test_support.verbose:
1097 sys.stdout.write("\n")
1098
1099 server = ThreadedEchoServer(CERTFILE,
1100 certreqs=ssl.CERT_NONE,
1101 ssl_version=ssl.PROTOCOL_TLSv1,
1102 cacerts=CERTFILE,
1103 chatty=True,
1104 connectionchatty=False)
1105 flag = threading.Event()
1106 server.start(flag)
1107 # wait for it to start
1108 flag.wait()
1109 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001110 s = ssl.wrap_socket(socket.socket(),
1111 server_side=False,
1112 certfile=CERTFILE,
1113 ca_certs=CERTFILE,
1114 cert_reqs=ssl.CERT_NONE,
1115 ssl_version=ssl.PROTOCOL_TLSv1)
1116 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001117 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001118 # helper methods for standardising recv* method signatures
1119 def _recv_into():
1120 b = bytearray("\0"*100)
1121 count = s.recv_into(b)
1122 return b[:count]
1123
1124 def _recvfrom_into():
1125 b = bytearray("\0"*100)
1126 count, addr = s.recvfrom_into(b)
1127 return b[:count]
1128
1129 # (name, method, whether to expect success, *args)
1130 send_methods = [
1131 ('send', s.send, True, []),
1132 ('sendto', s.sendto, False, ["some.address"]),
1133 ('sendall', s.sendall, True, []),
1134 ]
1135 recv_methods = [
1136 ('recv', s.recv, True, []),
1137 ('recvfrom', s.recvfrom, False, ["some.address"]),
1138 ('recv_into', _recv_into, True, []),
1139 ('recvfrom_into', _recvfrom_into, False, []),
1140 ]
1141 data_prefix = u"PREFIX_"
1142
1143 for meth_name, send_meth, expect_success, args in send_methods:
1144 indata = data_prefix + meth_name
1145 try:
1146 send_meth(indata.encode('ASCII', 'strict'), *args)
1147 outdata = s.read()
1148 outdata = outdata.decode('ASCII', 'strict')
1149 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001150 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001151 "While sending with <<%s>> bad data "
1152 "<<%r>> (%d) received; "
1153 "expected <<%r>> (%d)\n" % (
1154 meth_name, outdata[:20], len(outdata),
1155 indata[:20], len(indata)
1156 )
1157 )
1158 except ValueError as e:
1159 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001160 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001161 "Failed to send with method <<%s>>; "
1162 "expected to succeed.\n" % (meth_name,)
1163 )
1164 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001165 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001166 "Method <<%s>> failed with unexpected "
1167 "exception message: %s\n" % (
1168 meth_name, e
1169 )
1170 )
1171
1172 for meth_name, recv_meth, expect_success, args in recv_methods:
1173 indata = data_prefix + meth_name
1174 try:
1175 s.send(indata.encode('ASCII', 'strict'))
1176 outdata = recv_meth(*args)
1177 outdata = outdata.decode('ASCII', 'strict')
1178 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001179 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001180 "While receiving with <<%s>> bad data "
1181 "<<%r>> (%d) received; "
1182 "expected <<%r>> (%d)\n" % (
1183 meth_name, outdata[:20], len(outdata),
1184 indata[:20], len(indata)
1185 )
1186 )
1187 except ValueError as e:
1188 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001189 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001190 "Failed to receive with method <<%s>>; "
1191 "expected to succeed.\n" % (meth_name,)
1192 )
1193 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001194 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001195 "Method <<%s>> failed with unexpected "
1196 "exception message: %s\n" % (
1197 meth_name, e
1198 )
1199 )
1200 # consume data
1201 s.read()
1202
1203 s.write("over\n".encode("ASCII", "strict"))
1204 s.close()
1205 finally:
1206 server.stop()
1207 server.join()
1208
Antoine Pitroufc69af12010-04-24 20:04:58 +00001209 def test_handshake_timeout(self):
1210 # Issue #5103: SSL handshake must respect the socket timeout
1211 server = socket.socket(socket.AF_INET)
1212 host = "127.0.0.1"
1213 port = test_support.bind_port(server)
1214 started = threading.Event()
1215 finish = False
1216
1217 def serve():
1218 server.listen(5)
1219 started.set()
1220 conns = []
1221 while not finish:
1222 r, w, e = select.select([server], [], [], 0.1)
1223 if server in r:
1224 # Let the socket hang around rather than having
1225 # it closed by garbage collection.
1226 conns.append(server.accept()[0])
1227
1228 t = threading.Thread(target=serve)
1229 t.start()
1230 started.wait()
1231
1232 try:
1233 try:
1234 c = socket.socket(socket.AF_INET)
1235 c.settimeout(0.2)
1236 c.connect((host, port))
1237 # Will attempt handshake and time out
1238 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1239 ssl.wrap_socket, c)
1240 finally:
1241 c.close()
1242 try:
1243 c = socket.socket(socket.AF_INET)
1244 c.settimeout(0.2)
1245 c = ssl.wrap_socket(c)
1246 # Will attempt handshake and time out
1247 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1248 c.connect, (host, port))
1249 finally:
1250 c.close()
1251 finally:
1252 finish = True
1253 t.join()
1254 server.close()
1255
Bill Janssen61c001a2008-09-08 16:37:24 +00001256
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001257def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001258 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001259 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001260
Trent Nelsone41b0062008-04-08 23:47:30 +00001261 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001262 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001263 "keycert.pem")
1264 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1265 os.path.dirname(__file__) or os.curdir,
1266 "https_svn_python_org_root.pem")
1267
1268 if (not os.path.exists(CERTFILE) or
1269 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001270 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001271
1272 tests = [BasicTests]
1273
Bill Janssen296a59d2007-09-16 22:06:00 +00001274 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001275 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001276
Bill Janssen98d19da2007-09-10 21:51:02 +00001277 if _have_threads:
1278 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001279 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001280 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001281
Antoine Pitrou3945c862010-04-28 21:11:01 +00001282 try:
1283 test_support.run_unittest(*tests)
1284 finally:
1285 if _have_threads:
1286 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001287
1288if __name__ == "__main__":
1289 test_main()