blob: bab14529f8e23d75809417f05fbe83f4e13144a4 [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.
238 # NOTE: https://sha256.tbs-internet.com is another possible test host
239 remote = ("sha2.hboeck.de", 443)
240 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
241 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
242 cert_reqs=ssl.CERT_REQUIRED,
243 ca_certs=sha256_cert,)
244 with test_support.transient_internet():
245 try:
246 s.connect(remote)
247 if test_support.verbose:
248 sys.stdout.write("\nCipher with %r is %r\n" %
249 (remote, s.cipher()))
250 sys.stdout.write("Certificate is:\n%s\n" %
251 pprint.pformat(s.getpeercert()))
252 finally:
253 s.close()
254
Bill Janssen296a59d2007-09-16 22:06:00 +0000255
Bill Janssen98d19da2007-09-10 21:51:02 +0000256try:
257 import threading
258except ImportError:
259 _have_threads = False
260else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000261
Bill Janssen98d19da2007-09-10 21:51:02 +0000262 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000263
Bill Janssen98d19da2007-09-10 21:51:02 +0000264 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000265
Bill Janssen98d19da2007-09-10 21:51:02 +0000266 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000267
Bill Janssen98d19da2007-09-10 21:51:02 +0000268 """A mildly complicated class, because we want it to work both
269 with and without the SSL wrapper around the socket connection, so
270 that we can test the STARTTLS functionality."""
271
272 def __init__(self, server, connsock):
273 self.server = server
274 self.running = False
275 self.sock = connsock
276 self.sock.setblocking(1)
277 self.sslconn = None
278 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000279 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000280
Bill Janssen934b16d2008-06-28 22:19:33 +0000281 def show_conn_details(self):
282 if self.server.certreqs == ssl.CERT_REQUIRED:
283 cert = self.sslconn.getpeercert()
284 if test_support.verbose and self.server.chatty:
285 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
286 cert_binary = self.sslconn.getpeercert(True)
287 if test_support.verbose and self.server.chatty:
288 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
289 cipher = self.sslconn.cipher()
290 if test_support.verbose and self.server.chatty:
291 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
292
Bill Janssen98d19da2007-09-10 21:51:02 +0000293 def wrap_conn (self):
294 try:
295 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
296 certfile=self.server.certificate,
297 ssl_version=self.server.protocol,
298 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000299 cert_reqs=self.server.certreqs,
300 ciphers=self.server.ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +0000301 except:
302 if self.server.chatty:
303 handle_error("\n server: bad connection attempt from " +
304 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000305 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000306 if not self.server.expect_bad_connects:
307 # here, we want to stop the server, because this shouldn't
308 # happen in the context of our test case
309 self.running = False
310 # normally, we'd just stop here, but for the test
311 # harness, we want to stop the server
312 self.server.stop()
313 return False
314
315 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000316 return True
317
318 def read(self):
319 if self.sslconn:
320 return self.sslconn.read()
321 else:
322 return self.sock.recv(1024)
323
324 def write(self, bytes):
325 if self.sslconn:
326 return self.sslconn.write(bytes)
327 else:
328 return self.sock.send(bytes)
329
330 def close(self):
331 if self.sslconn:
332 self.sslconn.close()
333 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000334 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000335
336 def run (self):
337 self.running = True
338 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000339 if isinstance(self.sock, ssl.SSLSocket):
340 self.sslconn = self.sock
341 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000342 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000343 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000344 while self.running:
345 try:
346 msg = self.read()
347 if not msg:
348 # eof, so quit this handler
349 self.running = False
350 self.close()
351 elif msg.strip() == 'over':
352 if test_support.verbose and self.server.connectionchatty:
353 sys.stdout.write(" server: client closed connection\n")
354 self.close()
355 return
356 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
357 if test_support.verbose and self.server.connectionchatty:
358 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
359 self.write("OK\n")
360 if not self.wrap_conn():
361 return
Bill Janssen39295c22008-08-12 16:31:21 +0000362 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
363 if test_support.verbose and self.server.connectionchatty:
364 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
365 self.write("OK\n")
366 self.sslconn.unwrap()
367 self.sslconn = None
368 if test_support.verbose and self.server.connectionchatty:
369 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000370 else:
371 if (test_support.verbose and
372 self.server.connectionchatty):
373 ctype = (self.sslconn and "encrypted") or "unencrypted"
374 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
375 % (repr(msg), ctype, repr(msg.lower()), ctype))
376 self.write(msg.lower())
377 except ssl.SSLError:
378 if self.server.chatty:
379 handle_error("Test server failure:\n")
380 self.close()
381 self.running = False
382 # normally, we'd just stop here, but for the test
383 # harness, we want to stop the server
384 self.server.stop()
385 except:
386 handle_error('')
387
Trent Nelsone41b0062008-04-08 23:47:30 +0000388 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000389 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000390 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000391 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000392
Bill Janssen98d19da2007-09-10 21:51:02 +0000393 if ssl_version is None:
394 ssl_version = ssl.PROTOCOL_TLSv1
395 if certreqs is None:
396 certreqs = ssl.CERT_NONE
397 self.certificate = certificate
398 self.protocol = ssl_version
399 self.certreqs = certreqs
400 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000401 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000402 self.expect_bad_connects = expect_bad_connects
403 self.chatty = chatty
404 self.connectionchatty = connectionchatty
405 self.starttls_server = starttls_server
406 self.sock = socket.socket()
407 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000408 if wrap_accepting_socket:
409 self.sock = ssl.wrap_socket(self.sock, server_side=True,
410 certfile=self.certificate,
411 cert_reqs = self.certreqs,
412 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000413 ssl_version = self.protocol,
414 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000415 if test_support.verbose and self.chatty:
416 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
417 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000418 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000419 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000420 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000421
422 def start (self, flag=None):
423 self.flag = flag
424 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000425
426 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000427 self.sock.settimeout(0.5)
428 self.sock.listen(5)
429 self.active = True
430 if self.flag:
431 # signal an event
432 self.flag.set()
433 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000434 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000435 newconn, connaddr = self.sock.accept()
436 if test_support.verbose and self.chatty:
437 sys.stdout.write(' server: new connection from '
438 + str(connaddr) + '\n')
439 handler = self.ConnectionHandler(self, newconn)
440 handler.start()
441 except socket.timeout:
442 pass
443 except KeyboardInterrupt:
444 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000445 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000446 if self.chatty:
447 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000448 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000449
Bill Janssen98d19da2007-09-10 21:51:02 +0000450 def stop (self):
451 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000452
Bill Janssen934b16d2008-06-28 22:19:33 +0000453 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000454
Bill Janssen934b16d2008-06-28 22:19:33 +0000455 class EchoServer (asyncore.dispatcher):
456
457 class ConnectionHandler (asyncore.dispatcher_with_send):
458
459 def __init__(self, conn, certfile):
460 asyncore.dispatcher_with_send.__init__(self, conn)
461 self.socket = ssl.wrap_socket(conn, server_side=True,
462 certfile=certfile,
463 do_handshake_on_connect=True)
464
465 def readable(self):
466 if isinstance(self.socket, ssl.SSLSocket):
467 while self.socket.pending() > 0:
468 self.handle_read_event()
469 return True
470
471 def handle_read(self):
472 data = self.recv(1024)
473 self.send(data.lower())
474
475 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000476 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000477 if test_support.verbose:
478 sys.stdout.write(" server: closed connection %s\n" % self.socket)
479
480 def handle_error(self):
481 raise
482
483 def __init__(self, certfile):
484 self.certfile = certfile
485 asyncore.dispatcher.__init__(self)
486 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
487 self.port = test_support.bind_port(self.socket)
488 self.listen(5)
489
490 def handle_accept(self):
491 sock_obj, addr = self.accept()
492 if test_support.verbose:
493 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
494 self.ConnectionHandler(sock_obj, self.certfile)
495
496 def handle_error(self):
497 raise
498
499 def __init__(self, certfile):
500 self.flag = None
501 self.active = False
502 self.server = self.EchoServer(certfile)
503 self.port = self.server.port
504 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000505 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000506
507 def __str__(self):
508 return "<%s %s>" % (self.__class__.__name__, self.server)
509
510 def start (self, flag=None):
511 self.flag = flag
512 threading.Thread.start(self)
513
514 def run (self):
515 self.active = True
516 if self.flag:
517 self.flag.set()
518 while self.active:
519 try:
520 asyncore.loop(1)
521 except:
522 pass
523
524 def stop (self):
525 self.active = False
526 self.server.close()
527
528 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000529
530 class HTTPSServer(HTTPServer):
531
532 def __init__(self, server_address, RequestHandlerClass, certfile):
533
534 HTTPServer.__init__(self, server_address, RequestHandlerClass)
535 # we assume the certfile contains both private key and certificate
536 self.certfile = certfile
537 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000538 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000539 self.allow_reuse_address = True
540
Bill Janssen934b16d2008-06-28 22:19:33 +0000541 def __str__(self):
542 return ('<%s %s:%s>' %
543 (self.__class__.__name__,
544 self.server_name,
545 self.server_port))
546
Bill Janssen296a59d2007-09-16 22:06:00 +0000547 def get_request (self):
548 # override this to wrap socket with SSL
549 sock, addr = self.socket.accept()
550 sslconn = ssl.wrap_socket(sock, server_side=True,
551 certfile=self.certfile)
552 return sslconn, addr
553
554 # The methods overridden below this are mainly so that we
555 # can run it in a thread and be able to stop it from another
556 # You probably wouldn't need them in other uses.
557
558 def server_activate(self):
559 # We want to run this in a thread for testing purposes,
560 # so we override this to set timeout, so that we get
561 # a chance to stop the server
562 self.socket.settimeout(0.5)
563 HTTPServer.server_activate(self)
564
565 def serve_forever(self):
566 # We want this to run in a thread, so we use a slightly
567 # modified version of "forever".
568 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000569 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000570 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000571 # We need to lock while handling the request.
572 # Another thread can close the socket after self.active
573 # has been checked and before the request is handled.
574 # This causes an exception when using the closed socket.
575 with self.active_lock:
576 if not self.active:
577 break
578 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000579 except socket.timeout:
580 pass
581 except KeyboardInterrupt:
582 self.server_close()
583 return
584 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000585 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
586 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000587 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000588
589 def server_close(self):
590 # Again, we want this to run in a thread, so we need to override
591 # close to clear the "active" flag, so that serve_forever() will
592 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000593 with self.active_lock:
594 HTTPServer.server_close(self)
595 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000596
597 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
598
599 # need to override translate_path to get a known root,
600 # instead of using os.curdir, since the test could be
601 # run from anywhere
602
603 server_version = "TestHTTPS/1.0"
604
605 root = None
606
607 def translate_path(self, path):
608 """Translate a /-separated PATH to the local filename syntax.
609
610 Components that mean special things to the local file system
611 (e.g. drive or directory names) are ignored. (XXX They should
612 probably be diagnosed.)
613
614 """
615 # abandon query parameters
616 path = urlparse.urlparse(path)[2]
617 path = os.path.normpath(urllib.unquote(path))
618 words = path.split('/')
619 words = filter(None, words)
620 path = self.root
621 for word in words:
622 drive, word = os.path.splitdrive(word)
623 head, word = os.path.split(word)
624 if word in self.root: continue
625 path = os.path.join(path, word)
626 return path
627
628 def log_message(self, format, *args):
629
630 # we override this to suppress logging unless "verbose"
631
632 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000633 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
634 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000635 self.server.server_port,
636 self.request.cipher(),
637 self.log_date_time_string(),
638 format%args))
639
640
Trent Nelsone41b0062008-04-08 23:47:30 +0000641 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000642 self.flag = None
643 self.active = False
644 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000645 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000646 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000647 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000648 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000649 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000650
651 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000652 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000653
654 def start (self, flag=None):
655 self.flag = flag
656 threading.Thread.start(self)
657
658 def run (self):
659 self.active = True
660 if self.flag:
661 self.flag.set()
662 self.server.serve_forever()
663 self.active = False
664
665 def stop (self):
666 self.active = False
667 self.server.server_close()
668
669
Bill Janssen98d19da2007-09-10 21:51:02 +0000670 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000671 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000672 certreqs=ssl.CERT_REQUIRED,
673 cacerts=CERTFILE, chatty=False)
674 flag = threading.Event()
675 server.start(flag)
676 # wait for it to start
677 flag.wait()
678 # try to connect
679 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000680 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000681 s = ssl.wrap_socket(socket.socket(),
682 certfile=certfile,
683 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000684 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000685 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000686 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000687 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000688 except socket.error, x:
689 if test_support.verbose:
690 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000691 else:
692 raise test_support.TestFailed(
693 "Use of invalid cert should have failed!")
694 finally:
695 server.stop()
696 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000697
Bill Janssen98d19da2007-09-10 21:51:02 +0000698 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
699 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000700 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000701 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000702
Trent Nelsone41b0062008-04-08 23:47:30 +0000703 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000704 certreqs=certreqs,
705 ssl_version=protocol,
706 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000707 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000708 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000709 connectionchatty=connectionchatty,
710 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000711 flag = threading.Event()
712 server.start(flag)
713 # wait for it to start
714 flag.wait()
715 # try to connect
716 if client_protocol is None:
717 client_protocol = protocol
718 try:
719 try:
720 s = ssl.wrap_socket(socket.socket(),
721 certfile=client_certfile,
722 ca_certs=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000723 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000724 cert_reqs=certreqs,
725 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000726 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000727 except ssl.SSLError, x:
728 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
729 except Exception, x:
730 raise test_support.TestFailed("Unexpected exception: " + str(x))
731 else:
Antoine Pitrou5ba84912009-10-19 17:59:07 +0000732 for arg in [indata, bytearray(indata), memoryview(indata)]:
733 if connectionchatty:
734 if test_support.verbose:
735 sys.stdout.write(
736 " client: sending %s...\n" % (repr(arg)))
737 s.write(arg)
738 outdata = s.read()
739 if connectionchatty:
740 if test_support.verbose:
741 sys.stdout.write(" client: read %s\n" % repr(outdata))
742 if outdata != indata.lower():
743 raise test_support.TestFailed(
744 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
745 % (outdata[:min(len(outdata),20)], len(outdata),
746 indata[:min(len(indata),20)].lower(), len(indata)))
Bill Janssen98d19da2007-09-10 21:51:02 +0000747 s.write("over\n")
748 if connectionchatty:
749 if test_support.verbose:
750 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000751 s.close()
752 finally:
753 server.stop()
754 server.join()
755
756 def tryProtocolCombo (server_protocol,
757 client_protocol,
758 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000759 certsreqs=None):
760
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000761 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000762 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000763
764 if certsreqs == ssl.CERT_NONE:
765 certtype = "CERT_NONE"
766 elif certsreqs == ssl.CERT_OPTIONAL:
767 certtype = "CERT_OPTIONAL"
768 elif certsreqs == ssl.CERT_REQUIRED:
769 certtype = "CERT_REQUIRED"
770 if test_support.verbose:
771 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
772 sys.stdout.write(formatstr %
773 (ssl.get_protocol_name(client_protocol),
774 ssl.get_protocol_name(server_protocol),
775 certtype))
776 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000777 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
778 # will send an SSLv3 hello (rather than SSLv2) starting from
779 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000780 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000781 CERTFILE, CERTFILE, client_protocol,
782 ciphers="ALL", chatty=False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000783 except test_support.TestFailed:
784 if expectedToWork:
785 raise
786 else:
787 if not expectedToWork:
788 raise test_support.TestFailed(
789 "Client protocol %s succeeded with server protocol %s!"
790 % (ssl.get_protocol_name(client_protocol),
791 ssl.get_protocol_name(server_protocol)))
792
793
Bill Janssen934b16d2008-06-28 22:19:33 +0000794 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000795
796 def testRudeShutdown(self):
797
798 listener_ready = threading.Event()
799 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000800 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000801
802 # `listener` runs in a thread. It opens a socket listening on
803 # PORT, and sits in an accept() until the main thread connects.
804 # Then it rudely closes the socket, and sets Event `listener_gone`
805 # to let the main thread know the socket is gone.
806 def listener():
807 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000808 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000809 s.listen(5)
810 listener_ready.set()
811 s.accept()
812 s = None # reclaim the socket object, which also closes it
813 listener_gone.set()
814
815 def connector():
816 listener_ready.wait()
817 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000818 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000819 listener_gone.wait()
820 try:
821 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000822 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000823 pass
824 else:
825 raise test_support.TestFailed(
826 'connecting to closed SSL socket should have failed')
827
828 t = threading.Thread(target=listener)
829 t.start()
830 connector()
831 t.join()
832
833 def testEcho (self):
834
835 if test_support.verbose:
836 sys.stdout.write("\n")
837 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
838 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
839 chatty=True, connectionchatty=True)
840
841 def testReadCert(self):
842
843 if test_support.verbose:
844 sys.stdout.write("\n")
845 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000846 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000847 certreqs=ssl.CERT_NONE,
848 ssl_version=ssl.PROTOCOL_SSLv23,
849 cacerts=CERTFILE,
850 chatty=False)
851 flag = threading.Event()
852 server.start(flag)
853 # wait for it to start
854 flag.wait()
855 # try to connect
856 try:
857 try:
858 s = ssl.wrap_socket(socket.socket(),
859 certfile=CERTFILE,
860 ca_certs=CERTFILE,
861 cert_reqs=ssl.CERT_REQUIRED,
862 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000863 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000864 except ssl.SSLError, x:
865 raise test_support.TestFailed(
866 "Unexpected SSL error: " + str(x))
867 except Exception, x:
868 raise test_support.TestFailed(
869 "Unexpected exception: " + str(x))
870 else:
871 if not s:
872 raise test_support.TestFailed(
873 "Can't SSL-handshake with test server")
874 cert = s.getpeercert()
875 if not cert:
876 raise test_support.TestFailed(
877 "Can't get peer certificate.")
878 cipher = s.cipher()
879 if test_support.verbose:
880 sys.stdout.write(pprint.pformat(cert) + '\n')
881 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000882 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000883 raise test_support.TestFailed(
884 "No subject field in certificate: %s." %
885 pprint.pformat(cert))
886 if ((('organizationName', 'Python Software Foundation'),)
887 not in cert['subject']):
888 raise test_support.TestFailed(
889 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000890 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000891 s.close()
892 finally:
893 server.stop()
894 server.join()
895
896 def testNULLcert(self):
897 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
898 "nullcert.pem"))
899 def testMalformedCert(self):
900 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
901 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000902 def testWrongCert(self):
903 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
904 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000905 def testMalformedKey(self):
906 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
907 "badkey.pem"))
908
909 def testProtocolSSL2(self):
910 if test_support.verbose:
911 sys.stdout.write("\n")
912 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
913 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
914 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
915 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
916 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
917 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
918
919 def testProtocolSSL23(self):
920 if test_support.verbose:
921 sys.stdout.write("\n")
922 try:
923 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
924 except test_support.TestFailed, x:
925 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
926 if test_support.verbose:
927 sys.stdout.write(
928 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
929 % str(x))
930 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
931 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
932 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
933
934 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
935 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
936 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
937
938 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
939 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
940 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
941
942 def testProtocolSSL3(self):
943 if test_support.verbose:
944 sys.stdout.write("\n")
945 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
946 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
947 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
948 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
949 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
950 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
951
952 def testProtocolTLS1(self):
953 if test_support.verbose:
954 sys.stdout.write("\n")
955 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
956 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
957 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
958 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
959 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
960 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
961
962 def testSTARTTLS (self):
963
Bill Janssen39295c22008-08-12 16:31:21 +0000964 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000965
Trent Nelsone41b0062008-04-08 23:47:30 +0000966 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000967 ssl_version=ssl.PROTOCOL_TLSv1,
968 starttls_server=True,
969 chatty=True,
970 connectionchatty=True)
971 flag = threading.Event()
972 server.start(flag)
973 # wait for it to start
974 flag.wait()
975 # try to connect
976 wrapped = False
977 try:
978 try:
979 s = socket.socket()
980 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000981 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000982 except Exception, x:
983 raise test_support.TestFailed("Unexpected exception: " + str(x))
984 else:
985 if test_support.verbose:
986 sys.stdout.write("\n")
987 for indata in msgs:
988 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000989 sys.stdout.write(
990 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000991 if wrapped:
992 conn.write(indata)
993 outdata = conn.read()
994 else:
995 s.send(indata)
996 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +0000997 if (indata == "STARTTLS" and
998 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000999 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001000 sys.stdout.write(
1001 " client: read %s from server, starting TLS...\n"
1002 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001003 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +00001004 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +00001005 elif (indata == "ENDTLS" and
1006 outdata.strip().lower().startswith("ok")):
1007 if test_support.verbose:
1008 sys.stdout.write(
1009 " client: read %s from server, ending TLS...\n"
1010 % repr(outdata))
1011 s = conn.unwrap()
1012 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001013 else:
1014 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001015 sys.stdout.write(
1016 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001017 if test_support.verbose:
1018 sys.stdout.write(" client: closing connection.\n")
1019 if wrapped:
1020 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001021 else:
1022 s.send("over\n")
1023 s.close()
1024 finally:
1025 server.stop()
1026 server.join()
1027
Bill Janssen934b16d2008-06-28 22:19:33 +00001028 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001029
Bill Janssen934b16d2008-06-28 22:19:33 +00001030 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001031 flag = threading.Event()
1032 server.start(flag)
1033 # wait for it to start
1034 flag.wait()
1035 # try to connect
1036 try:
1037 if test_support.verbose:
1038 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001039 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001040 d2 = ''
1041 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001042 url = 'https://127.0.0.1:%d/%s' % (
1043 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001044 with test_support.check_py3k_warnings():
1045 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001046 dlen = f.info().getheader("content-length")
1047 if dlen and (int(dlen) > 0):
1048 d2 = f.read(int(dlen))
1049 if test_support.verbose:
1050 sys.stdout.write(
1051 " client: read %d bytes from remote server '%s'\n"
1052 % (len(d2), server))
1053 f.close()
1054 except:
1055 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1056 if test_support.verbose:
1057 sys.stdout.write('\n' + msg)
1058 raise test_support.TestFailed(msg)
1059 else:
1060 if not (d1 == d2):
1061 raise test_support.TestFailed(
1062 "Couldn't fetch data from HTTPS server")
1063 finally:
1064 server.stop()
1065 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001066
Bill Janssen934b16d2008-06-28 22:19:33 +00001067 def testWrappedAccept (self):
1068
1069 if test_support.verbose:
1070 sys.stdout.write("\n")
1071 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1072 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1073 chatty=True, connectionchatty=True,
1074 wrap_accepting_socket=True)
1075
1076
1077 def testAsyncoreServer (self):
1078
1079 indata = "TEST MESSAGE of mixed case\n"
1080
1081 if test_support.verbose:
1082 sys.stdout.write("\n")
1083 server = AsyncoreEchoServer(CERTFILE)
1084 flag = threading.Event()
1085 server.start(flag)
1086 # wait for it to start
1087 flag.wait()
1088 # try to connect
1089 try:
1090 try:
1091 s = ssl.wrap_socket(socket.socket())
1092 s.connect(('127.0.0.1', server.port))
1093 except ssl.SSLError, x:
1094 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1095 except Exception, x:
1096 raise test_support.TestFailed("Unexpected exception: " + str(x))
1097 else:
1098 if test_support.verbose:
1099 sys.stdout.write(
1100 " client: sending %s...\n" % (repr(indata)))
1101 s.write(indata)
1102 outdata = s.read()
1103 if test_support.verbose:
1104 sys.stdout.write(" client: read %s\n" % repr(outdata))
1105 if outdata != indata.lower():
1106 raise test_support.TestFailed(
1107 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1108 % (outdata[:min(len(outdata),20)], len(outdata),
1109 indata[:min(len(indata),20)].lower(), len(indata)))
1110 s.write("over\n")
1111 if test_support.verbose:
1112 sys.stdout.write(" client: closing connection.\n")
1113 s.close()
1114 finally:
1115 server.stop()
1116 # wait for server thread to end
1117 server.join()
1118
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001119
Bill Janssen61c001a2008-09-08 16:37:24 +00001120 def testAllRecvAndSendMethods(self):
1121
1122 if test_support.verbose:
1123 sys.stdout.write("\n")
1124
1125 server = ThreadedEchoServer(CERTFILE,
1126 certreqs=ssl.CERT_NONE,
1127 ssl_version=ssl.PROTOCOL_TLSv1,
1128 cacerts=CERTFILE,
1129 chatty=True,
1130 connectionchatty=False)
1131 flag = threading.Event()
1132 server.start(flag)
1133 # wait for it to start
1134 flag.wait()
1135 # try to connect
1136 try:
1137 s = ssl.wrap_socket(socket.socket(),
1138 server_side=False,
1139 certfile=CERTFILE,
1140 ca_certs=CERTFILE,
1141 cert_reqs=ssl.CERT_NONE,
1142 ssl_version=ssl.PROTOCOL_TLSv1)
1143 s.connect((HOST, server.port))
1144 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001145 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001146 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001147 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001148 else:
1149 # helper methods for standardising recv* method signatures
1150 def _recv_into():
1151 b = bytearray("\0"*100)
1152 count = s.recv_into(b)
1153 return b[:count]
1154
1155 def _recvfrom_into():
1156 b = bytearray("\0"*100)
1157 count, addr = s.recvfrom_into(b)
1158 return b[:count]
1159
1160 # (name, method, whether to expect success, *args)
1161 send_methods = [
1162 ('send', s.send, True, []),
1163 ('sendto', s.sendto, False, ["some.address"]),
1164 ('sendall', s.sendall, True, []),
1165 ]
1166 recv_methods = [
1167 ('recv', s.recv, True, []),
1168 ('recvfrom', s.recvfrom, False, ["some.address"]),
1169 ('recv_into', _recv_into, True, []),
1170 ('recvfrom_into', _recvfrom_into, False, []),
1171 ]
1172 data_prefix = u"PREFIX_"
1173
1174 for meth_name, send_meth, expect_success, args in send_methods:
1175 indata = data_prefix + meth_name
1176 try:
1177 send_meth(indata.encode('ASCII', 'strict'), *args)
1178 outdata = s.read()
1179 outdata = outdata.decode('ASCII', 'strict')
1180 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001181 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001182 "While sending with <<%s>> bad data "
1183 "<<%r>> (%d) received; "
1184 "expected <<%r>> (%d)\n" % (
1185 meth_name, outdata[:20], len(outdata),
1186 indata[:20], len(indata)
1187 )
1188 )
1189 except ValueError as e:
1190 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001191 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001192 "Failed to send with method <<%s>>; "
1193 "expected to succeed.\n" % (meth_name,)
1194 )
1195 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001196 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001197 "Method <<%s>> failed with unexpected "
1198 "exception message: %s\n" % (
1199 meth_name, e
1200 )
1201 )
1202
1203 for meth_name, recv_meth, expect_success, args in recv_methods:
1204 indata = data_prefix + meth_name
1205 try:
1206 s.send(indata.encode('ASCII', 'strict'))
1207 outdata = recv_meth(*args)
1208 outdata = outdata.decode('ASCII', 'strict')
1209 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001210 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001211 "While receiving with <<%s>> bad data "
1212 "<<%r>> (%d) received; "
1213 "expected <<%r>> (%d)\n" % (
1214 meth_name, outdata[:20], len(outdata),
1215 indata[:20], len(indata)
1216 )
1217 )
1218 except ValueError as e:
1219 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001220 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001221 "Failed to receive with method <<%s>>; "
1222 "expected to succeed.\n" % (meth_name,)
1223 )
1224 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001225 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001226 "Method <<%s>> failed with unexpected "
1227 "exception message: %s\n" % (
1228 meth_name, e
1229 )
1230 )
1231 # consume data
1232 s.read()
1233
1234 s.write("over\n".encode("ASCII", "strict"))
1235 s.close()
1236 finally:
1237 server.stop()
1238 server.join()
1239
1240
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001241def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001242 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001243 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001244
Trent Nelsone41b0062008-04-08 23:47:30 +00001245 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001246 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001247 "keycert.pem")
1248 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1249 os.path.dirname(__file__) or os.curdir,
1250 "https_svn_python_org_root.pem")
1251
1252 if (not os.path.exists(CERTFILE) or
1253 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001254 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001255
Bill Janssen934b16d2008-06-28 22:19:33 +00001256 TESTPORT = test_support.find_unused_port()
1257 if not TESTPORT:
1258 raise test_support.TestFailed("Can't find open port to test servers on!")
1259
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001260 tests = [BasicTests]
1261
Bill Janssen296a59d2007-09-16 22:06:00 +00001262 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001263 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001264
Bill Janssen98d19da2007-09-10 21:51:02 +00001265 if _have_threads:
1266 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001267 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001268 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001269
Bill Janssen98d19da2007-09-10 21:51:02 +00001270 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001271
Bill Janssen98d19da2007-09-10 21:51:02 +00001272 if _have_threads:
1273 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001274
1275if __name__ == "__main__":
1276 test_main()