blob: ebb556b0545b2722d504332ab38b670a25497780 [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
Bill Jansseneb257ac2008-09-29 18:56:38 +000037 def testSimpleSSLwrap(self):
38 try:
39 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
40 except IOError, e:
41 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
42 pass
43 else:
44 raise
45 try:
46 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
47 except IOError, e:
48 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
49 pass
50 else:
51 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000052
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000053class BasicTests(unittest.TestCase):
54
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000055 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000056 if not test_support.is_resource_enabled('network'):
57 return
Bill Janssen296a59d2007-09-16 22:06:00 +000058 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
59 cert_reqs=ssl.CERT_NONE)
60 s.connect(("svn.python.org", 443))
61 c = s.getpeercert()
62 if c:
63 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
64 s.close()
65
66 # this should fail because we have no verification certs
67 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
68 cert_reqs=ssl.CERT_REQUIRED)
69 try:
70 s.connect(("svn.python.org", 443))
71 except ssl.SSLError:
72 pass
73 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000074 s.close()
75
Bill Janssen98d19da2007-09-10 21:51:02 +000076 def testCrucialConstants(self):
77 ssl.PROTOCOL_SSLv2
78 ssl.PROTOCOL_SSLv23
79 ssl.PROTOCOL_SSLv3
80 ssl.PROTOCOL_TLSv1
81 ssl.CERT_NONE
82 ssl.CERT_OPTIONAL
83 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000084
Bill Janssen98d19da2007-09-10 21:51:02 +000085 def testRAND(self):
86 v = ssl.RAND_status()
87 if test_support.verbose:
88 sys.stdout.write("\n RAND_status is %d (%s)\n"
89 % (v, (v and "sufficient randomness") or
90 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000091 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000092 ssl.RAND_egd(1)
93 except TypeError:
94 pass
Guido van Rossume4729332007-08-26 19:35:09 +000095 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000096 print "didn't raise TypeError"
97 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000098
Bill Janssen98d19da2007-09-10 21:51:02 +000099 def testParseCert(self):
100 # note that this uses an 'unofficial' function in _ssl.c,
101 # provided solely for this test, to exercise the certificate
102 # parsing code
103 p = ssl._ssl._test_decode_cert(CERTFILE, False)
104 if test_support.verbose:
105 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000106
Bill Janssen296a59d2007-09-16 22:06:00 +0000107 def testDERtoPEM(self):
108
109 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
110 d1 = ssl.PEM_cert_to_DER_cert(pem)
111 p2 = ssl.DER_cert_to_PEM_cert(d1)
112 d2 = ssl.PEM_cert_to_DER_cert(p2)
113 if (d1 != d2):
114 raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
115
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000116 def test_openssl_version(self):
117 n = ssl.OPENSSL_VERSION_NUMBER
118 t = ssl.OPENSSL_VERSION_INFO
119 s = ssl.OPENSSL_VERSION
120 self.assertIsInstance(n, (int, long))
121 self.assertIsInstance(t, tuple)
122 self.assertIsInstance(s, str)
123 # Some sanity checks follow
124 # >= 0.9
125 self.assertGreaterEqual(n, 0x900000)
126 # < 2.0
127 self.assertLess(n, 0x20000000)
128 major, minor, fix, patch, status = t
129 self.assertGreaterEqual(major, 0)
130 self.assertLess(major, 2)
131 self.assertGreaterEqual(minor, 0)
132 self.assertLess(minor, 256)
133 self.assertGreaterEqual(fix, 0)
134 self.assertLess(fix, 256)
135 self.assertGreaterEqual(patch, 0)
136 self.assertLessEqual(patch, 26)
137 self.assertGreaterEqual(status, 0)
138 self.assertLessEqual(status, 15)
139 # Version string as returned by OpenSSL, the format might change
140 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
141 (s, t))
142
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000143 def test_ciphers(self):
144 if not test_support.is_resource_enabled('network'):
145 return
146 remote = ("svn.python.org", 443)
147 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
148 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
149 s.connect(remote)
150 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
151 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
152 s.connect(remote)
153 # Error checking occurs when connecting, because the SSL context
154 # isn't created before.
155 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
156 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
157 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
158 s.connect(remote)
159
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000160 @test_support.cpython_only
161 def test_refcycle(self):
162 # Issue #7943: an SSL object doesn't create reference cycles with
163 # itself.
164 s = socket.socket(socket.AF_INET)
165 ss = ssl.wrap_socket(s)
166 wr = weakref.ref(ss)
167 del ss
168 self.assertEqual(wr(), None)
169
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000170
Bill Janssen934b16d2008-06-28 22:19:33 +0000171class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000172
173 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000174 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
175 cert_reqs=ssl.CERT_NONE)
176 s.connect(("svn.python.org", 443))
177 c = s.getpeercert()
178 if c:
179 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
180 s.close()
181
182 # this should fail because we have no verification certs
183 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
184 cert_reqs=ssl.CERT_REQUIRED)
185 try:
186 s.connect(("svn.python.org", 443))
187 except ssl.SSLError:
188 pass
189 finally:
190 s.close()
191
192 # this should succeed because we specify the root cert
193 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
194 cert_reqs=ssl.CERT_REQUIRED,
195 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
196 try:
197 s.connect(("svn.python.org", 443))
198 except ssl.SSLError, x:
199 raise test_support.TestFailed("Unexpected exception %s" % x)
200 finally:
201 s.close()
202
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000203 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
204 def test_makefile_close(self):
205 # Issue #5238: creating a file-like object with makefile() shouldn't
206 # delay closing the underlying "real socket" (here tested with its
207 # file descriptor, hence skipping the test under Windows).
208 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
209 ss.connect(("svn.python.org", 443))
210 fd = ss.fileno()
211 f = ss.makefile()
212 f.close()
213 # The fd is still open
214 os.read(fd, 0)
215 # Closing the SSL socket should close the fd too
216 ss.close()
217 gc.collect()
218 with self.assertRaises(OSError) as e:
219 os.read(fd, 0)
220 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000221
222 def testNonBlockingHandshake(self):
223 s = socket.socket(socket.AF_INET)
224 s.connect(("svn.python.org", 443))
225 s.setblocking(False)
226 s = ssl.wrap_socket(s,
227 cert_reqs=ssl.CERT_NONE,
228 do_handshake_on_connect=False)
229 count = 0
230 while True:
231 try:
232 count += 1
233 s.do_handshake()
234 break
235 except ssl.SSLError, err:
236 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
237 select.select([s], [], [])
238 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
239 select.select([], [s], [])
240 else:
241 raise
242 s.close()
243 if test_support.verbose:
244 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
245
Bill Janssen296a59d2007-09-16 22:06:00 +0000246 def testFetchServerCert(self):
247
248 pem = ssl.get_server_certificate(("svn.python.org", 443))
249 if not pem:
250 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
251
252 try:
253 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
254 except ssl.SSLError:
255 #should fail
256 pass
257 else:
258 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
259
260 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
261 if not pem:
262 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
263 if test_support.verbose:
264 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
265
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000266 def test_algorithms(self):
267 # Issue #8484: all algorithms should be available when verifying a
268 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000269 # SHA256 was added in OpenSSL 0.9.8
270 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
271 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000272 # NOTE: https://sha256.tbs-internet.com is another possible test host
273 remote = ("sha2.hboeck.de", 443)
274 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
275 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
276 cert_reqs=ssl.CERT_REQUIRED,
277 ca_certs=sha256_cert,)
278 with test_support.transient_internet():
279 try:
280 s.connect(remote)
281 if test_support.verbose:
282 sys.stdout.write("\nCipher with %r is %r\n" %
283 (remote, s.cipher()))
284 sys.stdout.write("Certificate is:\n%s\n" %
285 pprint.pformat(s.getpeercert()))
286 finally:
287 s.close()
288
Bill Janssen296a59d2007-09-16 22:06:00 +0000289
Bill Janssen98d19da2007-09-10 21:51:02 +0000290try:
291 import threading
292except ImportError:
293 _have_threads = False
294else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000295
Bill Janssen98d19da2007-09-10 21:51:02 +0000296 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000297
Bill Janssen98d19da2007-09-10 21:51:02 +0000298 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000299
Bill Janssen98d19da2007-09-10 21:51:02 +0000300 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000301
Bill Janssen98d19da2007-09-10 21:51:02 +0000302 """A mildly complicated class, because we want it to work both
303 with and without the SSL wrapper around the socket connection, so
304 that we can test the STARTTLS functionality."""
305
306 def __init__(self, server, connsock):
307 self.server = server
308 self.running = False
309 self.sock = connsock
310 self.sock.setblocking(1)
311 self.sslconn = None
312 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000313 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000314
Bill Janssen934b16d2008-06-28 22:19:33 +0000315 def show_conn_details(self):
316 if self.server.certreqs == ssl.CERT_REQUIRED:
317 cert = self.sslconn.getpeercert()
318 if test_support.verbose and self.server.chatty:
319 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
320 cert_binary = self.sslconn.getpeercert(True)
321 if test_support.verbose and self.server.chatty:
322 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
323 cipher = self.sslconn.cipher()
324 if test_support.verbose and self.server.chatty:
325 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
326
Bill Janssen98d19da2007-09-10 21:51:02 +0000327 def wrap_conn (self):
328 try:
329 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
330 certfile=self.server.certificate,
331 ssl_version=self.server.protocol,
332 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000333 cert_reqs=self.server.certreqs,
334 ciphers=self.server.ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +0000335 except:
336 if self.server.chatty:
337 handle_error("\n server: bad connection attempt from " +
338 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000339 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000340 if not self.server.expect_bad_connects:
341 # here, we want to stop the server, because this shouldn't
342 # happen in the context of our test case
343 self.running = False
344 # normally, we'd just stop here, but for the test
345 # harness, we want to stop the server
346 self.server.stop()
347 return False
348
349 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000350 return True
351
352 def read(self):
353 if self.sslconn:
354 return self.sslconn.read()
355 else:
356 return self.sock.recv(1024)
357
358 def write(self, bytes):
359 if self.sslconn:
360 return self.sslconn.write(bytes)
361 else:
362 return self.sock.send(bytes)
363
364 def close(self):
365 if self.sslconn:
366 self.sslconn.close()
367 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000368 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000369
370 def run (self):
371 self.running = True
372 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000373 if isinstance(self.sock, ssl.SSLSocket):
374 self.sslconn = self.sock
375 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000376 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000377 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000378 while self.running:
379 try:
380 msg = self.read()
381 if not msg:
382 # eof, so quit this handler
383 self.running = False
384 self.close()
385 elif msg.strip() == 'over':
386 if test_support.verbose and self.server.connectionchatty:
387 sys.stdout.write(" server: client closed connection\n")
388 self.close()
389 return
390 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
391 if test_support.verbose and self.server.connectionchatty:
392 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
393 self.write("OK\n")
394 if not self.wrap_conn():
395 return
Bill Janssen39295c22008-08-12 16:31:21 +0000396 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
397 if test_support.verbose and self.server.connectionchatty:
398 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
399 self.write("OK\n")
400 self.sslconn.unwrap()
401 self.sslconn = None
402 if test_support.verbose and self.server.connectionchatty:
403 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000404 else:
405 if (test_support.verbose and
406 self.server.connectionchatty):
407 ctype = (self.sslconn and "encrypted") or "unencrypted"
408 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
409 % (repr(msg), ctype, repr(msg.lower()), ctype))
410 self.write(msg.lower())
411 except ssl.SSLError:
412 if self.server.chatty:
413 handle_error("Test server failure:\n")
414 self.close()
415 self.running = False
416 # normally, we'd just stop here, but for the test
417 # harness, we want to stop the server
418 self.server.stop()
419 except:
420 handle_error('')
421
Trent Nelsone41b0062008-04-08 23:47:30 +0000422 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000423 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000424 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000425 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000426
Bill Janssen98d19da2007-09-10 21:51:02 +0000427 if ssl_version is None:
428 ssl_version = ssl.PROTOCOL_TLSv1
429 if certreqs is None:
430 certreqs = ssl.CERT_NONE
431 self.certificate = certificate
432 self.protocol = ssl_version
433 self.certreqs = certreqs
434 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000435 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000436 self.expect_bad_connects = expect_bad_connects
437 self.chatty = chatty
438 self.connectionchatty = connectionchatty
439 self.starttls_server = starttls_server
440 self.sock = socket.socket()
441 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000442 if wrap_accepting_socket:
443 self.sock = ssl.wrap_socket(self.sock, server_side=True,
444 certfile=self.certificate,
445 cert_reqs = self.certreqs,
446 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000447 ssl_version = self.protocol,
448 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000449 if test_support.verbose and self.chatty:
450 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
451 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000452 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000453 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000454 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000455
456 def start (self, flag=None):
457 self.flag = flag
458 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000459
460 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000461 self.sock.settimeout(0.5)
462 self.sock.listen(5)
463 self.active = True
464 if self.flag:
465 # signal an event
466 self.flag.set()
467 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000468 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000469 newconn, connaddr = self.sock.accept()
470 if test_support.verbose and self.chatty:
471 sys.stdout.write(' server: new connection from '
472 + str(connaddr) + '\n')
473 handler = self.ConnectionHandler(self, newconn)
474 handler.start()
475 except socket.timeout:
476 pass
477 except KeyboardInterrupt:
478 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000479 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000480 if self.chatty:
481 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000482 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000483
Bill Janssen98d19da2007-09-10 21:51:02 +0000484 def stop (self):
485 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000486
Bill Janssen934b16d2008-06-28 22:19:33 +0000487 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000488
Bill Janssen934b16d2008-06-28 22:19:33 +0000489 class EchoServer (asyncore.dispatcher):
490
491 class ConnectionHandler (asyncore.dispatcher_with_send):
492
493 def __init__(self, conn, certfile):
494 asyncore.dispatcher_with_send.__init__(self, conn)
495 self.socket = ssl.wrap_socket(conn, server_side=True,
496 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000497 do_handshake_on_connect=False)
498 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000499
500 def readable(self):
501 if isinstance(self.socket, ssl.SSLSocket):
502 while self.socket.pending() > 0:
503 self.handle_read_event()
504 return True
505
Antoine Pitroufc69af12010-04-24 20:04:58 +0000506 def _do_ssl_handshake(self):
507 try:
508 self.socket.do_handshake()
509 except ssl.SSLError, err:
510 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
511 ssl.SSL_ERROR_WANT_WRITE):
512 return
513 elif err.args[0] == ssl.SSL_ERROR_EOF:
514 return self.handle_close()
515 raise
516 except socket.error, err:
517 if err.args[0] == errno.ECONNABORTED:
518 return self.handle_close()
519 else:
520 self._ssl_accepting = False
521
Bill Janssen934b16d2008-06-28 22:19:33 +0000522 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000523 if self._ssl_accepting:
524 self._do_ssl_handshake()
525 else:
526 data = self.recv(1024)
527 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000528
529 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000530 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000531 if test_support.verbose:
532 sys.stdout.write(" server: closed connection %s\n" % self.socket)
533
534 def handle_error(self):
535 raise
536
537 def __init__(self, certfile):
538 self.certfile = certfile
539 asyncore.dispatcher.__init__(self)
540 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
541 self.port = test_support.bind_port(self.socket)
542 self.listen(5)
543
544 def handle_accept(self):
545 sock_obj, addr = self.accept()
546 if test_support.verbose:
547 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
548 self.ConnectionHandler(sock_obj, self.certfile)
549
550 def handle_error(self):
551 raise
552
553 def __init__(self, certfile):
554 self.flag = None
555 self.active = False
556 self.server = self.EchoServer(certfile)
557 self.port = self.server.port
558 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000559 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000560
561 def __str__(self):
562 return "<%s %s>" % (self.__class__.__name__, self.server)
563
564 def start (self, flag=None):
565 self.flag = flag
566 threading.Thread.start(self)
567
568 def run (self):
569 self.active = True
570 if self.flag:
571 self.flag.set()
572 while self.active:
573 try:
574 asyncore.loop(1)
575 except:
576 pass
577
578 def stop (self):
579 self.active = False
580 self.server.close()
581
582 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000583
584 class HTTPSServer(HTTPServer):
585
586 def __init__(self, server_address, RequestHandlerClass, certfile):
587
588 HTTPServer.__init__(self, server_address, RequestHandlerClass)
589 # we assume the certfile contains both private key and certificate
590 self.certfile = certfile
591 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000592 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000593 self.allow_reuse_address = True
594
Bill Janssen934b16d2008-06-28 22:19:33 +0000595 def __str__(self):
596 return ('<%s %s:%s>' %
597 (self.__class__.__name__,
598 self.server_name,
599 self.server_port))
600
Bill Janssen296a59d2007-09-16 22:06:00 +0000601 def get_request (self):
602 # override this to wrap socket with SSL
603 sock, addr = self.socket.accept()
604 sslconn = ssl.wrap_socket(sock, server_side=True,
605 certfile=self.certfile)
606 return sslconn, addr
607
608 # The methods overridden below this are mainly so that we
609 # can run it in a thread and be able to stop it from another
610 # You probably wouldn't need them in other uses.
611
612 def server_activate(self):
613 # We want to run this in a thread for testing purposes,
614 # so we override this to set timeout, so that we get
615 # a chance to stop the server
616 self.socket.settimeout(0.5)
617 HTTPServer.server_activate(self)
618
619 def serve_forever(self):
620 # We want this to run in a thread, so we use a slightly
621 # modified version of "forever".
622 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000623 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000624 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000625 # We need to lock while handling the request.
626 # Another thread can close the socket after self.active
627 # has been checked and before the request is handled.
628 # This causes an exception when using the closed socket.
629 with self.active_lock:
630 if not self.active:
631 break
632 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000633 except socket.timeout:
634 pass
635 except KeyboardInterrupt:
636 self.server_close()
637 return
638 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000639 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
640 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000641 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000642
643 def server_close(self):
644 # Again, we want this to run in a thread, so we need to override
645 # close to clear the "active" flag, so that serve_forever() will
646 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000647 with self.active_lock:
648 HTTPServer.server_close(self)
649 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000650
651 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
652
653 # need to override translate_path to get a known root,
654 # instead of using os.curdir, since the test could be
655 # run from anywhere
656
657 server_version = "TestHTTPS/1.0"
658
659 root = None
660
661 def translate_path(self, path):
662 """Translate a /-separated PATH to the local filename syntax.
663
664 Components that mean special things to the local file system
665 (e.g. drive or directory names) are ignored. (XXX They should
666 probably be diagnosed.)
667
668 """
669 # abandon query parameters
670 path = urlparse.urlparse(path)[2]
671 path = os.path.normpath(urllib.unquote(path))
672 words = path.split('/')
673 words = filter(None, words)
674 path = self.root
675 for word in words:
676 drive, word = os.path.splitdrive(word)
677 head, word = os.path.split(word)
678 if word in self.root: continue
679 path = os.path.join(path, word)
680 return path
681
682 def log_message(self, format, *args):
683
684 # we override this to suppress logging unless "verbose"
685
686 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000687 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
688 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000689 self.server.server_port,
690 self.request.cipher(),
691 self.log_date_time_string(),
692 format%args))
693
694
Trent Nelsone41b0062008-04-08 23:47:30 +0000695 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000696 self.flag = None
697 self.active = False
698 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
699 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000700 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
701 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000702 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000703 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000704
705 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000706 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000707
708 def start (self, flag=None):
709 self.flag = flag
710 threading.Thread.start(self)
711
712 def run (self):
713 self.active = True
714 if self.flag:
715 self.flag.set()
716 self.server.serve_forever()
717 self.active = False
718
719 def stop (self):
720 self.active = False
721 self.server.server_close()
722
723
Bill Janssen98d19da2007-09-10 21:51:02 +0000724 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000725 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000726 certreqs=ssl.CERT_REQUIRED,
727 cacerts=CERTFILE, chatty=False)
728 flag = threading.Event()
729 server.start(flag)
730 # wait for it to start
731 flag.wait()
732 # try to connect
733 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000734 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000735 s = ssl.wrap_socket(socket.socket(),
736 certfile=certfile,
737 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000738 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000739 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000740 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000741 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000742 except socket.error, x:
743 if test_support.verbose:
744 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000745 else:
746 raise test_support.TestFailed(
747 "Use of invalid cert should have failed!")
748 finally:
749 server.stop()
750 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000751
Bill Janssen98d19da2007-09-10 21:51:02 +0000752 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
753 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000754 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000755 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000756
Trent Nelsone41b0062008-04-08 23:47:30 +0000757 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000758 certreqs=certreqs,
759 ssl_version=protocol,
760 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000761 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000762 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000763 connectionchatty=connectionchatty,
764 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000765 flag = threading.Event()
766 server.start(flag)
767 # wait for it to start
768 flag.wait()
769 # try to connect
770 if client_protocol is None:
771 client_protocol = protocol
772 try:
773 try:
774 s = ssl.wrap_socket(socket.socket(),
775 certfile=client_certfile,
776 ca_certs=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000777 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000778 cert_reqs=certreqs,
779 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000780 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000781 except ssl.SSLError, x:
782 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
783 except Exception, x:
784 raise test_support.TestFailed("Unexpected exception: " + str(x))
785 else:
Antoine Pitrou5ba84912009-10-19 17:59:07 +0000786 for arg in [indata, bytearray(indata), memoryview(indata)]:
787 if connectionchatty:
788 if test_support.verbose:
789 sys.stdout.write(
790 " client: sending %s...\n" % (repr(arg)))
791 s.write(arg)
792 outdata = s.read()
793 if connectionchatty:
794 if test_support.verbose:
795 sys.stdout.write(" client: read %s\n" % repr(outdata))
796 if outdata != indata.lower():
797 raise test_support.TestFailed(
798 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
799 % (outdata[:min(len(outdata),20)], len(outdata),
800 indata[:min(len(indata),20)].lower(), len(indata)))
Bill Janssen98d19da2007-09-10 21:51:02 +0000801 s.write("over\n")
802 if connectionchatty:
803 if test_support.verbose:
804 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000805 s.close()
806 finally:
807 server.stop()
808 server.join()
809
810 def tryProtocolCombo (server_protocol,
811 client_protocol,
812 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000813 certsreqs=None):
814
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000815 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000816 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000817
818 if certsreqs == ssl.CERT_NONE:
819 certtype = "CERT_NONE"
820 elif certsreqs == ssl.CERT_OPTIONAL:
821 certtype = "CERT_OPTIONAL"
822 elif certsreqs == ssl.CERT_REQUIRED:
823 certtype = "CERT_REQUIRED"
824 if test_support.verbose:
825 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
826 sys.stdout.write(formatstr %
827 (ssl.get_protocol_name(client_protocol),
828 ssl.get_protocol_name(server_protocol),
829 certtype))
830 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000831 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
832 # will send an SSLv3 hello (rather than SSLv2) starting from
833 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000834 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000835 CERTFILE, CERTFILE, client_protocol,
836 ciphers="ALL", chatty=False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000837 except test_support.TestFailed:
838 if expectedToWork:
839 raise
840 else:
841 if not expectedToWork:
842 raise test_support.TestFailed(
843 "Client protocol %s succeeded with server protocol %s!"
844 % (ssl.get_protocol_name(client_protocol),
845 ssl.get_protocol_name(server_protocol)))
846
847
Bill Janssen934b16d2008-06-28 22:19:33 +0000848 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000849
850 def testRudeShutdown(self):
851
852 listener_ready = threading.Event()
853 listener_gone = threading.Event()
854
Antoine Pitrou150acda2010-04-27 08:40:51 +0000855 s = socket.socket()
856 port = test_support.bind_port(s, HOST)
857
858 # `listener` runs in a thread. It sits in an accept() until
859 # the main thread connects. Then it rudely closes the socket,
860 # and sets Event `listener_gone` to let the main thread know
861 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000862 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000863 s.listen(5)
864 listener_ready.set()
865 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000866 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000867 listener_gone.set()
868
869 def connector():
870 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000871 c = socket.socket()
872 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000873 listener_gone.wait()
874 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000875 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000876 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000877 pass
878 else:
879 raise test_support.TestFailed(
880 'connecting to closed SSL socket should have failed')
881
882 t = threading.Thread(target=listener)
883 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000884 try:
885 connector()
886 finally:
887 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000888
889 def testEcho (self):
890
891 if test_support.verbose:
892 sys.stdout.write("\n")
893 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
894 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
895 chatty=True, connectionchatty=True)
896
897 def testReadCert(self):
898
899 if test_support.verbose:
900 sys.stdout.write("\n")
901 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000902 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000903 certreqs=ssl.CERT_NONE,
904 ssl_version=ssl.PROTOCOL_SSLv23,
905 cacerts=CERTFILE,
906 chatty=False)
907 flag = threading.Event()
908 server.start(flag)
909 # wait for it to start
910 flag.wait()
911 # try to connect
912 try:
913 try:
914 s = ssl.wrap_socket(socket.socket(),
915 certfile=CERTFILE,
916 ca_certs=CERTFILE,
917 cert_reqs=ssl.CERT_REQUIRED,
918 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000919 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000920 except ssl.SSLError, x:
921 raise test_support.TestFailed(
922 "Unexpected SSL error: " + str(x))
923 except Exception, x:
924 raise test_support.TestFailed(
925 "Unexpected exception: " + str(x))
926 else:
927 if not s:
928 raise test_support.TestFailed(
929 "Can't SSL-handshake with test server")
930 cert = s.getpeercert()
931 if not cert:
932 raise test_support.TestFailed(
933 "Can't get peer certificate.")
934 cipher = s.cipher()
935 if test_support.verbose:
936 sys.stdout.write(pprint.pformat(cert) + '\n')
937 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000938 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000939 raise test_support.TestFailed(
940 "No subject field in certificate: %s." %
941 pprint.pformat(cert))
942 if ((('organizationName', 'Python Software Foundation'),)
943 not in cert['subject']):
944 raise test_support.TestFailed(
945 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000946 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000947 s.close()
948 finally:
949 server.stop()
950 server.join()
951
952 def testNULLcert(self):
953 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
954 "nullcert.pem"))
955 def testMalformedCert(self):
956 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
957 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000958 def testWrongCert(self):
959 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
960 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000961 def testMalformedKey(self):
962 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
963 "badkey.pem"))
964
965 def testProtocolSSL2(self):
966 if test_support.verbose:
967 sys.stdout.write("\n")
968 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
969 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
970 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
971 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
972 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
973 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
974
975 def testProtocolSSL23(self):
976 if test_support.verbose:
977 sys.stdout.write("\n")
978 try:
979 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
980 except test_support.TestFailed, x:
981 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
982 if test_support.verbose:
983 sys.stdout.write(
984 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
985 % str(x))
986 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
987 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
988 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
989
990 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
991 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
992 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
993
994 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
995 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
996 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
997
998 def testProtocolSSL3(self):
999 if test_support.verbose:
1000 sys.stdout.write("\n")
1001 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1002 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1003 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1004 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1005 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1006 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
1007
1008 def testProtocolTLS1(self):
1009 if test_support.verbose:
1010 sys.stdout.write("\n")
1011 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1012 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1013 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1014 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1015 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1016 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
1017
1018 def testSTARTTLS (self):
1019
Bill Janssen39295c22008-08-12 16:31:21 +00001020 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00001021
Trent Nelsone41b0062008-04-08 23:47:30 +00001022 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001023 ssl_version=ssl.PROTOCOL_TLSv1,
1024 starttls_server=True,
1025 chatty=True,
1026 connectionchatty=True)
1027 flag = threading.Event()
1028 server.start(flag)
1029 # wait for it to start
1030 flag.wait()
1031 # try to connect
1032 wrapped = False
1033 try:
1034 try:
1035 s = socket.socket()
1036 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +00001037 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +00001038 except Exception, x:
1039 raise test_support.TestFailed("Unexpected exception: " + str(x))
1040 else:
1041 if test_support.verbose:
1042 sys.stdout.write("\n")
1043 for indata in msgs:
1044 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001045 sys.stdout.write(
1046 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001047 if wrapped:
1048 conn.write(indata)
1049 outdata = conn.read()
1050 else:
1051 s.send(indata)
1052 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001053 if (indata == "STARTTLS" and
1054 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001055 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001056 sys.stdout.write(
1057 " client: read %s from server, starting TLS...\n"
1058 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001059 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001060 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001061 elif (indata == "ENDTLS" and
1062 outdata.strip().lower().startswith("ok")):
1063 if test_support.verbose:
1064 sys.stdout.write(
1065 " client: read %s from server, ending TLS...\n"
1066 % repr(outdata))
1067 s = conn.unwrap()
1068 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001069 else:
1070 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001071 sys.stdout.write(
1072 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001073 if test_support.verbose:
1074 sys.stdout.write(" client: closing connection.\n")
1075 if wrapped:
1076 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001077 else:
1078 s.send("over\n")
1079 s.close()
1080 finally:
1081 server.stop()
1082 server.join()
1083
Bill Janssen934b16d2008-06-28 22:19:33 +00001084 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001085
Bill Janssen934b16d2008-06-28 22:19:33 +00001086 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001087 flag = threading.Event()
1088 server.start(flag)
1089 # wait for it to start
1090 flag.wait()
1091 # try to connect
1092 try:
1093 if test_support.verbose:
1094 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001095 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001096 d2 = ''
1097 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001098 url = 'https://127.0.0.1:%d/%s' % (
1099 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001100 with test_support.check_py3k_warnings():
1101 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001102 dlen = f.info().getheader("content-length")
1103 if dlen and (int(dlen) > 0):
1104 d2 = f.read(int(dlen))
1105 if test_support.verbose:
1106 sys.stdout.write(
1107 " client: read %d bytes from remote server '%s'\n"
1108 % (len(d2), server))
1109 f.close()
1110 except:
1111 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1112 if test_support.verbose:
1113 sys.stdout.write('\n' + msg)
1114 raise test_support.TestFailed(msg)
1115 else:
1116 if not (d1 == d2):
1117 raise test_support.TestFailed(
1118 "Couldn't fetch data from HTTPS server")
1119 finally:
1120 server.stop()
1121 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001122
Bill Janssen934b16d2008-06-28 22:19:33 +00001123 def testWrappedAccept (self):
1124
1125 if test_support.verbose:
1126 sys.stdout.write("\n")
1127 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1128 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1129 chatty=True, connectionchatty=True,
1130 wrap_accepting_socket=True)
1131
1132
1133 def testAsyncoreServer (self):
1134
1135 indata = "TEST MESSAGE of mixed case\n"
1136
1137 if test_support.verbose:
1138 sys.stdout.write("\n")
1139 server = AsyncoreEchoServer(CERTFILE)
1140 flag = threading.Event()
1141 server.start(flag)
1142 # wait for it to start
1143 flag.wait()
1144 # try to connect
1145 try:
1146 try:
1147 s = ssl.wrap_socket(socket.socket())
1148 s.connect(('127.0.0.1', server.port))
1149 except ssl.SSLError, x:
1150 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1151 except Exception, x:
1152 raise test_support.TestFailed("Unexpected exception: " + str(x))
1153 else:
1154 if test_support.verbose:
1155 sys.stdout.write(
1156 " client: sending %s...\n" % (repr(indata)))
1157 s.write(indata)
1158 outdata = s.read()
1159 if test_support.verbose:
1160 sys.stdout.write(" client: read %s\n" % repr(outdata))
1161 if outdata != indata.lower():
1162 raise test_support.TestFailed(
1163 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1164 % (outdata[:min(len(outdata),20)], len(outdata),
1165 indata[:min(len(indata),20)].lower(), len(indata)))
1166 s.write("over\n")
1167 if test_support.verbose:
1168 sys.stdout.write(" client: closing connection.\n")
1169 s.close()
1170 finally:
1171 server.stop()
1172 # wait for server thread to end
1173 server.join()
1174
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001175
Bill Janssen61c001a2008-09-08 16:37:24 +00001176 def testAllRecvAndSendMethods(self):
1177
1178 if test_support.verbose:
1179 sys.stdout.write("\n")
1180
1181 server = ThreadedEchoServer(CERTFILE,
1182 certreqs=ssl.CERT_NONE,
1183 ssl_version=ssl.PROTOCOL_TLSv1,
1184 cacerts=CERTFILE,
1185 chatty=True,
1186 connectionchatty=False)
1187 flag = threading.Event()
1188 server.start(flag)
1189 # wait for it to start
1190 flag.wait()
1191 # try to connect
1192 try:
1193 s = ssl.wrap_socket(socket.socket(),
1194 server_side=False,
1195 certfile=CERTFILE,
1196 ca_certs=CERTFILE,
1197 cert_reqs=ssl.CERT_NONE,
1198 ssl_version=ssl.PROTOCOL_TLSv1)
1199 s.connect((HOST, server.port))
1200 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001201 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001202 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001203 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001204 else:
1205 # helper methods for standardising recv* method signatures
1206 def _recv_into():
1207 b = bytearray("\0"*100)
1208 count = s.recv_into(b)
1209 return b[:count]
1210
1211 def _recvfrom_into():
1212 b = bytearray("\0"*100)
1213 count, addr = s.recvfrom_into(b)
1214 return b[:count]
1215
1216 # (name, method, whether to expect success, *args)
1217 send_methods = [
1218 ('send', s.send, True, []),
1219 ('sendto', s.sendto, False, ["some.address"]),
1220 ('sendall', s.sendall, True, []),
1221 ]
1222 recv_methods = [
1223 ('recv', s.recv, True, []),
1224 ('recvfrom', s.recvfrom, False, ["some.address"]),
1225 ('recv_into', _recv_into, True, []),
1226 ('recvfrom_into', _recvfrom_into, False, []),
1227 ]
1228 data_prefix = u"PREFIX_"
1229
1230 for meth_name, send_meth, expect_success, args in send_methods:
1231 indata = data_prefix + meth_name
1232 try:
1233 send_meth(indata.encode('ASCII', 'strict'), *args)
1234 outdata = s.read()
1235 outdata = outdata.decode('ASCII', 'strict')
1236 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001237 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001238 "While sending with <<%s>> bad data "
1239 "<<%r>> (%d) received; "
1240 "expected <<%r>> (%d)\n" % (
1241 meth_name, outdata[:20], len(outdata),
1242 indata[:20], len(indata)
1243 )
1244 )
1245 except ValueError as e:
1246 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001247 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001248 "Failed to send with method <<%s>>; "
1249 "expected to succeed.\n" % (meth_name,)
1250 )
1251 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001252 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001253 "Method <<%s>> failed with unexpected "
1254 "exception message: %s\n" % (
1255 meth_name, e
1256 )
1257 )
1258
1259 for meth_name, recv_meth, expect_success, args in recv_methods:
1260 indata = data_prefix + meth_name
1261 try:
1262 s.send(indata.encode('ASCII', 'strict'))
1263 outdata = recv_meth(*args)
1264 outdata = outdata.decode('ASCII', 'strict')
1265 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001266 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001267 "While receiving with <<%s>> bad data "
1268 "<<%r>> (%d) received; "
1269 "expected <<%r>> (%d)\n" % (
1270 meth_name, outdata[:20], len(outdata),
1271 indata[:20], len(indata)
1272 )
1273 )
1274 except ValueError as e:
1275 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001276 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001277 "Failed to receive with method <<%s>>; "
1278 "expected to succeed.\n" % (meth_name,)
1279 )
1280 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001281 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001282 "Method <<%s>> failed with unexpected "
1283 "exception message: %s\n" % (
1284 meth_name, e
1285 )
1286 )
1287 # consume data
1288 s.read()
1289
1290 s.write("over\n".encode("ASCII", "strict"))
1291 s.close()
1292 finally:
1293 server.stop()
1294 server.join()
1295
Antoine Pitroufc69af12010-04-24 20:04:58 +00001296 def test_handshake_timeout(self):
1297 # Issue #5103: SSL handshake must respect the socket timeout
1298 server = socket.socket(socket.AF_INET)
1299 host = "127.0.0.1"
1300 port = test_support.bind_port(server)
1301 started = threading.Event()
1302 finish = False
1303
1304 def serve():
1305 server.listen(5)
1306 started.set()
1307 conns = []
1308 while not finish:
1309 r, w, e = select.select([server], [], [], 0.1)
1310 if server in r:
1311 # Let the socket hang around rather than having
1312 # it closed by garbage collection.
1313 conns.append(server.accept()[0])
1314
1315 t = threading.Thread(target=serve)
1316 t.start()
1317 started.wait()
1318
1319 try:
1320 try:
1321 c = socket.socket(socket.AF_INET)
1322 c.settimeout(0.2)
1323 c.connect((host, port))
1324 # Will attempt handshake and time out
1325 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1326 ssl.wrap_socket, c)
1327 finally:
1328 c.close()
1329 try:
1330 c = socket.socket(socket.AF_INET)
1331 c.settimeout(0.2)
1332 c = ssl.wrap_socket(c)
1333 # Will attempt handshake and time out
1334 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1335 c.connect, (host, port))
1336 finally:
1337 c.close()
1338 finally:
1339 finish = True
1340 t.join()
1341 server.close()
1342
Bill Janssen61c001a2008-09-08 16:37:24 +00001343
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001344def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001345 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001346 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001347
Trent Nelsone41b0062008-04-08 23:47:30 +00001348 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001349 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001350 "keycert.pem")
1351 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1352 os.path.dirname(__file__) or os.curdir,
1353 "https_svn_python_org_root.pem")
1354
1355 if (not os.path.exists(CERTFILE) or
1356 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001357 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001358
1359 tests = [BasicTests]
1360
Bill Janssen296a59d2007-09-16 22:06:00 +00001361 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001362 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001363
Bill Janssen98d19da2007-09-10 21:51:02 +00001364 if _have_threads:
1365 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001366 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001367 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001368
Bill Janssen98d19da2007-09-10 21:51:02 +00001369 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001370
Bill Janssen98d19da2007-09-10 21:51:02 +00001371 if _have_threads:
1372 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001373
1374if __name__ == "__main__":
1375 test_main()