blob: bbccaeb4ddf53c320b0ce4d66ef5e7930f17aec2 [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]
Trent Nelsone41b0062008-04-08 23:47:30 +0000699 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000700 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000701 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
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()
Trent Nelsone41b0062008-04-08 23:47:30 +0000854 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000855
856 # `listener` runs in a thread. It opens a socket listening on
857 # PORT, and sits in an accept() until the main thread connects.
858 # Then it rudely closes the socket, and sets Event `listener_gone`
859 # to let the main thread know the socket is gone.
860 def listener():
861 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000862 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000863 s.listen(5)
864 listener_ready.set()
865 s.accept()
866 s = None # reclaim the socket object, which also closes it
867 listener_gone.set()
868
869 def connector():
870 listener_ready.wait()
871 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000872 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000873 listener_gone.wait()
874 try:
875 ssl_sock = ssl.wrap_socket(s)
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()
884 connector()
885 t.join()
886
887 def testEcho (self):
888
889 if test_support.verbose:
890 sys.stdout.write("\n")
891 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
892 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
893 chatty=True, connectionchatty=True)
894
895 def testReadCert(self):
896
897 if test_support.verbose:
898 sys.stdout.write("\n")
899 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000900 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000901 certreqs=ssl.CERT_NONE,
902 ssl_version=ssl.PROTOCOL_SSLv23,
903 cacerts=CERTFILE,
904 chatty=False)
905 flag = threading.Event()
906 server.start(flag)
907 # wait for it to start
908 flag.wait()
909 # try to connect
910 try:
911 try:
912 s = ssl.wrap_socket(socket.socket(),
913 certfile=CERTFILE,
914 ca_certs=CERTFILE,
915 cert_reqs=ssl.CERT_REQUIRED,
916 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000917 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000918 except ssl.SSLError, x:
919 raise test_support.TestFailed(
920 "Unexpected SSL error: " + str(x))
921 except Exception, x:
922 raise test_support.TestFailed(
923 "Unexpected exception: " + str(x))
924 else:
925 if not s:
926 raise test_support.TestFailed(
927 "Can't SSL-handshake with test server")
928 cert = s.getpeercert()
929 if not cert:
930 raise test_support.TestFailed(
931 "Can't get peer certificate.")
932 cipher = s.cipher()
933 if test_support.verbose:
934 sys.stdout.write(pprint.pformat(cert) + '\n')
935 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000936 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000937 raise test_support.TestFailed(
938 "No subject field in certificate: %s." %
939 pprint.pformat(cert))
940 if ((('organizationName', 'Python Software Foundation'),)
941 not in cert['subject']):
942 raise test_support.TestFailed(
943 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000944 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000945 s.close()
946 finally:
947 server.stop()
948 server.join()
949
950 def testNULLcert(self):
951 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
952 "nullcert.pem"))
953 def testMalformedCert(self):
954 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
955 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000956 def testWrongCert(self):
957 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
958 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000959 def testMalformedKey(self):
960 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
961 "badkey.pem"))
962
963 def testProtocolSSL2(self):
964 if test_support.verbose:
965 sys.stdout.write("\n")
966 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
967 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
968 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
969 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
970 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
971 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
972
973 def testProtocolSSL23(self):
974 if test_support.verbose:
975 sys.stdout.write("\n")
976 try:
977 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
978 except test_support.TestFailed, x:
979 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
980 if test_support.verbose:
981 sys.stdout.write(
982 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
983 % str(x))
984 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
985 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
986 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
987
988 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
989 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
990 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
991
992 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
993 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
994 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
995
996 def testProtocolSSL3(self):
997 if test_support.verbose:
998 sys.stdout.write("\n")
999 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1000 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1001 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1002 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1003 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1004 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
1005
1006 def testProtocolTLS1(self):
1007 if test_support.verbose:
1008 sys.stdout.write("\n")
1009 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1010 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1011 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1012 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1013 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1014 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
1015
1016 def testSTARTTLS (self):
1017
Bill Janssen39295c22008-08-12 16:31:21 +00001018 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +00001019
Trent Nelsone41b0062008-04-08 23:47:30 +00001020 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001021 ssl_version=ssl.PROTOCOL_TLSv1,
1022 starttls_server=True,
1023 chatty=True,
1024 connectionchatty=True)
1025 flag = threading.Event()
1026 server.start(flag)
1027 # wait for it to start
1028 flag.wait()
1029 # try to connect
1030 wrapped = False
1031 try:
1032 try:
1033 s = socket.socket()
1034 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +00001035 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +00001036 except Exception, x:
1037 raise test_support.TestFailed("Unexpected exception: " + str(x))
1038 else:
1039 if test_support.verbose:
1040 sys.stdout.write("\n")
1041 for indata in msgs:
1042 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001043 sys.stdout.write(
1044 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001045 if wrapped:
1046 conn.write(indata)
1047 outdata = conn.read()
1048 else:
1049 s.send(indata)
1050 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001051 if (indata == "STARTTLS" and
1052 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001053 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001054 sys.stdout.write(
1055 " client: read %s from server, starting TLS...\n"
1056 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001057 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001058 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001059 elif (indata == "ENDTLS" and
1060 outdata.strip().lower().startswith("ok")):
1061 if test_support.verbose:
1062 sys.stdout.write(
1063 " client: read %s from server, ending TLS...\n"
1064 % repr(outdata))
1065 s = conn.unwrap()
1066 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001067 else:
1068 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001069 sys.stdout.write(
1070 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001071 if test_support.verbose:
1072 sys.stdout.write(" client: closing connection.\n")
1073 if wrapped:
1074 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001075 else:
1076 s.send("over\n")
1077 s.close()
1078 finally:
1079 server.stop()
1080 server.join()
1081
Bill Janssen934b16d2008-06-28 22:19:33 +00001082 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001083
Bill Janssen934b16d2008-06-28 22:19:33 +00001084 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001085 flag = threading.Event()
1086 server.start(flag)
1087 # wait for it to start
1088 flag.wait()
1089 # try to connect
1090 try:
1091 if test_support.verbose:
1092 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001093 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001094 d2 = ''
1095 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001096 url = 'https://127.0.0.1:%d/%s' % (
1097 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001098 with test_support.check_py3k_warnings():
1099 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001100 dlen = f.info().getheader("content-length")
1101 if dlen and (int(dlen) > 0):
1102 d2 = f.read(int(dlen))
1103 if test_support.verbose:
1104 sys.stdout.write(
1105 " client: read %d bytes from remote server '%s'\n"
1106 % (len(d2), server))
1107 f.close()
1108 except:
1109 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1110 if test_support.verbose:
1111 sys.stdout.write('\n' + msg)
1112 raise test_support.TestFailed(msg)
1113 else:
1114 if not (d1 == d2):
1115 raise test_support.TestFailed(
1116 "Couldn't fetch data from HTTPS server")
1117 finally:
1118 server.stop()
1119 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001120
Bill Janssen934b16d2008-06-28 22:19:33 +00001121 def testWrappedAccept (self):
1122
1123 if test_support.verbose:
1124 sys.stdout.write("\n")
1125 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1126 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1127 chatty=True, connectionchatty=True,
1128 wrap_accepting_socket=True)
1129
1130
1131 def testAsyncoreServer (self):
1132
1133 indata = "TEST MESSAGE of mixed case\n"
1134
1135 if test_support.verbose:
1136 sys.stdout.write("\n")
1137 server = AsyncoreEchoServer(CERTFILE)
1138 flag = threading.Event()
1139 server.start(flag)
1140 # wait for it to start
1141 flag.wait()
1142 # try to connect
1143 try:
1144 try:
1145 s = ssl.wrap_socket(socket.socket())
1146 s.connect(('127.0.0.1', server.port))
1147 except ssl.SSLError, x:
1148 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1149 except Exception, x:
1150 raise test_support.TestFailed("Unexpected exception: " + str(x))
1151 else:
1152 if test_support.verbose:
1153 sys.stdout.write(
1154 " client: sending %s...\n" % (repr(indata)))
1155 s.write(indata)
1156 outdata = s.read()
1157 if test_support.verbose:
1158 sys.stdout.write(" client: read %s\n" % repr(outdata))
1159 if outdata != indata.lower():
1160 raise test_support.TestFailed(
1161 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1162 % (outdata[:min(len(outdata),20)], len(outdata),
1163 indata[:min(len(indata),20)].lower(), len(indata)))
1164 s.write("over\n")
1165 if test_support.verbose:
1166 sys.stdout.write(" client: closing connection.\n")
1167 s.close()
1168 finally:
1169 server.stop()
1170 # wait for server thread to end
1171 server.join()
1172
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001173
Bill Janssen61c001a2008-09-08 16:37:24 +00001174 def testAllRecvAndSendMethods(self):
1175
1176 if test_support.verbose:
1177 sys.stdout.write("\n")
1178
1179 server = ThreadedEchoServer(CERTFILE,
1180 certreqs=ssl.CERT_NONE,
1181 ssl_version=ssl.PROTOCOL_TLSv1,
1182 cacerts=CERTFILE,
1183 chatty=True,
1184 connectionchatty=False)
1185 flag = threading.Event()
1186 server.start(flag)
1187 # wait for it to start
1188 flag.wait()
1189 # try to connect
1190 try:
1191 s = ssl.wrap_socket(socket.socket(),
1192 server_side=False,
1193 certfile=CERTFILE,
1194 ca_certs=CERTFILE,
1195 cert_reqs=ssl.CERT_NONE,
1196 ssl_version=ssl.PROTOCOL_TLSv1)
1197 s.connect((HOST, server.port))
1198 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001199 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001200 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001201 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001202 else:
1203 # helper methods for standardising recv* method signatures
1204 def _recv_into():
1205 b = bytearray("\0"*100)
1206 count = s.recv_into(b)
1207 return b[:count]
1208
1209 def _recvfrom_into():
1210 b = bytearray("\0"*100)
1211 count, addr = s.recvfrom_into(b)
1212 return b[:count]
1213
1214 # (name, method, whether to expect success, *args)
1215 send_methods = [
1216 ('send', s.send, True, []),
1217 ('sendto', s.sendto, False, ["some.address"]),
1218 ('sendall', s.sendall, True, []),
1219 ]
1220 recv_methods = [
1221 ('recv', s.recv, True, []),
1222 ('recvfrom', s.recvfrom, False, ["some.address"]),
1223 ('recv_into', _recv_into, True, []),
1224 ('recvfrom_into', _recvfrom_into, False, []),
1225 ]
1226 data_prefix = u"PREFIX_"
1227
1228 for meth_name, send_meth, expect_success, args in send_methods:
1229 indata = data_prefix + meth_name
1230 try:
1231 send_meth(indata.encode('ASCII', 'strict'), *args)
1232 outdata = s.read()
1233 outdata = outdata.decode('ASCII', 'strict')
1234 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001235 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001236 "While sending with <<%s>> bad data "
1237 "<<%r>> (%d) received; "
1238 "expected <<%r>> (%d)\n" % (
1239 meth_name, outdata[:20], len(outdata),
1240 indata[:20], len(indata)
1241 )
1242 )
1243 except ValueError as e:
1244 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001245 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001246 "Failed to send with method <<%s>>; "
1247 "expected to succeed.\n" % (meth_name,)
1248 )
1249 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001250 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001251 "Method <<%s>> failed with unexpected "
1252 "exception message: %s\n" % (
1253 meth_name, e
1254 )
1255 )
1256
1257 for meth_name, recv_meth, expect_success, args in recv_methods:
1258 indata = data_prefix + meth_name
1259 try:
1260 s.send(indata.encode('ASCII', 'strict'))
1261 outdata = recv_meth(*args)
1262 outdata = outdata.decode('ASCII', 'strict')
1263 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001264 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001265 "While receiving with <<%s>> bad data "
1266 "<<%r>> (%d) received; "
1267 "expected <<%r>> (%d)\n" % (
1268 meth_name, outdata[:20], len(outdata),
1269 indata[:20], len(indata)
1270 )
1271 )
1272 except ValueError as e:
1273 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001274 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001275 "Failed to receive with method <<%s>>; "
1276 "expected to succeed.\n" % (meth_name,)
1277 )
1278 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001279 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001280 "Method <<%s>> failed with unexpected "
1281 "exception message: %s\n" % (
1282 meth_name, e
1283 )
1284 )
1285 # consume data
1286 s.read()
1287
1288 s.write("over\n".encode("ASCII", "strict"))
1289 s.close()
1290 finally:
1291 server.stop()
1292 server.join()
1293
Antoine Pitroufc69af12010-04-24 20:04:58 +00001294 def test_handshake_timeout(self):
1295 # Issue #5103: SSL handshake must respect the socket timeout
1296 server = socket.socket(socket.AF_INET)
1297 host = "127.0.0.1"
1298 port = test_support.bind_port(server)
1299 started = threading.Event()
1300 finish = False
1301
1302 def serve():
1303 server.listen(5)
1304 started.set()
1305 conns = []
1306 while not finish:
1307 r, w, e = select.select([server], [], [], 0.1)
1308 if server in r:
1309 # Let the socket hang around rather than having
1310 # it closed by garbage collection.
1311 conns.append(server.accept()[0])
1312
1313 t = threading.Thread(target=serve)
1314 t.start()
1315 started.wait()
1316
1317 try:
1318 try:
1319 c = socket.socket(socket.AF_INET)
1320 c.settimeout(0.2)
1321 c.connect((host, port))
1322 # Will attempt handshake and time out
1323 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1324 ssl.wrap_socket, c)
1325 finally:
1326 c.close()
1327 try:
1328 c = socket.socket(socket.AF_INET)
1329 c.settimeout(0.2)
1330 c = ssl.wrap_socket(c)
1331 # Will attempt handshake and time out
1332 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1333 c.connect, (host, port))
1334 finally:
1335 c.close()
1336 finally:
1337 finish = True
1338 t.join()
1339 server.close()
1340
Bill Janssen61c001a2008-09-08 16:37:24 +00001341
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001342def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001343 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001344 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001345
Trent Nelsone41b0062008-04-08 23:47:30 +00001346 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001347 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001348 "keycert.pem")
1349 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1350 os.path.dirname(__file__) or os.curdir,
1351 "https_svn_python_org_root.pem")
1352
1353 if (not os.path.exists(CERTFILE) or
1354 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001355 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001356
Bill Janssen934b16d2008-06-28 22:19:33 +00001357 TESTPORT = test_support.find_unused_port()
1358 if not TESTPORT:
1359 raise test_support.TestFailed("Can't find open port to test servers on!")
1360
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001361 tests = [BasicTests]
1362
Bill Janssen296a59d2007-09-16 22:06:00 +00001363 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001364 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001365
Bill Janssen98d19da2007-09-10 21:51:02 +00001366 if _have_threads:
1367 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001368 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001369 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001370
Bill Janssen98d19da2007-09-10 21:51:02 +00001371 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001372
Bill Janssen98d19da2007-09-10 21:51:02 +00001373 if _have_threads:
1374 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001375
1376if __name__ == "__main__":
1377 test_main()