blob: 3b868f04088b165e952f350e95207b109d681787 [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
Antoine Pitroud4030da2010-04-23 23:35:01 +000012import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import os
Antoine Pitroud4030da2010-04-23 23:35:01 +000014import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000016import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000017import shutil
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000018import traceback
Antoine Pitrou3df58d12010-04-23 23:07:37 +000019import weakref
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000020
Bill Janssen296a59d2007-09-16 22:06:00 +000021from BaseHTTPServer import HTTPServer
22from SimpleHTTPServer import SimpleHTTPRequestHandler
23
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000024# Optionally test SSL support, if we have it in the tested platform
25skip_expected = False
26try:
27 import ssl
28except ImportError:
29 skip_expected = True
30
Trent Nelsone41b0062008-04-08 23:47:30 +000031HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000032CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000033SVN_PYTHON_ORG_ROOT_CERT = None
Barry Warsaw82f88282013-08-23 13:26:49 -040034NULLBYTECERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000035
Neal Norwitz3e533c22007-08-27 01:03:18 +000036def handle_error(prefix):
37 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000038 if test_support.verbose:
39 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000040
Antoine Pitrou77a1c362010-04-27 09:54:14 +000041
42class BasicTests(unittest.TestCase):
43
Antoine Pitroud2867642010-04-28 21:12:43 +000044 def test_sslwrap_simple(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +000045 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000046 try:
47 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
48 except IOError, e:
49 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
50 pass
51 else:
52 raise
53 try:
54 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
55 except IOError, e:
56 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
57 pass
58 else:
59 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000060
Antoine Pitroud2867642010-04-28 21:12:43 +000061 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000062 ssl.PROTOCOL_SSLv2
63 ssl.PROTOCOL_SSLv23
64 ssl.PROTOCOL_SSLv3
65 ssl.PROTOCOL_TLSv1
66 ssl.CERT_NONE
67 ssl.CERT_OPTIONAL
68 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000069
Antoine Pitroud2867642010-04-28 21:12:43 +000070 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000071 v = ssl.RAND_status()
72 if test_support.verbose:
73 sys.stdout.write("\n RAND_status is %d (%s)\n"
74 % (v, (v and "sufficient randomness") or
75 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000076 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000077 ssl.RAND_egd(1)
78 except TypeError:
79 pass
Guido van Rossume4729332007-08-26 19:35:09 +000080 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000081 print "didn't raise TypeError"
82 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000083
Antoine Pitroud2867642010-04-28 21:12:43 +000084 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000085 # note that this uses an 'unofficial' function in _ssl.c,
86 # provided solely for this test, to exercise the certificate
87 # parsing code
88 p = ssl._ssl._test_decode_cert(CERTFILE, False)
89 if test_support.verbose:
90 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000091
Barry Warsaw82f88282013-08-23 13:26:49 -040092 def test_parse_cert_CVE_2013_4073(self):
93 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
94 if test_support.verbose:
95 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
96 subject = ((('countryName', 'US'),),
97 (('stateOrProvinceName', 'Oregon'),),
98 (('localityName', 'Beaverton'),),
99 (('organizationName', 'Python Software Foundation'),),
100 (('organizationalUnitName', 'Python Core Development'),),
101 (('commonName', 'null.python.org\x00example.org'),),
102 (('emailAddress', 'python-dev@python.org'),))
103 self.assertEqual(p['subject'], subject)
104 self.assertEqual(p['issuer'], subject)
105 self.assertEqual(p['subjectAltName'],
106 (('DNS', 'altnull.python.org\x00example.com'),
107 ('email', 'null@python.org\x00user@example.org'),
108 ('URI', 'http://null.python.org\x00http://example.org'),
109 ('IP Address', '192.0.2.1'),
110 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
111 )
112
Antoine Pitroud2867642010-04-28 21:12:43 +0000113 def test_DER_to_PEM(self):
114 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
115 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000116 d1 = ssl.PEM_cert_to_DER_cert(pem)
117 p2 = ssl.DER_cert_to_PEM_cert(d1)
118 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000119 self.assertEqual(d1, d2)
Antoine Pitrou12cb1292010-04-27 22:05:18 +0000120 if not p2.startswith(ssl.PEM_HEADER + '\n'):
121 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
122 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
123 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000124
Antoine Pitrou3df58d12010-04-23 23:07:37 +0000125 def test_refcycle(self):
126 # Issue #7943: an SSL object doesn't create reference cycles with
127 # itself.
128 s = socket.socket(socket.AF_INET)
129 ss = ssl.wrap_socket(s)
130 wr = weakref.ref(ss)
131 del ss
132 self.assertEqual(wr(), None)
133
Antoine Pitroud4030da2010-04-23 23:35:01 +0000134
Bill Janssen934b16d2008-06-28 22:19:33 +0000135class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000136
Antoine Pitroud2867642010-04-28 21:12:43 +0000137 def test_connect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000138 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
139 cert_reqs=ssl.CERT_NONE)
140 s.connect(("svn.python.org", 443))
141 c = s.getpeercert()
142 if c:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000143 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000144 s.close()
145
146 # this should fail because we have no verification certs
147 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
148 cert_reqs=ssl.CERT_REQUIRED)
149 try:
150 s.connect(("svn.python.org", 443))
151 except ssl.SSLError:
152 pass
153 finally:
154 s.close()
155
156 # this should succeed because we specify the root cert
157 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
158 cert_reqs=ssl.CERT_REQUIRED,
159 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
160 try:
161 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000162 finally:
163 s.close()
164
Antoine Pitrou0753d942010-04-24 11:09:52 +0000165 def test_makefile_close(self):
166 # Issue #5238: creating a file-like object with makefile() shouldn't
167 # delay closing the underlying "real socket" (here tested with its
168 # file descriptor, hence skipping the test under Windows).
169 if os.name == "nt":
170 if test_support.verbose:
171 print "Skipped: can't use a socket as a file under Windows"
172 return
173 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
174 ss.connect(("svn.python.org", 443))
175 fd = ss.fileno()
176 f = ss.makefile()
177 f.close()
178 # The fd is still open
179 os.read(fd, 0)
180 # Closing the SSL socket should close the fd too
181 ss.close()
182 gc.collect()
183 try:
184 os.read(fd, 0)
185 except OSError, e:
186 self.assertEqual(e.errno, errno.EBADF)
187 else:
188 self.fail("OSError wasn't raised")
Bill Janssen934b16d2008-06-28 22:19:33 +0000189
Antoine Pitroud2867642010-04-28 21:12:43 +0000190 def test_non_blocking_handshake(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000191 s = socket.socket(socket.AF_INET)
192 s.connect(("svn.python.org", 443))
193 s.setblocking(False)
194 s = ssl.wrap_socket(s,
195 cert_reqs=ssl.CERT_NONE,
196 do_handshake_on_connect=False)
197 count = 0
198 while True:
199 try:
200 count += 1
201 s.do_handshake()
202 break
203 except ssl.SSLError, err:
204 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
205 select.select([s], [], [])
206 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
207 select.select([], [s], [])
208 else:
209 raise
210 s.close()
211 if test_support.verbose:
212 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
213
Antoine Pitroud2867642010-04-28 21:12:43 +0000214 def test_get_server_certificate(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000215 pem = ssl.get_server_certificate(("svn.python.org", 443))
216 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000217 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000218
219 try:
220 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
221 except ssl.SSLError:
222 #should fail
223 pass
224 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000225 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000226
227 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
228 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000229 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000230 if test_support.verbose:
231 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
232
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000233 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000234 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000235 if test_support.verbose:
236 sys.stdout.write("test_algorithms disabled, "
237 "as it fails on some old OpenSSL versions")
238 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000239 # Issue #8484: all algorithms should be available when verifying a
240 # certificate.
241 # NOTE: https://sha256.tbs-internet.com is another possible test host
242 remote = ("sha2.hboeck.de", 443)
243 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
244 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
245 cert_reqs=ssl.CERT_REQUIRED,
246 ca_certs=sha256_cert,)
247 with test_support.transient_internet():
248 try:
249 s.connect(remote)
250 if test_support.verbose:
251 sys.stdout.write("\nCipher with %r is %r\n" %
252 (remote, s.cipher()))
253 sys.stdout.write("Certificate is:\n%s\n" %
254 pprint.pformat(s.getpeercert()))
255 finally:
256 s.close()
257
Bill Janssen296a59d2007-09-16 22:06:00 +0000258
Bill Janssen98d19da2007-09-10 21:51:02 +0000259try:
260 import threading
261except ImportError:
262 _have_threads = False
263else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000264 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000265
Bill Janssen98d19da2007-09-10 21:51:02 +0000266 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000267
Bill Janssen98d19da2007-09-10 21:51:02 +0000268 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000269
Bill Janssen98d19da2007-09-10 21:51:02 +0000270 """A mildly complicated class, because we want it to work both
271 with and without the SSL wrapper around the socket connection, so
272 that we can test the STARTTLS functionality."""
273
274 def __init__(self, server, connsock):
275 self.server = server
276 self.running = False
277 self.sock = connsock
278 self.sock.setblocking(1)
279 self.sslconn = None
280 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000281 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000282
Bill Janssen934b16d2008-06-28 22:19:33 +0000283 def show_conn_details(self):
284 if self.server.certreqs == ssl.CERT_REQUIRED:
285 cert = self.sslconn.getpeercert()
286 if test_support.verbose and self.server.chatty:
287 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
288 cert_binary = self.sslconn.getpeercert(True)
289 if test_support.verbose and self.server.chatty:
290 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
291 cipher = self.sslconn.cipher()
292 if test_support.verbose and self.server.chatty:
293 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
294
Antoine Pitroud2867642010-04-28 21:12:43 +0000295 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000296 try:
297 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
298 certfile=self.server.certificate,
299 ssl_version=self.server.protocol,
300 ca_certs=self.server.cacerts,
301 cert_reqs=self.server.certreqs)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000302 except ssl.SSLError:
303 # XXX Various errors can have happened here, for example
304 # a mismatching protocol version, an invalid certificate,
305 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000306 if self.server.chatty:
307 handle_error("\n server: bad connection attempt from " +
308 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000309 self.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000310 self.running = False
311 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000312 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000313 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000314 return True
315
316 def read(self):
317 if self.sslconn:
318 return self.sslconn.read()
319 else:
320 return self.sock.recv(1024)
321
322 def write(self, bytes):
323 if self.sslconn:
324 return self.sslconn.write(bytes)
325 else:
326 return self.sock.send(bytes)
327
328 def close(self):
329 if self.sslconn:
330 self.sslconn.close()
331 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000332 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000333
Antoine Pitroud2867642010-04-28 21:12:43 +0000334 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000335 self.running = True
336 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000337 if isinstance(self.sock, ssl.SSLSocket):
338 self.sslconn = self.sock
339 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000340 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000341 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000342 while self.running:
343 try:
344 msg = self.read()
345 if not msg:
346 # eof, so quit this handler
347 self.running = False
348 self.close()
349 elif msg.strip() == 'over':
350 if test_support.verbose and self.server.connectionchatty:
351 sys.stdout.write(" server: client closed connection\n")
352 self.close()
353 return
354 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
355 if test_support.verbose and self.server.connectionchatty:
356 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
357 self.write("OK\n")
358 if not self.wrap_conn():
359 return
Bill Janssen39295c22008-08-12 16:31:21 +0000360 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
361 if test_support.verbose and self.server.connectionchatty:
362 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
363 self.write("OK\n")
364 self.sslconn.unwrap()
365 self.sslconn = None
366 if test_support.verbose and self.server.connectionchatty:
367 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000368 else:
369 if (test_support.verbose and
370 self.server.connectionchatty):
371 ctype = (self.sslconn and "encrypted") or "unencrypted"
372 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
373 % (repr(msg), ctype, repr(msg.lower()), ctype))
374 self.write(msg.lower())
375 except ssl.SSLError:
376 if self.server.chatty:
377 handle_error("Test server failure:\n")
378 self.close()
379 self.running = False
380 # normally, we'd just stop here, but for the test
381 # harness, we want to stop the server
382 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000383
Trent Nelsone41b0062008-04-08 23:47:30 +0000384 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000385 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000386 chatty=True, connectionchatty=False, starttls_server=False,
387 wrap_accepting_socket=False):
388
Bill Janssen98d19da2007-09-10 21:51:02 +0000389 if ssl_version is None:
390 ssl_version = ssl.PROTOCOL_TLSv1
391 if certreqs is None:
392 certreqs = ssl.CERT_NONE
393 self.certificate = certificate
394 self.protocol = ssl_version
395 self.certreqs = certreqs
396 self.cacerts = cacerts
Bill Janssen98d19da2007-09-10 21:51:02 +0000397 self.chatty = chatty
398 self.connectionchatty = connectionchatty
399 self.starttls_server = starttls_server
400 self.sock = socket.socket()
401 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000402 if wrap_accepting_socket:
403 self.sock = ssl.wrap_socket(self.sock, server_side=True,
404 certfile=self.certificate,
405 cert_reqs = self.certreqs,
406 ca_certs = self.cacerts,
407 ssl_version = self.protocol)
408 if test_support.verbose and self.chatty:
409 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
410 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000411 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000412 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000413 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000414
Antoine Pitroud2867642010-04-28 21:12:43 +0000415 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000416 self.flag = flag
417 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000418
Antoine Pitroud2867642010-04-28 21:12:43 +0000419 def run(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000420 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000421 self.sock.listen(5)
422 self.active = True
423 if self.flag:
424 # signal an event
425 self.flag.set()
426 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000427 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000428 newconn, connaddr = self.sock.accept()
429 if test_support.verbose and self.chatty:
430 sys.stdout.write(' server: new connection from '
431 + str(connaddr) + '\n')
432 handler = self.ConnectionHandler(self, newconn)
433 handler.start()
434 except socket.timeout:
435 pass
436 except KeyboardInterrupt:
437 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000438 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000439
Antoine Pitroud2867642010-04-28 21:12:43 +0000440 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000441 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000442
Bill Janssen934b16d2008-06-28 22:19:33 +0000443 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000444
Antoine Pitroud2867642010-04-28 21:12:43 +0000445 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000446
Antoine Pitroud2867642010-04-28 21:12:43 +0000447 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000448
449 def __init__(self, conn, certfile):
450 asyncore.dispatcher_with_send.__init__(self, conn)
451 self.socket = ssl.wrap_socket(conn, server_side=True,
452 certfile=certfile,
Antoine Pitrouc689d962010-04-24 20:13:37 +0000453 do_handshake_on_connect=False)
454 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000455
456 def readable(self):
457 if isinstance(self.socket, ssl.SSLSocket):
458 while self.socket.pending() > 0:
459 self.handle_read_event()
460 return True
461
Antoine Pitrouc689d962010-04-24 20:13:37 +0000462 def _do_ssl_handshake(self):
463 try:
464 self.socket.do_handshake()
465 except ssl.SSLError, err:
466 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
467 ssl.SSL_ERROR_WANT_WRITE):
468 return
469 elif err.args[0] == ssl.SSL_ERROR_EOF:
470 return self.handle_close()
471 raise
472 except socket.error, err:
473 if err.args[0] == errno.ECONNABORTED:
474 return self.handle_close()
475 else:
476 self._ssl_accepting = False
477
Bill Janssen934b16d2008-06-28 22:19:33 +0000478 def handle_read(self):
Antoine Pitrouc689d962010-04-24 20:13:37 +0000479 if self._ssl_accepting:
480 self._do_ssl_handshake()
481 else:
482 data = self.recv(1024)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000483 if data and data.strip() != 'over':
484 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000485
486 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000487 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000488 if test_support.verbose:
489 sys.stdout.write(" server: closed connection %s\n" % self.socket)
490
491 def handle_error(self):
492 raise
493
494 def __init__(self, certfile):
495 self.certfile = certfile
496 asyncore.dispatcher.__init__(self)
497 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
498 self.port = test_support.bind_port(self.socket)
499 self.listen(5)
500
501 def handle_accept(self):
502 sock_obj, addr = self.accept()
503 if test_support.verbose:
504 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
505 self.ConnectionHandler(sock_obj, self.certfile)
506
507 def handle_error(self):
508 raise
509
510 def __init__(self, certfile):
511 self.flag = None
512 self.active = False
513 self.server = self.EchoServer(certfile)
514 self.port = self.server.port
515 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000516 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000517
518 def __str__(self):
519 return "<%s %s>" % (self.__class__.__name__, self.server)
520
Antoine Pitroud2867642010-04-28 21:12:43 +0000521 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000522 self.flag = flag
523 threading.Thread.start(self)
524
Antoine Pitroud2867642010-04-28 21:12:43 +0000525 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000526 self.active = True
527 if self.flag:
528 self.flag.set()
529 while self.active:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000530 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000531
Antoine Pitroud2867642010-04-28 21:12:43 +0000532 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000533 self.active = False
534 self.server.close()
535
536 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000537
538 class HTTPSServer(HTTPServer):
539
540 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000541 HTTPServer.__init__(self, server_address, RequestHandlerClass)
542 # we assume the certfile contains both private key and certificate
543 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000544 self.allow_reuse_address = True
545
Bill Janssen934b16d2008-06-28 22:19:33 +0000546 def __str__(self):
547 return ('<%s %s:%s>' %
548 (self.__class__.__name__,
549 self.server_name,
550 self.server_port))
551
Antoine Pitroud2867642010-04-28 21:12:43 +0000552 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000553 # override this to wrap socket with SSL
554 sock, addr = self.socket.accept()
555 sslconn = ssl.wrap_socket(sock, server_side=True,
556 certfile=self.certfile)
557 return sslconn, addr
558
Bill Janssen296a59d2007-09-16 22:06:00 +0000559 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000560 # need to override translate_path to get a known root,
561 # instead of using os.curdir, since the test could be
562 # run from anywhere
563
564 server_version = "TestHTTPS/1.0"
565
566 root = None
567
568 def translate_path(self, path):
569 """Translate a /-separated PATH to the local filename syntax.
570
571 Components that mean special things to the local file system
572 (e.g. drive or directory names) are ignored. (XXX They should
573 probably be diagnosed.)
574
575 """
576 # abandon query parameters
577 path = urlparse.urlparse(path)[2]
578 path = os.path.normpath(urllib.unquote(path))
579 words = path.split('/')
580 words = filter(None, words)
581 path = self.root
582 for word in words:
583 drive, word = os.path.splitdrive(word)
584 head, word = os.path.split(word)
585 if word in self.root: continue
586 path = os.path.join(path, word)
587 return path
588
589 def log_message(self, format, *args):
590
591 # we override this to suppress logging unless "verbose"
592
593 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000594 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
595 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000596 self.server.server_port,
597 self.request.cipher(),
598 self.log_date_time_string(),
599 format%args))
600
601
Trent Nelsone41b0062008-04-08 23:47:30 +0000602 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000603 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000604 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
605 self.server = self.HTTPSServer(
Antoine Pitrou6535b312010-04-27 08:43:11 +0000606 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
607 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000608 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000609 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000610
611 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000612 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000613
Antoine Pitroud2867642010-04-28 21:12:43 +0000614 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000615 self.flag = flag
616 threading.Thread.start(self)
617
Antoine Pitroud2867642010-04-28 21:12:43 +0000618 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000619 if self.flag:
620 self.flag.set()
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000621 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000622
Antoine Pitroud2867642010-04-28 21:12:43 +0000623 def stop(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000624 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000625
626
Antoine Pitroud2867642010-04-28 21:12:43 +0000627 def bad_cert_test(certfile):
628 """
629 Launch a server with CERT_REQUIRED, and check that trying to
630 connect to it with the given client certificate fails.
631 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000632 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000633 certreqs=ssl.CERT_REQUIRED,
634 cacerts=CERTFILE, chatty=False)
635 flag = threading.Event()
636 server.start(flag)
637 # wait for it to start
638 flag.wait()
639 # try to connect
640 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000641 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000642 s = ssl.wrap_socket(socket.socket(),
643 certfile=certfile,
644 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000645 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000646 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000647 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000648 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000649 except socket.error, x:
650 if test_support.verbose:
651 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000652 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000653 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000654 finally:
655 server.stop()
656 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000657
Antoine Pitroud2867642010-04-28 21:12:43 +0000658 def server_params_test(certfile, protocol, certreqs, cacertsfile,
659 client_certfile, client_protocol=None, indata="FOO\n",
660 chatty=True, connectionchatty=False,
661 wrap_accepting_socket=False):
662 """
663 Launch a server, connect a client to it and try various reads
664 and writes.
665 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000666 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000667 certreqs=certreqs,
668 ssl_version=protocol,
669 cacerts=cacertsfile,
670 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000671 connectionchatty=connectionchatty,
672 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000673 flag = threading.Event()
674 server.start(flag)
675 # wait for it to start
676 flag.wait()
677 # try to connect
678 if client_protocol is None:
679 client_protocol = protocol
680 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000681 s = ssl.wrap_socket(socket.socket(),
682 certfile=client_certfile,
683 ca_certs=cacertsfile,
684 cert_reqs=certreqs,
685 ssl_version=client_protocol)
686 s.connect((HOST, server.port))
687 if connectionchatty:
688 if test_support.verbose:
689 sys.stdout.write(
690 " client: sending %s...\n" % (repr(indata)))
691 s.write(indata)
692 outdata = s.read()
693 if connectionchatty:
694 if test_support.verbose:
695 sys.stdout.write(" client: read %s\n" % repr(outdata))
696 if outdata != indata.lower():
697 self.fail(
698 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
699 % (outdata[:min(len(outdata),20)], len(outdata),
700 indata[:min(len(indata),20)].lower(), len(indata)))
701 s.write("over\n")
702 if connectionchatty:
703 if test_support.verbose:
704 sys.stdout.write(" client: closing connection.\n")
705 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000706 finally:
707 server.stop()
708 server.join()
709
Antoine Pitroud2867642010-04-28 21:12:43 +0000710 def try_protocol_combo(server_protocol,
711 client_protocol,
712 expect_success,
713 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000714 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000715 certsreqs = ssl.CERT_NONE
Antoine Pitroud2867642010-04-28 21:12:43 +0000716 certtype = {
717 ssl.CERT_NONE: "CERT_NONE",
718 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
719 ssl.CERT_REQUIRED: "CERT_REQUIRED",
720 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000721 if test_support.verbose:
Antoine Pitroud2867642010-04-28 21:12:43 +0000722 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000723 sys.stdout.write(formatstr %
724 (ssl.get_protocol_name(client_protocol),
725 ssl.get_protocol_name(server_protocol),
726 certtype))
727 try:
Antoine Pitroud2867642010-04-28 21:12:43 +0000728 server_params_test(CERTFILE, server_protocol, certsreqs,
729 CERTFILE, CERTFILE, client_protocol,
730 chatty=False)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000731 # Protocol mismatch can result in either an SSLError, or a
732 # "Connection reset by peer" error.
733 except ssl.SSLError:
Antoine Pitroud2867642010-04-28 21:12:43 +0000734 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000735 raise
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000736 except socket.error as e:
Antoine Pitroud2867642010-04-28 21:12:43 +0000737 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000738 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000739 else:
Antoine Pitroud2867642010-04-28 21:12:43 +0000740 if not expect_success:
Antoine Pitrou12226692010-05-06 13:49:10 +0000741 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000742 "Client protocol %s succeeded with server protocol %s!"
743 % (ssl.get_protocol_name(client_protocol),
744 ssl.get_protocol_name(server_protocol)))
745
746
Bill Janssen934b16d2008-06-28 22:19:33 +0000747 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000748
Antoine Pitroud2867642010-04-28 21:12:43 +0000749 def test_rude_shutdown(self):
750 """A brutal shutdown of an SSL server should raise an IOError
751 in the client when attempting handshake.
752 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000753 listener_ready = threading.Event()
754 listener_gone = threading.Event()
755
Antoine Pitrou6535b312010-04-27 08:43:11 +0000756 s = socket.socket()
757 port = test_support.bind_port(s, HOST)
758
759 # `listener` runs in a thread. It sits in an accept() until
760 # the main thread connects. Then it rudely closes the socket,
761 # and sets Event `listener_gone` to let the main thread know
762 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000763 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000764 s.listen(5)
765 listener_ready.set()
766 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000767 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000768 listener_gone.set()
769
770 def connector():
771 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000772 c = socket.socket()
773 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000774 listener_gone.wait()
775 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000776 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000777 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000778 pass
779 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000780 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000781
782 t = threading.Thread(target=listener)
783 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000784 try:
785 connector()
786 finally:
787 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000788
Antoine Pitroud2867642010-04-28 21:12:43 +0000789 def test_echo(self):
790 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000791 if test_support.verbose:
792 sys.stdout.write("\n")
Antoine Pitroud2867642010-04-28 21:12:43 +0000793 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
794 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
795 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000796
Antoine Pitroud2867642010-04-28 21:12:43 +0000797 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000798 if test_support.verbose:
799 sys.stdout.write("\n")
800 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000801 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000802 certreqs=ssl.CERT_NONE,
803 ssl_version=ssl.PROTOCOL_SSLv23,
804 cacerts=CERTFILE,
805 chatty=False)
806 flag = threading.Event()
807 server.start(flag)
808 # wait for it to start
809 flag.wait()
810 # try to connect
811 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000812 s = ssl.wrap_socket(socket.socket(),
813 certfile=CERTFILE,
814 ca_certs=CERTFILE,
815 cert_reqs=ssl.CERT_REQUIRED,
816 ssl_version=ssl.PROTOCOL_SSLv23)
817 s.connect((HOST, server.port))
818 cert = s.getpeercert()
819 self.assertTrue(cert, "Can't get peer certificate.")
820 cipher = s.cipher()
821 if test_support.verbose:
822 sys.stdout.write(pprint.pformat(cert) + '\n')
823 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
824 if 'subject' not in cert:
825 self.fail("No subject field in certificate: %s." %
826 pprint.pformat(cert))
827 if ((('organizationName', 'Python Software Foundation'),)
828 not in cert['subject']):
829 self.fail(
830 "Missing or invalid 'organizationName' field in certificate subject; "
831 "should be 'Python Software Foundation'.")
832 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000833 finally:
834 server.stop()
835 server.join()
836
Antoine Pitroud2867642010-04-28 21:12:43 +0000837 def test_empty_cert(self):
838 """Connecting with an empty cert file"""
839 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
840 "nullcert.pem"))
841 def test_malformed_cert(self):
842 """Connecting with a badly formatted certificate (syntax error)"""
843 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
844 "badcert.pem"))
845 def test_nonexisting_cert(self):
846 """Connecting with a non-existing cert file"""
847 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
848 "wrongcert.pem"))
849 def test_malformed_key(self):
850 """Connecting with a badly formatted key (syntax error)"""
851 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
852 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000853
Antoine Pitroud2867642010-04-28 21:12:43 +0000854 def test_protocol_sslv2(self):
855 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000856 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000857 sys.stdout.write("\ntest_protocol_sslv2 disabled, "
858 "as it fails on OpenSSL 1.0.0+")
859 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000860 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
861 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
862 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
863 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
864 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
865 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000866
Antoine Pitroud2867642010-04-28 21:12:43 +0000867 def test_protocol_sslv23(self):
868 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000869 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000870 sys.stdout.write("\ntest_protocol_sslv23 disabled, "
871 "as it fails on OpenSSL 1.0.0+")
872 return
Bill Janssen98d19da2007-09-10 21:51:02 +0000873 try:
Antoine Pitroud2867642010-04-28 21:12:43 +0000874 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000875 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000876 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
877 if test_support.verbose:
878 sys.stdout.write(
879 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
880 % str(x))
Antoine Pitroud2867642010-04-28 21:12:43 +0000881 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
882 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
883 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000884
Antoine Pitroud2867642010-04-28 21:12:43 +0000885 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
886 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
887 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000888
Antoine Pitroud2867642010-04-28 21:12:43 +0000889 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
890 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
891 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000892
Antoine Pitroud2867642010-04-28 21:12:43 +0000893 def test_protocol_sslv3(self):
894 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000895 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000896 sys.stdout.write("\ntest_protocol_sslv3 disabled, "
897 "as it fails on OpenSSL 1.0.0+")
898 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000899 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
900 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
901 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
902 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
903 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
904 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000905
Antoine Pitroud2867642010-04-28 21:12:43 +0000906 def test_protocol_tlsv1(self):
907 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000908 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000909 sys.stdout.write("\ntest_protocol_tlsv1 disabled, "
910 "as it fails on OpenSSL 1.0.0+")
911 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000912 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
913 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
914 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
915 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
916 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
917 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000918
Antoine Pitroud2867642010-04-28 21:12:43 +0000919 def test_starttls(self):
920 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000921 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000922
Trent Nelsone41b0062008-04-08 23:47:30 +0000923 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000924 ssl_version=ssl.PROTOCOL_TLSv1,
925 starttls_server=True,
926 chatty=True,
927 connectionchatty=True)
928 flag = threading.Event()
929 server.start(flag)
930 # wait for it to start
931 flag.wait()
932 # try to connect
933 wrapped = False
934 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000935 s = socket.socket()
936 s.setblocking(1)
937 s.connect((HOST, server.port))
938 if test_support.verbose:
939 sys.stdout.write("\n")
940 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000941 if test_support.verbose:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000942 sys.stdout.write(
943 " client: sending %s...\n" % repr(indata))
944 if wrapped:
945 conn.write(indata)
946 outdata = conn.read()
947 else:
948 s.send(indata)
949 outdata = s.recv(1024)
950 if (indata == "STARTTLS" and
951 outdata.strip().lower().startswith("ok")):
Antoine Pitroud2867642010-04-28 21:12:43 +0000952 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +0000953 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000954 sys.stdout.write(
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000955 " client: read %s from server, starting TLS...\n"
956 % repr(outdata))
957 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
958 wrapped = True
959 elif (indata == "ENDTLS" and
960 outdata.strip().lower().startswith("ok")):
Antoine Pitroud2867642010-04-28 21:12:43 +0000961 # ENDTLS ok, switch back to clear text
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000962 if test_support.verbose:
963 sys.stdout.write(
964 " client: read %s from server, ending TLS...\n"
965 % repr(outdata))
966 s = conn.unwrap()
967 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000968 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000969 if test_support.verbose:
970 sys.stdout.write(
971 " client: read %s from server\n" % repr(outdata))
972 if test_support.verbose:
973 sys.stdout.write(" client: closing connection.\n")
974 if wrapped:
975 conn.write("over\n")
976 else:
977 s.send("over\n")
978 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000979 finally:
980 server.stop()
981 server.join()
982
Antoine Pitroud2867642010-04-28 21:12:43 +0000983 def test_socketserver(self):
984 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +0000985 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000986 flag = threading.Event()
987 server.start(flag)
988 # wait for it to start
989 flag.wait()
990 # try to connect
991 try:
992 if test_support.verbose:
993 sys.stdout.write('\n')
Antoine Pitroud2867642010-04-28 21:12:43 +0000994 with open(CERTFILE, 'rb') as f:
995 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000996 d2 = ''
997 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +0000998 url = 'https://127.0.0.1:%d/%s' % (
999 server.port, os.path.split(CERTFILE)[1])
Ezio Melottia65e2af2010-08-02 19:56:05 +00001000 with test_support._check_py3k_warnings():
1001 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001002 dlen = f.info().getheader("content-length")
1003 if dlen and (int(dlen) > 0):
1004 d2 = f.read(int(dlen))
1005 if test_support.verbose:
1006 sys.stdout.write(
1007 " client: read %d bytes from remote server '%s'\n"
1008 % (len(d2), server))
1009 f.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001010 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001011 finally:
1012 server.stop()
1013 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001014
Antoine Pitroud2867642010-04-28 21:12:43 +00001015 def test_wrapped_accept(self):
1016 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001017 if test_support.verbose:
1018 sys.stdout.write("\n")
Antoine Pitroud2867642010-04-28 21:12:43 +00001019 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1020 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1021 chatty=True, connectionchatty=True,
1022 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001023
Antoine Pitroud2867642010-04-28 21:12:43 +00001024 def test_asyncore_server(self):
1025 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001026 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:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001037 s = ssl.wrap_socket(socket.socket())
1038 s.connect(('127.0.0.1', server.port))
1039 if test_support.verbose:
1040 sys.stdout.write(
1041 " client: sending %s...\n" % (repr(indata)))
1042 s.write(indata)
1043 outdata = s.read()
1044 if test_support.verbose:
1045 sys.stdout.write(" client: read %s\n" % repr(outdata))
1046 if outdata != indata.lower():
1047 self.fail(
1048 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1049 % (outdata[:min(len(outdata),20)], len(outdata),
1050 indata[:min(len(indata),20)].lower(), len(indata)))
1051 s.write("over\n")
1052 if test_support.verbose:
1053 sys.stdout.write(" client: closing connection.\n")
1054 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001055 finally:
1056 server.stop()
1057 # wait for server thread to end
1058 server.join()
1059
Antoine Pitroud2867642010-04-28 21:12:43 +00001060 def test_recv_send(self):
1061 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001062 if test_support.verbose:
1063 sys.stdout.write("\n")
1064
1065 server = ThreadedEchoServer(CERTFILE,
1066 certreqs=ssl.CERT_NONE,
1067 ssl_version=ssl.PROTOCOL_TLSv1,
1068 cacerts=CERTFILE,
1069 chatty=True,
1070 connectionchatty=False)
1071 flag = threading.Event()
1072 server.start(flag)
1073 # wait for it to start
1074 flag.wait()
1075 # try to connect
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001076 s = ssl.wrap_socket(socket.socket(),
1077 server_side=False,
1078 certfile=CERTFILE,
1079 ca_certs=CERTFILE,
1080 cert_reqs=ssl.CERT_NONE,
1081 ssl_version=ssl.PROTOCOL_TLSv1)
1082 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001083 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001084 # helper methods for standardising recv* method signatures
1085 def _recv_into():
1086 b = bytearray("\0"*100)
1087 count = s.recv_into(b)
1088 return b[:count]
1089
1090 def _recvfrom_into():
1091 b = bytearray("\0"*100)
1092 count, addr = s.recvfrom_into(b)
1093 return b[:count]
1094
1095 # (name, method, whether to expect success, *args)
1096 send_methods = [
1097 ('send', s.send, True, []),
1098 ('sendto', s.sendto, False, ["some.address"]),
1099 ('sendall', s.sendall, True, []),
1100 ]
1101 recv_methods = [
1102 ('recv', s.recv, True, []),
1103 ('recvfrom', s.recvfrom, False, ["some.address"]),
1104 ('recv_into', _recv_into, True, []),
1105 ('recvfrom_into', _recvfrom_into, False, []),
1106 ]
1107 data_prefix = u"PREFIX_"
1108
1109 for meth_name, send_meth, expect_success, args in send_methods:
1110 indata = data_prefix + meth_name
1111 try:
1112 send_meth(indata.encode('ASCII', 'strict'), *args)
1113 outdata = s.read()
1114 outdata = outdata.decode('ASCII', 'strict')
1115 if outdata != indata.lower():
1116 raise support.TestFailed(
1117 "While sending with <<%s>> bad data "
1118 "<<%r>> (%d) received; "
1119 "expected <<%r>> (%d)\n" % (
1120 meth_name, outdata[:20], len(outdata),
1121 indata[:20], len(indata)
1122 )
1123 )
1124 except ValueError as e:
1125 if expect_success:
1126 raise support.TestFailed(
1127 "Failed to send with method <<%s>>; "
1128 "expected to succeed.\n" % (meth_name,)
1129 )
1130 if not str(e).startswith(meth_name):
1131 raise support.TestFailed(
1132 "Method <<%s>> failed with unexpected "
1133 "exception message: %s\n" % (
1134 meth_name, e
1135 )
1136 )
1137
1138 for meth_name, recv_meth, expect_success, args in recv_methods:
1139 indata = data_prefix + meth_name
1140 try:
1141 s.send(indata.encode('ASCII', 'strict'))
1142 outdata = recv_meth(*args)
1143 outdata = outdata.decode('ASCII', 'strict')
1144 if outdata != indata.lower():
1145 raise support.TestFailed(
1146 "While receiving with <<%s>> bad data "
1147 "<<%r>> (%d) received; "
1148 "expected <<%r>> (%d)\n" % (
1149 meth_name, outdata[:20], len(outdata),
1150 indata[:20], len(indata)
1151 )
1152 )
1153 except ValueError as e:
1154 if expect_success:
1155 raise support.TestFailed(
1156 "Failed to receive with method <<%s>>; "
1157 "expected to succeed.\n" % (meth_name,)
1158 )
1159 if not str(e).startswith(meth_name):
1160 raise support.TestFailed(
1161 "Method <<%s>> failed with unexpected "
1162 "exception message: %s\n" % (
1163 meth_name, e
1164 )
1165 )
1166 # consume data
1167 s.read()
1168
1169 s.write("over\n".encode("ASCII", "strict"))
1170 s.close()
1171 finally:
1172 server.stop()
1173 server.join()
1174
Antoine Pitrouc689d962010-04-24 20:13:37 +00001175 def test_handshake_timeout(self):
1176 # Issue #5103: SSL handshake must respect the socket timeout
1177 server = socket.socket(socket.AF_INET)
1178 host = "127.0.0.1"
1179 port = test_support.bind_port(server)
1180 started = threading.Event()
1181 finish = False
1182
1183 def serve():
1184 server.listen(5)
1185 started.set()
1186 conns = []
1187 while not finish:
1188 r, w, e = select.select([server], [], [], 0.1)
1189 if server in r:
1190 # Let the socket hang around rather than having
1191 # it closed by garbage collection.
1192 conns.append(server.accept()[0])
1193
1194 t = threading.Thread(target=serve)
1195 t.start()
1196 started.wait()
1197
1198 try:
1199 try:
1200 c = socket.socket(socket.AF_INET)
1201 c.settimeout(0.2)
1202 c.connect((host, port))
1203 # Will attempt handshake and time out
1204 try:
1205 ssl.wrap_socket(c)
1206 except ssl.SSLError, e:
1207 self.assertTrue("timed out" in str(e), str(e))
1208 else:
1209 self.fail("SSLError wasn't raised")
1210 finally:
1211 c.close()
1212 try:
1213 c = socket.socket(socket.AF_INET)
1214 c.settimeout(0.2)
1215 c = ssl.wrap_socket(c)
1216 # Will attempt handshake and time out
1217 try:
1218 c.connect((host, port))
1219 except ssl.SSLError, e:
1220 self.assertTrue("timed out" in str(e), str(e))
1221 else:
1222 self.fail("SSLError wasn't raised")
1223 finally:
1224 c.close()
1225 finally:
1226 finish = True
1227 t.join()
1228 server.close()
1229
Bill Janssen61c001a2008-09-08 16:37:24 +00001230
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001231def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001232 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001233 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001234
Barry Warsaw82f88282013-08-23 13:26:49 -04001235 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NULLBYTECERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001236 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001237 "keycert.pem")
1238 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1239 os.path.dirname(__file__) or os.curdir,
1240 "https_svn_python_org_root.pem")
Barry Warsaw82f88282013-08-23 13:26:49 -04001241 NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1242 "nullbytecert.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001243
1244 if (not os.path.exists(CERTFILE) or
Barry Warsaw82f88282013-08-23 13:26:49 -04001245 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
1246 not os.path.exists(NULLBYTECERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001247 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001248
1249 tests = [BasicTests]
1250
Bill Janssen296a59d2007-09-16 22:06:00 +00001251 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001252 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001253
Bill Janssen98d19da2007-09-10 21:51:02 +00001254 if _have_threads:
1255 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001256 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001257 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001258
Antoine Pitroud2867642010-04-28 21:12:43 +00001259 try:
1260 test_support.run_unittest(*tests)
1261 finally:
1262 if _have_threads:
1263 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001264
1265if __name__ == "__main__":
1266 test_main()