blob: ad5864726596019be3df63dca532eb8b2141475e [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 errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000010import subprocess
11import time
12import os
13import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000014import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import shutil
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000016import traceback
17
Bill Janssen296a59d2007-09-16 22:06:00 +000018from BaseHTTPServer import HTTPServer
19from SimpleHTTPServer import SimpleHTTPRequestHandler
20
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000021# Optionally test SSL support, if we have it in the tested platform
22skip_expected = False
23try:
24 import ssl
25except ImportError:
26 skip_expected = True
27
Trent Nelsone41b0062008-04-08 23:47:30 +000028HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000029CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000030SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000031
Neal Norwitz3e533c22007-08-27 01:03:18 +000032def handle_error(prefix):
33 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000034 if test_support.verbose:
35 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000036
Bill Jansseneb257ac2008-09-29 18:56:38 +000037 def testSimpleSSLwrap(self):
38 try:
39 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
40 except IOError, e:
41 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
42 pass
43 else:
44 raise
45 try:
46 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
47 except IOError, e:
48 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
49 pass
50 else:
51 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000052
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000053class BasicTests(unittest.TestCase):
54
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000055 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000056 if not test_support.is_resource_enabled('network'):
57 return
Bill Janssen296a59d2007-09-16 22:06:00 +000058 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
59 cert_reqs=ssl.CERT_NONE)
60 s.connect(("svn.python.org", 443))
61 c = s.getpeercert()
62 if c:
63 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
64 s.close()
65
66 # this should fail because we have no verification certs
67 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
68 cert_reqs=ssl.CERT_REQUIRED)
69 try:
70 s.connect(("svn.python.org", 443))
71 except ssl.SSLError:
72 pass
73 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000074 s.close()
75
Bill Janssen98d19da2007-09-10 21:51:02 +000076 def testCrucialConstants(self):
77 ssl.PROTOCOL_SSLv2
78 ssl.PROTOCOL_SSLv23
79 ssl.PROTOCOL_SSLv3
80 ssl.PROTOCOL_TLSv1
81 ssl.CERT_NONE
82 ssl.CERT_OPTIONAL
83 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000084
Bill Janssen98d19da2007-09-10 21:51:02 +000085 def testRAND(self):
86 v = ssl.RAND_status()
87 if test_support.verbose:
88 sys.stdout.write("\n RAND_status is %d (%s)\n"
89 % (v, (v and "sufficient randomness") or
90 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000091 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000092 ssl.RAND_egd(1)
93 except TypeError:
94 pass
Guido van Rossume4729332007-08-26 19:35:09 +000095 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000096 print "didn't raise TypeError"
97 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000098
Bill Janssen98d19da2007-09-10 21:51:02 +000099 def testParseCert(self):
100 # note that this uses an 'unofficial' function in _ssl.c,
101 # provided solely for this test, to exercise the certificate
102 # parsing code
103 p = ssl._ssl._test_decode_cert(CERTFILE, False)
104 if test_support.verbose:
105 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000106
Bill Janssen296a59d2007-09-16 22:06:00 +0000107 def testDERtoPEM(self):
108
109 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
110 d1 = ssl.PEM_cert_to_DER_cert(pem)
111 p2 = ssl.DER_cert_to_PEM_cert(d1)
112 d2 = ssl.PEM_cert_to_DER_cert(p2)
113 if (d1 != d2):
114 raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
115
Bill Janssen934b16d2008-06-28 22:19:33 +0000116class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000117
118 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000119 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
120 cert_reqs=ssl.CERT_NONE)
121 s.connect(("svn.python.org", 443))
122 c = s.getpeercert()
123 if c:
124 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
125 s.close()
126
127 # this should fail because we have no verification certs
128 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
129 cert_reqs=ssl.CERT_REQUIRED)
130 try:
131 s.connect(("svn.python.org", 443))
132 except ssl.SSLError:
133 pass
134 finally:
135 s.close()
136
137 # this should succeed because we specify the root cert
138 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
139 cert_reqs=ssl.CERT_REQUIRED,
140 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
141 try:
142 s.connect(("svn.python.org", 443))
143 except ssl.SSLError, x:
144 raise test_support.TestFailed("Unexpected exception %s" % x)
145 finally:
146 s.close()
147
Bill Janssen934b16d2008-06-28 22:19:33 +0000148
149 def testNonBlockingHandshake(self):
150 s = socket.socket(socket.AF_INET)
151 s.connect(("svn.python.org", 443))
152 s.setblocking(False)
153 s = ssl.wrap_socket(s,
154 cert_reqs=ssl.CERT_NONE,
155 do_handshake_on_connect=False)
156 count = 0
157 while True:
158 try:
159 count += 1
160 s.do_handshake()
161 break
162 except ssl.SSLError, err:
163 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
164 select.select([s], [], [])
165 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
166 select.select([], [s], [])
167 else:
168 raise
169 s.close()
170 if test_support.verbose:
171 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
172
Bill Janssen296a59d2007-09-16 22:06:00 +0000173 def testFetchServerCert(self):
174
175 pem = ssl.get_server_certificate(("svn.python.org", 443))
176 if not pem:
177 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
178
179 try:
180 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
181 except ssl.SSLError:
182 #should fail
183 pass
184 else:
185 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
186
187 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
188 if not pem:
189 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
190 if test_support.verbose:
191 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
192
Antoine Pitrou878602a2010-04-21 19:41:28 +0000193 def test_algorithms(self):
194 # Issue #8484: all algorithms should be available when verifying a
195 # certificate.
196 # NOTE: https://sha256.tbs-internet.com is another possible test host
197 remote = ("sha2.hboeck.de", 443)
198 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
199 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
200 cert_reqs=ssl.CERT_REQUIRED,
201 ca_certs=sha256_cert,)
202 with test_support.transient_internet():
203 try:
204 s.connect(remote)
205 if test_support.verbose:
206 sys.stdout.write("\nCipher with %r is %r\n" %
207 (remote, s.cipher()))
208 sys.stdout.write("Certificate is:\n%s\n" %
209 pprint.pformat(s.getpeercert()))
210 finally:
211 s.close()
212
Bill Janssen296a59d2007-09-16 22:06:00 +0000213
Bill Janssen98d19da2007-09-10 21:51:02 +0000214try:
215 import threading
216except ImportError:
217 _have_threads = False
218else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000219
Bill Janssen98d19da2007-09-10 21:51:02 +0000220 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000221
Bill Janssen98d19da2007-09-10 21:51:02 +0000222 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000223
Bill Janssen98d19da2007-09-10 21:51:02 +0000224 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000225
Bill Janssen98d19da2007-09-10 21:51:02 +0000226 """A mildly complicated class, because we want it to work both
227 with and without the SSL wrapper around the socket connection, so
228 that we can test the STARTTLS functionality."""
229
230 def __init__(self, server, connsock):
231 self.server = server
232 self.running = False
233 self.sock = connsock
234 self.sock.setblocking(1)
235 self.sslconn = None
236 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000237 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000238
Bill Janssen934b16d2008-06-28 22:19:33 +0000239 def show_conn_details(self):
240 if self.server.certreqs == ssl.CERT_REQUIRED:
241 cert = self.sslconn.getpeercert()
242 if test_support.verbose and self.server.chatty:
243 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
244 cert_binary = self.sslconn.getpeercert(True)
245 if test_support.verbose and self.server.chatty:
246 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
247 cipher = self.sslconn.cipher()
248 if test_support.verbose and self.server.chatty:
249 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
250
Bill Janssen98d19da2007-09-10 21:51:02 +0000251 def wrap_conn (self):
252 try:
253 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
254 certfile=self.server.certificate,
255 ssl_version=self.server.protocol,
256 ca_certs=self.server.cacerts,
257 cert_reqs=self.server.certreqs)
258 except:
259 if self.server.chatty:
260 handle_error("\n server: bad connection attempt from " +
261 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000262 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000263 if not self.server.expect_bad_connects:
264 # here, we want to stop the server, because this shouldn't
265 # happen in the context of our test case
266 self.running = False
267 # normally, we'd just stop here, but for the test
268 # harness, we want to stop the server
269 self.server.stop()
270 return False
271
272 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000273 return True
274
275 def read(self):
276 if self.sslconn:
277 return self.sslconn.read()
278 else:
279 return self.sock.recv(1024)
280
281 def write(self, bytes):
282 if self.sslconn:
283 return self.sslconn.write(bytes)
284 else:
285 return self.sock.send(bytes)
286
287 def close(self):
288 if self.sslconn:
289 self.sslconn.close()
290 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000291 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000292
293 def run (self):
294 self.running = True
295 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000296 if isinstance(self.sock, ssl.SSLSocket):
297 self.sslconn = self.sock
298 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000299 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000300 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000301 while self.running:
302 try:
303 msg = self.read()
304 if not msg:
305 # eof, so quit this handler
306 self.running = False
307 self.close()
308 elif msg.strip() == 'over':
309 if test_support.verbose and self.server.connectionchatty:
310 sys.stdout.write(" server: client closed connection\n")
311 self.close()
312 return
313 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
314 if test_support.verbose and self.server.connectionchatty:
315 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
316 self.write("OK\n")
317 if not self.wrap_conn():
318 return
Bill Janssen39295c22008-08-12 16:31:21 +0000319 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
320 if test_support.verbose and self.server.connectionchatty:
321 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
322 self.write("OK\n")
323 self.sslconn.unwrap()
324 self.sslconn = None
325 if test_support.verbose and self.server.connectionchatty:
326 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000327 else:
328 if (test_support.verbose and
329 self.server.connectionchatty):
330 ctype = (self.sslconn and "encrypted") or "unencrypted"
331 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
332 % (repr(msg), ctype, repr(msg.lower()), ctype))
333 self.write(msg.lower())
334 except ssl.SSLError:
335 if self.server.chatty:
336 handle_error("Test server failure:\n")
337 self.close()
338 self.running = False
339 # normally, we'd just stop here, but for the test
340 # harness, we want to stop the server
341 self.server.stop()
342 except:
343 handle_error('')
344
Trent Nelsone41b0062008-04-08 23:47:30 +0000345 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000346 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000347 chatty=True, connectionchatty=False, starttls_server=False,
348 wrap_accepting_socket=False):
349
Bill Janssen98d19da2007-09-10 21:51:02 +0000350 if ssl_version is None:
351 ssl_version = ssl.PROTOCOL_TLSv1
352 if certreqs is None:
353 certreqs = ssl.CERT_NONE
354 self.certificate = certificate
355 self.protocol = ssl_version
356 self.certreqs = certreqs
357 self.cacerts = cacerts
358 self.expect_bad_connects = expect_bad_connects
359 self.chatty = chatty
360 self.connectionchatty = connectionchatty
361 self.starttls_server = starttls_server
362 self.sock = socket.socket()
363 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000364 if wrap_accepting_socket:
365 self.sock = ssl.wrap_socket(self.sock, server_side=True,
366 certfile=self.certificate,
367 cert_reqs = self.certreqs,
368 ca_certs = self.cacerts,
369 ssl_version = self.protocol)
370 if test_support.verbose and self.chatty:
371 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
372 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000373 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000374 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000375 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000376
377 def start (self, flag=None):
378 self.flag = flag
379 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000380
381 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000382 self.sock.settimeout(0.5)
383 self.sock.listen(5)
384 self.active = True
385 if self.flag:
386 # signal an event
387 self.flag.set()
388 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000389 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000390 newconn, connaddr = self.sock.accept()
391 if test_support.verbose and self.chatty:
392 sys.stdout.write(' server: new connection from '
393 + str(connaddr) + '\n')
394 handler = self.ConnectionHandler(self, newconn)
395 handler.start()
396 except socket.timeout:
397 pass
398 except KeyboardInterrupt:
399 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000400 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000401 if self.chatty:
402 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000403 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000404
Bill Janssen98d19da2007-09-10 21:51:02 +0000405 def stop (self):
406 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000407
Bill Janssen934b16d2008-06-28 22:19:33 +0000408 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000409
Bill Janssen934b16d2008-06-28 22:19:33 +0000410 class EchoServer (asyncore.dispatcher):
411
412 class ConnectionHandler (asyncore.dispatcher_with_send):
413
414 def __init__(self, conn, certfile):
415 asyncore.dispatcher_with_send.__init__(self, conn)
416 self.socket = ssl.wrap_socket(conn, server_side=True,
417 certfile=certfile,
418 do_handshake_on_connect=True)
419
420 def readable(self):
421 if isinstance(self.socket, ssl.SSLSocket):
422 while self.socket.pending() > 0:
423 self.handle_read_event()
424 return True
425
426 def handle_read(self):
427 data = self.recv(1024)
428 self.send(data.lower())
429
430 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000431 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000432 if test_support.verbose:
433 sys.stdout.write(" server: closed connection %s\n" % self.socket)
434
435 def handle_error(self):
436 raise
437
438 def __init__(self, certfile):
439 self.certfile = certfile
440 asyncore.dispatcher.__init__(self)
441 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
442 self.port = test_support.bind_port(self.socket)
443 self.listen(5)
444
445 def handle_accept(self):
446 sock_obj, addr = self.accept()
447 if test_support.verbose:
448 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
449 self.ConnectionHandler(sock_obj, self.certfile)
450
451 def handle_error(self):
452 raise
453
454 def __init__(self, certfile):
455 self.flag = None
456 self.active = False
457 self.server = self.EchoServer(certfile)
458 self.port = self.server.port
459 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000460 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000461
462 def __str__(self):
463 return "<%s %s>" % (self.__class__.__name__, self.server)
464
465 def start (self, flag=None):
466 self.flag = flag
467 threading.Thread.start(self)
468
469 def run (self):
470 self.active = True
471 if self.flag:
472 self.flag.set()
473 while self.active:
474 try:
475 asyncore.loop(1)
476 except:
477 pass
478
479 def stop (self):
480 self.active = False
481 self.server.close()
482
483 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000484
485 class HTTPSServer(HTTPServer):
486
487 def __init__(self, server_address, RequestHandlerClass, certfile):
488
489 HTTPServer.__init__(self, server_address, RequestHandlerClass)
490 # we assume the certfile contains both private key and certificate
491 self.certfile = certfile
492 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000493 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000494 self.allow_reuse_address = True
495
Bill Janssen934b16d2008-06-28 22:19:33 +0000496 def __str__(self):
497 return ('<%s %s:%s>' %
498 (self.__class__.__name__,
499 self.server_name,
500 self.server_port))
501
Bill Janssen296a59d2007-09-16 22:06:00 +0000502 def get_request (self):
503 # override this to wrap socket with SSL
504 sock, addr = self.socket.accept()
505 sslconn = ssl.wrap_socket(sock, server_side=True,
506 certfile=self.certfile)
507 return sslconn, addr
508
509 # The methods overridden below this are mainly so that we
510 # can run it in a thread and be able to stop it from another
511 # You probably wouldn't need them in other uses.
512
513 def server_activate(self):
514 # We want to run this in a thread for testing purposes,
515 # so we override this to set timeout, so that we get
516 # a chance to stop the server
517 self.socket.settimeout(0.5)
518 HTTPServer.server_activate(self)
519
520 def serve_forever(self):
521 # We want this to run in a thread, so we use a slightly
522 # modified version of "forever".
523 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000524 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000525 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000526 # We need to lock while handling the request.
527 # Another thread can close the socket after self.active
528 # has been checked and before the request is handled.
529 # This causes an exception when using the closed socket.
530 with self.active_lock:
531 if not self.active:
532 break
533 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000534 except socket.timeout:
535 pass
536 except KeyboardInterrupt:
537 self.server_close()
538 return
539 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000540 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
541 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000542 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000543
544 def server_close(self):
545 # Again, we want this to run in a thread, so we need to override
546 # close to clear the "active" flag, so that serve_forever() will
547 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000548 with self.active_lock:
549 HTTPServer.server_close(self)
550 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000551
552 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
553
554 # need to override translate_path to get a known root,
555 # instead of using os.curdir, since the test could be
556 # run from anywhere
557
558 server_version = "TestHTTPS/1.0"
559
560 root = None
561
562 def translate_path(self, path):
563 """Translate a /-separated PATH to the local filename syntax.
564
565 Components that mean special things to the local file system
566 (e.g. drive or directory names) are ignored. (XXX They should
567 probably be diagnosed.)
568
569 """
570 # abandon query parameters
571 path = urlparse.urlparse(path)[2]
572 path = os.path.normpath(urllib.unquote(path))
573 words = path.split('/')
574 words = filter(None, words)
575 path = self.root
576 for word in words:
577 drive, word = os.path.splitdrive(word)
578 head, word = os.path.split(word)
579 if word in self.root: continue
580 path = os.path.join(path, word)
581 return path
582
583 def log_message(self, format, *args):
584
585 # we override this to suppress logging unless "verbose"
586
587 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000588 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
589 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000590 self.server.server_port,
591 self.request.cipher(),
592 self.log_date_time_string(),
593 format%args))
594
595
Trent Nelsone41b0062008-04-08 23:47:30 +0000596 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000597 self.flag = None
598 self.active = False
599 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000600 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000601 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000602 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000603 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000604 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000605
606 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000607 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000608
609 def start (self, flag=None):
610 self.flag = flag
611 threading.Thread.start(self)
612
613 def run (self):
614 self.active = True
615 if self.flag:
616 self.flag.set()
617 self.server.serve_forever()
618 self.active = False
619
620 def stop (self):
621 self.active = False
622 self.server.server_close()
623
624
Bill Janssen98d19da2007-09-10 21:51:02 +0000625 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000626 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000627 certreqs=ssl.CERT_REQUIRED,
628 cacerts=CERTFILE, chatty=False)
629 flag = threading.Event()
630 server.start(flag)
631 # wait for it to start
632 flag.wait()
633 # try to connect
634 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000635 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000636 s = ssl.wrap_socket(socket.socket(),
637 certfile=certfile,
638 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000639 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000640 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000641 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000642 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000643 except socket.error, x:
644 if test_support.verbose:
645 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000646 else:
647 raise test_support.TestFailed(
648 "Use of invalid cert should have failed!")
649 finally:
650 server.stop()
651 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000652
Bill Janssen98d19da2007-09-10 21:51:02 +0000653 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
654 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000655 chatty=True, connectionchatty=False,
656 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000657
Trent Nelsone41b0062008-04-08 23:47:30 +0000658 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000659 certreqs=certreqs,
660 ssl_version=protocol,
661 cacerts=cacertsfile,
662 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000663 connectionchatty=connectionchatty,
664 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000665 flag = threading.Event()
666 server.start(flag)
667 # wait for it to start
668 flag.wait()
669 # try to connect
670 if client_protocol is None:
671 client_protocol = protocol
672 try:
673 try:
674 s = ssl.wrap_socket(socket.socket(),
675 certfile=client_certfile,
676 ca_certs=cacertsfile,
677 cert_reqs=certreqs,
678 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000679 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000680 except ssl.SSLError, x:
681 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
682 except Exception, x:
683 raise test_support.TestFailed("Unexpected exception: " + str(x))
684 else:
685 if connectionchatty:
686 if test_support.verbose:
687 sys.stdout.write(
688 " client: sending %s...\n" % (repr(indata)))
689 s.write(indata)
690 outdata = s.read()
691 if connectionchatty:
692 if test_support.verbose:
693 sys.stdout.write(" client: read %s\n" % repr(outdata))
694 if outdata != indata.lower():
695 raise test_support.TestFailed(
696 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
697 % (outdata[:min(len(outdata),20)], len(outdata),
698 indata[:min(len(indata),20)].lower(), len(indata)))
699 s.write("over\n")
700 if connectionchatty:
701 if test_support.verbose:
702 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000703 s.close()
704 finally:
705 server.stop()
706 server.join()
707
708 def tryProtocolCombo (server_protocol,
709 client_protocol,
710 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000711 certsreqs=None):
712
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000713 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000714 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000715
716 if certsreqs == ssl.CERT_NONE:
717 certtype = "CERT_NONE"
718 elif certsreqs == ssl.CERT_OPTIONAL:
719 certtype = "CERT_OPTIONAL"
720 elif certsreqs == ssl.CERT_REQUIRED:
721 certtype = "CERT_REQUIRED"
722 if test_support.verbose:
723 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
724 sys.stdout.write(formatstr %
725 (ssl.get_protocol_name(client_protocol),
726 ssl.get_protocol_name(server_protocol),
727 certtype))
728 try:
729 serverParamsTest(CERTFILE, server_protocol, certsreqs,
730 CERTFILE, CERTFILE, client_protocol, chatty=False)
731 except test_support.TestFailed:
732 if expectedToWork:
733 raise
734 else:
735 if not expectedToWork:
736 raise test_support.TestFailed(
737 "Client protocol %s succeeded with server protocol %s!"
738 % (ssl.get_protocol_name(client_protocol),
739 ssl.get_protocol_name(server_protocol)))
740
741
Bill Janssen934b16d2008-06-28 22:19:33 +0000742 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000743
744 def testRudeShutdown(self):
745
746 listener_ready = threading.Event()
747 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000748 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000749
750 # `listener` runs in a thread. It opens a socket listening on
751 # PORT, and sits in an accept() until the main thread connects.
752 # Then it rudely closes the socket, and sets Event `listener_gone`
753 # to let the main thread know the socket is gone.
754 def listener():
755 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000756 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000757 s.listen(5)
758 listener_ready.set()
759 s.accept()
760 s = None # reclaim the socket object, which also closes it
761 listener_gone.set()
762
763 def connector():
764 listener_ready.wait()
765 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000766 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000767 listener_gone.wait()
768 try:
769 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000770 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000771 pass
772 else:
773 raise test_support.TestFailed(
774 'connecting to closed SSL socket should have failed')
775
776 t = threading.Thread(target=listener)
777 t.start()
778 connector()
779 t.join()
780
781 def testEcho (self):
782
783 if test_support.verbose:
784 sys.stdout.write("\n")
785 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
786 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
787 chatty=True, connectionchatty=True)
788
789 def testReadCert(self):
790
791 if test_support.verbose:
792 sys.stdout.write("\n")
793 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000794 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000795 certreqs=ssl.CERT_NONE,
796 ssl_version=ssl.PROTOCOL_SSLv23,
797 cacerts=CERTFILE,
798 chatty=False)
799 flag = threading.Event()
800 server.start(flag)
801 # wait for it to start
802 flag.wait()
803 # try to connect
804 try:
805 try:
806 s = ssl.wrap_socket(socket.socket(),
807 certfile=CERTFILE,
808 ca_certs=CERTFILE,
809 cert_reqs=ssl.CERT_REQUIRED,
810 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000811 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000812 except ssl.SSLError, x:
813 raise test_support.TestFailed(
814 "Unexpected SSL error: " + str(x))
815 except Exception, x:
816 raise test_support.TestFailed(
817 "Unexpected exception: " + str(x))
818 else:
819 if not s:
820 raise test_support.TestFailed(
821 "Can't SSL-handshake with test server")
822 cert = s.getpeercert()
823 if not cert:
824 raise test_support.TestFailed(
825 "Can't get peer certificate.")
826 cipher = s.cipher()
827 if test_support.verbose:
828 sys.stdout.write(pprint.pformat(cert) + '\n')
829 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
830 if not cert.has_key('subject'):
831 raise test_support.TestFailed(
832 "No subject field in certificate: %s." %
833 pprint.pformat(cert))
834 if ((('organizationName', 'Python Software Foundation'),)
835 not in cert['subject']):
836 raise test_support.TestFailed(
837 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000838 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000839 s.close()
840 finally:
841 server.stop()
842 server.join()
843
844 def testNULLcert(self):
845 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
846 "nullcert.pem"))
847 def testMalformedCert(self):
848 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
849 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000850 def testWrongCert(self):
851 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
852 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000853 def testMalformedKey(self):
854 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
855 "badkey.pem"))
856
857 def testProtocolSSL2(self):
858 if test_support.verbose:
859 sys.stdout.write("\n")
860 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
861 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
862 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
863 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
864 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
865 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
866
867 def testProtocolSSL23(self):
868 if test_support.verbose:
869 sys.stdout.write("\n")
870 try:
871 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
872 except test_support.TestFailed, x:
873 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
874 if test_support.verbose:
875 sys.stdout.write(
876 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
877 % str(x))
878 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
879 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
880 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
881
882 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
883 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
884 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
885
886 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
887 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
888 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
889
890 def testProtocolSSL3(self):
891 if test_support.verbose:
892 sys.stdout.write("\n")
893 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
894 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
895 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
896 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
897 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
898 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
899
900 def testProtocolTLS1(self):
901 if test_support.verbose:
902 sys.stdout.write("\n")
903 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
904 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
905 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
906 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
907 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
908 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
909
910 def testSTARTTLS (self):
911
Bill Janssen39295c22008-08-12 16:31:21 +0000912 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000913
Trent Nelsone41b0062008-04-08 23:47:30 +0000914 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000915 ssl_version=ssl.PROTOCOL_TLSv1,
916 starttls_server=True,
917 chatty=True,
918 connectionchatty=True)
919 flag = threading.Event()
920 server.start(flag)
921 # wait for it to start
922 flag.wait()
923 # try to connect
924 wrapped = False
925 try:
926 try:
927 s = socket.socket()
928 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000929 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000930 except Exception, x:
931 raise test_support.TestFailed("Unexpected exception: " + str(x))
932 else:
933 if test_support.verbose:
934 sys.stdout.write("\n")
935 for indata in msgs:
936 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000937 sys.stdout.write(
938 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000939 if wrapped:
940 conn.write(indata)
941 outdata = conn.read()
942 else:
943 s.send(indata)
944 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +0000945 if (indata == "STARTTLS" and
946 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000947 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000948 sys.stdout.write(
949 " client: read %s from server, starting TLS...\n"
950 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000951 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000952 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +0000953 elif (indata == "ENDTLS" and
954 outdata.strip().lower().startswith("ok")):
955 if test_support.verbose:
956 sys.stdout.write(
957 " client: read %s from server, ending TLS...\n"
958 % repr(outdata))
959 s = conn.unwrap()
960 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000961 else:
962 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000963 sys.stdout.write(
964 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000965 if test_support.verbose:
966 sys.stdout.write(" client: closing connection.\n")
967 if wrapped:
968 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000969 else:
970 s.send("over\n")
971 s.close()
972 finally:
973 server.stop()
974 server.join()
975
Bill Janssen934b16d2008-06-28 22:19:33 +0000976 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000977
Bill Janssen934b16d2008-06-28 22:19:33 +0000978 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000979 flag = threading.Event()
980 server.start(flag)
981 # wait for it to start
982 flag.wait()
983 # try to connect
984 try:
985 if test_support.verbose:
986 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +0000987 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000988 d2 = ''
989 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +0000990 url = 'https://127.0.0.1:%d/%s' % (
991 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +0000992 f = urllib.urlopen(url)
993 dlen = f.info().getheader("content-length")
994 if dlen and (int(dlen) > 0):
995 d2 = f.read(int(dlen))
996 if test_support.verbose:
997 sys.stdout.write(
998 " client: read %d bytes from remote server '%s'\n"
999 % (len(d2), server))
1000 f.close()
1001 except:
1002 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1003 if test_support.verbose:
1004 sys.stdout.write('\n' + msg)
1005 raise test_support.TestFailed(msg)
1006 else:
1007 if not (d1 == d2):
1008 raise test_support.TestFailed(
1009 "Couldn't fetch data from HTTPS server")
1010 finally:
1011 server.stop()
1012 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001013
Bill Janssen934b16d2008-06-28 22:19:33 +00001014 def testWrappedAccept (self):
1015
1016 if test_support.verbose:
1017 sys.stdout.write("\n")
1018 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1019 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1020 chatty=True, connectionchatty=True,
1021 wrap_accepting_socket=True)
1022
1023
1024 def testAsyncoreServer (self):
1025
1026 indata = "TEST MESSAGE of mixed case\n"
1027
1028 if test_support.verbose:
1029 sys.stdout.write("\n")
1030 server = AsyncoreEchoServer(CERTFILE)
1031 flag = threading.Event()
1032 server.start(flag)
1033 # wait for it to start
1034 flag.wait()
1035 # try to connect
1036 try:
1037 try:
1038 s = ssl.wrap_socket(socket.socket())
1039 s.connect(('127.0.0.1', server.port))
1040 except ssl.SSLError, x:
1041 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1042 except Exception, x:
1043 raise test_support.TestFailed("Unexpected exception: " + str(x))
1044 else:
1045 if test_support.verbose:
1046 sys.stdout.write(
1047 " client: sending %s...\n" % (repr(indata)))
1048 s.write(indata)
1049 outdata = s.read()
1050 if test_support.verbose:
1051 sys.stdout.write(" client: read %s\n" % repr(outdata))
1052 if outdata != indata.lower():
1053 raise test_support.TestFailed(
1054 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1055 % (outdata[:min(len(outdata),20)], len(outdata),
1056 indata[:min(len(indata),20)].lower(), len(indata)))
1057 s.write("over\n")
1058 if test_support.verbose:
1059 sys.stdout.write(" client: closing connection.\n")
1060 s.close()
1061 finally:
1062 server.stop()
1063 # wait for server thread to end
1064 server.join()
1065
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001066
Bill Janssen61c001a2008-09-08 16:37:24 +00001067 def testAllRecvAndSendMethods(self):
1068
1069 if test_support.verbose:
1070 sys.stdout.write("\n")
1071
1072 server = ThreadedEchoServer(CERTFILE,
1073 certreqs=ssl.CERT_NONE,
1074 ssl_version=ssl.PROTOCOL_TLSv1,
1075 cacerts=CERTFILE,
1076 chatty=True,
1077 connectionchatty=False)
1078 flag = threading.Event()
1079 server.start(flag)
1080 # wait for it to start
1081 flag.wait()
1082 # try to connect
1083 try:
1084 s = ssl.wrap_socket(socket.socket(),
1085 server_side=False,
1086 certfile=CERTFILE,
1087 ca_certs=CERTFILE,
1088 cert_reqs=ssl.CERT_NONE,
1089 ssl_version=ssl.PROTOCOL_TLSv1)
1090 s.connect((HOST, server.port))
1091 except ssl.SSLError as x:
1092 raise support.TestFailed("Unexpected SSL error: " + str(x))
1093 except Exception as x:
1094 raise support.TestFailed("Unexpected exception: " + str(x))
1095 else:
1096 # helper methods for standardising recv* method signatures
1097 def _recv_into():
1098 b = bytearray("\0"*100)
1099 count = s.recv_into(b)
1100 return b[:count]
1101
1102 def _recvfrom_into():
1103 b = bytearray("\0"*100)
1104 count, addr = s.recvfrom_into(b)
1105 return b[:count]
1106
1107 # (name, method, whether to expect success, *args)
1108 send_methods = [
1109 ('send', s.send, True, []),
1110 ('sendto', s.sendto, False, ["some.address"]),
1111 ('sendall', s.sendall, True, []),
1112 ]
1113 recv_methods = [
1114 ('recv', s.recv, True, []),
1115 ('recvfrom', s.recvfrom, False, ["some.address"]),
1116 ('recv_into', _recv_into, True, []),
1117 ('recvfrom_into', _recvfrom_into, False, []),
1118 ]
1119 data_prefix = u"PREFIX_"
1120
1121 for meth_name, send_meth, expect_success, args in send_methods:
1122 indata = data_prefix + meth_name
1123 try:
1124 send_meth(indata.encode('ASCII', 'strict'), *args)
1125 outdata = s.read()
1126 outdata = outdata.decode('ASCII', 'strict')
1127 if outdata != indata.lower():
1128 raise support.TestFailed(
1129 "While sending with <<%s>> bad data "
1130 "<<%r>> (%d) received; "
1131 "expected <<%r>> (%d)\n" % (
1132 meth_name, outdata[:20], len(outdata),
1133 indata[:20], len(indata)
1134 )
1135 )
1136 except ValueError as e:
1137 if expect_success:
1138 raise support.TestFailed(
1139 "Failed to send with method <<%s>>; "
1140 "expected to succeed.\n" % (meth_name,)
1141 )
1142 if not str(e).startswith(meth_name):
1143 raise support.TestFailed(
1144 "Method <<%s>> failed with unexpected "
1145 "exception message: %s\n" % (
1146 meth_name, e
1147 )
1148 )
1149
1150 for meth_name, recv_meth, expect_success, args in recv_methods:
1151 indata = data_prefix + meth_name
1152 try:
1153 s.send(indata.encode('ASCII', 'strict'))
1154 outdata = recv_meth(*args)
1155 outdata = outdata.decode('ASCII', 'strict')
1156 if outdata != indata.lower():
1157 raise support.TestFailed(
1158 "While receiving with <<%s>> bad data "
1159 "<<%r>> (%d) received; "
1160 "expected <<%r>> (%d)\n" % (
1161 meth_name, outdata[:20], len(outdata),
1162 indata[:20], len(indata)
1163 )
1164 )
1165 except ValueError as e:
1166 if expect_success:
1167 raise support.TestFailed(
1168 "Failed to receive with method <<%s>>; "
1169 "expected to succeed.\n" % (meth_name,)
1170 )
1171 if not str(e).startswith(meth_name):
1172 raise support.TestFailed(
1173 "Method <<%s>> failed with unexpected "
1174 "exception message: %s\n" % (
1175 meth_name, e
1176 )
1177 )
1178 # consume data
1179 s.read()
1180
1181 s.write("over\n".encode("ASCII", "strict"))
1182 s.close()
1183 finally:
1184 server.stop()
1185 server.join()
1186
1187
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001188def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001189 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001190 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001191
Trent Nelsone41b0062008-04-08 23:47:30 +00001192 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001193 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001194 "keycert.pem")
1195 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1196 os.path.dirname(__file__) or os.curdir,
1197 "https_svn_python_org_root.pem")
1198
1199 if (not os.path.exists(CERTFILE) or
1200 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001201 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001202
Bill Janssen934b16d2008-06-28 22:19:33 +00001203 TESTPORT = test_support.find_unused_port()
1204 if not TESTPORT:
1205 raise test_support.TestFailed("Can't find open port to test servers on!")
1206
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001207 tests = [BasicTests]
1208
Bill Janssen296a59d2007-09-16 22:06:00 +00001209 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001210 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001211
Bill Janssen98d19da2007-09-10 21:51:02 +00001212 if _have_threads:
1213 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001214 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001215 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001216
Bill Janssen98d19da2007-09-10 21:51:02 +00001217 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001218
Bill Janssen98d19da2007-09-10 21:51:02 +00001219 if _have_threads:
1220 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001221
1222if __name__ == "__main__":
1223 test_main()