blob: feb6f50eb4a04da3d5856a9285c8a75b1dba2b25 [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
Antoine Pitroub558f172010-04-23 23:25:45 +000010import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000011import os
Antoine Pitroub558f172010-04-23 23:25:45 +000012import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000014import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import traceback
Antoine Pitroudfb299b2010-04-23 22:54:59 +000016import weakref
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000017
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
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000037
38class BasicTests(unittest.TestCase):
39
Bill Jansseneb257ac2008-09-29 18:56:38 +000040 def testSimpleSSLwrap(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000041 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000042 try:
43 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
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
49 try:
50 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
51 except IOError, e:
52 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
53 pass
54 else:
55 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000056
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000057 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000058 if not test_support.is_resource_enabled('network'):
59 return
Bill Janssen296a59d2007-09-16 22:06:00 +000060 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
61 cert_reqs=ssl.CERT_NONE)
62 s.connect(("svn.python.org", 443))
63 c = s.getpeercert()
64 if c:
Antoine Pitroudb187842010-04-27 10:32:58 +000065 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +000066 s.close()
67
68 # this should fail because we have no verification certs
69 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
70 cert_reqs=ssl.CERT_REQUIRED)
71 try:
72 s.connect(("svn.python.org", 443))
73 except ssl.SSLError:
74 pass
75 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000076 s.close()
77
Bill Janssen98d19da2007-09-10 21:51:02 +000078 def testCrucialConstants(self):
79 ssl.PROTOCOL_SSLv2
80 ssl.PROTOCOL_SSLv23
81 ssl.PROTOCOL_SSLv3
82 ssl.PROTOCOL_TLSv1
83 ssl.CERT_NONE
84 ssl.CERT_OPTIONAL
85 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000086
Bill Janssen98d19da2007-09-10 21:51:02 +000087 def testRAND(self):
88 v = ssl.RAND_status()
89 if test_support.verbose:
90 sys.stdout.write("\n RAND_status is %d (%s)\n"
91 % (v, (v and "sufficient randomness") or
92 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000093 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000094 ssl.RAND_egd(1)
95 except TypeError:
96 pass
Guido van Rossume4729332007-08-26 19:35:09 +000097 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000098 print "didn't raise TypeError"
99 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000100
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 def testParseCert(self):
102 # note that this uses an 'unofficial' function in _ssl.c,
103 # provided solely for this test, to exercise the certificate
104 # parsing code
105 p = ssl._ssl._test_decode_cert(CERTFILE, False)
106 if test_support.verbose:
107 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000108
Bill Janssen296a59d2007-09-16 22:06:00 +0000109 def testDERtoPEM(self):
110
111 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
112 d1 = ssl.PEM_cert_to_DER_cert(pem)
113 p2 = ssl.DER_cert_to_PEM_cert(d1)
114 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitroudb187842010-04-27 10:32:58 +0000115 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +0000116 if not p2.startswith(ssl.PEM_HEADER + '\n'):
117 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
118 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
119 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000120
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000121 def test_openssl_version(self):
122 n = ssl.OPENSSL_VERSION_NUMBER
123 t = ssl.OPENSSL_VERSION_INFO
124 s = ssl.OPENSSL_VERSION
125 self.assertIsInstance(n, (int, long))
126 self.assertIsInstance(t, tuple)
127 self.assertIsInstance(s, str)
128 # Some sanity checks follow
129 # >= 0.9
130 self.assertGreaterEqual(n, 0x900000)
131 # < 2.0
132 self.assertLess(n, 0x20000000)
133 major, minor, fix, patch, status = t
134 self.assertGreaterEqual(major, 0)
135 self.assertLess(major, 2)
136 self.assertGreaterEqual(minor, 0)
137 self.assertLess(minor, 256)
138 self.assertGreaterEqual(fix, 0)
139 self.assertLess(fix, 256)
140 self.assertGreaterEqual(patch, 0)
141 self.assertLessEqual(patch, 26)
142 self.assertGreaterEqual(status, 0)
143 self.assertLessEqual(status, 15)
144 # Version string as returned by OpenSSL, the format might change
145 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
146 (s, t))
147
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000148 def test_ciphers(self):
149 if not test_support.is_resource_enabled('network'):
150 return
151 remote = ("svn.python.org", 443)
152 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
153 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
154 s.connect(remote)
155 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
156 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
157 s.connect(remote)
158 # Error checking occurs when connecting, because the SSL context
159 # isn't created before.
160 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
161 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
162 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
163 s.connect(remote)
164
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000165 @test_support.cpython_only
166 def test_refcycle(self):
167 # Issue #7943: an SSL object doesn't create reference cycles with
168 # itself.
169 s = socket.socket(socket.AF_INET)
170 ss = ssl.wrap_socket(s)
171 wr = weakref.ref(ss)
172 del ss
173 self.assertEqual(wr(), None)
174
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000175
Bill Janssen934b16d2008-06-28 22:19:33 +0000176class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000177
178 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000179 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
180 cert_reqs=ssl.CERT_NONE)
181 s.connect(("svn.python.org", 443))
182 c = s.getpeercert()
183 if c:
Antoine Pitroudb187842010-04-27 10:32:58 +0000184 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000185 s.close()
186
187 # this should fail because we have no verification certs
188 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
189 cert_reqs=ssl.CERT_REQUIRED)
190 try:
191 s.connect(("svn.python.org", 443))
192 except ssl.SSLError:
193 pass
194 finally:
195 s.close()
196
197 # this should succeed because we specify the root cert
198 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
199 cert_reqs=ssl.CERT_REQUIRED,
200 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
201 try:
202 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000203 finally:
204 s.close()
205
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000206 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
207 def test_makefile_close(self):
208 # Issue #5238: creating a file-like object with makefile() shouldn't
209 # delay closing the underlying "real socket" (here tested with its
210 # file descriptor, hence skipping the test under Windows).
211 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
212 ss.connect(("svn.python.org", 443))
213 fd = ss.fileno()
214 f = ss.makefile()
215 f.close()
216 # The fd is still open
217 os.read(fd, 0)
218 # Closing the SSL socket should close the fd too
219 ss.close()
220 gc.collect()
221 with self.assertRaises(OSError) as e:
222 os.read(fd, 0)
223 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000224
225 def testNonBlockingHandshake(self):
226 s = socket.socket(socket.AF_INET)
227 s.connect(("svn.python.org", 443))
228 s.setblocking(False)
229 s = ssl.wrap_socket(s,
230 cert_reqs=ssl.CERT_NONE,
231 do_handshake_on_connect=False)
232 count = 0
233 while True:
234 try:
235 count += 1
236 s.do_handshake()
237 break
238 except ssl.SSLError, err:
239 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
240 select.select([s], [], [])
241 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
242 select.select([], [s], [])
243 else:
244 raise
245 s.close()
246 if test_support.verbose:
247 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
248
Bill Janssen296a59d2007-09-16 22:06:00 +0000249 def testFetchServerCert(self):
250
251 pem = ssl.get_server_certificate(("svn.python.org", 443))
252 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000253 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000254
255 try:
256 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
257 except ssl.SSLError:
258 #should fail
259 pass
260 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000261 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000262
263 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
264 if not pem:
Antoine Pitroudb187842010-04-27 10:32:58 +0000265 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000266 if test_support.verbose:
267 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
268
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000269 def test_algorithms(self):
270 # Issue #8484: all algorithms should be available when verifying a
271 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000272 # SHA256 was added in OpenSSL 0.9.8
273 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
274 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000275 # NOTE: https://sha256.tbs-internet.com is another possible test host
276 remote = ("sha2.hboeck.de", 443)
277 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
278 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
279 cert_reqs=ssl.CERT_REQUIRED,
280 ca_certs=sha256_cert,)
281 with test_support.transient_internet():
282 try:
283 s.connect(remote)
284 if test_support.verbose:
285 sys.stdout.write("\nCipher with %r is %r\n" %
286 (remote, s.cipher()))
287 sys.stdout.write("Certificate is:\n%s\n" %
288 pprint.pformat(s.getpeercert()))
289 finally:
290 s.close()
291
Bill Janssen296a59d2007-09-16 22:06:00 +0000292
Bill Janssen98d19da2007-09-10 21:51:02 +0000293try:
294 import threading
295except ImportError:
296 _have_threads = False
297else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000298
Bill Janssen98d19da2007-09-10 21:51:02 +0000299 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000300
Bill Janssen98d19da2007-09-10 21:51:02 +0000301 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000302
Bill Janssen98d19da2007-09-10 21:51:02 +0000303 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000304
Bill Janssen98d19da2007-09-10 21:51:02 +0000305 """A mildly complicated class, because we want it to work both
306 with and without the SSL wrapper around the socket connection, so
307 that we can test the STARTTLS functionality."""
308
309 def __init__(self, server, connsock):
310 self.server = server
311 self.running = False
312 self.sock = connsock
313 self.sock.setblocking(1)
314 self.sslconn = None
315 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000316 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000317
Bill Janssen934b16d2008-06-28 22:19:33 +0000318 def show_conn_details(self):
319 if self.server.certreqs == ssl.CERT_REQUIRED:
320 cert = self.sslconn.getpeercert()
321 if test_support.verbose and self.server.chatty:
322 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
323 cert_binary = self.sslconn.getpeercert(True)
324 if test_support.verbose and self.server.chatty:
325 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
326 cipher = self.sslconn.cipher()
327 if test_support.verbose and self.server.chatty:
328 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
329
Bill Janssen98d19da2007-09-10 21:51:02 +0000330 def wrap_conn (self):
331 try:
332 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
333 certfile=self.server.certificate,
334 ssl_version=self.server.protocol,
335 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000336 cert_reqs=self.server.certreqs,
337 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000338 except ssl.SSLError:
339 # XXX Various errors can have happened here, for example
340 # a mismatching protocol version, an invalid certificate,
341 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000342 if self.server.chatty:
343 handle_error("\n server: bad connection attempt from " +
344 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000345 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000346 self.running = False
347 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000348 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000349 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000350 return True
351
352 def read(self):
353 if self.sslconn:
354 return self.sslconn.read()
355 else:
356 return self.sock.recv(1024)
357
358 def write(self, bytes):
359 if self.sslconn:
360 return self.sslconn.write(bytes)
361 else:
362 return self.sock.send(bytes)
363
364 def close(self):
365 if self.sslconn:
366 self.sslconn.close()
367 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000368 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000369
370 def run (self):
371 self.running = True
372 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000373 if isinstance(self.sock, ssl.SSLSocket):
374 self.sslconn = self.sock
375 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000376 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000377 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000378 while self.running:
379 try:
380 msg = self.read()
381 if not msg:
382 # eof, so quit this handler
383 self.running = False
384 self.close()
385 elif msg.strip() == 'over':
386 if test_support.verbose and self.server.connectionchatty:
387 sys.stdout.write(" server: client closed connection\n")
388 self.close()
389 return
390 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
391 if test_support.verbose and self.server.connectionchatty:
392 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
393 self.write("OK\n")
394 if not self.wrap_conn():
395 return
Bill Janssen39295c22008-08-12 16:31:21 +0000396 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
397 if test_support.verbose and self.server.connectionchatty:
398 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
399 self.write("OK\n")
400 self.sslconn.unwrap()
401 self.sslconn = None
402 if test_support.verbose and self.server.connectionchatty:
403 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000404 else:
405 if (test_support.verbose and
406 self.server.connectionchatty):
407 ctype = (self.sslconn and "encrypted") or "unencrypted"
408 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
409 % (repr(msg), ctype, repr(msg.lower()), ctype))
410 self.write(msg.lower())
411 except ssl.SSLError:
412 if self.server.chatty:
413 handle_error("Test server failure:\n")
414 self.close()
415 self.running = False
416 # normally, we'd just stop here, but for the test
417 # harness, we want to stop the server
418 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000419
Trent Nelsone41b0062008-04-08 23:47:30 +0000420 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000421 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000422 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000423 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000424
Bill Janssen98d19da2007-09-10 21:51:02 +0000425 if ssl_version is None:
426 ssl_version = ssl.PROTOCOL_TLSv1
427 if certreqs is None:
428 certreqs = ssl.CERT_NONE
429 self.certificate = certificate
430 self.protocol = ssl_version
431 self.certreqs = certreqs
432 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000433 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000434 self.chatty = chatty
435 self.connectionchatty = connectionchatty
436 self.starttls_server = starttls_server
437 self.sock = socket.socket()
438 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000439 if wrap_accepting_socket:
440 self.sock = ssl.wrap_socket(self.sock, server_side=True,
441 certfile=self.certificate,
442 cert_reqs = self.certreqs,
443 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000444 ssl_version = self.protocol,
445 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000446 if test_support.verbose and self.chatty:
447 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
448 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000449 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000450 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000451 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000452
453 def start (self, flag=None):
454 self.flag = flag
455 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000456
457 def run (self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000458 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000459 self.sock.listen(5)
460 self.active = True
461 if self.flag:
462 # signal an event
463 self.flag.set()
464 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000465 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000466 newconn, connaddr = self.sock.accept()
467 if test_support.verbose and self.chatty:
468 sys.stdout.write(' server: new connection from '
469 + str(connaddr) + '\n')
470 handler = self.ConnectionHandler(self, newconn)
471 handler.start()
472 except socket.timeout:
473 pass
474 except KeyboardInterrupt:
475 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000476 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000477
Bill Janssen98d19da2007-09-10 21:51:02 +0000478 def stop (self):
479 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000480
Bill Janssen934b16d2008-06-28 22:19:33 +0000481 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000482
Bill Janssen934b16d2008-06-28 22:19:33 +0000483 class EchoServer (asyncore.dispatcher):
484
485 class ConnectionHandler (asyncore.dispatcher_with_send):
486
487 def __init__(self, conn, certfile):
488 asyncore.dispatcher_with_send.__init__(self, conn)
489 self.socket = ssl.wrap_socket(conn, server_side=True,
490 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000491 do_handshake_on_connect=False)
492 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000493
494 def readable(self):
495 if isinstance(self.socket, ssl.SSLSocket):
496 while self.socket.pending() > 0:
497 self.handle_read_event()
498 return True
499
Antoine Pitroufc69af12010-04-24 20:04:58 +0000500 def _do_ssl_handshake(self):
501 try:
502 self.socket.do_handshake()
503 except ssl.SSLError, err:
504 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
505 ssl.SSL_ERROR_WANT_WRITE):
506 return
507 elif err.args[0] == ssl.SSL_ERROR_EOF:
508 return self.handle_close()
509 raise
510 except socket.error, err:
511 if err.args[0] == errno.ECONNABORTED:
512 return self.handle_close()
513 else:
514 self._ssl_accepting = False
515
Bill Janssen934b16d2008-06-28 22:19:33 +0000516 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000517 if self._ssl_accepting:
518 self._do_ssl_handshake()
519 else:
520 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000521 if data and data.strip() != 'over':
522 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000523
524 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000525 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000526 if test_support.verbose:
527 sys.stdout.write(" server: closed connection %s\n" % self.socket)
528
529 def handle_error(self):
530 raise
531
532 def __init__(self, certfile):
533 self.certfile = certfile
534 asyncore.dispatcher.__init__(self)
535 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
536 self.port = test_support.bind_port(self.socket)
537 self.listen(5)
538
539 def handle_accept(self):
540 sock_obj, addr = self.accept()
541 if test_support.verbose:
542 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
543 self.ConnectionHandler(sock_obj, self.certfile)
544
545 def handle_error(self):
546 raise
547
548 def __init__(self, certfile):
549 self.flag = None
550 self.active = False
551 self.server = self.EchoServer(certfile)
552 self.port = self.server.port
553 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000554 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000555
556 def __str__(self):
557 return "<%s %s>" % (self.__class__.__name__, self.server)
558
559 def start (self, flag=None):
560 self.flag = flag
561 threading.Thread.start(self)
562
563 def run (self):
564 self.active = True
565 if self.flag:
566 self.flag.set()
567 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000568 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000569
570 def stop (self):
571 self.active = False
572 self.server.close()
573
574 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000575
576 class HTTPSServer(HTTPServer):
577
578 def __init__(self, server_address, RequestHandlerClass, certfile):
579
580 HTTPServer.__init__(self, server_address, RequestHandlerClass)
581 # we assume the certfile contains both private key and certificate
582 self.certfile = certfile
583 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000584 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000585 self.allow_reuse_address = True
586
Bill Janssen934b16d2008-06-28 22:19:33 +0000587 def __str__(self):
588 return ('<%s %s:%s>' %
589 (self.__class__.__name__,
590 self.server_name,
591 self.server_port))
592
Bill Janssen296a59d2007-09-16 22:06:00 +0000593 def get_request (self):
594 # override this to wrap socket with SSL
595 sock, addr = self.socket.accept()
596 sslconn = ssl.wrap_socket(sock, server_side=True,
597 certfile=self.certfile)
598 return sslconn, addr
599
Bill Janssen296a59d2007-09-16 22:06:00 +0000600 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
601
602 # need to override translate_path to get a known root,
603 # instead of using os.curdir, since the test could be
604 # run from anywhere
605
606 server_version = "TestHTTPS/1.0"
607
608 root = None
609
610 def translate_path(self, path):
611 """Translate a /-separated PATH to the local filename syntax.
612
613 Components that mean special things to the local file system
614 (e.g. drive or directory names) are ignored. (XXX They should
615 probably be diagnosed.)
616
617 """
618 # abandon query parameters
619 path = urlparse.urlparse(path)[2]
620 path = os.path.normpath(urllib.unquote(path))
621 words = path.split('/')
622 words = filter(None, words)
623 path = self.root
624 for word in words:
625 drive, word = os.path.splitdrive(word)
626 head, word = os.path.split(word)
627 if word in self.root: continue
628 path = os.path.join(path, word)
629 return path
630
631 def log_message(self, format, *args):
632
633 # we override this to suppress logging unless "verbose"
634
635 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000636 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
637 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000638 self.server.server_port,
639 self.request.cipher(),
640 self.log_date_time_string(),
641 format%args))
642
643
Trent Nelsone41b0062008-04-08 23:47:30 +0000644 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000645 self.flag = None
646 self.active = False
647 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
648 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000649 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
650 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000651 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000652 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000653
654 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000655 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000656
657 def start (self, flag=None):
658 self.flag = flag
659 threading.Thread.start(self)
660
661 def run (self):
662 self.active = True
663 if self.flag:
664 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000665 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000666 self.active = False
667
668 def stop (self):
669 self.active = False
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000670 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000671
672
Bill Janssen98d19da2007-09-10 21:51:02 +0000673 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000674 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000675 certreqs=ssl.CERT_REQUIRED,
676 cacerts=CERTFILE, chatty=False)
677 flag = threading.Event()
678 server.start(flag)
679 # wait for it to start
680 flag.wait()
681 # try to connect
682 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000683 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000684 s = ssl.wrap_socket(socket.socket(),
685 certfile=certfile,
686 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000687 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000688 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000689 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000690 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000691 except socket.error, x:
692 if test_support.verbose:
693 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000694 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000695 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000696 finally:
697 server.stop()
698 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000699
Bill Janssen98d19da2007-09-10 21:51:02 +0000700 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
701 client_certfile, client_protocol=None, indata="FOO\n",
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000702 ciphers=None, chatty=True, connectionchatty=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000703 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000704
Trent Nelsone41b0062008-04-08 23:47:30 +0000705 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000706 certreqs=certreqs,
707 ssl_version=protocol,
708 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000709 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000710 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000711 connectionchatty=connectionchatty,
712 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000713 flag = threading.Event()
714 server.start(flag)
715 # wait for it to start
716 flag.wait()
717 # try to connect
718 if client_protocol is None:
719 client_protocol = protocol
720 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000721 s = ssl.wrap_socket(socket.socket(),
722 certfile=client_certfile,
723 ca_certs=cacertsfile,
724 ciphers=ciphers,
725 cert_reqs=certreqs,
726 ssl_version=client_protocol)
727 s.connect((HOST, server.port))
728 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000729 if connectionchatty:
730 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000731 sys.stdout.write(
732 " client: sending %s...\n" % (repr(arg)))
733 s.write(arg)
734 outdata = s.read()
735 if connectionchatty:
736 if test_support.verbose:
737 sys.stdout.write(" client: read %s\n" % repr(outdata))
738 if outdata != indata.lower():
739 self.fail(
740 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
741 % (outdata[:min(len(outdata),20)], len(outdata),
742 indata[:min(len(indata),20)].lower(), len(indata)))
743 s.write("over\n")
744 if connectionchatty:
745 if test_support.verbose:
746 sys.stdout.write(" client: closing connection.\n")
747 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000748 finally:
749 server.stop()
750 server.join()
751
752 def tryProtocolCombo (server_protocol,
753 client_protocol,
754 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000755 certsreqs=None):
756
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000757 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000758 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000759
760 if certsreqs == ssl.CERT_NONE:
761 certtype = "CERT_NONE"
762 elif certsreqs == ssl.CERT_OPTIONAL:
763 certtype = "CERT_OPTIONAL"
764 elif certsreqs == ssl.CERT_REQUIRED:
765 certtype = "CERT_REQUIRED"
766 if test_support.verbose:
767 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
768 sys.stdout.write(formatstr %
769 (ssl.get_protocol_name(client_protocol),
770 ssl.get_protocol_name(server_protocol),
771 certtype))
772 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000773 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
774 # will send an SSLv3 hello (rather than SSLv2) starting from
775 # OpenSSL 1.0.0 (see issue #8322).
Bill Janssen98d19da2007-09-10 21:51:02 +0000776 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000777 CERTFILE, CERTFILE, client_protocol,
778 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000779 # Protocol mismatch can result in either an SSLError, or a
780 # "Connection reset by peer" error.
781 except ssl.SSLError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000782 if expectedToWork:
783 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000784 except socket.error as e:
785 if expectedToWork or e.errno != errno.ECONNRESET:
786 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000787 else:
788 if not expectedToWork:
Antoine Pitroudb187842010-04-27 10:32:58 +0000789 self.fail(
Bill Janssen98d19da2007-09-10 21:51:02 +0000790 "Client protocol %s succeeded with server protocol %s!"
791 % (ssl.get_protocol_name(client_protocol),
792 ssl.get_protocol_name(server_protocol)))
793
794
Bill Janssen934b16d2008-06-28 22:19:33 +0000795 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000796
797 def testRudeShutdown(self):
798
799 listener_ready = threading.Event()
800 listener_gone = threading.Event()
801
Antoine Pitrou150acda2010-04-27 08:40:51 +0000802 s = socket.socket()
803 port = test_support.bind_port(s, HOST)
804
805 # `listener` runs in a thread. It sits in an accept() until
806 # the main thread connects. Then it rudely closes the socket,
807 # and sets Event `listener_gone` to let the main thread know
808 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000809 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000810 s.listen(5)
811 listener_ready.set()
812 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000813 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000814 listener_gone.set()
815
816 def connector():
817 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000818 c = socket.socket()
819 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000820 listener_gone.wait()
821 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000822 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000823 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000824 pass
825 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000826 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000827
828 t = threading.Thread(target=listener)
829 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000830 try:
831 connector()
832 finally:
833 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000834
835 def testEcho (self):
836
837 if test_support.verbose:
838 sys.stdout.write("\n")
839 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
840 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
841 chatty=True, connectionchatty=True)
842
843 def testReadCert(self):
844
845 if test_support.verbose:
846 sys.stdout.write("\n")
847 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000848 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000849 certreqs=ssl.CERT_NONE,
850 ssl_version=ssl.PROTOCOL_SSLv23,
851 cacerts=CERTFILE,
852 chatty=False)
853 flag = threading.Event()
854 server.start(flag)
855 # wait for it to start
856 flag.wait()
857 # try to connect
858 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000859 s = ssl.wrap_socket(socket.socket(),
860 certfile=CERTFILE,
861 ca_certs=CERTFILE,
862 cert_reqs=ssl.CERT_REQUIRED,
863 ssl_version=ssl.PROTOCOL_SSLv23)
864 s.connect((HOST, server.port))
865 cert = s.getpeercert()
866 self.assertTrue(cert, "Can't get peer certificate.")
867 cipher = s.cipher()
868 if test_support.verbose:
869 sys.stdout.write(pprint.pformat(cert) + '\n')
870 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
871 if 'subject' not in cert:
872 self.fail("No subject field in certificate: %s." %
873 pprint.pformat(cert))
874 if ((('organizationName', 'Python Software Foundation'),)
875 not in cert['subject']):
876 self.fail(
877 "Missing or invalid 'organizationName' field in certificate subject; "
878 "should be 'Python Software Foundation'.")
879 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000880 finally:
881 server.stop()
882 server.join()
883
884 def testNULLcert(self):
885 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
886 "nullcert.pem"))
887 def testMalformedCert(self):
888 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
889 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000890 def testWrongCert(self):
891 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
892 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000893 def testMalformedKey(self):
894 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
895 "badkey.pem"))
896
897 def testProtocolSSL2(self):
898 if test_support.verbose:
899 sys.stdout.write("\n")
900 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
901 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
902 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
903 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
904 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
905 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
906
907 def testProtocolSSL23(self):
908 if test_support.verbose:
909 sys.stdout.write("\n")
910 try:
911 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000912 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000913 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
914 if test_support.verbose:
915 sys.stdout.write(
916 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
917 % str(x))
918 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
919 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
920 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
921
922 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
923 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
924 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
925
926 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
927 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
928 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
929
930 def testProtocolSSL3(self):
931 if test_support.verbose:
932 sys.stdout.write("\n")
933 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
934 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
935 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
936 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
937 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
938 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
939
940 def testProtocolTLS1(self):
941 if test_support.verbose:
942 sys.stdout.write("\n")
943 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
944 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
945 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
946 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
947 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
948 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
949
950 def testSTARTTLS (self):
951
Bill Janssen39295c22008-08-12 16:31:21 +0000952 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000953
Trent Nelsone41b0062008-04-08 23:47:30 +0000954 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000955 ssl_version=ssl.PROTOCOL_TLSv1,
956 starttls_server=True,
957 chatty=True,
958 connectionchatty=True)
959 flag = threading.Event()
960 server.start(flag)
961 # wait for it to start
962 flag.wait()
963 # try to connect
964 wrapped = False
965 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000966 s = socket.socket()
967 s.setblocking(1)
968 s.connect((HOST, server.port))
969 if test_support.verbose:
970 sys.stdout.write("\n")
971 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000972 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000973 sys.stdout.write(
974 " client: sending %s...\n" % repr(indata))
975 if wrapped:
976 conn.write(indata)
977 outdata = conn.read()
978 else:
979 s.send(indata)
980 outdata = s.recv(1024)
981 if (indata == "STARTTLS" and
982 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000983 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000984 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +0000985 " client: read %s from server, starting TLS...\n"
986 % repr(outdata))
987 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
988 wrapped = True
989 elif (indata == "ENDTLS" and
990 outdata.strip().lower().startswith("ok")):
991 if test_support.verbose:
992 sys.stdout.write(
993 " client: read %s from server, ending TLS...\n"
994 % repr(outdata))
995 s = conn.unwrap()
996 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000997 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000998 if test_support.verbose:
999 sys.stdout.write(
1000 " client: read %s from server\n" % repr(outdata))
1001 if test_support.verbose:
1002 sys.stdout.write(" client: closing connection.\n")
1003 if wrapped:
1004 conn.write("over\n")
1005 else:
1006 s.send("over\n")
1007 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001008 finally:
1009 server.stop()
1010 server.join()
1011
Bill Janssen934b16d2008-06-28 22:19:33 +00001012 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001013
Bill Janssen934b16d2008-06-28 22:19:33 +00001014 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001015 flag = threading.Event()
1016 server.start(flag)
1017 # wait for it to start
1018 flag.wait()
1019 # try to connect
1020 try:
1021 if test_support.verbose:
1022 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001023 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001024 d2 = ''
1025 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001026 url = 'https://127.0.0.1:%d/%s' % (
1027 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001028 with test_support.check_py3k_warnings():
1029 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001030 dlen = f.info().getheader("content-length")
1031 if dlen and (int(dlen) > 0):
1032 d2 = f.read(int(dlen))
1033 if test_support.verbose:
1034 sys.stdout.write(
1035 " client: read %d bytes from remote server '%s'\n"
1036 % (len(d2), server))
1037 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001038 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001039 finally:
1040 server.stop()
1041 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001042
Bill Janssen934b16d2008-06-28 22:19:33 +00001043 def testWrappedAccept (self):
1044
1045 if test_support.verbose:
1046 sys.stdout.write("\n")
1047 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1048 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1049 chatty=True, connectionchatty=True,
1050 wrap_accepting_socket=True)
1051
1052
1053 def testAsyncoreServer (self):
1054
1055 indata = "TEST MESSAGE of mixed case\n"
1056
1057 if test_support.verbose:
1058 sys.stdout.write("\n")
1059 server = AsyncoreEchoServer(CERTFILE)
1060 flag = threading.Event()
1061 server.start(flag)
1062 # wait for it to start
1063 flag.wait()
1064 # try to connect
1065 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001066 s = ssl.wrap_socket(socket.socket())
1067 s.connect(('127.0.0.1', server.port))
1068 if test_support.verbose:
1069 sys.stdout.write(
1070 " client: sending %s...\n" % (repr(indata)))
1071 s.write(indata)
1072 outdata = s.read()
1073 if test_support.verbose:
1074 sys.stdout.write(" client: read %s\n" % repr(outdata))
1075 if outdata != indata.lower():
1076 self.fail(
1077 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1078 % (outdata[:min(len(outdata),20)], len(outdata),
1079 indata[:min(len(indata),20)].lower(), len(indata)))
1080 s.write("over\n")
1081 if test_support.verbose:
1082 sys.stdout.write(" client: closing connection.\n")
1083 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001084 finally:
1085 server.stop()
1086 # wait for server thread to end
1087 server.join()
1088
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001089
Bill Janssen61c001a2008-09-08 16:37:24 +00001090 def testAllRecvAndSendMethods(self):
1091
1092 if test_support.verbose:
1093 sys.stdout.write("\n")
1094
1095 server = ThreadedEchoServer(CERTFILE,
1096 certreqs=ssl.CERT_NONE,
1097 ssl_version=ssl.PROTOCOL_TLSv1,
1098 cacerts=CERTFILE,
1099 chatty=True,
1100 connectionchatty=False)
1101 flag = threading.Event()
1102 server.start(flag)
1103 # wait for it to start
1104 flag.wait()
1105 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001106 s = ssl.wrap_socket(socket.socket(),
1107 server_side=False,
1108 certfile=CERTFILE,
1109 ca_certs=CERTFILE,
1110 cert_reqs=ssl.CERT_NONE,
1111 ssl_version=ssl.PROTOCOL_TLSv1)
1112 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001113 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001114 # helper methods for standardising recv* method signatures
1115 def _recv_into():
1116 b = bytearray("\0"*100)
1117 count = s.recv_into(b)
1118 return b[:count]
1119
1120 def _recvfrom_into():
1121 b = bytearray("\0"*100)
1122 count, addr = s.recvfrom_into(b)
1123 return b[:count]
1124
1125 # (name, method, whether to expect success, *args)
1126 send_methods = [
1127 ('send', s.send, True, []),
1128 ('sendto', s.sendto, False, ["some.address"]),
1129 ('sendall', s.sendall, True, []),
1130 ]
1131 recv_methods = [
1132 ('recv', s.recv, True, []),
1133 ('recvfrom', s.recvfrom, False, ["some.address"]),
1134 ('recv_into', _recv_into, True, []),
1135 ('recvfrom_into', _recvfrom_into, False, []),
1136 ]
1137 data_prefix = u"PREFIX_"
1138
1139 for meth_name, send_meth, expect_success, args in send_methods:
1140 indata = data_prefix + meth_name
1141 try:
1142 send_meth(indata.encode('ASCII', 'strict'), *args)
1143 outdata = s.read()
1144 outdata = outdata.decode('ASCII', 'strict')
1145 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001146 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001147 "While sending with <<%s>> bad data "
1148 "<<%r>> (%d) received; "
1149 "expected <<%r>> (%d)\n" % (
1150 meth_name, outdata[:20], len(outdata),
1151 indata[:20], len(indata)
1152 )
1153 )
1154 except ValueError as e:
1155 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001156 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001157 "Failed to send with method <<%s>>; "
1158 "expected to succeed.\n" % (meth_name,)
1159 )
1160 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001161 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001162 "Method <<%s>> failed with unexpected "
1163 "exception message: %s\n" % (
1164 meth_name, e
1165 )
1166 )
1167
1168 for meth_name, recv_meth, expect_success, args in recv_methods:
1169 indata = data_prefix + meth_name
1170 try:
1171 s.send(indata.encode('ASCII', 'strict'))
1172 outdata = recv_meth(*args)
1173 outdata = outdata.decode('ASCII', 'strict')
1174 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001175 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001176 "While receiving with <<%s>> bad data "
1177 "<<%r>> (%d) received; "
1178 "expected <<%r>> (%d)\n" % (
1179 meth_name, outdata[:20], len(outdata),
1180 indata[:20], len(indata)
1181 )
1182 )
1183 except ValueError as e:
1184 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001185 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001186 "Failed to receive with method <<%s>>; "
1187 "expected to succeed.\n" % (meth_name,)
1188 )
1189 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001190 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001191 "Method <<%s>> failed with unexpected "
1192 "exception message: %s\n" % (
1193 meth_name, e
1194 )
1195 )
1196 # consume data
1197 s.read()
1198
1199 s.write("over\n".encode("ASCII", "strict"))
1200 s.close()
1201 finally:
1202 server.stop()
1203 server.join()
1204
Antoine Pitroufc69af12010-04-24 20:04:58 +00001205 def test_handshake_timeout(self):
1206 # Issue #5103: SSL handshake must respect the socket timeout
1207 server = socket.socket(socket.AF_INET)
1208 host = "127.0.0.1"
1209 port = test_support.bind_port(server)
1210 started = threading.Event()
1211 finish = False
1212
1213 def serve():
1214 server.listen(5)
1215 started.set()
1216 conns = []
1217 while not finish:
1218 r, w, e = select.select([server], [], [], 0.1)
1219 if server in r:
1220 # Let the socket hang around rather than having
1221 # it closed by garbage collection.
1222 conns.append(server.accept()[0])
1223
1224 t = threading.Thread(target=serve)
1225 t.start()
1226 started.wait()
1227
1228 try:
1229 try:
1230 c = socket.socket(socket.AF_INET)
1231 c.settimeout(0.2)
1232 c.connect((host, port))
1233 # Will attempt handshake and time out
1234 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1235 ssl.wrap_socket, c)
1236 finally:
1237 c.close()
1238 try:
1239 c = socket.socket(socket.AF_INET)
1240 c.settimeout(0.2)
1241 c = ssl.wrap_socket(c)
1242 # Will attempt handshake and time out
1243 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1244 c.connect, (host, port))
1245 finally:
1246 c.close()
1247 finally:
1248 finish = True
1249 t.join()
1250 server.close()
1251
Bill Janssen61c001a2008-09-08 16:37:24 +00001252
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001253def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001254 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001255 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001256
Trent Nelsone41b0062008-04-08 23:47:30 +00001257 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001258 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001259 "keycert.pem")
1260 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1261 os.path.dirname(__file__) or os.curdir,
1262 "https_svn_python_org_root.pem")
1263
1264 if (not os.path.exists(CERTFILE) or
1265 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001266 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001267
1268 tests = [BasicTests]
1269
Bill Janssen296a59d2007-09-16 22:06:00 +00001270 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001271 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001272
Bill Janssen98d19da2007-09-10 21:51:02 +00001273 if _have_threads:
1274 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001275 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001276 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001277
Bill Janssen98d19da2007-09-10 21:51:02 +00001278 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001279
Bill Janssen98d19da2007-09-10 21:51:02 +00001280 if _have_threads:
1281 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001282
1283if __name__ == "__main__":
1284 test_main()