blob: 458db269e5d9330057e5e2aa8609481e32526c03 [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
10import os
11import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000012import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import traceback
14
Bill Janssen296a59d2007-09-16 22:06:00 +000015from BaseHTTPServer import HTTPServer
16from SimpleHTTPServer import SimpleHTTPRequestHandler
17
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000018# Optionally test SSL support, if we have it in the tested platform
19skip_expected = False
20try:
21 import ssl
22except ImportError:
23 skip_expected = True
24
Trent Nelsone41b0062008-04-08 23:47:30 +000025HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000026CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000027SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000028
Neal Norwitz3e533c22007-08-27 01:03:18 +000029def handle_error(prefix):
30 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000031 if test_support.verbose:
32 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000033
Bill Jansseneb257ac2008-09-29 18:56:38 +000034 def testSimpleSSLwrap(self):
35 try:
36 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
37 except IOError, e:
38 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
39 pass
40 else:
41 raise
42 try:
43 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
44 except IOError, e:
45 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
46 pass
47 else:
48 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000049
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000050class BasicTests(unittest.TestCase):
51
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000052 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000053 if not test_support.is_resource_enabled('network'):
54 return
Bill Janssen296a59d2007-09-16 22:06:00 +000055 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
56 cert_reqs=ssl.CERT_NONE)
57 s.connect(("svn.python.org", 443))
58 c = s.getpeercert()
59 if c:
60 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
61 s.close()
62
63 # this should fail because we have no verification certs
64 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
65 cert_reqs=ssl.CERT_REQUIRED)
66 try:
67 s.connect(("svn.python.org", 443))
68 except ssl.SSLError:
69 pass
70 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000071 s.close()
72
Bill Janssen98d19da2007-09-10 21:51:02 +000073 def testCrucialConstants(self):
74 ssl.PROTOCOL_SSLv2
75 ssl.PROTOCOL_SSLv23
76 ssl.PROTOCOL_SSLv3
77 ssl.PROTOCOL_TLSv1
78 ssl.CERT_NONE
79 ssl.CERT_OPTIONAL
80 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000081
Bill Janssen98d19da2007-09-10 21:51:02 +000082 def testRAND(self):
83 v = ssl.RAND_status()
84 if test_support.verbose:
85 sys.stdout.write("\n RAND_status is %d (%s)\n"
86 % (v, (v and "sufficient randomness") or
87 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000088 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000089 ssl.RAND_egd(1)
90 except TypeError:
91 pass
Guido van Rossume4729332007-08-26 19:35:09 +000092 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000093 print "didn't raise TypeError"
94 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000095
Bill Janssen98d19da2007-09-10 21:51:02 +000096 def testParseCert(self):
97 # note that this uses an 'unofficial' function in _ssl.c,
98 # provided solely for this test, to exercise the certificate
99 # parsing code
100 p = ssl._ssl._test_decode_cert(CERTFILE, False)
101 if test_support.verbose:
102 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000103
Bill Janssen296a59d2007-09-16 22:06:00 +0000104 def testDERtoPEM(self):
105
106 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
107 d1 = ssl.PEM_cert_to_DER_cert(pem)
108 p2 = ssl.DER_cert_to_PEM_cert(d1)
109 d2 = ssl.PEM_cert_to_DER_cert(p2)
110 if (d1 != d2):
111 raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
112
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000113 def test_openssl_version(self):
114 n = ssl.OPENSSL_VERSION_NUMBER
115 t = ssl.OPENSSL_VERSION_INFO
116 s = ssl.OPENSSL_VERSION
117 self.assertIsInstance(n, (int, long))
118 self.assertIsInstance(t, tuple)
119 self.assertIsInstance(s, str)
120 # Some sanity checks follow
121 # >= 0.9
122 self.assertGreaterEqual(n, 0x900000)
123 # < 2.0
124 self.assertLess(n, 0x20000000)
125 major, minor, fix, patch, status = t
126 self.assertGreaterEqual(major, 0)
127 self.assertLess(major, 2)
128 self.assertGreaterEqual(minor, 0)
129 self.assertLess(minor, 256)
130 self.assertGreaterEqual(fix, 0)
131 self.assertLess(fix, 256)
132 self.assertGreaterEqual(patch, 0)
133 self.assertLessEqual(patch, 26)
134 self.assertGreaterEqual(status, 0)
135 self.assertLessEqual(status, 15)
136 # Version string as returned by OpenSSL, the format might change
137 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
138 (s, t))
139
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000140 def test_ciphers(self):
141 if not test_support.is_resource_enabled('network'):
142 return
143 remote = ("svn.python.org", 443)
144 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
145 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
146 s.connect(remote)
147 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
148 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
149 s.connect(remote)
150 # Error checking occurs when connecting, because the SSL context
151 # isn't created before.
152 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
153 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
154 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
155 s.connect(remote)
156
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000157
Bill Janssen934b16d2008-06-28 22:19:33 +0000158class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000159
160 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000161 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
162 cert_reqs=ssl.CERT_NONE)
163 s.connect(("svn.python.org", 443))
164 c = s.getpeercert()
165 if c:
166 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
167 s.close()
168
169 # this should fail because we have no verification certs
170 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
171 cert_reqs=ssl.CERT_REQUIRED)
172 try:
173 s.connect(("svn.python.org", 443))
174 except ssl.SSLError:
175 pass
176 finally:
177 s.close()
178
179 # this should succeed because we specify the root cert
180 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
181 cert_reqs=ssl.CERT_REQUIRED,
182 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
183 try:
184 s.connect(("svn.python.org", 443))
185 except ssl.SSLError, x:
186 raise test_support.TestFailed("Unexpected exception %s" % x)
187 finally:
188 s.close()
189
Bill Janssen934b16d2008-06-28 22:19:33 +0000190
191 def testNonBlockingHandshake(self):
192 s = socket.socket(socket.AF_INET)
193 s.connect(("svn.python.org", 443))
194 s.setblocking(False)
195 s = ssl.wrap_socket(s,
196 cert_reqs=ssl.CERT_NONE,
197 do_handshake_on_connect=False)
198 count = 0
199 while True:
200 try:
201 count += 1
202 s.do_handshake()
203 break
204 except ssl.SSLError, err:
205 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
206 select.select([s], [], [])
207 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
208 select.select([], [s], [])
209 else:
210 raise
211 s.close()
212 if test_support.verbose:
213 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
214
Bill Janssen296a59d2007-09-16 22:06:00 +0000215 def testFetchServerCert(self):
216
217 pem = ssl.get_server_certificate(("svn.python.org", 443))
218 if not pem:
219 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
220
221 try:
222 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
223 except ssl.SSLError:
224 #should fail
225 pass
226 else:
227 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
228
229 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
230 if not pem:
231 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
232 if test_support.verbose:
233 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
234
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000235 def test_algorithms(self):
236 # Issue #8484: all algorithms should be available when verifying a
237 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000238 # SHA256 was added in OpenSSL 0.9.8
239 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
240 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000241 # NOTE: https://sha256.tbs-internet.com is another possible test host
242 remote = ("sha2.hboeck.de", 443)
243 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
244 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
245 cert_reqs=ssl.CERT_REQUIRED,
246 ca_certs=sha256_cert,)
247 with test_support.transient_internet():
248 try:
249 s.connect(remote)
250 if test_support.verbose:
251 sys.stdout.write("\nCipher with %r is %r\n" %
252 (remote, s.cipher()))
253 sys.stdout.write("Certificate is:\n%s\n" %
254 pprint.pformat(s.getpeercert()))
255 finally:
256 s.close()
257
Bill Janssen296a59d2007-09-16 22:06:00 +0000258
Bill Janssen98d19da2007-09-10 21:51:02 +0000259try:
260 import threading
261except ImportError:
262 _have_threads = False
263else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000264
Bill Janssen98d19da2007-09-10 21:51:02 +0000265 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000266
Bill Janssen98d19da2007-09-10 21:51:02 +0000267 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000268
Bill Janssen98d19da2007-09-10 21:51:02 +0000269 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000270
Bill Janssen98d19da2007-09-10 21:51:02 +0000271 """A mildly complicated class, because we want it to work both
272 with and without the SSL wrapper around the socket connection, so
273 that we can test the STARTTLS functionality."""
274
275 def __init__(self, server, connsock):
276 self.server = server
277 self.running = False
278 self.sock = connsock
279 self.sock.setblocking(1)
280 self.sslconn = None
281 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000282 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000283
Bill Janssen934b16d2008-06-28 22:19:33 +0000284 def show_conn_details(self):
285 if self.server.certreqs == ssl.CERT_REQUIRED:
286 cert = self.sslconn.getpeercert()
287 if test_support.verbose and self.server.chatty:
288 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
289 cert_binary = self.sslconn.getpeercert(True)
290 if test_support.verbose and self.server.chatty:
291 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
292 cipher = self.sslconn.cipher()
293 if test_support.verbose and self.server.chatty:
294 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
295
Bill Janssen98d19da2007-09-10 21:51:02 +0000296 def wrap_conn (self):
297 try:
298 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
299 certfile=self.server.certificate,
300 ssl_version=self.server.protocol,
301 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000302 cert_reqs=self.server.certreqs,
303 ciphers=self.server.ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +0000304 except:
305 if self.server.chatty:
306 handle_error("\n server: bad connection attempt from " +
307 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000308 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000309 if not self.server.expect_bad_connects:
310 # here, we want to stop the server, because this shouldn't
311 # happen in the context of our test case
312 self.running = False
313 # normally, we'd just stop here, but for the test
314 # harness, we want to stop the server
315 self.server.stop()
316 return False
317
318 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000319 return True
320
321 def read(self):
322 if self.sslconn:
323 return self.sslconn.read()
324 else:
325 return self.sock.recv(1024)
326
327 def write(self, bytes):
328 if self.sslconn:
329 return self.sslconn.write(bytes)
330 else:
331 return self.sock.send(bytes)
332
333 def close(self):
334 if self.sslconn:
335 self.sslconn.close()
336 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000337 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000338
339 def run (self):
340 self.running = True
341 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000342 if isinstance(self.sock, ssl.SSLSocket):
343 self.sslconn = self.sock
344 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000345 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000346 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000347 while self.running:
348 try:
349 msg = self.read()
350 if not msg:
351 # eof, so quit this handler
352 self.running = False
353 self.close()
354 elif msg.strip() == 'over':
355 if test_support.verbose and self.server.connectionchatty:
356 sys.stdout.write(" server: client closed connection\n")
357 self.close()
358 return
359 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
360 if test_support.verbose and self.server.connectionchatty:
361 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
362 self.write("OK\n")
363 if not self.wrap_conn():
364 return
Bill Janssen39295c22008-08-12 16:31:21 +0000365 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
366 if test_support.verbose and self.server.connectionchatty:
367 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
368 self.write("OK\n")
369 self.sslconn.unwrap()
370 self.sslconn = None
371 if test_support.verbose and self.server.connectionchatty:
372 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000373 else:
374 if (test_support.verbose and
375 self.server.connectionchatty):
376 ctype = (self.sslconn and "encrypted") or "unencrypted"
377 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
378 % (repr(msg), ctype, repr(msg.lower()), ctype))
379 self.write(msg.lower())
380 except ssl.SSLError:
381 if self.server.chatty:
382 handle_error("Test server failure:\n")
383 self.close()
384 self.running = False
385 # normally, we'd just stop here, but for the test
386 # harness, we want to stop the server
387 self.server.stop()
388 except:
389 handle_error('')
390
Trent Nelsone41b0062008-04-08 23:47:30 +0000391 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000392 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000393 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000394 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000395
Bill Janssen98d19da2007-09-10 21:51:02 +0000396 if ssl_version is None:
397 ssl_version = ssl.PROTOCOL_TLSv1
398 if certreqs is None:
399 certreqs = ssl.CERT_NONE
400 self.certificate = certificate
401 self.protocol = ssl_version
402 self.certreqs = certreqs
403 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000404 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000405 self.expect_bad_connects = expect_bad_connects
406 self.chatty = chatty
407 self.connectionchatty = connectionchatty
408 self.starttls_server = starttls_server
409 self.sock = socket.socket()
410 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000411 if wrap_accepting_socket:
412 self.sock = ssl.wrap_socket(self.sock, server_side=True,
413 certfile=self.certificate,
414 cert_reqs = self.certreqs,
415 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000416 ssl_version = self.protocol,
417 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000418 if test_support.verbose and self.chatty:
419 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
420 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000421 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000422 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000423 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000424
425 def start (self, flag=None):
426 self.flag = flag
427 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000428
429 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000430 self.sock.settimeout(0.5)
431 self.sock.listen(5)
432 self.active = True
433 if self.flag:
434 # signal an event
435 self.flag.set()
436 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000437 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000438 newconn, connaddr = self.sock.accept()
439 if test_support.verbose and self.chatty:
440 sys.stdout.write(' server: new connection from '
441 + str(connaddr) + '\n')
442 handler = self.ConnectionHandler(self, newconn)
443 handler.start()
444 except socket.timeout:
445 pass
446 except KeyboardInterrupt:
447 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000448 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000449 if self.chatty:
450 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000451 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000452
Bill Janssen98d19da2007-09-10 21:51:02 +0000453 def stop (self):
454 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000455
Bill Janssen934b16d2008-06-28 22:19:33 +0000456 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000457
Bill Janssen934b16d2008-06-28 22:19:33 +0000458 class EchoServer (asyncore.dispatcher):
459
460 class ConnectionHandler (asyncore.dispatcher_with_send):
461
462 def __init__(self, conn, certfile):
463 asyncore.dispatcher_with_send.__init__(self, conn)
464 self.socket = ssl.wrap_socket(conn, server_side=True,
465 certfile=certfile,
466 do_handshake_on_connect=True)
467
468 def readable(self):
469 if isinstance(self.socket, ssl.SSLSocket):
470 while self.socket.pending() > 0:
471 self.handle_read_event()
472 return True
473
474 def handle_read(self):
475 data = self.recv(1024)
476 self.send(data.lower())
477
478 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000479 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000480 if test_support.verbose:
481 sys.stdout.write(" server: closed connection %s\n" % self.socket)
482
483 def handle_error(self):
484 raise
485
486 def __init__(self, certfile):
487 self.certfile = certfile
488 asyncore.dispatcher.__init__(self)
489 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
490 self.port = test_support.bind_port(self.socket)
491 self.listen(5)
492
493 def handle_accept(self):
494 sock_obj, addr = self.accept()
495 if test_support.verbose:
496 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
497 self.ConnectionHandler(sock_obj, self.certfile)
498
499 def handle_error(self):
500 raise
501
502 def __init__(self, certfile):
503 self.flag = None
504 self.active = False
505 self.server = self.EchoServer(certfile)
506 self.port = self.server.port
507 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000508 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000509
510 def __str__(self):
511 return "<%s %s>" % (self.__class__.__name__, self.server)
512
513 def start (self, flag=None):
514 self.flag = flag
515 threading.Thread.start(self)
516
517 def run (self):
518 self.active = True
519 if self.flag:
520 self.flag.set()
521 while self.active:
522 try:
523 asyncore.loop(1)
524 except:
525 pass
526
527 def stop (self):
528 self.active = False
529 self.server.close()
530
531 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000532
533 class HTTPSServer(HTTPServer):
534
535 def __init__(self, server_address, RequestHandlerClass, certfile):
536
537 HTTPServer.__init__(self, server_address, RequestHandlerClass)
538 # we assume the certfile contains both private key and certificate
539 self.certfile = certfile
540 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000541 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000542 self.allow_reuse_address = True
543
Bill Janssen934b16d2008-06-28 22:19:33 +0000544 def __str__(self):
545 return ('<%s %s:%s>' %
546 (self.__class__.__name__,
547 self.server_name,
548 self.server_port))
549
Bill Janssen296a59d2007-09-16 22:06:00 +0000550 def get_request (self):
551 # override this to wrap socket with SSL
552 sock, addr = self.socket.accept()
553 sslconn = ssl.wrap_socket(sock, server_side=True,
554 certfile=self.certfile)
555 return sslconn, addr
556
557 # The methods overridden below this are mainly so that we
558 # can run it in a thread and be able to stop it from another
559 # You probably wouldn't need them in other uses.
560
561 def server_activate(self):
562 # We want to run this in a thread for testing purposes,
563 # so we override this to set timeout, so that we get
564 # a chance to stop the server
565 self.socket.settimeout(0.5)
566 HTTPServer.server_activate(self)
567
568 def serve_forever(self):
569 # We want this to run in a thread, so we use a slightly
570 # modified version of "forever".
571 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000572 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000573 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000574 # We need to lock while handling the request.
575 # Another thread can close the socket after self.active
576 # has been checked and before the request is handled.
577 # This causes an exception when using the closed socket.
578 with self.active_lock:
579 if not self.active:
580 break
581 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000582 except socket.timeout:
583 pass
584 except KeyboardInterrupt:
585 self.server_close()
586 return
587 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000588 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
589 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000590 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000591
592 def server_close(self):
593 # Again, we want this to run in a thread, so we need to override
594 # close to clear the "active" flag, so that serve_forever() will
595 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000596 with self.active_lock:
597 HTTPServer.server_close(self)
598 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000599
600 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
601
602 # need to override translate_path to get a known root,
603 # instead of using os.curdir, since the test could be
604 # run from anywhere
605
606 server_version = "TestHTTPS/1.0"
607
608 root = None
609
610 def translate_path(self, path):
611 """Translate a /-separated PATH to the local filename syntax.
612
613 Components that mean special things to the local file system
614 (e.g. drive or directory names) are ignored. (XXX They should
615 probably be diagnosed.)
616
617 """
618 # abandon query parameters
619 path = urlparse.urlparse(path)[2]
620 path = os.path.normpath(urllib.unquote(path))
621 words = path.split('/')
622 words = filter(None, words)
623 path = self.root
624 for word in words:
625 drive, word = os.path.splitdrive(word)
626 head, word = os.path.split(word)
627 if word in self.root: continue
628 path = os.path.join(path, word)
629 return path
630
631 def log_message(self, format, *args):
632
633 # we override this to suppress logging unless "verbose"
634
635 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000636 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
637 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000638 self.server.server_port,
639 self.request.cipher(),
640 self.log_date_time_string(),
641 format%args))
642
643
Trent Nelsone41b0062008-04-08 23:47:30 +0000644 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000645 self.flag = None
646 self.active = False
647 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000648 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000649 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000650 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000651 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000652 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000653
654 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000655 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000656
657 def start (self, flag=None):
658 self.flag = flag
659 threading.Thread.start(self)
660
661 def run (self):
662 self.active = True
663 if self.flag:
664 self.flag.set()
665 self.server.serve_forever()
666 self.active = False
667
668 def stop (self):
669 self.active = False
670 self.server.server_close()
671
672
Bill Janssen98d19da2007-09-10 21:51:02 +0000673 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000674 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000675 certreqs=ssl.CERT_REQUIRED,
676 cacerts=CERTFILE, chatty=False)
677 flag = threading.Event()
678 server.start(flag)
679 # wait for it to start
680 flag.wait()
681 # try to connect
682 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000683 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000684 s = ssl.wrap_socket(socket.socket(),
685 certfile=certfile,
686 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000687 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000688 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000689 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000690 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000691 except socket.error, x:
692 if test_support.verbose:
693 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000694 else:
695 raise test_support.TestFailed(
696 "Use of invalid cert should have failed!")
697 finally:
698 server.stop()
699 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000700
Bill Janssen98d19da2007-09-10 21:51:02 +0000701 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
702 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000703 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000704 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000705
Trent Nelsone41b0062008-04-08 23:47:30 +0000706 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000707 certreqs=certreqs,
708 ssl_version=protocol,
709 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000710 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000711 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000712 connectionchatty=connectionchatty,
713 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000714 flag = threading.Event()
715 server.start(flag)
716 # wait for it to start
717 flag.wait()
718 # try to connect
719 if client_protocol is None:
720 client_protocol = protocol
721 try:
722 try:
723 s = ssl.wrap_socket(socket.socket(),
724 certfile=client_certfile,
725 ca_certs=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000726 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000727 cert_reqs=certreqs,
728 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000729 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000730 except ssl.SSLError, x:
731 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
732 except Exception, x:
733 raise test_support.TestFailed("Unexpected exception: " + str(x))
734 else:
Antoine Pitrou5ba84912009-10-19 17:59:07 +0000735 for arg in [indata, bytearray(indata), memoryview(indata)]:
736 if connectionchatty:
737 if test_support.verbose:
738 sys.stdout.write(
739 " client: sending %s...\n" % (repr(arg)))
740 s.write(arg)
741 outdata = s.read()
742 if connectionchatty:
743 if test_support.verbose:
744 sys.stdout.write(" client: read %s\n" % repr(outdata))
745 if outdata != indata.lower():
746 raise test_support.TestFailed(
747 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
748 % (outdata[:min(len(outdata),20)], len(outdata),
749 indata[:min(len(indata),20)].lower(), len(indata)))
Bill Janssen98d19da2007-09-10 21:51:02 +0000750 s.write("over\n")
751 if connectionchatty:
752 if test_support.verbose:
753 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000754 s.close()
755 finally:
756 server.stop()
757 server.join()
758
759 def tryProtocolCombo (server_protocol,
760 client_protocol,
761 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000762 certsreqs=None):
763
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000764 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000765 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000766
767 if certsreqs == ssl.CERT_NONE:
768 certtype = "CERT_NONE"
769 elif certsreqs == ssl.CERT_OPTIONAL:
770 certtype = "CERT_OPTIONAL"
771 elif certsreqs == ssl.CERT_REQUIRED:
772 certtype = "CERT_REQUIRED"
773 if test_support.verbose:
774 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
775 sys.stdout.write(formatstr %
776 (ssl.get_protocol_name(client_protocol),
777 ssl.get_protocol_name(server_protocol),
778 certtype))
779 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000780 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
781 # will send an SSLv3 hello (rather than SSLv2) starting from
782 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000783 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000784 CERTFILE, CERTFILE, client_protocol,
785 ciphers="ALL", chatty=False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000786 except test_support.TestFailed:
787 if expectedToWork:
788 raise
789 else:
790 if not expectedToWork:
791 raise test_support.TestFailed(
792 "Client protocol %s succeeded with server protocol %s!"
793 % (ssl.get_protocol_name(client_protocol),
794 ssl.get_protocol_name(server_protocol)))
795
796
Bill Janssen934b16d2008-06-28 22:19:33 +0000797 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000798
799 def testRudeShutdown(self):
800
801 listener_ready = threading.Event()
802 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000803 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000804
805 # `listener` runs in a thread. It opens a socket listening on
806 # PORT, and sits in an accept() until the main thread connects.
807 # Then it rudely closes the socket, and sets Event `listener_gone`
808 # to let the main thread know the socket is gone.
809 def listener():
810 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000811 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000812 s.listen(5)
813 listener_ready.set()
814 s.accept()
815 s = None # reclaim the socket object, which also closes it
816 listener_gone.set()
817
818 def connector():
819 listener_ready.wait()
820 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000821 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000822 listener_gone.wait()
823 try:
824 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000825 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000826 pass
827 else:
828 raise test_support.TestFailed(
829 'connecting to closed SSL socket should have failed')
830
831 t = threading.Thread(target=listener)
832 t.start()
833 connector()
834 t.join()
835
836 def testEcho (self):
837
838 if test_support.verbose:
839 sys.stdout.write("\n")
840 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
841 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
842 chatty=True, connectionchatty=True)
843
844 def testReadCert(self):
845
846 if test_support.verbose:
847 sys.stdout.write("\n")
848 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000849 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000850 certreqs=ssl.CERT_NONE,
851 ssl_version=ssl.PROTOCOL_SSLv23,
852 cacerts=CERTFILE,
853 chatty=False)
854 flag = threading.Event()
855 server.start(flag)
856 # wait for it to start
857 flag.wait()
858 # try to connect
859 try:
860 try:
861 s = ssl.wrap_socket(socket.socket(),
862 certfile=CERTFILE,
863 ca_certs=CERTFILE,
864 cert_reqs=ssl.CERT_REQUIRED,
865 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000866 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000867 except ssl.SSLError, x:
868 raise test_support.TestFailed(
869 "Unexpected SSL error: " + str(x))
870 except Exception, x:
871 raise test_support.TestFailed(
872 "Unexpected exception: " + str(x))
873 else:
874 if not s:
875 raise test_support.TestFailed(
876 "Can't SSL-handshake with test server")
877 cert = s.getpeercert()
878 if not cert:
879 raise test_support.TestFailed(
880 "Can't get peer certificate.")
881 cipher = s.cipher()
882 if test_support.verbose:
883 sys.stdout.write(pprint.pformat(cert) + '\n')
884 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000885 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000886 raise test_support.TestFailed(
887 "No subject field in certificate: %s." %
888 pprint.pformat(cert))
889 if ((('organizationName', 'Python Software Foundation'),)
890 not in cert['subject']):
891 raise test_support.TestFailed(
892 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000893 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000894 s.close()
895 finally:
896 server.stop()
897 server.join()
898
899 def testNULLcert(self):
900 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
901 "nullcert.pem"))
902 def testMalformedCert(self):
903 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
904 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000905 def testWrongCert(self):
906 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
907 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000908 def testMalformedKey(self):
909 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
910 "badkey.pem"))
911
912 def testProtocolSSL2(self):
913 if test_support.verbose:
914 sys.stdout.write("\n")
915 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
916 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
917 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
918 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
919 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
920 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
921
922 def testProtocolSSL23(self):
923 if test_support.verbose:
924 sys.stdout.write("\n")
925 try:
926 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
927 except test_support.TestFailed, x:
928 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
929 if test_support.verbose:
930 sys.stdout.write(
931 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
932 % str(x))
933 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
934 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
935 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
936
937 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
938 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
939 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
940
941 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
942 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
943 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
944
945 def testProtocolSSL3(self):
946 if test_support.verbose:
947 sys.stdout.write("\n")
948 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
949 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
950 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
951 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
952 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
953 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
954
955 def testProtocolTLS1(self):
956 if test_support.verbose:
957 sys.stdout.write("\n")
958 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
959 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
960 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
961 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
962 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
963 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
964
965 def testSTARTTLS (self):
966
Bill Janssen39295c22008-08-12 16:31:21 +0000967 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000968
Trent Nelsone41b0062008-04-08 23:47:30 +0000969 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000970 ssl_version=ssl.PROTOCOL_TLSv1,
971 starttls_server=True,
972 chatty=True,
973 connectionchatty=True)
974 flag = threading.Event()
975 server.start(flag)
976 # wait for it to start
977 flag.wait()
978 # try to connect
979 wrapped = False
980 try:
981 try:
982 s = socket.socket()
983 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000984 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000985 except Exception, x:
986 raise test_support.TestFailed("Unexpected exception: " + str(x))
987 else:
988 if test_support.verbose:
989 sys.stdout.write("\n")
990 for indata in msgs:
991 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000992 sys.stdout.write(
993 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000994 if wrapped:
995 conn.write(indata)
996 outdata = conn.read()
997 else:
998 s.send(indata)
999 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001000 if (indata == "STARTTLS" and
1001 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001002 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001003 sys.stdout.write(
1004 " client: read %s from server, starting TLS...\n"
1005 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001006 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001007 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001008 elif (indata == "ENDTLS" and
1009 outdata.strip().lower().startswith("ok")):
1010 if test_support.verbose:
1011 sys.stdout.write(
1012 " client: read %s from server, ending TLS...\n"
1013 % repr(outdata))
1014 s = conn.unwrap()
1015 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001016 else:
1017 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001018 sys.stdout.write(
1019 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001020 if test_support.verbose:
1021 sys.stdout.write(" client: closing connection.\n")
1022 if wrapped:
1023 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001024 else:
1025 s.send("over\n")
1026 s.close()
1027 finally:
1028 server.stop()
1029 server.join()
1030
Bill Janssen934b16d2008-06-28 22:19:33 +00001031 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001032
Bill Janssen934b16d2008-06-28 22:19:33 +00001033 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001034 flag = threading.Event()
1035 server.start(flag)
1036 # wait for it to start
1037 flag.wait()
1038 # try to connect
1039 try:
1040 if test_support.verbose:
1041 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001042 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001043 d2 = ''
1044 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001045 url = 'https://127.0.0.1:%d/%s' % (
1046 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001047 with test_support.check_py3k_warnings():
1048 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001049 dlen = f.info().getheader("content-length")
1050 if dlen and (int(dlen) > 0):
1051 d2 = f.read(int(dlen))
1052 if test_support.verbose:
1053 sys.stdout.write(
1054 " client: read %d bytes from remote server '%s'\n"
1055 % (len(d2), server))
1056 f.close()
1057 except:
1058 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1059 if test_support.verbose:
1060 sys.stdout.write('\n' + msg)
1061 raise test_support.TestFailed(msg)
1062 else:
1063 if not (d1 == d2):
1064 raise test_support.TestFailed(
1065 "Couldn't fetch data from HTTPS server")
1066 finally:
1067 server.stop()
1068 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001069
Bill Janssen934b16d2008-06-28 22:19:33 +00001070 def testWrappedAccept (self):
1071
1072 if test_support.verbose:
1073 sys.stdout.write("\n")
1074 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1075 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1076 chatty=True, connectionchatty=True,
1077 wrap_accepting_socket=True)
1078
1079
1080 def testAsyncoreServer (self):
1081
1082 indata = "TEST MESSAGE of mixed case\n"
1083
1084 if test_support.verbose:
1085 sys.stdout.write("\n")
1086 server = AsyncoreEchoServer(CERTFILE)
1087 flag = threading.Event()
1088 server.start(flag)
1089 # wait for it to start
1090 flag.wait()
1091 # try to connect
1092 try:
1093 try:
1094 s = ssl.wrap_socket(socket.socket())
1095 s.connect(('127.0.0.1', server.port))
1096 except ssl.SSLError, x:
1097 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1098 except Exception, x:
1099 raise test_support.TestFailed("Unexpected exception: " + str(x))
1100 else:
1101 if test_support.verbose:
1102 sys.stdout.write(
1103 " client: sending %s...\n" % (repr(indata)))
1104 s.write(indata)
1105 outdata = s.read()
1106 if test_support.verbose:
1107 sys.stdout.write(" client: read %s\n" % repr(outdata))
1108 if outdata != indata.lower():
1109 raise test_support.TestFailed(
1110 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1111 % (outdata[:min(len(outdata),20)], len(outdata),
1112 indata[:min(len(indata),20)].lower(), len(indata)))
1113 s.write("over\n")
1114 if test_support.verbose:
1115 sys.stdout.write(" client: closing connection.\n")
1116 s.close()
1117 finally:
1118 server.stop()
1119 # wait for server thread to end
1120 server.join()
1121
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001122
Bill Janssen61c001a2008-09-08 16:37:24 +00001123 def testAllRecvAndSendMethods(self):
1124
1125 if test_support.verbose:
1126 sys.stdout.write("\n")
1127
1128 server = ThreadedEchoServer(CERTFILE,
1129 certreqs=ssl.CERT_NONE,
1130 ssl_version=ssl.PROTOCOL_TLSv1,
1131 cacerts=CERTFILE,
1132 chatty=True,
1133 connectionchatty=False)
1134 flag = threading.Event()
1135 server.start(flag)
1136 # wait for it to start
1137 flag.wait()
1138 # try to connect
1139 try:
1140 s = ssl.wrap_socket(socket.socket(),
1141 server_side=False,
1142 certfile=CERTFILE,
1143 ca_certs=CERTFILE,
1144 cert_reqs=ssl.CERT_NONE,
1145 ssl_version=ssl.PROTOCOL_TLSv1)
1146 s.connect((HOST, server.port))
1147 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001148 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001149 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001150 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001151 else:
1152 # helper methods for standardising recv* method signatures
1153 def _recv_into():
1154 b = bytearray("\0"*100)
1155 count = s.recv_into(b)
1156 return b[:count]
1157
1158 def _recvfrom_into():
1159 b = bytearray("\0"*100)
1160 count, addr = s.recvfrom_into(b)
1161 return b[:count]
1162
1163 # (name, method, whether to expect success, *args)
1164 send_methods = [
1165 ('send', s.send, True, []),
1166 ('sendto', s.sendto, False, ["some.address"]),
1167 ('sendall', s.sendall, True, []),
1168 ]
1169 recv_methods = [
1170 ('recv', s.recv, True, []),
1171 ('recvfrom', s.recvfrom, False, ["some.address"]),
1172 ('recv_into', _recv_into, True, []),
1173 ('recvfrom_into', _recvfrom_into, False, []),
1174 ]
1175 data_prefix = u"PREFIX_"
1176
1177 for meth_name, send_meth, expect_success, args in send_methods:
1178 indata = data_prefix + meth_name
1179 try:
1180 send_meth(indata.encode('ASCII', 'strict'), *args)
1181 outdata = s.read()
1182 outdata = outdata.decode('ASCII', 'strict')
1183 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001184 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001185 "While sending with <<%s>> bad data "
1186 "<<%r>> (%d) received; "
1187 "expected <<%r>> (%d)\n" % (
1188 meth_name, outdata[:20], len(outdata),
1189 indata[:20], len(indata)
1190 )
1191 )
1192 except ValueError as e:
1193 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001194 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001195 "Failed to send with method <<%s>>; "
1196 "expected to succeed.\n" % (meth_name,)
1197 )
1198 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001199 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001200 "Method <<%s>> failed with unexpected "
1201 "exception message: %s\n" % (
1202 meth_name, e
1203 )
1204 )
1205
1206 for meth_name, recv_meth, expect_success, args in recv_methods:
1207 indata = data_prefix + meth_name
1208 try:
1209 s.send(indata.encode('ASCII', 'strict'))
1210 outdata = recv_meth(*args)
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 receiving 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 receive 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 # consume data
1235 s.read()
1236
1237 s.write("over\n".encode("ASCII", "strict"))
1238 s.close()
1239 finally:
1240 server.stop()
1241 server.join()
1242
1243
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001244def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001245 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001246 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001247
Trent Nelsone41b0062008-04-08 23:47:30 +00001248 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001249 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001250 "keycert.pem")
1251 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1252 os.path.dirname(__file__) or os.curdir,
1253 "https_svn_python_org_root.pem")
1254
1255 if (not os.path.exists(CERTFILE) or
1256 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001257 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001258
Bill Janssen934b16d2008-06-28 22:19:33 +00001259 TESTPORT = test_support.find_unused_port()
1260 if not TESTPORT:
1261 raise test_support.TestFailed("Can't find open port to test servers on!")
1262
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001263 tests = [BasicTests]
1264
Bill Janssen296a59d2007-09-16 22:06:00 +00001265 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001266 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001267
Bill Janssen98d19da2007-09-10 21:51:02 +00001268 if _have_threads:
1269 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001270 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001271 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001272
Bill Janssen98d19da2007-09-10 21:51:02 +00001273 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001274
Bill Janssen98d19da2007-09-10 21:51:02 +00001275 if _have_threads:
1276 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001277
1278if __name__ == "__main__":
1279 test_main()