blob: c418cd4ea85c379ac83088adfa86e6f1035a6426 [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 Pitroub558f172010-04-23 23:25:45 +0000170 def test_makefile_close(self):
171 # Issue #5238: creating a file-like object with makefile() shouldn't
172 # leak the underlying file descriptor.
173 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
174 fd = ss.fileno()
175 f = ss.makefile()
176 f.close()
177 # The fd is still open
178 os.read(fd, 0)
179 # Closing the SSL socket should close the fd too
180 ss.close()
181 gc.collect()
182 with self.assertRaises(OSError) as e:
183 os.read(fd, 0)
184 self.assertEqual(e.exception.errno, errno.EBADF)
185
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000186
Bill Janssen934b16d2008-06-28 22:19:33 +0000187class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000188
189 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000190 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
191 cert_reqs=ssl.CERT_NONE)
192 s.connect(("svn.python.org", 443))
193 c = s.getpeercert()
194 if c:
195 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
196 s.close()
197
198 # this should fail because we have no verification certs
199 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
200 cert_reqs=ssl.CERT_REQUIRED)
201 try:
202 s.connect(("svn.python.org", 443))
203 except ssl.SSLError:
204 pass
205 finally:
206 s.close()
207
208 # this should succeed because we specify the root cert
209 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
210 cert_reqs=ssl.CERT_REQUIRED,
211 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
212 try:
213 s.connect(("svn.python.org", 443))
214 except ssl.SSLError, x:
215 raise test_support.TestFailed("Unexpected exception %s" % x)
216 finally:
217 s.close()
218
Bill Janssen934b16d2008-06-28 22:19:33 +0000219
220 def testNonBlockingHandshake(self):
221 s = socket.socket(socket.AF_INET)
222 s.connect(("svn.python.org", 443))
223 s.setblocking(False)
224 s = ssl.wrap_socket(s,
225 cert_reqs=ssl.CERT_NONE,
226 do_handshake_on_connect=False)
227 count = 0
228 while True:
229 try:
230 count += 1
231 s.do_handshake()
232 break
233 except ssl.SSLError, err:
234 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
235 select.select([s], [], [])
236 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
237 select.select([], [s], [])
238 else:
239 raise
240 s.close()
241 if test_support.verbose:
242 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
243
Bill Janssen296a59d2007-09-16 22:06:00 +0000244 def testFetchServerCert(self):
245
246 pem = ssl.get_server_certificate(("svn.python.org", 443))
247 if not pem:
248 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
249
250 try:
251 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
252 except ssl.SSLError:
253 #should fail
254 pass
255 else:
256 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
257
258 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
259 if not pem:
260 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
261 if test_support.verbose:
262 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
263
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000264 def test_algorithms(self):
265 # Issue #8484: all algorithms should be available when verifying a
266 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000267 # SHA256 was added in OpenSSL 0.9.8
268 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
269 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000270 # NOTE: https://sha256.tbs-internet.com is another possible test host
271 remote = ("sha2.hboeck.de", 443)
272 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
273 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
274 cert_reqs=ssl.CERT_REQUIRED,
275 ca_certs=sha256_cert,)
276 with test_support.transient_internet():
277 try:
278 s.connect(remote)
279 if test_support.verbose:
280 sys.stdout.write("\nCipher with %r is %r\n" %
281 (remote, s.cipher()))
282 sys.stdout.write("Certificate is:\n%s\n" %
283 pprint.pformat(s.getpeercert()))
284 finally:
285 s.close()
286
Bill Janssen296a59d2007-09-16 22:06:00 +0000287
Bill Janssen98d19da2007-09-10 21:51:02 +0000288try:
289 import threading
290except ImportError:
291 _have_threads = False
292else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000293
Bill Janssen98d19da2007-09-10 21:51:02 +0000294 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000295
Bill Janssen98d19da2007-09-10 21:51:02 +0000296 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000297
Bill Janssen98d19da2007-09-10 21:51:02 +0000298 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000299
Bill Janssen98d19da2007-09-10 21:51:02 +0000300 """A mildly complicated class, because we want it to work both
301 with and without the SSL wrapper around the socket connection, so
302 that we can test the STARTTLS functionality."""
303
304 def __init__(self, server, connsock):
305 self.server = server
306 self.running = False
307 self.sock = connsock
308 self.sock.setblocking(1)
309 self.sslconn = None
310 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000311 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000312
Bill Janssen934b16d2008-06-28 22:19:33 +0000313 def show_conn_details(self):
314 if self.server.certreqs == ssl.CERT_REQUIRED:
315 cert = self.sslconn.getpeercert()
316 if test_support.verbose and self.server.chatty:
317 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
318 cert_binary = self.sslconn.getpeercert(True)
319 if test_support.verbose and self.server.chatty:
320 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
321 cipher = self.sslconn.cipher()
322 if test_support.verbose and self.server.chatty:
323 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
324
Bill Janssen98d19da2007-09-10 21:51:02 +0000325 def wrap_conn (self):
326 try:
327 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
328 certfile=self.server.certificate,
329 ssl_version=self.server.protocol,
330 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000331 cert_reqs=self.server.certreqs,
332 ciphers=self.server.ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +0000333 except:
334 if self.server.chatty:
335 handle_error("\n server: bad connection attempt from " +
336 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000337 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000338 if not self.server.expect_bad_connects:
339 # here, we want to stop the server, because this shouldn't
340 # happen in the context of our test case
341 self.running = False
342 # normally, we'd just stop here, but for the test
343 # harness, we want to stop the server
344 self.server.stop()
345 return False
346
347 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000348 return True
349
350 def read(self):
351 if self.sslconn:
352 return self.sslconn.read()
353 else:
354 return self.sock.recv(1024)
355
356 def write(self, bytes):
357 if self.sslconn:
358 return self.sslconn.write(bytes)
359 else:
360 return self.sock.send(bytes)
361
362 def close(self):
363 if self.sslconn:
364 self.sslconn.close()
365 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000366 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000367
368 def run (self):
369 self.running = True
370 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000371 if isinstance(self.sock, ssl.SSLSocket):
372 self.sslconn = self.sock
373 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000374 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000375 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000376 while self.running:
377 try:
378 msg = self.read()
379 if not msg:
380 # eof, so quit this handler
381 self.running = False
382 self.close()
383 elif msg.strip() == 'over':
384 if test_support.verbose and self.server.connectionchatty:
385 sys.stdout.write(" server: client closed connection\n")
386 self.close()
387 return
388 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
389 if test_support.verbose and self.server.connectionchatty:
390 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
391 self.write("OK\n")
392 if not self.wrap_conn():
393 return
Bill Janssen39295c22008-08-12 16:31:21 +0000394 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
395 if test_support.verbose and self.server.connectionchatty:
396 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
397 self.write("OK\n")
398 self.sslconn.unwrap()
399 self.sslconn = None
400 if test_support.verbose and self.server.connectionchatty:
401 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000402 else:
403 if (test_support.verbose and
404 self.server.connectionchatty):
405 ctype = (self.sslconn and "encrypted") or "unencrypted"
406 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
407 % (repr(msg), ctype, repr(msg.lower()), ctype))
408 self.write(msg.lower())
409 except ssl.SSLError:
410 if self.server.chatty:
411 handle_error("Test server failure:\n")
412 self.close()
413 self.running = False
414 # normally, we'd just stop here, but for the test
415 # harness, we want to stop the server
416 self.server.stop()
417 except:
418 handle_error('')
419
Trent Nelsone41b0062008-04-08 23:47:30 +0000420 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000421 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000422 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000423 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000424
Bill Janssen98d19da2007-09-10 21:51:02 +0000425 if ssl_version is None:
426 ssl_version = ssl.PROTOCOL_TLSv1
427 if certreqs is None:
428 certreqs = ssl.CERT_NONE
429 self.certificate = certificate
430 self.protocol = ssl_version
431 self.certreqs = certreqs
432 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000433 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000434 self.expect_bad_connects = expect_bad_connects
435 self.chatty = chatty
436 self.connectionchatty = connectionchatty
437 self.starttls_server = starttls_server
438 self.sock = socket.socket()
439 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000440 if wrap_accepting_socket:
441 self.sock = ssl.wrap_socket(self.sock, server_side=True,
442 certfile=self.certificate,
443 cert_reqs = self.certreqs,
444 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000445 ssl_version = self.protocol,
446 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000447 if test_support.verbose and self.chatty:
448 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
449 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000450 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000451 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000452 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000453
454 def start (self, flag=None):
455 self.flag = flag
456 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000457
458 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000459 self.sock.settimeout(0.5)
460 self.sock.listen(5)
461 self.active = True
462 if self.flag:
463 # signal an event
464 self.flag.set()
465 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000466 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000467 newconn, connaddr = self.sock.accept()
468 if test_support.verbose and self.chatty:
469 sys.stdout.write(' server: new connection from '
470 + str(connaddr) + '\n')
471 handler = self.ConnectionHandler(self, newconn)
472 handler.start()
473 except socket.timeout:
474 pass
475 except KeyboardInterrupt:
476 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000477 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000478 if self.chatty:
479 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000480 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000481
Bill Janssen98d19da2007-09-10 21:51:02 +0000482 def stop (self):
483 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000484
Bill Janssen934b16d2008-06-28 22:19:33 +0000485 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000486
Bill Janssen934b16d2008-06-28 22:19:33 +0000487 class EchoServer (asyncore.dispatcher):
488
489 class ConnectionHandler (asyncore.dispatcher_with_send):
490
491 def __init__(self, conn, certfile):
492 asyncore.dispatcher_with_send.__init__(self, conn)
493 self.socket = ssl.wrap_socket(conn, server_side=True,
494 certfile=certfile,
495 do_handshake_on_connect=True)
496
497 def readable(self):
498 if isinstance(self.socket, ssl.SSLSocket):
499 while self.socket.pending() > 0:
500 self.handle_read_event()
501 return True
502
503 def handle_read(self):
504 data = self.recv(1024)
505 self.send(data.lower())
506
507 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000508 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000509 if test_support.verbose:
510 sys.stdout.write(" server: closed connection %s\n" % self.socket)
511
512 def handle_error(self):
513 raise
514
515 def __init__(self, certfile):
516 self.certfile = certfile
517 asyncore.dispatcher.__init__(self)
518 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
519 self.port = test_support.bind_port(self.socket)
520 self.listen(5)
521
522 def handle_accept(self):
523 sock_obj, addr = self.accept()
524 if test_support.verbose:
525 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
526 self.ConnectionHandler(sock_obj, self.certfile)
527
528 def handle_error(self):
529 raise
530
531 def __init__(self, certfile):
532 self.flag = None
533 self.active = False
534 self.server = self.EchoServer(certfile)
535 self.port = self.server.port
536 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000537 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000538
539 def __str__(self):
540 return "<%s %s>" % (self.__class__.__name__, self.server)
541
542 def start (self, flag=None):
543 self.flag = flag
544 threading.Thread.start(self)
545
546 def run (self):
547 self.active = True
548 if self.flag:
549 self.flag.set()
550 while self.active:
551 try:
552 asyncore.loop(1)
553 except:
554 pass
555
556 def stop (self):
557 self.active = False
558 self.server.close()
559
560 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000561
562 class HTTPSServer(HTTPServer):
563
564 def __init__(self, server_address, RequestHandlerClass, certfile):
565
566 HTTPServer.__init__(self, server_address, RequestHandlerClass)
567 # we assume the certfile contains both private key and certificate
568 self.certfile = certfile
569 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000570 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000571 self.allow_reuse_address = True
572
Bill Janssen934b16d2008-06-28 22:19:33 +0000573 def __str__(self):
574 return ('<%s %s:%s>' %
575 (self.__class__.__name__,
576 self.server_name,
577 self.server_port))
578
Bill Janssen296a59d2007-09-16 22:06:00 +0000579 def get_request (self):
580 # override this to wrap socket with SSL
581 sock, addr = self.socket.accept()
582 sslconn = ssl.wrap_socket(sock, server_side=True,
583 certfile=self.certfile)
584 return sslconn, addr
585
586 # The methods overridden below this are mainly so that we
587 # can run it in a thread and be able to stop it from another
588 # You probably wouldn't need them in other uses.
589
590 def server_activate(self):
591 # We want to run this in a thread for testing purposes,
592 # so we override this to set timeout, so that we get
593 # a chance to stop the server
594 self.socket.settimeout(0.5)
595 HTTPServer.server_activate(self)
596
597 def serve_forever(self):
598 # We want this to run in a thread, so we use a slightly
599 # modified version of "forever".
600 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000601 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000602 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000603 # We need to lock while handling the request.
604 # Another thread can close the socket after self.active
605 # has been checked and before the request is handled.
606 # This causes an exception when using the closed socket.
607 with self.active_lock:
608 if not self.active:
609 break
610 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000611 except socket.timeout:
612 pass
613 except KeyboardInterrupt:
614 self.server_close()
615 return
616 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000617 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
618 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000619 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000620
621 def server_close(self):
622 # Again, we want this to run in a thread, so we need to override
623 # close to clear the "active" flag, so that serve_forever() will
624 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000625 with self.active_lock:
626 HTTPServer.server_close(self)
627 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000628
629 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
630
631 # need to override translate_path to get a known root,
632 # instead of using os.curdir, since the test could be
633 # run from anywhere
634
635 server_version = "TestHTTPS/1.0"
636
637 root = None
638
639 def translate_path(self, path):
640 """Translate a /-separated PATH to the local filename syntax.
641
642 Components that mean special things to the local file system
643 (e.g. drive or directory names) are ignored. (XXX They should
644 probably be diagnosed.)
645
646 """
647 # abandon query parameters
648 path = urlparse.urlparse(path)[2]
649 path = os.path.normpath(urllib.unquote(path))
650 words = path.split('/')
651 words = filter(None, words)
652 path = self.root
653 for word in words:
654 drive, word = os.path.splitdrive(word)
655 head, word = os.path.split(word)
656 if word in self.root: continue
657 path = os.path.join(path, word)
658 return path
659
660 def log_message(self, format, *args):
661
662 # we override this to suppress logging unless "verbose"
663
664 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000665 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
666 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000667 self.server.server_port,
668 self.request.cipher(),
669 self.log_date_time_string(),
670 format%args))
671
672
Trent Nelsone41b0062008-04-08 23:47:30 +0000673 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000674 self.flag = None
675 self.active = False
676 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000677 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000678 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000679 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000680 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000681 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000682
683 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000684 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000685
686 def start (self, flag=None):
687 self.flag = flag
688 threading.Thread.start(self)
689
690 def run (self):
691 self.active = True
692 if self.flag:
693 self.flag.set()
694 self.server.serve_forever()
695 self.active = False
696
697 def stop (self):
698 self.active = False
699 self.server.server_close()
700
701
Bill Janssen98d19da2007-09-10 21:51:02 +0000702 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000703 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000704 certreqs=ssl.CERT_REQUIRED,
705 cacerts=CERTFILE, chatty=False)
706 flag = threading.Event()
707 server.start(flag)
708 # wait for it to start
709 flag.wait()
710 # try to connect
711 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000712 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000713 s = ssl.wrap_socket(socket.socket(),
714 certfile=certfile,
715 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000716 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000717 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000718 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000719 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000720 except socket.error, x:
721 if test_support.verbose:
722 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000723 else:
724 raise test_support.TestFailed(
725 "Use of invalid cert should have failed!")
726 finally:
727 server.stop()
728 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000729
Bill Janssen98d19da2007-09-10 21:51:02 +0000730 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
731 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000732 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000733 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000734
Trent Nelsone41b0062008-04-08 23:47:30 +0000735 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000736 certreqs=certreqs,
737 ssl_version=protocol,
738 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000739 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000740 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000741 connectionchatty=connectionchatty,
742 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000743 flag = threading.Event()
744 server.start(flag)
745 # wait for it to start
746 flag.wait()
747 # try to connect
748 if client_protocol is None:
749 client_protocol = protocol
750 try:
751 try:
752 s = ssl.wrap_socket(socket.socket(),
753 certfile=client_certfile,
754 ca_certs=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000755 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000756 cert_reqs=certreqs,
757 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000758 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000759 except ssl.SSLError, x:
760 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
761 except Exception, x:
762 raise test_support.TestFailed("Unexpected exception: " + str(x))
763 else:
Antoine Pitrou5ba84912009-10-19 17:59:07 +0000764 for arg in [indata, bytearray(indata), memoryview(indata)]:
765 if connectionchatty:
766 if test_support.verbose:
767 sys.stdout.write(
768 " client: sending %s...\n" % (repr(arg)))
769 s.write(arg)
770 outdata = s.read()
771 if connectionchatty:
772 if test_support.verbose:
773 sys.stdout.write(" client: read %s\n" % repr(outdata))
774 if outdata != indata.lower():
775 raise test_support.TestFailed(
776 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
777 % (outdata[:min(len(outdata),20)], len(outdata),
778 indata[:min(len(indata),20)].lower(), len(indata)))
Bill Janssen98d19da2007-09-10 21:51:02 +0000779 s.write("over\n")
780 if connectionchatty:
781 if test_support.verbose:
782 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000783 s.close()
784 finally:
785 server.stop()
786 server.join()
787
788 def tryProtocolCombo (server_protocol,
789 client_protocol,
790 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000791 certsreqs=None):
792
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000793 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000794 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000795
796 if certsreqs == ssl.CERT_NONE:
797 certtype = "CERT_NONE"
798 elif certsreqs == ssl.CERT_OPTIONAL:
799 certtype = "CERT_OPTIONAL"
800 elif certsreqs == ssl.CERT_REQUIRED:
801 certtype = "CERT_REQUIRED"
802 if test_support.verbose:
803 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
804 sys.stdout.write(formatstr %
805 (ssl.get_protocol_name(client_protocol),
806 ssl.get_protocol_name(server_protocol),
807 certtype))
808 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000809 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
810 # will send an SSLv3 hello (rather than SSLv2) starting from
811 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000812 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000813 CERTFILE, CERTFILE, client_protocol,
814 ciphers="ALL", chatty=False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000815 except test_support.TestFailed:
816 if expectedToWork:
817 raise
818 else:
819 if not expectedToWork:
820 raise test_support.TestFailed(
821 "Client protocol %s succeeded with server protocol %s!"
822 % (ssl.get_protocol_name(client_protocol),
823 ssl.get_protocol_name(server_protocol)))
824
825
Bill Janssen934b16d2008-06-28 22:19:33 +0000826 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000827
828 def testRudeShutdown(self):
829
830 listener_ready = threading.Event()
831 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000832 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000833
834 # `listener` runs in a thread. It opens a socket listening on
835 # PORT, and sits in an accept() until the main thread connects.
836 # Then it rudely closes the socket, and sets Event `listener_gone`
837 # to let the main thread know the socket is gone.
838 def listener():
839 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000840 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000841 s.listen(5)
842 listener_ready.set()
843 s.accept()
844 s = None # reclaim the socket object, which also closes it
845 listener_gone.set()
846
847 def connector():
848 listener_ready.wait()
849 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000850 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000851 listener_gone.wait()
852 try:
853 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000854 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000855 pass
856 else:
857 raise test_support.TestFailed(
858 'connecting to closed SSL socket should have failed')
859
860 t = threading.Thread(target=listener)
861 t.start()
862 connector()
863 t.join()
864
865 def testEcho (self):
866
867 if test_support.verbose:
868 sys.stdout.write("\n")
869 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
870 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
871 chatty=True, connectionchatty=True)
872
873 def testReadCert(self):
874
875 if test_support.verbose:
876 sys.stdout.write("\n")
877 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000878 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000879 certreqs=ssl.CERT_NONE,
880 ssl_version=ssl.PROTOCOL_SSLv23,
881 cacerts=CERTFILE,
882 chatty=False)
883 flag = threading.Event()
884 server.start(flag)
885 # wait for it to start
886 flag.wait()
887 # try to connect
888 try:
889 try:
890 s = ssl.wrap_socket(socket.socket(),
891 certfile=CERTFILE,
892 ca_certs=CERTFILE,
893 cert_reqs=ssl.CERT_REQUIRED,
894 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000895 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000896 except ssl.SSLError, x:
897 raise test_support.TestFailed(
898 "Unexpected SSL error: " + str(x))
899 except Exception, x:
900 raise test_support.TestFailed(
901 "Unexpected exception: " + str(x))
902 else:
903 if not s:
904 raise test_support.TestFailed(
905 "Can't SSL-handshake with test server")
906 cert = s.getpeercert()
907 if not cert:
908 raise test_support.TestFailed(
909 "Can't get peer certificate.")
910 cipher = s.cipher()
911 if test_support.verbose:
912 sys.stdout.write(pprint.pformat(cert) + '\n')
913 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000914 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000915 raise test_support.TestFailed(
916 "No subject field in certificate: %s." %
917 pprint.pformat(cert))
918 if ((('organizationName', 'Python Software Foundation'),)
919 not in cert['subject']):
920 raise test_support.TestFailed(
921 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000922 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000923 s.close()
924 finally:
925 server.stop()
926 server.join()
927
928 def testNULLcert(self):
929 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
930 "nullcert.pem"))
931 def testMalformedCert(self):
932 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
933 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000934 def testWrongCert(self):
935 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
936 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000937 def testMalformedKey(self):
938 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
939 "badkey.pem"))
940
941 def testProtocolSSL2(self):
942 if test_support.verbose:
943 sys.stdout.write("\n")
944 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
945 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
946 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
947 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
948 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
949 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
950
951 def testProtocolSSL23(self):
952 if test_support.verbose:
953 sys.stdout.write("\n")
954 try:
955 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
956 except test_support.TestFailed, x:
957 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
958 if test_support.verbose:
959 sys.stdout.write(
960 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
961 % str(x))
962 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
963 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
964 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
965
966 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
967 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
968 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
969
970 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
971 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
972 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
973
974 def testProtocolSSL3(self):
975 if test_support.verbose:
976 sys.stdout.write("\n")
977 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
978 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
979 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
980 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
981 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
982 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
983
984 def testProtocolTLS1(self):
985 if test_support.verbose:
986 sys.stdout.write("\n")
987 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
988 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
989 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
990 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
991 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
992 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
993
994 def testSTARTTLS (self):
995
Bill Janssen39295c22008-08-12 16:31:21 +0000996 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000997
Trent Nelsone41b0062008-04-08 23:47:30 +0000998 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000999 ssl_version=ssl.PROTOCOL_TLSv1,
1000 starttls_server=True,
1001 chatty=True,
1002 connectionchatty=True)
1003 flag = threading.Event()
1004 server.start(flag)
1005 # wait for it to start
1006 flag.wait()
1007 # try to connect
1008 wrapped = False
1009 try:
1010 try:
1011 s = socket.socket()
1012 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +00001013 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +00001014 except Exception, x:
1015 raise test_support.TestFailed("Unexpected exception: " + str(x))
1016 else:
1017 if test_support.verbose:
1018 sys.stdout.write("\n")
1019 for indata in msgs:
1020 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001021 sys.stdout.write(
1022 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001023 if wrapped:
1024 conn.write(indata)
1025 outdata = conn.read()
1026 else:
1027 s.send(indata)
1028 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001029 if (indata == "STARTTLS" and
1030 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001031 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001032 sys.stdout.write(
1033 " client: read %s from server, starting TLS...\n"
1034 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001035 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001036 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001037 elif (indata == "ENDTLS" and
1038 outdata.strip().lower().startswith("ok")):
1039 if test_support.verbose:
1040 sys.stdout.write(
1041 " client: read %s from server, ending TLS...\n"
1042 % repr(outdata))
1043 s = conn.unwrap()
1044 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001045 else:
1046 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001047 sys.stdout.write(
1048 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001049 if test_support.verbose:
1050 sys.stdout.write(" client: closing connection.\n")
1051 if wrapped:
1052 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001053 else:
1054 s.send("over\n")
1055 s.close()
1056 finally:
1057 server.stop()
1058 server.join()
1059
Bill Janssen934b16d2008-06-28 22:19:33 +00001060 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001061
Bill Janssen934b16d2008-06-28 22:19:33 +00001062 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001063 flag = threading.Event()
1064 server.start(flag)
1065 # wait for it to start
1066 flag.wait()
1067 # try to connect
1068 try:
1069 if test_support.verbose:
1070 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001071 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001072 d2 = ''
1073 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001074 url = 'https://127.0.0.1:%d/%s' % (
1075 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001076 with test_support.check_py3k_warnings():
1077 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001078 dlen = f.info().getheader("content-length")
1079 if dlen and (int(dlen) > 0):
1080 d2 = f.read(int(dlen))
1081 if test_support.verbose:
1082 sys.stdout.write(
1083 " client: read %d bytes from remote server '%s'\n"
1084 % (len(d2), server))
1085 f.close()
1086 except:
1087 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1088 if test_support.verbose:
1089 sys.stdout.write('\n' + msg)
1090 raise test_support.TestFailed(msg)
1091 else:
1092 if not (d1 == d2):
1093 raise test_support.TestFailed(
1094 "Couldn't fetch data from HTTPS server")
1095 finally:
1096 server.stop()
1097 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001098
Bill Janssen934b16d2008-06-28 22:19:33 +00001099 def testWrappedAccept (self):
1100
1101 if test_support.verbose:
1102 sys.stdout.write("\n")
1103 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1104 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1105 chatty=True, connectionchatty=True,
1106 wrap_accepting_socket=True)
1107
1108
1109 def testAsyncoreServer (self):
1110
1111 indata = "TEST MESSAGE of mixed case\n"
1112
1113 if test_support.verbose:
1114 sys.stdout.write("\n")
1115 server = AsyncoreEchoServer(CERTFILE)
1116 flag = threading.Event()
1117 server.start(flag)
1118 # wait for it to start
1119 flag.wait()
1120 # try to connect
1121 try:
1122 try:
1123 s = ssl.wrap_socket(socket.socket())
1124 s.connect(('127.0.0.1', server.port))
1125 except ssl.SSLError, x:
1126 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1127 except Exception, x:
1128 raise test_support.TestFailed("Unexpected exception: " + str(x))
1129 else:
1130 if test_support.verbose:
1131 sys.stdout.write(
1132 " client: sending %s...\n" % (repr(indata)))
1133 s.write(indata)
1134 outdata = s.read()
1135 if test_support.verbose:
1136 sys.stdout.write(" client: read %s\n" % repr(outdata))
1137 if outdata != indata.lower():
1138 raise test_support.TestFailed(
1139 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1140 % (outdata[:min(len(outdata),20)], len(outdata),
1141 indata[:min(len(indata),20)].lower(), len(indata)))
1142 s.write("over\n")
1143 if test_support.verbose:
1144 sys.stdout.write(" client: closing connection.\n")
1145 s.close()
1146 finally:
1147 server.stop()
1148 # wait for server thread to end
1149 server.join()
1150
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001151
Bill Janssen61c001a2008-09-08 16:37:24 +00001152 def testAllRecvAndSendMethods(self):
1153
1154 if test_support.verbose:
1155 sys.stdout.write("\n")
1156
1157 server = ThreadedEchoServer(CERTFILE,
1158 certreqs=ssl.CERT_NONE,
1159 ssl_version=ssl.PROTOCOL_TLSv1,
1160 cacerts=CERTFILE,
1161 chatty=True,
1162 connectionchatty=False)
1163 flag = threading.Event()
1164 server.start(flag)
1165 # wait for it to start
1166 flag.wait()
1167 # try to connect
1168 try:
1169 s = ssl.wrap_socket(socket.socket(),
1170 server_side=False,
1171 certfile=CERTFILE,
1172 ca_certs=CERTFILE,
1173 cert_reqs=ssl.CERT_NONE,
1174 ssl_version=ssl.PROTOCOL_TLSv1)
1175 s.connect((HOST, server.port))
1176 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001177 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001178 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001179 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001180 else:
1181 # helper methods for standardising recv* method signatures
1182 def _recv_into():
1183 b = bytearray("\0"*100)
1184 count = s.recv_into(b)
1185 return b[:count]
1186
1187 def _recvfrom_into():
1188 b = bytearray("\0"*100)
1189 count, addr = s.recvfrom_into(b)
1190 return b[:count]
1191
1192 # (name, method, whether to expect success, *args)
1193 send_methods = [
1194 ('send', s.send, True, []),
1195 ('sendto', s.sendto, False, ["some.address"]),
1196 ('sendall', s.sendall, True, []),
1197 ]
1198 recv_methods = [
1199 ('recv', s.recv, True, []),
1200 ('recvfrom', s.recvfrom, False, ["some.address"]),
1201 ('recv_into', _recv_into, True, []),
1202 ('recvfrom_into', _recvfrom_into, False, []),
1203 ]
1204 data_prefix = u"PREFIX_"
1205
1206 for meth_name, send_meth, expect_success, args in send_methods:
1207 indata = data_prefix + meth_name
1208 try:
1209 send_meth(indata.encode('ASCII', 'strict'), *args)
1210 outdata = s.read()
1211 outdata = outdata.decode('ASCII', 'strict')
1212 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001213 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001214 "While sending with <<%s>> bad data "
1215 "<<%r>> (%d) received; "
1216 "expected <<%r>> (%d)\n" % (
1217 meth_name, outdata[:20], len(outdata),
1218 indata[:20], len(indata)
1219 )
1220 )
1221 except ValueError as e:
1222 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001223 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001224 "Failed to send with method <<%s>>; "
1225 "expected to succeed.\n" % (meth_name,)
1226 )
1227 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001228 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001229 "Method <<%s>> failed with unexpected "
1230 "exception message: %s\n" % (
1231 meth_name, e
1232 )
1233 )
1234
1235 for meth_name, recv_meth, expect_success, args in recv_methods:
1236 indata = data_prefix + meth_name
1237 try:
1238 s.send(indata.encode('ASCII', 'strict'))
1239 outdata = recv_meth(*args)
1240 outdata = outdata.decode('ASCII', 'strict')
1241 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001242 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001243 "While receiving with <<%s>> bad data "
1244 "<<%r>> (%d) received; "
1245 "expected <<%r>> (%d)\n" % (
1246 meth_name, outdata[:20], len(outdata),
1247 indata[:20], len(indata)
1248 )
1249 )
1250 except ValueError as e:
1251 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001252 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001253 "Failed to receive with method <<%s>>; "
1254 "expected to succeed.\n" % (meth_name,)
1255 )
1256 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001257 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001258 "Method <<%s>> failed with unexpected "
1259 "exception message: %s\n" % (
1260 meth_name, e
1261 )
1262 )
1263 # consume data
1264 s.read()
1265
1266 s.write("over\n".encode("ASCII", "strict"))
1267 s.close()
1268 finally:
1269 server.stop()
1270 server.join()
1271
1272
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001273def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001274 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001275 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001276
Trent Nelsone41b0062008-04-08 23:47:30 +00001277 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001278 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001279 "keycert.pem")
1280 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1281 os.path.dirname(__file__) or os.curdir,
1282 "https_svn_python_org_root.pem")
1283
1284 if (not os.path.exists(CERTFILE) or
1285 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001286 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001287
Bill Janssen934b16d2008-06-28 22:19:33 +00001288 TESTPORT = test_support.find_unused_port()
1289 if not TESTPORT:
1290 raise test_support.TestFailed("Can't find open port to test servers on!")
1291
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001292 tests = [BasicTests]
1293
Bill Janssen296a59d2007-09-16 22:06:00 +00001294 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001295 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001296
Bill Janssen98d19da2007-09-10 21:51:02 +00001297 if _have_threads:
1298 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001299 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001300 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001301
Bill Janssen98d19da2007-09-10 21:51:02 +00001302 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001303
Bill Janssen98d19da2007-09-10 21:51:02 +00001304 if _have_threads:
1305 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001306
1307if __name__ == "__main__":
1308 test_main()