blob: 5917b513df7e2f1e0a14264560ee405111a74297 [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
Antoine Pitroudfb299b2010-04-23 22:54:59 +000014import weakref
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015
Bill Janssen296a59d2007-09-16 22:06:00 +000016from BaseHTTPServer import HTTPServer
17from SimpleHTTPServer import SimpleHTTPRequestHandler
18
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000019# Optionally test SSL support, if we have it in the tested platform
20skip_expected = False
21try:
22 import ssl
23except ImportError:
24 skip_expected = True
25
Trent Nelsone41b0062008-04-08 23:47:30 +000026HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000027CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000028SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000029
Neal Norwitz3e533c22007-08-27 01:03:18 +000030def handle_error(prefix):
31 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000032 if test_support.verbose:
33 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000034
Bill Jansseneb257ac2008-09-29 18:56:38 +000035 def testSimpleSSLwrap(self):
36 try:
37 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
38 except IOError, e:
39 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
40 pass
41 else:
42 raise
43 try:
44 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
45 except IOError, e:
46 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
47 pass
48 else:
49 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000050
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000051class BasicTests(unittest.TestCase):
52
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000053 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000054 if not test_support.is_resource_enabled('network'):
55 return
Bill Janssen296a59d2007-09-16 22:06:00 +000056 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
57 cert_reqs=ssl.CERT_NONE)
58 s.connect(("svn.python.org", 443))
59 c = s.getpeercert()
60 if c:
61 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
62 s.close()
63
64 # this should fail because we have no verification certs
65 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
66 cert_reqs=ssl.CERT_REQUIRED)
67 try:
68 s.connect(("svn.python.org", 443))
69 except ssl.SSLError:
70 pass
71 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000072 s.close()
73
Bill Janssen98d19da2007-09-10 21:51:02 +000074 def testCrucialConstants(self):
75 ssl.PROTOCOL_SSLv2
76 ssl.PROTOCOL_SSLv23
77 ssl.PROTOCOL_SSLv3
78 ssl.PROTOCOL_TLSv1
79 ssl.CERT_NONE
80 ssl.CERT_OPTIONAL
81 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000082
Bill Janssen98d19da2007-09-10 21:51:02 +000083 def testRAND(self):
84 v = ssl.RAND_status()
85 if test_support.verbose:
86 sys.stdout.write("\n RAND_status is %d (%s)\n"
87 % (v, (v and "sufficient randomness") or
88 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000089 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000090 ssl.RAND_egd(1)
91 except TypeError:
92 pass
Guido van Rossume4729332007-08-26 19:35:09 +000093 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000094 print "didn't raise TypeError"
95 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000096
Bill Janssen98d19da2007-09-10 21:51:02 +000097 def testParseCert(self):
98 # note that this uses an 'unofficial' function in _ssl.c,
99 # provided solely for this test, to exercise the certificate
100 # parsing code
101 p = ssl._ssl._test_decode_cert(CERTFILE, False)
102 if test_support.verbose:
103 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000104
Bill Janssen296a59d2007-09-16 22:06:00 +0000105 def testDERtoPEM(self):
106
107 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
108 d1 = ssl.PEM_cert_to_DER_cert(pem)
109 p2 = ssl.DER_cert_to_PEM_cert(d1)
110 d2 = ssl.PEM_cert_to_DER_cert(p2)
111 if (d1 != d2):
112 raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
113
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000114 def test_openssl_version(self):
115 n = ssl.OPENSSL_VERSION_NUMBER
116 t = ssl.OPENSSL_VERSION_INFO
117 s = ssl.OPENSSL_VERSION
118 self.assertIsInstance(n, (int, long))
119 self.assertIsInstance(t, tuple)
120 self.assertIsInstance(s, str)
121 # Some sanity checks follow
122 # >= 0.9
123 self.assertGreaterEqual(n, 0x900000)
124 # < 2.0
125 self.assertLess(n, 0x20000000)
126 major, minor, fix, patch, status = t
127 self.assertGreaterEqual(major, 0)
128 self.assertLess(major, 2)
129 self.assertGreaterEqual(minor, 0)
130 self.assertLess(minor, 256)
131 self.assertGreaterEqual(fix, 0)
132 self.assertLess(fix, 256)
133 self.assertGreaterEqual(patch, 0)
134 self.assertLessEqual(patch, 26)
135 self.assertGreaterEqual(status, 0)
136 self.assertLessEqual(status, 15)
137 # Version string as returned by OpenSSL, the format might change
138 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
139 (s, t))
140
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000141 def test_ciphers(self):
142 if not test_support.is_resource_enabled('network'):
143 return
144 remote = ("svn.python.org", 443)
145 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
146 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
147 s.connect(remote)
148 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
149 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
150 s.connect(remote)
151 # Error checking occurs when connecting, because the SSL context
152 # isn't created before.
153 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
154 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
155 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
156 s.connect(remote)
157
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000158 @test_support.cpython_only
159 def test_refcycle(self):
160 # Issue #7943: an SSL object doesn't create reference cycles with
161 # itself.
162 s = socket.socket(socket.AF_INET)
163 ss = ssl.wrap_socket(s)
164 wr = weakref.ref(ss)
165 del ss
166 self.assertEqual(wr(), None)
167
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000168
Bill Janssen934b16d2008-06-28 22:19:33 +0000169class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000170
171 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000172 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
173 cert_reqs=ssl.CERT_NONE)
174 s.connect(("svn.python.org", 443))
175 c = s.getpeercert()
176 if c:
177 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
178 s.close()
179
180 # this should fail because we have no verification certs
181 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
182 cert_reqs=ssl.CERT_REQUIRED)
183 try:
184 s.connect(("svn.python.org", 443))
185 except ssl.SSLError:
186 pass
187 finally:
188 s.close()
189
190 # this should succeed because we specify the root cert
191 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
192 cert_reqs=ssl.CERT_REQUIRED,
193 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
194 try:
195 s.connect(("svn.python.org", 443))
196 except ssl.SSLError, x:
197 raise test_support.TestFailed("Unexpected exception %s" % x)
198 finally:
199 s.close()
200
Bill Janssen934b16d2008-06-28 22:19:33 +0000201
202 def testNonBlockingHandshake(self):
203 s = socket.socket(socket.AF_INET)
204 s.connect(("svn.python.org", 443))
205 s.setblocking(False)
206 s = ssl.wrap_socket(s,
207 cert_reqs=ssl.CERT_NONE,
208 do_handshake_on_connect=False)
209 count = 0
210 while True:
211 try:
212 count += 1
213 s.do_handshake()
214 break
215 except ssl.SSLError, err:
216 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
217 select.select([s], [], [])
218 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
219 select.select([], [s], [])
220 else:
221 raise
222 s.close()
223 if test_support.verbose:
224 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
225
Bill Janssen296a59d2007-09-16 22:06:00 +0000226 def testFetchServerCert(self):
227
228 pem = ssl.get_server_certificate(("svn.python.org", 443))
229 if not pem:
230 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
231
232 try:
233 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
234 except ssl.SSLError:
235 #should fail
236 pass
237 else:
238 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
239
240 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
241 if not pem:
242 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
243 if test_support.verbose:
244 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
245
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000246 def test_algorithms(self):
247 # Issue #8484: all algorithms should be available when verifying a
248 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000249 # SHA256 was added in OpenSSL 0.9.8
250 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
251 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000252 # NOTE: https://sha256.tbs-internet.com is another possible test host
253 remote = ("sha2.hboeck.de", 443)
254 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
255 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
256 cert_reqs=ssl.CERT_REQUIRED,
257 ca_certs=sha256_cert,)
258 with test_support.transient_internet():
259 try:
260 s.connect(remote)
261 if test_support.verbose:
262 sys.stdout.write("\nCipher with %r is %r\n" %
263 (remote, s.cipher()))
264 sys.stdout.write("Certificate is:\n%s\n" %
265 pprint.pformat(s.getpeercert()))
266 finally:
267 s.close()
268
Bill Janssen296a59d2007-09-16 22:06:00 +0000269
Bill Janssen98d19da2007-09-10 21:51:02 +0000270try:
271 import threading
272except ImportError:
273 _have_threads = False
274else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000275
Bill Janssen98d19da2007-09-10 21:51:02 +0000276 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000277
Bill Janssen98d19da2007-09-10 21:51:02 +0000278 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000279
Bill Janssen98d19da2007-09-10 21:51:02 +0000280 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000281
Bill Janssen98d19da2007-09-10 21:51:02 +0000282 """A mildly complicated class, because we want it to work both
283 with and without the SSL wrapper around the socket connection, so
284 that we can test the STARTTLS functionality."""
285
286 def __init__(self, server, connsock):
287 self.server = server
288 self.running = False
289 self.sock = connsock
290 self.sock.setblocking(1)
291 self.sslconn = None
292 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000293 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000294
Bill Janssen934b16d2008-06-28 22:19:33 +0000295 def show_conn_details(self):
296 if self.server.certreqs == ssl.CERT_REQUIRED:
297 cert = self.sslconn.getpeercert()
298 if test_support.verbose and self.server.chatty:
299 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
300 cert_binary = self.sslconn.getpeercert(True)
301 if test_support.verbose and self.server.chatty:
302 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
303 cipher = self.sslconn.cipher()
304 if test_support.verbose and self.server.chatty:
305 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
306
Bill Janssen98d19da2007-09-10 21:51:02 +0000307 def wrap_conn (self):
308 try:
309 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
310 certfile=self.server.certificate,
311 ssl_version=self.server.protocol,
312 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000313 cert_reqs=self.server.certreqs,
314 ciphers=self.server.ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +0000315 except:
316 if self.server.chatty:
317 handle_error("\n server: bad connection attempt from " +
318 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000319 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000320 if not self.server.expect_bad_connects:
321 # here, we want to stop the server, because this shouldn't
322 # happen in the context of our test case
323 self.running = False
324 # normally, we'd just stop here, but for the test
325 # harness, we want to stop the server
326 self.server.stop()
327 return False
328
329 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000330 return True
331
332 def read(self):
333 if self.sslconn:
334 return self.sslconn.read()
335 else:
336 return self.sock.recv(1024)
337
338 def write(self, bytes):
339 if self.sslconn:
340 return self.sslconn.write(bytes)
341 else:
342 return self.sock.send(bytes)
343
344 def close(self):
345 if self.sslconn:
346 self.sslconn.close()
347 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000348 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000349
350 def run (self):
351 self.running = True
352 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000353 if isinstance(self.sock, ssl.SSLSocket):
354 self.sslconn = self.sock
355 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000356 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000357 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000358 while self.running:
359 try:
360 msg = self.read()
361 if not msg:
362 # eof, so quit this handler
363 self.running = False
364 self.close()
365 elif msg.strip() == 'over':
366 if test_support.verbose and self.server.connectionchatty:
367 sys.stdout.write(" server: client closed connection\n")
368 self.close()
369 return
370 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
371 if test_support.verbose and self.server.connectionchatty:
372 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
373 self.write("OK\n")
374 if not self.wrap_conn():
375 return
Bill Janssen39295c22008-08-12 16:31:21 +0000376 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
377 if test_support.verbose and self.server.connectionchatty:
378 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
379 self.write("OK\n")
380 self.sslconn.unwrap()
381 self.sslconn = None
382 if test_support.verbose and self.server.connectionchatty:
383 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000384 else:
385 if (test_support.verbose and
386 self.server.connectionchatty):
387 ctype = (self.sslconn and "encrypted") or "unencrypted"
388 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
389 % (repr(msg), ctype, repr(msg.lower()), ctype))
390 self.write(msg.lower())
391 except ssl.SSLError:
392 if self.server.chatty:
393 handle_error("Test server failure:\n")
394 self.close()
395 self.running = False
396 # normally, we'd just stop here, but for the test
397 # harness, we want to stop the server
398 self.server.stop()
399 except:
400 handle_error('')
401
Trent Nelsone41b0062008-04-08 23:47:30 +0000402 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000403 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000404 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000405 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000406
Bill Janssen98d19da2007-09-10 21:51:02 +0000407 if ssl_version is None:
408 ssl_version = ssl.PROTOCOL_TLSv1
409 if certreqs is None:
410 certreqs = ssl.CERT_NONE
411 self.certificate = certificate
412 self.protocol = ssl_version
413 self.certreqs = certreqs
414 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000415 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000416 self.expect_bad_connects = expect_bad_connects
417 self.chatty = chatty
418 self.connectionchatty = connectionchatty
419 self.starttls_server = starttls_server
420 self.sock = socket.socket()
421 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000422 if wrap_accepting_socket:
423 self.sock = ssl.wrap_socket(self.sock, server_side=True,
424 certfile=self.certificate,
425 cert_reqs = self.certreqs,
426 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000427 ssl_version = self.protocol,
428 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000429 if test_support.verbose and self.chatty:
430 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
431 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000432 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000433 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000434 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000435
436 def start (self, flag=None):
437 self.flag = flag
438 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000439
440 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000441 self.sock.settimeout(0.5)
442 self.sock.listen(5)
443 self.active = True
444 if self.flag:
445 # signal an event
446 self.flag.set()
447 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000448 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000449 newconn, connaddr = self.sock.accept()
450 if test_support.verbose and self.chatty:
451 sys.stdout.write(' server: new connection from '
452 + str(connaddr) + '\n')
453 handler = self.ConnectionHandler(self, newconn)
454 handler.start()
455 except socket.timeout:
456 pass
457 except KeyboardInterrupt:
458 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000459 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000460 if self.chatty:
461 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000462 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000463
Bill Janssen98d19da2007-09-10 21:51:02 +0000464 def stop (self):
465 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000466
Bill Janssen934b16d2008-06-28 22:19:33 +0000467 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000468
Bill Janssen934b16d2008-06-28 22:19:33 +0000469 class EchoServer (asyncore.dispatcher):
470
471 class ConnectionHandler (asyncore.dispatcher_with_send):
472
473 def __init__(self, conn, certfile):
474 asyncore.dispatcher_with_send.__init__(self, conn)
475 self.socket = ssl.wrap_socket(conn, server_side=True,
476 certfile=certfile,
477 do_handshake_on_connect=True)
478
479 def readable(self):
480 if isinstance(self.socket, ssl.SSLSocket):
481 while self.socket.pending() > 0:
482 self.handle_read_event()
483 return True
484
485 def handle_read(self):
486 data = self.recv(1024)
487 self.send(data.lower())
488
489 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000490 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000491 if test_support.verbose:
492 sys.stdout.write(" server: closed connection %s\n" % self.socket)
493
494 def handle_error(self):
495 raise
496
497 def __init__(self, certfile):
498 self.certfile = certfile
499 asyncore.dispatcher.__init__(self)
500 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
501 self.port = test_support.bind_port(self.socket)
502 self.listen(5)
503
504 def handle_accept(self):
505 sock_obj, addr = self.accept()
506 if test_support.verbose:
507 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
508 self.ConnectionHandler(sock_obj, self.certfile)
509
510 def handle_error(self):
511 raise
512
513 def __init__(self, certfile):
514 self.flag = None
515 self.active = False
516 self.server = self.EchoServer(certfile)
517 self.port = self.server.port
518 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000519 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000520
521 def __str__(self):
522 return "<%s %s>" % (self.__class__.__name__, self.server)
523
524 def start (self, flag=None):
525 self.flag = flag
526 threading.Thread.start(self)
527
528 def run (self):
529 self.active = True
530 if self.flag:
531 self.flag.set()
532 while self.active:
533 try:
534 asyncore.loop(1)
535 except:
536 pass
537
538 def stop (self):
539 self.active = False
540 self.server.close()
541
542 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000543
544 class HTTPSServer(HTTPServer):
545
546 def __init__(self, server_address, RequestHandlerClass, certfile):
547
548 HTTPServer.__init__(self, server_address, RequestHandlerClass)
549 # we assume the certfile contains both private key and certificate
550 self.certfile = certfile
551 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000552 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000553 self.allow_reuse_address = True
554
Bill Janssen934b16d2008-06-28 22:19:33 +0000555 def __str__(self):
556 return ('<%s %s:%s>' %
557 (self.__class__.__name__,
558 self.server_name,
559 self.server_port))
560
Bill Janssen296a59d2007-09-16 22:06:00 +0000561 def get_request (self):
562 # override this to wrap socket with SSL
563 sock, addr = self.socket.accept()
564 sslconn = ssl.wrap_socket(sock, server_side=True,
565 certfile=self.certfile)
566 return sslconn, addr
567
568 # The methods overridden below this are mainly so that we
569 # can run it in a thread and be able to stop it from another
570 # You probably wouldn't need them in other uses.
571
572 def server_activate(self):
573 # We want to run this in a thread for testing purposes,
574 # so we override this to set timeout, so that we get
575 # a chance to stop the server
576 self.socket.settimeout(0.5)
577 HTTPServer.server_activate(self)
578
579 def serve_forever(self):
580 # We want this to run in a thread, so we use a slightly
581 # modified version of "forever".
582 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000583 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000584 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000585 # We need to lock while handling the request.
586 # Another thread can close the socket after self.active
587 # has been checked and before the request is handled.
588 # This causes an exception when using the closed socket.
589 with self.active_lock:
590 if not self.active:
591 break
592 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000593 except socket.timeout:
594 pass
595 except KeyboardInterrupt:
596 self.server_close()
597 return
598 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000599 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
600 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000601 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000602
603 def server_close(self):
604 # Again, we want this to run in a thread, so we need to override
605 # close to clear the "active" flag, so that serve_forever() will
606 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000607 with self.active_lock:
608 HTTPServer.server_close(self)
609 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000610
611 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
612
613 # need to override translate_path to get a known root,
614 # instead of using os.curdir, since the test could be
615 # run from anywhere
616
617 server_version = "TestHTTPS/1.0"
618
619 root = None
620
621 def translate_path(self, path):
622 """Translate a /-separated PATH to the local filename syntax.
623
624 Components that mean special things to the local file system
625 (e.g. drive or directory names) are ignored. (XXX They should
626 probably be diagnosed.)
627
628 """
629 # abandon query parameters
630 path = urlparse.urlparse(path)[2]
631 path = os.path.normpath(urllib.unquote(path))
632 words = path.split('/')
633 words = filter(None, words)
634 path = self.root
635 for word in words:
636 drive, word = os.path.splitdrive(word)
637 head, word = os.path.split(word)
638 if word in self.root: continue
639 path = os.path.join(path, word)
640 return path
641
642 def log_message(self, format, *args):
643
644 # we override this to suppress logging unless "verbose"
645
646 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000647 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
648 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000649 self.server.server_port,
650 self.request.cipher(),
651 self.log_date_time_string(),
652 format%args))
653
654
Trent Nelsone41b0062008-04-08 23:47:30 +0000655 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000656 self.flag = None
657 self.active = False
658 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000659 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000660 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000661 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000662 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000663 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000664
665 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000666 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000667
668 def start (self, flag=None):
669 self.flag = flag
670 threading.Thread.start(self)
671
672 def run (self):
673 self.active = True
674 if self.flag:
675 self.flag.set()
676 self.server.serve_forever()
677 self.active = False
678
679 def stop (self):
680 self.active = False
681 self.server.server_close()
682
683
Bill Janssen98d19da2007-09-10 21:51:02 +0000684 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000685 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000686 certreqs=ssl.CERT_REQUIRED,
687 cacerts=CERTFILE, chatty=False)
688 flag = threading.Event()
689 server.start(flag)
690 # wait for it to start
691 flag.wait()
692 # try to connect
693 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000694 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000695 s = ssl.wrap_socket(socket.socket(),
696 certfile=certfile,
697 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000698 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000699 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000700 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000701 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000702 except socket.error, x:
703 if test_support.verbose:
704 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000705 else:
706 raise test_support.TestFailed(
707 "Use of invalid cert should have failed!")
708 finally:
709 server.stop()
710 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000711
Bill Janssen98d19da2007-09-10 21:51:02 +0000712 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
713 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000714 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000715 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000716
Trent Nelsone41b0062008-04-08 23:47:30 +0000717 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000718 certreqs=certreqs,
719 ssl_version=protocol,
720 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000721 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000722 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000723 connectionchatty=connectionchatty,
724 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000725 flag = threading.Event()
726 server.start(flag)
727 # wait for it to start
728 flag.wait()
729 # try to connect
730 if client_protocol is None:
731 client_protocol = protocol
732 try:
733 try:
734 s = ssl.wrap_socket(socket.socket(),
735 certfile=client_certfile,
736 ca_certs=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000737 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000738 cert_reqs=certreqs,
739 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000740 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000741 except ssl.SSLError, x:
742 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
743 except Exception, x:
744 raise test_support.TestFailed("Unexpected exception: " + str(x))
745 else:
Antoine Pitrou5ba84912009-10-19 17:59:07 +0000746 for arg in [indata, bytearray(indata), memoryview(indata)]:
747 if connectionchatty:
748 if test_support.verbose:
749 sys.stdout.write(
750 " client: sending %s...\n" % (repr(arg)))
751 s.write(arg)
752 outdata = s.read()
753 if connectionchatty:
754 if test_support.verbose:
755 sys.stdout.write(" client: read %s\n" % repr(outdata))
756 if outdata != indata.lower():
757 raise test_support.TestFailed(
758 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
759 % (outdata[:min(len(outdata),20)], len(outdata),
760 indata[:min(len(indata),20)].lower(), len(indata)))
Bill Janssen98d19da2007-09-10 21:51:02 +0000761 s.write("over\n")
762 if connectionchatty:
763 if test_support.verbose:
764 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000765 s.close()
766 finally:
767 server.stop()
768 server.join()
769
770 def tryProtocolCombo (server_protocol,
771 client_protocol,
772 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000773 certsreqs=None):
774
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000775 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000776 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000777
778 if certsreqs == ssl.CERT_NONE:
779 certtype = "CERT_NONE"
780 elif certsreqs == ssl.CERT_OPTIONAL:
781 certtype = "CERT_OPTIONAL"
782 elif certsreqs == ssl.CERT_REQUIRED:
783 certtype = "CERT_REQUIRED"
784 if test_support.verbose:
785 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
786 sys.stdout.write(formatstr %
787 (ssl.get_protocol_name(client_protocol),
788 ssl.get_protocol_name(server_protocol),
789 certtype))
790 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000791 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
792 # will send an SSLv3 hello (rather than SSLv2) starting from
793 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000794 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000795 CERTFILE, CERTFILE, client_protocol,
796 ciphers="ALL", chatty=False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000797 except test_support.TestFailed:
798 if expectedToWork:
799 raise
800 else:
801 if not expectedToWork:
802 raise test_support.TestFailed(
803 "Client protocol %s succeeded with server protocol %s!"
804 % (ssl.get_protocol_name(client_protocol),
805 ssl.get_protocol_name(server_protocol)))
806
807
Bill Janssen934b16d2008-06-28 22:19:33 +0000808 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000809
810 def testRudeShutdown(self):
811
812 listener_ready = threading.Event()
813 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000814 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000815
816 # `listener` runs in a thread. It opens a socket listening on
817 # PORT, and sits in an accept() until the main thread connects.
818 # Then it rudely closes the socket, and sets Event `listener_gone`
819 # to let the main thread know the socket is gone.
820 def listener():
821 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000822 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000823 s.listen(5)
824 listener_ready.set()
825 s.accept()
826 s = None # reclaim the socket object, which also closes it
827 listener_gone.set()
828
829 def connector():
830 listener_ready.wait()
831 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000832 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000833 listener_gone.wait()
834 try:
835 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000836 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000837 pass
838 else:
839 raise test_support.TestFailed(
840 'connecting to closed SSL socket should have failed')
841
842 t = threading.Thread(target=listener)
843 t.start()
844 connector()
845 t.join()
846
847 def testEcho (self):
848
849 if test_support.verbose:
850 sys.stdout.write("\n")
851 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
852 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
853 chatty=True, connectionchatty=True)
854
855 def testReadCert(self):
856
857 if test_support.verbose:
858 sys.stdout.write("\n")
859 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000860 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000861 certreqs=ssl.CERT_NONE,
862 ssl_version=ssl.PROTOCOL_SSLv23,
863 cacerts=CERTFILE,
864 chatty=False)
865 flag = threading.Event()
866 server.start(flag)
867 # wait for it to start
868 flag.wait()
869 # try to connect
870 try:
871 try:
872 s = ssl.wrap_socket(socket.socket(),
873 certfile=CERTFILE,
874 ca_certs=CERTFILE,
875 cert_reqs=ssl.CERT_REQUIRED,
876 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000877 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000878 except ssl.SSLError, x:
879 raise test_support.TestFailed(
880 "Unexpected SSL error: " + str(x))
881 except Exception, x:
882 raise test_support.TestFailed(
883 "Unexpected exception: " + str(x))
884 else:
885 if not s:
886 raise test_support.TestFailed(
887 "Can't SSL-handshake with test server")
888 cert = s.getpeercert()
889 if not cert:
890 raise test_support.TestFailed(
891 "Can't get peer certificate.")
892 cipher = s.cipher()
893 if test_support.verbose:
894 sys.stdout.write(pprint.pformat(cert) + '\n')
895 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000896 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000897 raise test_support.TestFailed(
898 "No subject field in certificate: %s." %
899 pprint.pformat(cert))
900 if ((('organizationName', 'Python Software Foundation'),)
901 not in cert['subject']):
902 raise test_support.TestFailed(
903 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000904 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000905 s.close()
906 finally:
907 server.stop()
908 server.join()
909
910 def testNULLcert(self):
911 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
912 "nullcert.pem"))
913 def testMalformedCert(self):
914 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
915 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000916 def testWrongCert(self):
917 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
918 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000919 def testMalformedKey(self):
920 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
921 "badkey.pem"))
922
923 def testProtocolSSL2(self):
924 if test_support.verbose:
925 sys.stdout.write("\n")
926 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
927 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
928 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
929 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
930 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
931 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
932
933 def testProtocolSSL23(self):
934 if test_support.verbose:
935 sys.stdout.write("\n")
936 try:
937 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
938 except test_support.TestFailed, x:
939 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
940 if test_support.verbose:
941 sys.stdout.write(
942 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
943 % str(x))
944 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
945 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
946 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
947
948 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
949 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
950 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
951
952 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
953 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
954 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
955
956 def testProtocolSSL3(self):
957 if test_support.verbose:
958 sys.stdout.write("\n")
959 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
960 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
961 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
962 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
963 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
964 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
965
966 def testProtocolTLS1(self):
967 if test_support.verbose:
968 sys.stdout.write("\n")
969 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
970 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
971 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
972 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
973 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
974 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
975
976 def testSTARTTLS (self):
977
Bill Janssen39295c22008-08-12 16:31:21 +0000978 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000979
Trent Nelsone41b0062008-04-08 23:47:30 +0000980 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000981 ssl_version=ssl.PROTOCOL_TLSv1,
982 starttls_server=True,
983 chatty=True,
984 connectionchatty=True)
985 flag = threading.Event()
986 server.start(flag)
987 # wait for it to start
988 flag.wait()
989 # try to connect
990 wrapped = False
991 try:
992 try:
993 s = socket.socket()
994 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000995 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000996 except Exception, x:
997 raise test_support.TestFailed("Unexpected exception: " + str(x))
998 else:
999 if test_support.verbose:
1000 sys.stdout.write("\n")
1001 for indata in msgs:
1002 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001003 sys.stdout.write(
1004 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001005 if wrapped:
1006 conn.write(indata)
1007 outdata = conn.read()
1008 else:
1009 s.send(indata)
1010 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +00001011 if (indata == "STARTTLS" and
1012 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +00001013 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001014 sys.stdout.write(
1015 " client: read %s from server, starting TLS...\n"
1016 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001017 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001018 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001019 elif (indata == "ENDTLS" and
1020 outdata.strip().lower().startswith("ok")):
1021 if test_support.verbose:
1022 sys.stdout.write(
1023 " client: read %s from server, ending TLS...\n"
1024 % repr(outdata))
1025 s = conn.unwrap()
1026 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001027 else:
1028 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001029 sys.stdout.write(
1030 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001031 if test_support.verbose:
1032 sys.stdout.write(" client: closing connection.\n")
1033 if wrapped:
1034 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001035 else:
1036 s.send("over\n")
1037 s.close()
1038 finally:
1039 server.stop()
1040 server.join()
1041
Bill Janssen934b16d2008-06-28 22:19:33 +00001042 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001043
Bill Janssen934b16d2008-06-28 22:19:33 +00001044 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001045 flag = threading.Event()
1046 server.start(flag)
1047 # wait for it to start
1048 flag.wait()
1049 # try to connect
1050 try:
1051 if test_support.verbose:
1052 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001053 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001054 d2 = ''
1055 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001056 url = 'https://127.0.0.1:%d/%s' % (
1057 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001058 with test_support.check_py3k_warnings():
1059 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001060 dlen = f.info().getheader("content-length")
1061 if dlen and (int(dlen) > 0):
1062 d2 = f.read(int(dlen))
1063 if test_support.verbose:
1064 sys.stdout.write(
1065 " client: read %d bytes from remote server '%s'\n"
1066 % (len(d2), server))
1067 f.close()
1068 except:
1069 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1070 if test_support.verbose:
1071 sys.stdout.write('\n' + msg)
1072 raise test_support.TestFailed(msg)
1073 else:
1074 if not (d1 == d2):
1075 raise test_support.TestFailed(
1076 "Couldn't fetch data from HTTPS server")
1077 finally:
1078 server.stop()
1079 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001080
Bill Janssen934b16d2008-06-28 22:19:33 +00001081 def testWrappedAccept (self):
1082
1083 if test_support.verbose:
1084 sys.stdout.write("\n")
1085 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1086 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1087 chatty=True, connectionchatty=True,
1088 wrap_accepting_socket=True)
1089
1090
1091 def testAsyncoreServer (self):
1092
1093 indata = "TEST MESSAGE of mixed case\n"
1094
1095 if test_support.verbose:
1096 sys.stdout.write("\n")
1097 server = AsyncoreEchoServer(CERTFILE)
1098 flag = threading.Event()
1099 server.start(flag)
1100 # wait for it to start
1101 flag.wait()
1102 # try to connect
1103 try:
1104 try:
1105 s = ssl.wrap_socket(socket.socket())
1106 s.connect(('127.0.0.1', server.port))
1107 except ssl.SSLError, x:
1108 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1109 except Exception, x:
1110 raise test_support.TestFailed("Unexpected exception: " + str(x))
1111 else:
1112 if test_support.verbose:
1113 sys.stdout.write(
1114 " client: sending %s...\n" % (repr(indata)))
1115 s.write(indata)
1116 outdata = s.read()
1117 if test_support.verbose:
1118 sys.stdout.write(" client: read %s\n" % repr(outdata))
1119 if outdata != indata.lower():
1120 raise test_support.TestFailed(
1121 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1122 % (outdata[:min(len(outdata),20)], len(outdata),
1123 indata[:min(len(indata),20)].lower(), len(indata)))
1124 s.write("over\n")
1125 if test_support.verbose:
1126 sys.stdout.write(" client: closing connection.\n")
1127 s.close()
1128 finally:
1129 server.stop()
1130 # wait for server thread to end
1131 server.join()
1132
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001133
Bill Janssen61c001a2008-09-08 16:37:24 +00001134 def testAllRecvAndSendMethods(self):
1135
1136 if test_support.verbose:
1137 sys.stdout.write("\n")
1138
1139 server = ThreadedEchoServer(CERTFILE,
1140 certreqs=ssl.CERT_NONE,
1141 ssl_version=ssl.PROTOCOL_TLSv1,
1142 cacerts=CERTFILE,
1143 chatty=True,
1144 connectionchatty=False)
1145 flag = threading.Event()
1146 server.start(flag)
1147 # wait for it to start
1148 flag.wait()
1149 # try to connect
1150 try:
1151 s = ssl.wrap_socket(socket.socket(),
1152 server_side=False,
1153 certfile=CERTFILE,
1154 ca_certs=CERTFILE,
1155 cert_reqs=ssl.CERT_NONE,
1156 ssl_version=ssl.PROTOCOL_TLSv1)
1157 s.connect((HOST, server.port))
1158 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001159 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001160 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001161 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001162 else:
1163 # helper methods for standardising recv* method signatures
1164 def _recv_into():
1165 b = bytearray("\0"*100)
1166 count = s.recv_into(b)
1167 return b[:count]
1168
1169 def _recvfrom_into():
1170 b = bytearray("\0"*100)
1171 count, addr = s.recvfrom_into(b)
1172 return b[:count]
1173
1174 # (name, method, whether to expect success, *args)
1175 send_methods = [
1176 ('send', s.send, True, []),
1177 ('sendto', s.sendto, False, ["some.address"]),
1178 ('sendall', s.sendall, True, []),
1179 ]
1180 recv_methods = [
1181 ('recv', s.recv, True, []),
1182 ('recvfrom', s.recvfrom, False, ["some.address"]),
1183 ('recv_into', _recv_into, True, []),
1184 ('recvfrom_into', _recvfrom_into, False, []),
1185 ]
1186 data_prefix = u"PREFIX_"
1187
1188 for meth_name, send_meth, expect_success, args in send_methods:
1189 indata = data_prefix + meth_name
1190 try:
1191 send_meth(indata.encode('ASCII', 'strict'), *args)
1192 outdata = s.read()
1193 outdata = outdata.decode('ASCII', 'strict')
1194 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001195 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001196 "While sending with <<%s>> bad data "
1197 "<<%r>> (%d) received; "
1198 "expected <<%r>> (%d)\n" % (
1199 meth_name, outdata[:20], len(outdata),
1200 indata[:20], len(indata)
1201 )
1202 )
1203 except ValueError as e:
1204 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001205 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001206 "Failed to send with method <<%s>>; "
1207 "expected to succeed.\n" % (meth_name,)
1208 )
1209 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001210 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001211 "Method <<%s>> failed with unexpected "
1212 "exception message: %s\n" % (
1213 meth_name, e
1214 )
1215 )
1216
1217 for meth_name, recv_meth, expect_success, args in recv_methods:
1218 indata = data_prefix + meth_name
1219 try:
1220 s.send(indata.encode('ASCII', 'strict'))
1221 outdata = recv_meth(*args)
1222 outdata = outdata.decode('ASCII', 'strict')
1223 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001224 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001225 "While receiving with <<%s>> bad data "
1226 "<<%r>> (%d) received; "
1227 "expected <<%r>> (%d)\n" % (
1228 meth_name, outdata[:20], len(outdata),
1229 indata[:20], len(indata)
1230 )
1231 )
1232 except ValueError as e:
1233 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001234 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001235 "Failed to receive with method <<%s>>; "
1236 "expected to succeed.\n" % (meth_name,)
1237 )
1238 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001239 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001240 "Method <<%s>> failed with unexpected "
1241 "exception message: %s\n" % (
1242 meth_name, e
1243 )
1244 )
1245 # consume data
1246 s.read()
1247
1248 s.write("over\n".encode("ASCII", "strict"))
1249 s.close()
1250 finally:
1251 server.stop()
1252 server.join()
1253
1254
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001255def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001256 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001257 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001258
Trent Nelsone41b0062008-04-08 23:47:30 +00001259 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001260 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001261 "keycert.pem")
1262 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1263 os.path.dirname(__file__) or os.curdir,
1264 "https_svn_python_org_root.pem")
1265
1266 if (not os.path.exists(CERTFILE) or
1267 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001268 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001269
Bill Janssen934b16d2008-06-28 22:19:33 +00001270 TESTPORT = test_support.find_unused_port()
1271 if not TESTPORT:
1272 raise test_support.TestFailed("Can't find open port to test servers on!")
1273
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001274 tests = [BasicTests]
1275
Bill Janssen296a59d2007-09-16 22:06:00 +00001276 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001277 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001278
Bill Janssen98d19da2007-09-10 21:51:02 +00001279 if _have_threads:
1280 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001281 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001282 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001283
Bill Janssen98d19da2007-09-10 21:51:02 +00001284 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001285
Bill Janssen98d19da2007-09-10 21:51:02 +00001286 if _have_threads:
1287 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001288
1289if __name__ == "__main__":
1290 test_main()