blob: 619968585d30bdda8bdcbbe2ac25c0c436ac11d8 [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
235
Bill Janssen98d19da2007-09-10 21:51:02 +0000236try:
237 import threading
238except ImportError:
239 _have_threads = False
240else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000241
Bill Janssen98d19da2007-09-10 21:51:02 +0000242 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000243
Bill Janssen98d19da2007-09-10 21:51:02 +0000244 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000245
Bill Janssen98d19da2007-09-10 21:51:02 +0000246 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000247
Bill Janssen98d19da2007-09-10 21:51:02 +0000248 """A mildly complicated class, because we want it to work both
249 with and without the SSL wrapper around the socket connection, so
250 that we can test the STARTTLS functionality."""
251
252 def __init__(self, server, connsock):
253 self.server = server
254 self.running = False
255 self.sock = connsock
256 self.sock.setblocking(1)
257 self.sslconn = None
258 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000259 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000260
Bill Janssen934b16d2008-06-28 22:19:33 +0000261 def show_conn_details(self):
262 if self.server.certreqs == ssl.CERT_REQUIRED:
263 cert = self.sslconn.getpeercert()
264 if test_support.verbose and self.server.chatty:
265 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
266 cert_binary = self.sslconn.getpeercert(True)
267 if test_support.verbose and self.server.chatty:
268 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
269 cipher = self.sslconn.cipher()
270 if test_support.verbose and self.server.chatty:
271 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
272
Bill Janssen98d19da2007-09-10 21:51:02 +0000273 def wrap_conn (self):
274 try:
275 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
276 certfile=self.server.certificate,
277 ssl_version=self.server.protocol,
278 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000279 cert_reqs=self.server.certreqs,
280 ciphers=self.server.ciphers)
Bill Janssen98d19da2007-09-10 21:51:02 +0000281 except:
282 if self.server.chatty:
283 handle_error("\n server: bad connection attempt from " +
284 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000285 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000286 if not self.server.expect_bad_connects:
287 # here, we want to stop the server, because this shouldn't
288 # happen in the context of our test case
289 self.running = False
290 # normally, we'd just stop here, but for the test
291 # harness, we want to stop the server
292 self.server.stop()
293 return False
294
295 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000296 return True
297
298 def read(self):
299 if self.sslconn:
300 return self.sslconn.read()
301 else:
302 return self.sock.recv(1024)
303
304 def write(self, bytes):
305 if self.sslconn:
306 return self.sslconn.write(bytes)
307 else:
308 return self.sock.send(bytes)
309
310 def close(self):
311 if self.sslconn:
312 self.sslconn.close()
313 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000314 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000315
316 def run (self):
317 self.running = True
318 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000319 if isinstance(self.sock, ssl.SSLSocket):
320 self.sslconn = self.sock
321 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000322 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000323 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000324 while self.running:
325 try:
326 msg = self.read()
327 if not msg:
328 # eof, so quit this handler
329 self.running = False
330 self.close()
331 elif msg.strip() == 'over':
332 if test_support.verbose and self.server.connectionchatty:
333 sys.stdout.write(" server: client closed connection\n")
334 self.close()
335 return
336 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
337 if test_support.verbose and self.server.connectionchatty:
338 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
339 self.write("OK\n")
340 if not self.wrap_conn():
341 return
Bill Janssen39295c22008-08-12 16:31:21 +0000342 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
343 if test_support.verbose and self.server.connectionchatty:
344 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
345 self.write("OK\n")
346 self.sslconn.unwrap()
347 self.sslconn = None
348 if test_support.verbose and self.server.connectionchatty:
349 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000350 else:
351 if (test_support.verbose and
352 self.server.connectionchatty):
353 ctype = (self.sslconn and "encrypted") or "unencrypted"
354 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
355 % (repr(msg), ctype, repr(msg.lower()), ctype))
356 self.write(msg.lower())
357 except ssl.SSLError:
358 if self.server.chatty:
359 handle_error("Test server failure:\n")
360 self.close()
361 self.running = False
362 # normally, we'd just stop here, but for the test
363 # harness, we want to stop the server
364 self.server.stop()
365 except:
366 handle_error('')
367
Trent Nelsone41b0062008-04-08 23:47:30 +0000368 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000369 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000370 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000371 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000372
Bill Janssen98d19da2007-09-10 21:51:02 +0000373 if ssl_version is None:
374 ssl_version = ssl.PROTOCOL_TLSv1
375 if certreqs is None:
376 certreqs = ssl.CERT_NONE
377 self.certificate = certificate
378 self.protocol = ssl_version
379 self.certreqs = certreqs
380 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000381 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000382 self.expect_bad_connects = expect_bad_connects
383 self.chatty = chatty
384 self.connectionchatty = connectionchatty
385 self.starttls_server = starttls_server
386 self.sock = socket.socket()
387 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000388 if wrap_accepting_socket:
389 self.sock = ssl.wrap_socket(self.sock, server_side=True,
390 certfile=self.certificate,
391 cert_reqs = self.certreqs,
392 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000393 ssl_version = self.protocol,
394 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000395 if test_support.verbose and self.chatty:
396 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
397 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000398 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000399 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000400 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000401
402 def start (self, flag=None):
403 self.flag = flag
404 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000405
406 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000407 self.sock.settimeout(0.5)
408 self.sock.listen(5)
409 self.active = True
410 if self.flag:
411 # signal an event
412 self.flag.set()
413 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000414 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000415 newconn, connaddr = self.sock.accept()
416 if test_support.verbose and self.chatty:
417 sys.stdout.write(' server: new connection from '
418 + str(connaddr) + '\n')
419 handler = self.ConnectionHandler(self, newconn)
420 handler.start()
421 except socket.timeout:
422 pass
423 except KeyboardInterrupt:
424 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000425 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000426 if self.chatty:
427 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000428 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000429
Bill Janssen98d19da2007-09-10 21:51:02 +0000430 def stop (self):
431 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000432
Bill Janssen934b16d2008-06-28 22:19:33 +0000433 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000434
Bill Janssen934b16d2008-06-28 22:19:33 +0000435 class EchoServer (asyncore.dispatcher):
436
437 class ConnectionHandler (asyncore.dispatcher_with_send):
438
439 def __init__(self, conn, certfile):
440 asyncore.dispatcher_with_send.__init__(self, conn)
441 self.socket = ssl.wrap_socket(conn, server_side=True,
442 certfile=certfile,
443 do_handshake_on_connect=True)
444
445 def readable(self):
446 if isinstance(self.socket, ssl.SSLSocket):
447 while self.socket.pending() > 0:
448 self.handle_read_event()
449 return True
450
451 def handle_read(self):
452 data = self.recv(1024)
453 self.send(data.lower())
454
455 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000456 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000457 if test_support.verbose:
458 sys.stdout.write(" server: closed connection %s\n" % self.socket)
459
460 def handle_error(self):
461 raise
462
463 def __init__(self, certfile):
464 self.certfile = certfile
465 asyncore.dispatcher.__init__(self)
466 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
467 self.port = test_support.bind_port(self.socket)
468 self.listen(5)
469
470 def handle_accept(self):
471 sock_obj, addr = self.accept()
472 if test_support.verbose:
473 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
474 self.ConnectionHandler(sock_obj, self.certfile)
475
476 def handle_error(self):
477 raise
478
479 def __init__(self, certfile):
480 self.flag = None
481 self.active = False
482 self.server = self.EchoServer(certfile)
483 self.port = self.server.port
484 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000485 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000486
487 def __str__(self):
488 return "<%s %s>" % (self.__class__.__name__, self.server)
489
490 def start (self, flag=None):
491 self.flag = flag
492 threading.Thread.start(self)
493
494 def run (self):
495 self.active = True
496 if self.flag:
497 self.flag.set()
498 while self.active:
499 try:
500 asyncore.loop(1)
501 except:
502 pass
503
504 def stop (self):
505 self.active = False
506 self.server.close()
507
508 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000509
510 class HTTPSServer(HTTPServer):
511
512 def __init__(self, server_address, RequestHandlerClass, certfile):
513
514 HTTPServer.__init__(self, server_address, RequestHandlerClass)
515 # we assume the certfile contains both private key and certificate
516 self.certfile = certfile
517 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000518 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000519 self.allow_reuse_address = True
520
Bill Janssen934b16d2008-06-28 22:19:33 +0000521 def __str__(self):
522 return ('<%s %s:%s>' %
523 (self.__class__.__name__,
524 self.server_name,
525 self.server_port))
526
Bill Janssen296a59d2007-09-16 22:06:00 +0000527 def get_request (self):
528 # override this to wrap socket with SSL
529 sock, addr = self.socket.accept()
530 sslconn = ssl.wrap_socket(sock, server_side=True,
531 certfile=self.certfile)
532 return sslconn, addr
533
534 # The methods overridden below this are mainly so that we
535 # can run it in a thread and be able to stop it from another
536 # You probably wouldn't need them in other uses.
537
538 def server_activate(self):
539 # We want to run this in a thread for testing purposes,
540 # so we override this to set timeout, so that we get
541 # a chance to stop the server
542 self.socket.settimeout(0.5)
543 HTTPServer.server_activate(self)
544
545 def serve_forever(self):
546 # We want this to run in a thread, so we use a slightly
547 # modified version of "forever".
548 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000549 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000550 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000551 # We need to lock while handling the request.
552 # Another thread can close the socket after self.active
553 # has been checked and before the request is handled.
554 # This causes an exception when using the closed socket.
555 with self.active_lock:
556 if not self.active:
557 break
558 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000559 except socket.timeout:
560 pass
561 except KeyboardInterrupt:
562 self.server_close()
563 return
564 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000565 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
566 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000567 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000568
569 def server_close(self):
570 # Again, we want this to run in a thread, so we need to override
571 # close to clear the "active" flag, so that serve_forever() will
572 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000573 with self.active_lock:
574 HTTPServer.server_close(self)
575 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000576
577 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
578
579 # need to override translate_path to get a known root,
580 # instead of using os.curdir, since the test could be
581 # run from anywhere
582
583 server_version = "TestHTTPS/1.0"
584
585 root = None
586
587 def translate_path(self, path):
588 """Translate a /-separated PATH to the local filename syntax.
589
590 Components that mean special things to the local file system
591 (e.g. drive or directory names) are ignored. (XXX They should
592 probably be diagnosed.)
593
594 """
595 # abandon query parameters
596 path = urlparse.urlparse(path)[2]
597 path = os.path.normpath(urllib.unquote(path))
598 words = path.split('/')
599 words = filter(None, words)
600 path = self.root
601 for word in words:
602 drive, word = os.path.splitdrive(word)
603 head, word = os.path.split(word)
604 if word in self.root: continue
605 path = os.path.join(path, word)
606 return path
607
608 def log_message(self, format, *args):
609
610 # we override this to suppress logging unless "verbose"
611
612 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000613 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
614 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000615 self.server.server_port,
616 self.request.cipher(),
617 self.log_date_time_string(),
618 format%args))
619
620
Trent Nelsone41b0062008-04-08 23:47:30 +0000621 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000622 self.flag = None
623 self.active = False
624 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000625 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000626 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000627 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000628 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000629 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000630
631 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000632 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000633
634 def start (self, flag=None):
635 self.flag = flag
636 threading.Thread.start(self)
637
638 def run (self):
639 self.active = True
640 if self.flag:
641 self.flag.set()
642 self.server.serve_forever()
643 self.active = False
644
645 def stop (self):
646 self.active = False
647 self.server.server_close()
648
649
Bill Janssen98d19da2007-09-10 21:51:02 +0000650 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000651 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000652 certreqs=ssl.CERT_REQUIRED,
653 cacerts=CERTFILE, chatty=False)
654 flag = threading.Event()
655 server.start(flag)
656 # wait for it to start
657 flag.wait()
658 # try to connect
659 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000660 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000661 s = ssl.wrap_socket(socket.socket(),
662 certfile=certfile,
663 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000664 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000665 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000666 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000667 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000668 except socket.error, x:
669 if test_support.verbose:
670 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000671 else:
672 raise test_support.TestFailed(
673 "Use of invalid cert should have failed!")
674 finally:
675 server.stop()
676 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000677
Bill Janssen98d19da2007-09-10 21:51:02 +0000678 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
679 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000680 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000681 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000682
Trent Nelsone41b0062008-04-08 23:47:30 +0000683 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000684 certreqs=certreqs,
685 ssl_version=protocol,
686 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000687 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000688 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000689 connectionchatty=connectionchatty,
690 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000691 flag = threading.Event()
692 server.start(flag)
693 # wait for it to start
694 flag.wait()
695 # try to connect
696 if client_protocol is None:
697 client_protocol = protocol
698 try:
699 try:
700 s = ssl.wrap_socket(socket.socket(),
701 certfile=client_certfile,
702 ca_certs=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000703 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000704 cert_reqs=certreqs,
705 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000706 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000707 except ssl.SSLError, x:
708 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
709 except Exception, x:
710 raise test_support.TestFailed("Unexpected exception: " + str(x))
711 else:
Antoine Pitrou5ba84912009-10-19 17:59:07 +0000712 for arg in [indata, bytearray(indata), memoryview(indata)]:
713 if connectionchatty:
714 if test_support.verbose:
715 sys.stdout.write(
716 " client: sending %s...\n" % (repr(arg)))
717 s.write(arg)
718 outdata = s.read()
719 if connectionchatty:
720 if test_support.verbose:
721 sys.stdout.write(" client: read %s\n" % repr(outdata))
722 if outdata != indata.lower():
723 raise test_support.TestFailed(
724 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
725 % (outdata[:min(len(outdata),20)], len(outdata),
726 indata[:min(len(indata),20)].lower(), len(indata)))
Bill Janssen98d19da2007-09-10 21:51:02 +0000727 s.write("over\n")
728 if connectionchatty:
729 if test_support.verbose:
730 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000731 s.close()
732 finally:
733 server.stop()
734 server.join()
735
736 def tryProtocolCombo (server_protocol,
737 client_protocol,
738 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000739 certsreqs=None):
740
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000741 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000742 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000743
744 if certsreqs == ssl.CERT_NONE:
745 certtype = "CERT_NONE"
746 elif certsreqs == ssl.CERT_OPTIONAL:
747 certtype = "CERT_OPTIONAL"
748 elif certsreqs == ssl.CERT_REQUIRED:
749 certtype = "CERT_REQUIRED"
750 if test_support.verbose:
751 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
752 sys.stdout.write(formatstr %
753 (ssl.get_protocol_name(client_protocol),
754 ssl.get_protocol_name(server_protocol),
755 certtype))
756 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000757 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
758 # will send an SSLv3 hello (rather than SSLv2) starting from
759 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000760 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000761 CERTFILE, CERTFILE, client_protocol,
762 ciphers="ALL", chatty=False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000763 except test_support.TestFailed:
764 if expectedToWork:
765 raise
766 else:
767 if not expectedToWork:
768 raise test_support.TestFailed(
769 "Client protocol %s succeeded with server protocol %s!"
770 % (ssl.get_protocol_name(client_protocol),
771 ssl.get_protocol_name(server_protocol)))
772
773
Bill Janssen934b16d2008-06-28 22:19:33 +0000774 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000775
776 def testRudeShutdown(self):
777
778 listener_ready = threading.Event()
779 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000780 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000781
782 # `listener` runs in a thread. It opens a socket listening on
783 # PORT, and sits in an accept() until the main thread connects.
784 # Then it rudely closes the socket, and sets Event `listener_gone`
785 # to let the main thread know the socket is gone.
786 def listener():
787 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000788 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000789 s.listen(5)
790 listener_ready.set()
791 s.accept()
792 s = None # reclaim the socket object, which also closes it
793 listener_gone.set()
794
795 def connector():
796 listener_ready.wait()
797 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000798 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000799 listener_gone.wait()
800 try:
801 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000802 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000803 pass
804 else:
805 raise test_support.TestFailed(
806 'connecting to closed SSL socket should have failed')
807
808 t = threading.Thread(target=listener)
809 t.start()
810 connector()
811 t.join()
812
813 def testEcho (self):
814
815 if test_support.verbose:
816 sys.stdout.write("\n")
817 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
818 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
819 chatty=True, connectionchatty=True)
820
821 def testReadCert(self):
822
823 if test_support.verbose:
824 sys.stdout.write("\n")
825 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000826 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000827 certreqs=ssl.CERT_NONE,
828 ssl_version=ssl.PROTOCOL_SSLv23,
829 cacerts=CERTFILE,
830 chatty=False)
831 flag = threading.Event()
832 server.start(flag)
833 # wait for it to start
834 flag.wait()
835 # try to connect
836 try:
837 try:
838 s = ssl.wrap_socket(socket.socket(),
839 certfile=CERTFILE,
840 ca_certs=CERTFILE,
841 cert_reqs=ssl.CERT_REQUIRED,
842 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000843 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000844 except ssl.SSLError, x:
845 raise test_support.TestFailed(
846 "Unexpected SSL error: " + str(x))
847 except Exception, x:
848 raise test_support.TestFailed(
849 "Unexpected exception: " + str(x))
850 else:
851 if not s:
852 raise test_support.TestFailed(
853 "Can't SSL-handshake with test server")
854 cert = s.getpeercert()
855 if not cert:
856 raise test_support.TestFailed(
857 "Can't get peer certificate.")
858 cipher = s.cipher()
859 if test_support.verbose:
860 sys.stdout.write(pprint.pformat(cert) + '\n')
861 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Florent Xicluna07627882010-03-21 01:14:24 +0000862 if 'subject' not in cert:
Bill Janssen98d19da2007-09-10 21:51:02 +0000863 raise test_support.TestFailed(
864 "No subject field in certificate: %s." %
865 pprint.pformat(cert))
866 if ((('organizationName', 'Python Software Foundation'),)
867 not in cert['subject']):
868 raise test_support.TestFailed(
869 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000870 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000871 s.close()
872 finally:
873 server.stop()
874 server.join()
875
876 def testNULLcert(self):
877 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
878 "nullcert.pem"))
879 def testMalformedCert(self):
880 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
881 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000882 def testWrongCert(self):
883 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
884 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000885 def testMalformedKey(self):
886 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
887 "badkey.pem"))
888
889 def testProtocolSSL2(self):
890 if test_support.verbose:
891 sys.stdout.write("\n")
892 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
893 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
894 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
895 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
896 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
897 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
898
899 def testProtocolSSL23(self):
900 if test_support.verbose:
901 sys.stdout.write("\n")
902 try:
903 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
904 except test_support.TestFailed, x:
905 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
906 if test_support.verbose:
907 sys.stdout.write(
908 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
909 % str(x))
910 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
911 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
912 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
913
914 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
915 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
916 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
917
918 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
919 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
920 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
921
922 def testProtocolSSL3(self):
923 if test_support.verbose:
924 sys.stdout.write("\n")
925 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
926 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
927 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
928 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
929 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
930 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
931
932 def testProtocolTLS1(self):
933 if test_support.verbose:
934 sys.stdout.write("\n")
935 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
936 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
937 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
938 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
939 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
940 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
941
942 def testSTARTTLS (self):
943
Bill Janssen39295c22008-08-12 16:31:21 +0000944 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000945
Trent Nelsone41b0062008-04-08 23:47:30 +0000946 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000947 ssl_version=ssl.PROTOCOL_TLSv1,
948 starttls_server=True,
949 chatty=True,
950 connectionchatty=True)
951 flag = threading.Event()
952 server.start(flag)
953 # wait for it to start
954 flag.wait()
955 # try to connect
956 wrapped = False
957 try:
958 try:
959 s = socket.socket()
960 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000961 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000962 except Exception, x:
963 raise test_support.TestFailed("Unexpected exception: " + str(x))
964 else:
965 if test_support.verbose:
966 sys.stdout.write("\n")
967 for indata in msgs:
968 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000969 sys.stdout.write(
970 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000971 if wrapped:
972 conn.write(indata)
973 outdata = conn.read()
974 else:
975 s.send(indata)
976 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +0000977 if (indata == "STARTTLS" and
978 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000979 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000980 sys.stdout.write(
981 " client: read %s from server, starting TLS...\n"
982 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000983 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000984 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +0000985 elif (indata == "ENDTLS" and
986 outdata.strip().lower().startswith("ok")):
987 if test_support.verbose:
988 sys.stdout.write(
989 " client: read %s from server, ending TLS...\n"
990 % repr(outdata))
991 s = conn.unwrap()
992 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000993 else:
994 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000995 sys.stdout.write(
996 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000997 if test_support.verbose:
998 sys.stdout.write(" client: closing connection.\n")
999 if wrapped:
1000 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001001 else:
1002 s.send("over\n")
1003 s.close()
1004 finally:
1005 server.stop()
1006 server.join()
1007
Bill Janssen934b16d2008-06-28 22:19:33 +00001008 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001009
Bill Janssen934b16d2008-06-28 22:19:33 +00001010 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001011 flag = threading.Event()
1012 server.start(flag)
1013 # wait for it to start
1014 flag.wait()
1015 # try to connect
1016 try:
1017 if test_support.verbose:
1018 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001019 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001020 d2 = ''
1021 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001022 url = 'https://127.0.0.1:%d/%s' % (
1023 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001024 with test_support.check_py3k_warnings():
1025 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001026 dlen = f.info().getheader("content-length")
1027 if dlen and (int(dlen) > 0):
1028 d2 = f.read(int(dlen))
1029 if test_support.verbose:
1030 sys.stdout.write(
1031 " client: read %d bytes from remote server '%s'\n"
1032 % (len(d2), server))
1033 f.close()
1034 except:
1035 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1036 if test_support.verbose:
1037 sys.stdout.write('\n' + msg)
1038 raise test_support.TestFailed(msg)
1039 else:
1040 if not (d1 == d2):
1041 raise test_support.TestFailed(
1042 "Couldn't fetch data from HTTPS server")
1043 finally:
1044 server.stop()
1045 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001046
Bill Janssen934b16d2008-06-28 22:19:33 +00001047 def testWrappedAccept (self):
1048
1049 if test_support.verbose:
1050 sys.stdout.write("\n")
1051 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1052 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1053 chatty=True, connectionchatty=True,
1054 wrap_accepting_socket=True)
1055
1056
1057 def testAsyncoreServer (self):
1058
1059 indata = "TEST MESSAGE of mixed case\n"
1060
1061 if test_support.verbose:
1062 sys.stdout.write("\n")
1063 server = AsyncoreEchoServer(CERTFILE)
1064 flag = threading.Event()
1065 server.start(flag)
1066 # wait for it to start
1067 flag.wait()
1068 # try to connect
1069 try:
1070 try:
1071 s = ssl.wrap_socket(socket.socket())
1072 s.connect(('127.0.0.1', server.port))
1073 except ssl.SSLError, x:
1074 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1075 except Exception, x:
1076 raise test_support.TestFailed("Unexpected exception: " + str(x))
1077 else:
1078 if test_support.verbose:
1079 sys.stdout.write(
1080 " client: sending %s...\n" % (repr(indata)))
1081 s.write(indata)
1082 outdata = s.read()
1083 if test_support.verbose:
1084 sys.stdout.write(" client: read %s\n" % repr(outdata))
1085 if outdata != indata.lower():
1086 raise test_support.TestFailed(
1087 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1088 % (outdata[:min(len(outdata),20)], len(outdata),
1089 indata[:min(len(indata),20)].lower(), len(indata)))
1090 s.write("over\n")
1091 if test_support.verbose:
1092 sys.stdout.write(" client: closing connection.\n")
1093 s.close()
1094 finally:
1095 server.stop()
1096 # wait for server thread to end
1097 server.join()
1098
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001099
Bill Janssen61c001a2008-09-08 16:37:24 +00001100 def testAllRecvAndSendMethods(self):
1101
1102 if test_support.verbose:
1103 sys.stdout.write("\n")
1104
1105 server = ThreadedEchoServer(CERTFILE,
1106 certreqs=ssl.CERT_NONE,
1107 ssl_version=ssl.PROTOCOL_TLSv1,
1108 cacerts=CERTFILE,
1109 chatty=True,
1110 connectionchatty=False)
1111 flag = threading.Event()
1112 server.start(flag)
1113 # wait for it to start
1114 flag.wait()
1115 # try to connect
1116 try:
1117 s = ssl.wrap_socket(socket.socket(),
1118 server_side=False,
1119 certfile=CERTFILE,
1120 ca_certs=CERTFILE,
1121 cert_reqs=ssl.CERT_NONE,
1122 ssl_version=ssl.PROTOCOL_TLSv1)
1123 s.connect((HOST, server.port))
1124 except ssl.SSLError as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001125 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001126 except Exception as x:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001127 self.fail("Unexpected exception: " + str(x))
Bill Janssen61c001a2008-09-08 16:37:24 +00001128 else:
1129 # helper methods for standardising recv* method signatures
1130 def _recv_into():
1131 b = bytearray("\0"*100)
1132 count = s.recv_into(b)
1133 return b[:count]
1134
1135 def _recvfrom_into():
1136 b = bytearray("\0"*100)
1137 count, addr = s.recvfrom_into(b)
1138 return b[:count]
1139
1140 # (name, method, whether to expect success, *args)
1141 send_methods = [
1142 ('send', s.send, True, []),
1143 ('sendto', s.sendto, False, ["some.address"]),
1144 ('sendall', s.sendall, True, []),
1145 ]
1146 recv_methods = [
1147 ('recv', s.recv, True, []),
1148 ('recvfrom', s.recvfrom, False, ["some.address"]),
1149 ('recv_into', _recv_into, True, []),
1150 ('recvfrom_into', _recvfrom_into, False, []),
1151 ]
1152 data_prefix = u"PREFIX_"
1153
1154 for meth_name, send_meth, expect_success, args in send_methods:
1155 indata = data_prefix + meth_name
1156 try:
1157 send_meth(indata.encode('ASCII', 'strict'), *args)
1158 outdata = s.read()
1159 outdata = outdata.decode('ASCII', 'strict')
1160 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001161 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001162 "While sending with <<%s>> bad data "
1163 "<<%r>> (%d) received; "
1164 "expected <<%r>> (%d)\n" % (
1165 meth_name, outdata[:20], len(outdata),
1166 indata[:20], len(indata)
1167 )
1168 )
1169 except ValueError as e:
1170 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001171 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001172 "Failed to send with method <<%s>>; "
1173 "expected to succeed.\n" % (meth_name,)
1174 )
1175 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001176 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001177 "Method <<%s>> failed with unexpected "
1178 "exception message: %s\n" % (
1179 meth_name, e
1180 )
1181 )
1182
1183 for meth_name, recv_meth, expect_success, args in recv_methods:
1184 indata = data_prefix + meth_name
1185 try:
1186 s.send(indata.encode('ASCII', 'strict'))
1187 outdata = recv_meth(*args)
1188 outdata = outdata.decode('ASCII', 'strict')
1189 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001190 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001191 "While receiving with <<%s>> bad data "
1192 "<<%r>> (%d) received; "
1193 "expected <<%r>> (%d)\n" % (
1194 meth_name, outdata[:20], len(outdata),
1195 indata[:20], len(indata)
1196 )
1197 )
1198 except ValueError as e:
1199 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001200 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001201 "Failed to receive with method <<%s>>; "
1202 "expected to succeed.\n" % (meth_name,)
1203 )
1204 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001205 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001206 "Method <<%s>> failed with unexpected "
1207 "exception message: %s\n" % (
1208 meth_name, e
1209 )
1210 )
1211 # consume data
1212 s.read()
1213
1214 s.write("over\n".encode("ASCII", "strict"))
1215 s.close()
1216 finally:
1217 server.stop()
1218 server.join()
1219
1220
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001221def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001222 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001223 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001224
Trent Nelsone41b0062008-04-08 23:47:30 +00001225 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001226 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001227 "keycert.pem")
1228 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1229 os.path.dirname(__file__) or os.curdir,
1230 "https_svn_python_org_root.pem")
1231
1232 if (not os.path.exists(CERTFILE) or
1233 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001234 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001235
Bill Janssen934b16d2008-06-28 22:19:33 +00001236 TESTPORT = test_support.find_unused_port()
1237 if not TESTPORT:
1238 raise test_support.TestFailed("Can't find open port to test servers on!")
1239
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001240 tests = [BasicTests]
1241
Bill Janssen296a59d2007-09-16 22:06:00 +00001242 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001243 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001244
Bill Janssen98d19da2007-09-10 21:51:02 +00001245 if _have_threads:
1246 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001247 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001248 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001249
Bill Janssen98d19da2007-09-10 21:51:02 +00001250 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001251
Bill Janssen98d19da2007-09-10 21:51:02 +00001252 if _have_threads:
1253 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001254
1255if __name__ == "__main__":
1256 test_main()