blob: 2c401dc69060a2a6840521ecb0c6ac567a2876e9 [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,
497 do_handshake_on_connect=True)
498
499 def readable(self):
500 if isinstance(self.socket, ssl.SSLSocket):
501 while self.socket.pending() > 0:
502 self.handle_read_event()
503 return True
504
505 def handle_read(self):
506 data = self.recv(1024)
507 self.send(data.lower())
508
509 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000510 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000511 if test_support.verbose:
512 sys.stdout.write(" server: closed connection %s\n" % self.socket)
513
514 def handle_error(self):
515 raise
516
517 def __init__(self, certfile):
518 self.certfile = certfile
519 asyncore.dispatcher.__init__(self)
520 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
521 self.port = test_support.bind_port(self.socket)
522 self.listen(5)
523
524 def handle_accept(self):
525 sock_obj, addr = self.accept()
526 if test_support.verbose:
527 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
528 self.ConnectionHandler(sock_obj, self.certfile)
529
530 def handle_error(self):
531 raise
532
533 def __init__(self, certfile):
534 self.flag = None
535 self.active = False
536 self.server = self.EchoServer(certfile)
537 self.port = self.server.port
538 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000539 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000540
541 def __str__(self):
542 return "<%s %s>" % (self.__class__.__name__, self.server)
543
544 def start (self, flag=None):
545 self.flag = flag
546 threading.Thread.start(self)
547
548 def run (self):
549 self.active = True
550 if self.flag:
551 self.flag.set()
552 while self.active:
553 try:
554 asyncore.loop(1)
555 except:
556 pass
557
558 def stop (self):
559 self.active = False
560 self.server.close()
561
562 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000563
564 class HTTPSServer(HTTPServer):
565
566 def __init__(self, server_address, RequestHandlerClass, certfile):
567
568 HTTPServer.__init__(self, server_address, RequestHandlerClass)
569 # we assume the certfile contains both private key and certificate
570 self.certfile = certfile
571 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000572 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000573 self.allow_reuse_address = True
574
Bill Janssen934b16d2008-06-28 22:19:33 +0000575 def __str__(self):
576 return ('<%s %s:%s>' %
577 (self.__class__.__name__,
578 self.server_name,
579 self.server_port))
580
Bill Janssen296a59d2007-09-16 22:06:00 +0000581 def get_request (self):
582 # override this to wrap socket with SSL
583 sock, addr = self.socket.accept()
584 sslconn = ssl.wrap_socket(sock, server_side=True,
585 certfile=self.certfile)
586 return sslconn, addr
587
588 # The methods overridden below this are mainly so that we
589 # can run it in a thread and be able to stop it from another
590 # You probably wouldn't need them in other uses.
591
592 def server_activate(self):
593 # We want to run this in a thread for testing purposes,
594 # so we override this to set timeout, so that we get
595 # a chance to stop the server
596 self.socket.settimeout(0.5)
597 HTTPServer.server_activate(self)
598
599 def serve_forever(self):
600 # We want this to run in a thread, so we use a slightly
601 # modified version of "forever".
602 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000603 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000604 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000605 # We need to lock while handling the request.
606 # Another thread can close the socket after self.active
607 # has been checked and before the request is handled.
608 # This causes an exception when using the closed socket.
609 with self.active_lock:
610 if not self.active:
611 break
612 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000613 except socket.timeout:
614 pass
615 except KeyboardInterrupt:
616 self.server_close()
617 return
618 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000619 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
620 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000621 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000622
623 def server_close(self):
624 # Again, we want this to run in a thread, so we need to override
625 # close to clear the "active" flag, so that serve_forever() will
626 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000627 with self.active_lock:
628 HTTPServer.server_close(self)
629 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000630
631 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
632
633 # need to override translate_path to get a known root,
634 # instead of using os.curdir, since the test could be
635 # run from anywhere
636
637 server_version = "TestHTTPS/1.0"
638
639 root = None
640
641 def translate_path(self, path):
642 """Translate a /-separated PATH to the local filename syntax.
643
644 Components that mean special things to the local file system
645 (e.g. drive or directory names) are ignored. (XXX They should
646 probably be diagnosed.)
647
648 """
649 # abandon query parameters
650 path = urlparse.urlparse(path)[2]
651 path = os.path.normpath(urllib.unquote(path))
652 words = path.split('/')
653 words = filter(None, words)
654 path = self.root
655 for word in words:
656 drive, word = os.path.splitdrive(word)
657 head, word = os.path.split(word)
658 if word in self.root: continue
659 path = os.path.join(path, word)
660 return path
661
662 def log_message(self, format, *args):
663
664 # we override this to suppress logging unless "verbose"
665
666 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000667 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
668 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000669 self.server.server_port,
670 self.request.cipher(),
671 self.log_date_time_string(),
672 format%args))
673
674
Trent Nelsone41b0062008-04-08 23:47:30 +0000675 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000676 self.flag = None
677 self.active = False
678 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000679 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000680 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000681 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000682 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000683 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000684
685 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000686 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000687
688 def start (self, flag=None):
689 self.flag = flag
690 threading.Thread.start(self)
691
692 def run (self):
693 self.active = True
694 if self.flag:
695 self.flag.set()
696 self.server.serve_forever()
697 self.active = False
698
699 def stop (self):
700 self.active = False
701 self.server.server_close()
702
703
Bill Janssen98d19da2007-09-10 21:51:02 +0000704 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000705 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000706 certreqs=ssl.CERT_REQUIRED,
707 cacerts=CERTFILE, chatty=False)
708 flag = threading.Event()
709 server.start(flag)
710 # wait for it to start
711 flag.wait()
712 # try to connect
713 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000714 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000715 s = ssl.wrap_socket(socket.socket(),
716 certfile=certfile,
717 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000718 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000719 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000720 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000721 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000722 except socket.error, x:
723 if test_support.verbose:
724 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000725 else:
726 raise test_support.TestFailed(
727 "Use of invalid cert should have failed!")
728 finally:
729 server.stop()
730 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000731
Bill Janssen98d19da2007-09-10 21:51:02 +0000732 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
733 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000734 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000735 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000736
Trent Nelsone41b0062008-04-08 23:47:30 +0000737 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000738 certreqs=certreqs,
739 ssl_version=protocol,
740 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000741 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000742 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000743 connectionchatty=connectionchatty,
744 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000745 flag = threading.Event()
746 server.start(flag)
747 # wait for it to start
748 flag.wait()
749 # try to connect
750 if client_protocol is None:
751 client_protocol = protocol
752 try:
753 try:
754 s = ssl.wrap_socket(socket.socket(),
755 certfile=client_certfile,
756 ca_certs=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000757 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000758 cert_reqs=certreqs,
759 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000760 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000761 except ssl.SSLError, x:
762 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
763 except Exception, x:
764 raise test_support.TestFailed("Unexpected exception: " + str(x))
765 else:
Antoine Pitrou5ba84912009-10-19 17:59:07 +0000766 for arg in [indata, bytearray(indata), memoryview(indata)]:
767 if connectionchatty:
768 if test_support.verbose:
769 sys.stdout.write(
770 " client: sending %s...\n" % (repr(arg)))
771 s.write(arg)
772 outdata = s.read()
773 if connectionchatty:
774 if test_support.verbose:
775 sys.stdout.write(" client: read %s\n" % repr(outdata))
776 if outdata != indata.lower():
777 raise test_support.TestFailed(
778 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
779 % (outdata[:min(len(outdata),20)], len(outdata),
780 indata[:min(len(indata),20)].lower(), len(indata)))
Bill Janssen98d19da2007-09-10 21:51:02 +0000781 s.write("over\n")
782 if connectionchatty:
783 if test_support.verbose:
784 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000785 s.close()
786 finally:
787 server.stop()
788 server.join()
789
790 def tryProtocolCombo (server_protocol,
791 client_protocol,
792 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000793 certsreqs=None):
794
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000795 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000796 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000797
798 if certsreqs == ssl.CERT_NONE:
799 certtype = "CERT_NONE"
800 elif certsreqs == ssl.CERT_OPTIONAL:
801 certtype = "CERT_OPTIONAL"
802 elif certsreqs == ssl.CERT_REQUIRED:
803 certtype = "CERT_REQUIRED"
804 if test_support.verbose:
805 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
806 sys.stdout.write(formatstr %
807 (ssl.get_protocol_name(client_protocol),
808 ssl.get_protocol_name(server_protocol),
809 certtype))
810 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000811 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
812 # will send an SSLv3 hello (rather than SSLv2) starting from
813 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000814 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000815 CERTFILE, CERTFILE, client_protocol,
816 ciphers="ALL", chatty=False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000817 except test_support.TestFailed:
818 if expectedToWork:
819 raise
820 else:
821 if not expectedToWork:
822 raise test_support.TestFailed(
823 "Client protocol %s succeeded with server protocol %s!"
824 % (ssl.get_protocol_name(client_protocol),
825 ssl.get_protocol_name(server_protocol)))
826
827
Bill Janssen934b16d2008-06-28 22:19:33 +0000828 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000829
830 def testRudeShutdown(self):
831
832 listener_ready = threading.Event()
833 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000834 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000835
836 # `listener` runs in a thread. It opens a socket listening on
837 # PORT, and sits in an accept() until the main thread connects.
838 # Then it rudely closes the socket, and sets Event `listener_gone`
839 # to let the main thread know the socket is gone.
840 def listener():
841 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000842 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000843 s.listen(5)
844 listener_ready.set()
845 s.accept()
846 s = None # reclaim the socket object, which also closes it
847 listener_gone.set()
848
849 def connector():
850 listener_ready.wait()
851 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000852 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000853 listener_gone.wait()
854 try:
855 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000856 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000857 pass
858 else:
859 raise test_support.TestFailed(
860 'connecting to closed SSL socket should have failed')
861
862 t = threading.Thread(target=listener)
863 t.start()
864 connector()
865 t.join()
866
867 def testEcho (self):
868
869 if test_support.verbose:
870 sys.stdout.write("\n")
871 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
872 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
873 chatty=True, connectionchatty=True)
874
875 def testReadCert(self):
876
877 if test_support.verbose:
878 sys.stdout.write("\n")
879 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000880 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000881 certreqs=ssl.CERT_NONE,
882 ssl_version=ssl.PROTOCOL_SSLv23,
883 cacerts=CERTFILE,
884 chatty=False)
885 flag = threading.Event()
886 server.start(flag)
887 # wait for it to start
888 flag.wait()
889 # try to connect
890 try:
891 try:
892 s = ssl.wrap_socket(socket.socket(),
893 certfile=CERTFILE,
894 ca_certs=CERTFILE,
895 cert_reqs=ssl.CERT_REQUIRED,
896 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000897 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000898 except ssl.SSLError, x:
899 raise test_support.TestFailed(
900 "Unexpected SSL error: " + str(x))
901 except Exception, x:
902 raise test_support.TestFailed(
903 "Unexpected exception: " + str(x))
904 else:
905 if not s:
906 raise test_support.TestFailed(
907 "Can't SSL-handshake with test server")
908 cert = s.getpeercert()
909 if not cert:
910 raise test_support.TestFailed(
911 "Can't get peer certificate.")
912 cipher = s.cipher()
913 if test_support.verbose:
914 sys.stdout.write(pprint.pformat(cert) + '\n')
915 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000916 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000917 raise test_support.TestFailed(
918 "No subject field in certificate: %s." %
919 pprint.pformat(cert))
920 if ((('organizationName', 'Python Software Foundation'),)
921 not in cert['subject']):
922 raise test_support.TestFailed(
923 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000924 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000925 s.close()
926 finally:
927 server.stop()
928 server.join()
929
930 def testNULLcert(self):
931 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
932 "nullcert.pem"))
933 def testMalformedCert(self):
934 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
935 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000936 def testWrongCert(self):
937 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
938 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000939 def testMalformedKey(self):
940 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
941 "badkey.pem"))
942
943 def testProtocolSSL2(self):
944 if test_support.verbose:
945 sys.stdout.write("\n")
946 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
947 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
948 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
949 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
950 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
951 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
952
953 def testProtocolSSL23(self):
954 if test_support.verbose:
955 sys.stdout.write("\n")
956 try:
957 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
958 except test_support.TestFailed, x:
959 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
960 if test_support.verbose:
961 sys.stdout.write(
962 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
963 % str(x))
964 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
965 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
966 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
967
968 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
969 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
970 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
971
972 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
973 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
974 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
975
976 def testProtocolSSL3(self):
977 if test_support.verbose:
978 sys.stdout.write("\n")
979 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
980 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
981 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
982 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
983 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
984 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
985
986 def testProtocolTLS1(self):
987 if test_support.verbose:
988 sys.stdout.write("\n")
989 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
990 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
991 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
992 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
993 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
994 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
995
996 def testSTARTTLS (self):
997
Bill Janssen39295c22008-08-12 16:31:21 +0000998 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000999
Trent Nelsone41b0062008-04-08 23:47:30 +00001000 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +00001001 ssl_version=ssl.PROTOCOL_TLSv1,
1002 starttls_server=True,
1003 chatty=True,
1004 connectionchatty=True)
1005 flag = threading.Event()
1006 server.start(flag)
1007 # wait for it to start
1008 flag.wait()
1009 # try to connect
1010 wrapped = False
1011 try:
1012 try:
1013 s = socket.socket()
1014 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +00001015 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +00001016 except Exception, x:
1017 raise test_support.TestFailed("Unexpected exception: " + str(x))
1018 else:
1019 if test_support.verbose:
1020 sys.stdout.write("\n")
1021 for indata in msgs:
1022 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001023 sys.stdout.write(
1024 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001025 if wrapped:
1026 conn.write(indata)
1027 outdata = conn.read()
1028 else:
1029 s.send(indata)
1030 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001031 if (indata == "STARTTLS" and
1032 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001033 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001034 sys.stdout.write(
1035 " client: read %s from server, starting TLS...\n"
1036 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001037 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001038 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001039 elif (indata == "ENDTLS" and
1040 outdata.strip().lower().startswith("ok")):
1041 if test_support.verbose:
1042 sys.stdout.write(
1043 " client: read %s from server, ending TLS...\n"
1044 % repr(outdata))
1045 s = conn.unwrap()
1046 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001047 else:
1048 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001049 sys.stdout.write(
1050 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001051 if test_support.verbose:
1052 sys.stdout.write(" client: closing connection.\n")
1053 if wrapped:
1054 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001055 else:
1056 s.send("over\n")
1057 s.close()
1058 finally:
1059 server.stop()
1060 server.join()
1061
Bill Janssen934b16d2008-06-28 22:19:33 +00001062 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001063
Bill Janssen934b16d2008-06-28 22:19:33 +00001064 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001065 flag = threading.Event()
1066 server.start(flag)
1067 # wait for it to start
1068 flag.wait()
1069 # try to connect
1070 try:
1071 if test_support.verbose:
1072 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001073 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001074 d2 = ''
1075 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001076 url = 'https://127.0.0.1:%d/%s' % (
1077 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001078 with test_support.check_py3k_warnings():
1079 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001080 dlen = f.info().getheader("content-length")
1081 if dlen and (int(dlen) > 0):
1082 d2 = f.read(int(dlen))
1083 if test_support.verbose:
1084 sys.stdout.write(
1085 " client: read %d bytes from remote server '%s'\n"
1086 % (len(d2), server))
1087 f.close()
1088 except:
1089 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1090 if test_support.verbose:
1091 sys.stdout.write('\n' + msg)
1092 raise test_support.TestFailed(msg)
1093 else:
1094 if not (d1 == d2):
1095 raise test_support.TestFailed(
1096 "Couldn't fetch data from HTTPS server")
1097 finally:
1098 server.stop()
1099 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001100
Bill Janssen934b16d2008-06-28 22:19:33 +00001101 def testWrappedAccept (self):
1102
1103 if test_support.verbose:
1104 sys.stdout.write("\n")
1105 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1106 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1107 chatty=True, connectionchatty=True,
1108 wrap_accepting_socket=True)
1109
1110
1111 def testAsyncoreServer (self):
1112
1113 indata = "TEST MESSAGE of mixed case\n"
1114
1115 if test_support.verbose:
1116 sys.stdout.write("\n")
1117 server = AsyncoreEchoServer(CERTFILE)
1118 flag = threading.Event()
1119 server.start(flag)
1120 # wait for it to start
1121 flag.wait()
1122 # try to connect
1123 try:
1124 try:
1125 s = ssl.wrap_socket(socket.socket())
1126 s.connect(('127.0.0.1', server.port))
1127 except ssl.SSLError, x:
1128 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1129 except Exception, x:
1130 raise test_support.TestFailed("Unexpected exception: " + str(x))
1131 else:
1132 if test_support.verbose:
1133 sys.stdout.write(
1134 " client: sending %s...\n" % (repr(indata)))
1135 s.write(indata)
1136 outdata = s.read()
1137 if test_support.verbose:
1138 sys.stdout.write(" client: read %s\n" % repr(outdata))
1139 if outdata != indata.lower():
1140 raise test_support.TestFailed(
1141 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1142 % (outdata[:min(len(outdata),20)], len(outdata),
1143 indata[:min(len(indata),20)].lower(), len(indata)))
1144 s.write("over\n")
1145 if test_support.verbose:
1146 sys.stdout.write(" client: closing connection.\n")
1147 s.close()
1148 finally:
1149 server.stop()
1150 # wait for server thread to end
1151 server.join()
1152
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001153
Bill Janssen61c001a2008-09-08 16:37:24 +00001154 def testAllRecvAndSendMethods(self):
1155
1156 if test_support.verbose:
1157 sys.stdout.write("\n")
1158
1159 server = ThreadedEchoServer(CERTFILE,
1160 certreqs=ssl.CERT_NONE,
1161 ssl_version=ssl.PROTOCOL_TLSv1,
1162 cacerts=CERTFILE,
1163 chatty=True,
1164 connectionchatty=False)
1165 flag = threading.Event()
1166 server.start(flag)
1167 # wait for it to start
1168 flag.wait()
1169 # try to connect
1170 try:
1171 s = ssl.wrap_socket(socket.socket(),
1172 server_side=False,
1173 certfile=CERTFILE,
1174 ca_certs=CERTFILE,
1175 cert_reqs=ssl.CERT_NONE,
1176 ssl_version=ssl.PROTOCOL_TLSv1)
1177 s.connect((HOST, server.port))
1178 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001179 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001180 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001181 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001182 else:
1183 # helper methods for standardising recv* method signatures
1184 def _recv_into():
1185 b = bytearray("\0"*100)
1186 count = s.recv_into(b)
1187 return b[:count]
1188
1189 def _recvfrom_into():
1190 b = bytearray("\0"*100)
1191 count, addr = s.recvfrom_into(b)
1192 return b[:count]
1193
1194 # (name, method, whether to expect success, *args)
1195 send_methods = [
1196 ('send', s.send, True, []),
1197 ('sendto', s.sendto, False, ["some.address"]),
1198 ('sendall', s.sendall, True, []),
1199 ]
1200 recv_methods = [
1201 ('recv', s.recv, True, []),
1202 ('recvfrom', s.recvfrom, False, ["some.address"]),
1203 ('recv_into', _recv_into, True, []),
1204 ('recvfrom_into', _recvfrom_into, False, []),
1205 ]
1206 data_prefix = u"PREFIX_"
1207
1208 for meth_name, send_meth, expect_success, args in send_methods:
1209 indata = data_prefix + meth_name
1210 try:
1211 send_meth(indata.encode('ASCII', 'strict'), *args)
1212 outdata = s.read()
1213 outdata = outdata.decode('ASCII', 'strict')
1214 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001215 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001216 "While sending with <<%s>> bad data "
1217 "<<%r>> (%d) received; "
1218 "expected <<%r>> (%d)\n" % (
1219 meth_name, outdata[:20], len(outdata),
1220 indata[:20], len(indata)
1221 )
1222 )
1223 except ValueError as e:
1224 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001225 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001226 "Failed to send with method <<%s>>; "
1227 "expected to succeed.\n" % (meth_name,)
1228 )
1229 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001230 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001231 "Method <<%s>> failed with unexpected "
1232 "exception message: %s\n" % (
1233 meth_name, e
1234 )
1235 )
1236
1237 for meth_name, recv_meth, expect_success, args in recv_methods:
1238 indata = data_prefix + meth_name
1239 try:
1240 s.send(indata.encode('ASCII', 'strict'))
1241 outdata = recv_meth(*args)
1242 outdata = outdata.decode('ASCII', 'strict')
1243 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001244 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001245 "While receiving with <<%s>> bad data "
1246 "<<%r>> (%d) received; "
1247 "expected <<%r>> (%d)\n" % (
1248 meth_name, outdata[:20], len(outdata),
1249 indata[:20], len(indata)
1250 )
1251 )
1252 except ValueError as e:
1253 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001254 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001255 "Failed to receive with method <<%s>>; "
1256 "expected to succeed.\n" % (meth_name,)
1257 )
1258 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001259 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001260 "Method <<%s>> failed with unexpected "
1261 "exception message: %s\n" % (
1262 meth_name, e
1263 )
1264 )
1265 # consume data
1266 s.read()
1267
1268 s.write("over\n".encode("ASCII", "strict"))
1269 s.close()
1270 finally:
1271 server.stop()
1272 server.join()
1273
1274
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001275def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001276 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001277 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001278
Trent Nelsone41b0062008-04-08 23:47:30 +00001279 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001280 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001281 "keycert.pem")
1282 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1283 os.path.dirname(__file__) or os.curdir,
1284 "https_svn_python_org_root.pem")
1285
1286 if (not os.path.exists(CERTFILE) or
1287 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001288 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001289
Bill Janssen934b16d2008-06-28 22:19:33 +00001290 TESTPORT = test_support.find_unused_port()
1291 if not TESTPORT:
1292 raise test_support.TestFailed("Can't find open port to test servers on!")
1293
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001294 tests = [BasicTests]
1295
Bill Janssen296a59d2007-09-16 22:06:00 +00001296 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001297 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001298
Bill Janssen98d19da2007-09-10 21:51:02 +00001299 if _have_threads:
1300 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001301 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001302 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001303
Bill Janssen98d19da2007-09-10 21:51:02 +00001304 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001305
Bill Janssen98d19da2007-09-10 21:51:02 +00001306 if _have_threads:
1307 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001308
1309if __name__ == "__main__":
1310 test_main()