blob: 59294b45479fc0eae68365706cd19d968c0c8c97 [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)
Christian Heimesbde29852013-09-03 14:47:00 +0200105 san = (('DNS', 'altnull.python.org\x00example.com'),
106 ('email', 'null@python.org\x00user@example.org'),
107 ('URI', 'http://null.python.org\x00http://example.org'),
108 ('IP Address', '192.0.2.1'))
Christian Heimes8f65ef82013-08-25 14:12:41 +0200109
Christian Heimesbde29852013-09-03 14:47:00 +0200110 self.assertEqual(p['subjectAltName'][:4], san)
Barry Warsaw82f88282013-08-23 13:26:49 -0400111
Antoine Pitroud2867642010-04-28 21:12:43 +0000112 def test_DER_to_PEM(self):
113 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
114 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000115 d1 = ssl.PEM_cert_to_DER_cert(pem)
116 p2 = ssl.DER_cert_to_PEM_cert(d1)
117 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000118 self.assertEqual(d1, d2)
Antoine Pitrou12cb1292010-04-27 22:05:18 +0000119 if not p2.startswith(ssl.PEM_HEADER + '\n'):
120 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
121 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
122 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000123
Antoine Pitrou3df58d12010-04-23 23:07:37 +0000124 def test_refcycle(self):
125 # Issue #7943: an SSL object doesn't create reference cycles with
126 # itself.
127 s = socket.socket(socket.AF_INET)
128 ss = ssl.wrap_socket(s)
129 wr = weakref.ref(ss)
130 del ss
131 self.assertEqual(wr(), None)
132
Antoine Pitroud4030da2010-04-23 23:35:01 +0000133
Bill Janssen934b16d2008-06-28 22:19:33 +0000134class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000135
Antoine Pitroud2867642010-04-28 21:12:43 +0000136 def test_connect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000137 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
138 cert_reqs=ssl.CERT_NONE)
139 s.connect(("svn.python.org", 443))
140 c = s.getpeercert()
141 if c:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000142 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000143 s.close()
144
145 # this should fail because we have no verification certs
146 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
147 cert_reqs=ssl.CERT_REQUIRED)
148 try:
149 s.connect(("svn.python.org", 443))
150 except ssl.SSLError:
151 pass
152 finally:
153 s.close()
154
155 # this should succeed because we specify the root cert
156 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
157 cert_reqs=ssl.CERT_REQUIRED,
158 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
159 try:
160 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000161 finally:
162 s.close()
163
Antoine Pitrou0753d942010-04-24 11:09:52 +0000164 def test_makefile_close(self):
165 # Issue #5238: creating a file-like object with makefile() shouldn't
166 # delay closing the underlying "real socket" (here tested with its
167 # file descriptor, hence skipping the test under Windows).
168 if os.name == "nt":
169 if test_support.verbose:
170 print "Skipped: can't use a socket as a file under Windows"
171 return
172 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
173 ss.connect(("svn.python.org", 443))
174 fd = ss.fileno()
175 f = ss.makefile()
176 f.close()
177 # The fd is still open
178 os.read(fd, 0)
179 # Closing the SSL socket should close the fd too
180 ss.close()
181 gc.collect()
182 try:
183 os.read(fd, 0)
184 except OSError, e:
185 self.assertEqual(e.errno, errno.EBADF)
186 else:
187 self.fail("OSError wasn't raised")
Bill Janssen934b16d2008-06-28 22:19:33 +0000188
Antoine Pitroud2867642010-04-28 21:12:43 +0000189 def test_non_blocking_handshake(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000190 s = socket.socket(socket.AF_INET)
191 s.connect(("svn.python.org", 443))
192 s.setblocking(False)
193 s = ssl.wrap_socket(s,
194 cert_reqs=ssl.CERT_NONE,
195 do_handshake_on_connect=False)
196 count = 0
197 while True:
198 try:
199 count += 1
200 s.do_handshake()
201 break
202 except ssl.SSLError, err:
203 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
204 select.select([s], [], [])
205 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
206 select.select([], [s], [])
207 else:
208 raise
209 s.close()
210 if test_support.verbose:
211 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
212
Antoine Pitroud2867642010-04-28 21:12:43 +0000213 def test_get_server_certificate(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000214 pem = ssl.get_server_certificate(("svn.python.org", 443))
215 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000216 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000217
218 try:
219 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
220 except ssl.SSLError:
221 #should fail
222 pass
223 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000224 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000225
226 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
227 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000228 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000229 if test_support.verbose:
230 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
231
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000232 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000233 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000234 if test_support.verbose:
235 sys.stdout.write("test_algorithms disabled, "
236 "as it fails on some old OpenSSL versions")
237 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000238 # Issue #8484: all algorithms should be available when verifying a
239 # certificate.
240 # NOTE: https://sha256.tbs-internet.com is another possible test host
241 remote = ("sha2.hboeck.de", 443)
242 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
243 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
244 cert_reqs=ssl.CERT_REQUIRED,
245 ca_certs=sha256_cert,)
246 with test_support.transient_internet():
247 try:
248 s.connect(remote)
249 if test_support.verbose:
250 sys.stdout.write("\nCipher with %r is %r\n" %
251 (remote, s.cipher()))
252 sys.stdout.write("Certificate is:\n%s\n" %
253 pprint.pformat(s.getpeercert()))
254 finally:
255 s.close()
256
Bill Janssen296a59d2007-09-16 22:06:00 +0000257
Bill Janssen98d19da2007-09-10 21:51:02 +0000258try:
259 import threading
260except ImportError:
261 _have_threads = False
262else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000263 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000264
Bill Janssen98d19da2007-09-10 21:51:02 +0000265 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000266
Bill Janssen98d19da2007-09-10 21:51:02 +0000267 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000268
Bill Janssen98d19da2007-09-10 21:51:02 +0000269 """A mildly complicated class, because we want it to work both
270 with and without the SSL wrapper around the socket connection, so
271 that we can test the STARTTLS functionality."""
272
273 def __init__(self, server, connsock):
274 self.server = server
275 self.running = False
276 self.sock = connsock
277 self.sock.setblocking(1)
278 self.sslconn = None
279 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000280 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000281
Bill Janssen934b16d2008-06-28 22:19:33 +0000282 def show_conn_details(self):
283 if self.server.certreqs == ssl.CERT_REQUIRED:
284 cert = self.sslconn.getpeercert()
285 if test_support.verbose and self.server.chatty:
286 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
287 cert_binary = self.sslconn.getpeercert(True)
288 if test_support.verbose and self.server.chatty:
289 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
290 cipher = self.sslconn.cipher()
291 if test_support.verbose and self.server.chatty:
292 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
293
Antoine Pitroud2867642010-04-28 21:12:43 +0000294 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000295 try:
296 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
297 certfile=self.server.certificate,
298 ssl_version=self.server.protocol,
299 ca_certs=self.server.cacerts,
300 cert_reqs=self.server.certreqs)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000301 except ssl.SSLError:
302 # XXX Various errors can have happened here, for example
303 # a mismatching protocol version, an invalid certificate,
304 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000305 if self.server.chatty:
306 handle_error("\n server: bad connection attempt from " +
307 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000308 self.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000309 self.running = False
310 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000311 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000312 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000313 return True
314
315 def read(self):
316 if self.sslconn:
317 return self.sslconn.read()
318 else:
319 return self.sock.recv(1024)
320
321 def write(self, bytes):
322 if self.sslconn:
323 return self.sslconn.write(bytes)
324 else:
325 return self.sock.send(bytes)
326
327 def close(self):
328 if self.sslconn:
329 self.sslconn.close()
330 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000331 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000332
Antoine Pitroud2867642010-04-28 21:12:43 +0000333 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000334 self.running = True
335 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000336 if isinstance(self.sock, ssl.SSLSocket):
337 self.sslconn = self.sock
338 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000339 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000340 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000341 while self.running:
342 try:
343 msg = self.read()
344 if not msg:
345 # eof, so quit this handler
346 self.running = False
347 self.close()
348 elif msg.strip() == 'over':
349 if test_support.verbose and self.server.connectionchatty:
350 sys.stdout.write(" server: client closed connection\n")
351 self.close()
352 return
353 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
354 if test_support.verbose and self.server.connectionchatty:
355 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
356 self.write("OK\n")
357 if not self.wrap_conn():
358 return
Bill Janssen39295c22008-08-12 16:31:21 +0000359 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
360 if test_support.verbose and self.server.connectionchatty:
361 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
362 self.write("OK\n")
363 self.sslconn.unwrap()
364 self.sslconn = None
365 if test_support.verbose and self.server.connectionchatty:
366 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000367 else:
368 if (test_support.verbose and
369 self.server.connectionchatty):
370 ctype = (self.sslconn and "encrypted") or "unencrypted"
371 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
372 % (repr(msg), ctype, repr(msg.lower()), ctype))
373 self.write(msg.lower())
374 except ssl.SSLError:
375 if self.server.chatty:
376 handle_error("Test server failure:\n")
377 self.close()
378 self.running = False
379 # normally, we'd just stop here, but for the test
380 # harness, we want to stop the server
381 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000382
Trent Nelsone41b0062008-04-08 23:47:30 +0000383 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000384 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000385 chatty=True, connectionchatty=False, starttls_server=False,
386 wrap_accepting_socket=False):
387
Bill Janssen98d19da2007-09-10 21:51:02 +0000388 if ssl_version is None:
389 ssl_version = ssl.PROTOCOL_TLSv1
390 if certreqs is None:
391 certreqs = ssl.CERT_NONE
392 self.certificate = certificate
393 self.protocol = ssl_version
394 self.certreqs = certreqs
395 self.cacerts = cacerts
Bill Janssen98d19da2007-09-10 21:51:02 +0000396 self.chatty = chatty
397 self.connectionchatty = connectionchatty
398 self.starttls_server = starttls_server
399 self.sock = socket.socket()
400 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000401 if wrap_accepting_socket:
402 self.sock = ssl.wrap_socket(self.sock, server_side=True,
403 certfile=self.certificate,
404 cert_reqs = self.certreqs,
405 ca_certs = self.cacerts,
406 ssl_version = self.protocol)
407 if test_support.verbose and self.chatty:
408 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
409 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000410 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000411 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000412 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000413
Antoine Pitroud2867642010-04-28 21:12:43 +0000414 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000415 self.flag = flag
416 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000417
Antoine Pitroud2867642010-04-28 21:12:43 +0000418 def run(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000419 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000420 self.sock.listen(5)
421 self.active = True
422 if self.flag:
423 # signal an event
424 self.flag.set()
425 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000426 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000427 newconn, connaddr = self.sock.accept()
428 if test_support.verbose and self.chatty:
429 sys.stdout.write(' server: new connection from '
430 + str(connaddr) + '\n')
431 handler = self.ConnectionHandler(self, newconn)
432 handler.start()
433 except socket.timeout:
434 pass
435 except KeyboardInterrupt:
436 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000437 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000438
Antoine Pitroud2867642010-04-28 21:12:43 +0000439 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000440 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000441
Bill Janssen934b16d2008-06-28 22:19:33 +0000442 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000443
Antoine Pitroud2867642010-04-28 21:12:43 +0000444 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000445
Antoine Pitroud2867642010-04-28 21:12:43 +0000446 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000447
448 def __init__(self, conn, certfile):
449 asyncore.dispatcher_with_send.__init__(self, conn)
450 self.socket = ssl.wrap_socket(conn, server_side=True,
451 certfile=certfile,
Antoine Pitrouc689d962010-04-24 20:13:37 +0000452 do_handshake_on_connect=False)
453 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000454
455 def readable(self):
456 if isinstance(self.socket, ssl.SSLSocket):
457 while self.socket.pending() > 0:
458 self.handle_read_event()
459 return True
460
Antoine Pitrouc689d962010-04-24 20:13:37 +0000461 def _do_ssl_handshake(self):
462 try:
463 self.socket.do_handshake()
464 except ssl.SSLError, err:
465 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
466 ssl.SSL_ERROR_WANT_WRITE):
467 return
468 elif err.args[0] == ssl.SSL_ERROR_EOF:
469 return self.handle_close()
470 raise
471 except socket.error, err:
472 if err.args[0] == errno.ECONNABORTED:
473 return self.handle_close()
474 else:
475 self._ssl_accepting = False
476
Bill Janssen934b16d2008-06-28 22:19:33 +0000477 def handle_read(self):
Antoine Pitrouc689d962010-04-24 20:13:37 +0000478 if self._ssl_accepting:
479 self._do_ssl_handshake()
480 else:
481 data = self.recv(1024)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000482 if data and data.strip() != 'over':
483 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000484
485 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000486 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000487 if test_support.verbose:
488 sys.stdout.write(" server: closed connection %s\n" % self.socket)
489
490 def handle_error(self):
491 raise
492
493 def __init__(self, certfile):
494 self.certfile = certfile
495 asyncore.dispatcher.__init__(self)
496 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
497 self.port = test_support.bind_port(self.socket)
498 self.listen(5)
499
500 def handle_accept(self):
501 sock_obj, addr = self.accept()
502 if test_support.verbose:
503 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
504 self.ConnectionHandler(sock_obj, self.certfile)
505
506 def handle_error(self):
507 raise
508
509 def __init__(self, certfile):
510 self.flag = None
511 self.active = False
512 self.server = self.EchoServer(certfile)
513 self.port = self.server.port
514 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000515 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000516
517 def __str__(self):
518 return "<%s %s>" % (self.__class__.__name__, self.server)
519
Antoine Pitroud2867642010-04-28 21:12:43 +0000520 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000521 self.flag = flag
522 threading.Thread.start(self)
523
Antoine Pitroud2867642010-04-28 21:12:43 +0000524 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000525 self.active = True
526 if self.flag:
527 self.flag.set()
528 while self.active:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000529 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000530
Antoine Pitroud2867642010-04-28 21:12:43 +0000531 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000532 self.active = False
533 self.server.close()
534
535 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000536
537 class HTTPSServer(HTTPServer):
538
539 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000540 HTTPServer.__init__(self, server_address, RequestHandlerClass)
541 # we assume the certfile contains both private key and certificate
542 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000543 self.allow_reuse_address = True
544
Bill Janssen934b16d2008-06-28 22:19:33 +0000545 def __str__(self):
546 return ('<%s %s:%s>' %
547 (self.__class__.__name__,
548 self.server_name,
549 self.server_port))
550
Antoine Pitroud2867642010-04-28 21:12:43 +0000551 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000552 # override this to wrap socket with SSL
553 sock, addr = self.socket.accept()
554 sslconn = ssl.wrap_socket(sock, server_side=True,
555 certfile=self.certfile)
556 return sslconn, addr
557
Bill Janssen296a59d2007-09-16 22:06:00 +0000558 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000559 # need to override translate_path to get a known root,
560 # instead of using os.curdir, since the test could be
561 # run from anywhere
562
563 server_version = "TestHTTPS/1.0"
564
565 root = None
566
567 def translate_path(self, path):
568 """Translate a /-separated PATH to the local filename syntax.
569
570 Components that mean special things to the local file system
571 (e.g. drive or directory names) are ignored. (XXX They should
572 probably be diagnosed.)
573
574 """
575 # abandon query parameters
576 path = urlparse.urlparse(path)[2]
577 path = os.path.normpath(urllib.unquote(path))
578 words = path.split('/')
579 words = filter(None, words)
580 path = self.root
581 for word in words:
582 drive, word = os.path.splitdrive(word)
583 head, word = os.path.split(word)
584 if word in self.root: continue
585 path = os.path.join(path, word)
586 return path
587
588 def log_message(self, format, *args):
589
590 # we override this to suppress logging unless "verbose"
591
592 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000593 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
594 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000595 self.server.server_port,
596 self.request.cipher(),
597 self.log_date_time_string(),
598 format%args))
599
600
Trent Nelsone41b0062008-04-08 23:47:30 +0000601 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000602 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000603 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
604 self.server = self.HTTPSServer(
Antoine Pitrou6535b312010-04-27 08:43:11 +0000605 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
606 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000607 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000608 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000609
610 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000611 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000612
Antoine Pitroud2867642010-04-28 21:12:43 +0000613 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000614 self.flag = flag
615 threading.Thread.start(self)
616
Antoine Pitroud2867642010-04-28 21:12:43 +0000617 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000618 if self.flag:
619 self.flag.set()
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000620 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000621
Antoine Pitroud2867642010-04-28 21:12:43 +0000622 def stop(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000623 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000624
625
Antoine Pitroud2867642010-04-28 21:12:43 +0000626 def bad_cert_test(certfile):
627 """
628 Launch a server with CERT_REQUIRED, and check that trying to
629 connect to it with the given client certificate fails.
630 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000631 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000632 certreqs=ssl.CERT_REQUIRED,
633 cacerts=CERTFILE, chatty=False)
634 flag = threading.Event()
635 server.start(flag)
636 # wait for it to start
637 flag.wait()
638 # try to connect
639 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000640 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000641 s = ssl.wrap_socket(socket.socket(),
642 certfile=certfile,
643 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000644 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000645 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000646 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000647 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000648 except socket.error, x:
649 if test_support.verbose:
650 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000651 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000652 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000653 finally:
654 server.stop()
655 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000656
Antoine Pitroud2867642010-04-28 21:12:43 +0000657 def server_params_test(certfile, protocol, certreqs, cacertsfile,
658 client_certfile, client_protocol=None, indata="FOO\n",
659 chatty=True, connectionchatty=False,
660 wrap_accepting_socket=False):
661 """
662 Launch a server, connect a client to it and try various reads
663 and writes.
664 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000665 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000666 certreqs=certreqs,
667 ssl_version=protocol,
668 cacerts=cacertsfile,
669 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000670 connectionchatty=connectionchatty,
671 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000672 flag = threading.Event()
673 server.start(flag)
674 # wait for it to start
675 flag.wait()
676 # try to connect
677 if client_protocol is None:
678 client_protocol = protocol
679 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000680 s = ssl.wrap_socket(socket.socket(),
681 certfile=client_certfile,
682 ca_certs=cacertsfile,
683 cert_reqs=certreqs,
684 ssl_version=client_protocol)
685 s.connect((HOST, server.port))
686 if connectionchatty:
687 if test_support.verbose:
688 sys.stdout.write(
689 " client: sending %s...\n" % (repr(indata)))
690 s.write(indata)
691 outdata = s.read()
692 if connectionchatty:
693 if test_support.verbose:
694 sys.stdout.write(" client: read %s\n" % repr(outdata))
695 if outdata != indata.lower():
696 self.fail(
697 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
698 % (outdata[:min(len(outdata),20)], len(outdata),
699 indata[:min(len(indata),20)].lower(), len(indata)))
700 s.write("over\n")
701 if connectionchatty:
702 if test_support.verbose:
703 sys.stdout.write(" client: closing connection.\n")
704 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000705 finally:
706 server.stop()
707 server.join()
708
Antoine Pitroud2867642010-04-28 21:12:43 +0000709 def try_protocol_combo(server_protocol,
710 client_protocol,
711 expect_success,
712 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000713 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000714 certsreqs = ssl.CERT_NONE
Antoine Pitroud2867642010-04-28 21:12:43 +0000715 certtype = {
716 ssl.CERT_NONE: "CERT_NONE",
717 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
718 ssl.CERT_REQUIRED: "CERT_REQUIRED",
719 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000720 if test_support.verbose:
Antoine Pitroud2867642010-04-28 21:12:43 +0000721 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000722 sys.stdout.write(formatstr %
723 (ssl.get_protocol_name(client_protocol),
724 ssl.get_protocol_name(server_protocol),
725 certtype))
726 try:
Antoine Pitroud2867642010-04-28 21:12:43 +0000727 server_params_test(CERTFILE, server_protocol, certsreqs,
728 CERTFILE, CERTFILE, client_protocol,
729 chatty=False)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000730 # Protocol mismatch can result in either an SSLError, or a
731 # "Connection reset by peer" error.
732 except ssl.SSLError:
Antoine Pitroud2867642010-04-28 21:12:43 +0000733 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000734 raise
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000735 except socket.error as e:
Antoine Pitroud2867642010-04-28 21:12:43 +0000736 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000737 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000738 else:
Antoine Pitroud2867642010-04-28 21:12:43 +0000739 if not expect_success:
Antoine Pitrou12226692010-05-06 13:49:10 +0000740 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000741 "Client protocol %s succeeded with server protocol %s!"
742 % (ssl.get_protocol_name(client_protocol),
743 ssl.get_protocol_name(server_protocol)))
744
745
Bill Janssen934b16d2008-06-28 22:19:33 +0000746 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000747
Antoine Pitroud2867642010-04-28 21:12:43 +0000748 def test_rude_shutdown(self):
749 """A brutal shutdown of an SSL server should raise an IOError
750 in the client when attempting handshake.
751 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000752 listener_ready = threading.Event()
753 listener_gone = threading.Event()
754
Antoine Pitrou6535b312010-04-27 08:43:11 +0000755 s = socket.socket()
756 port = test_support.bind_port(s, HOST)
757
758 # `listener` runs in a thread. It sits in an accept() until
759 # the main thread connects. Then it rudely closes the socket,
760 # and sets Event `listener_gone` to let the main thread know
761 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000762 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000763 s.listen(5)
764 listener_ready.set()
765 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000766 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000767 listener_gone.set()
768
769 def connector():
770 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000771 c = socket.socket()
772 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000773 listener_gone.wait()
774 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000775 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000776 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000777 pass
778 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000779 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000780
781 t = threading.Thread(target=listener)
782 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000783 try:
784 connector()
785 finally:
786 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000787
Antoine Pitroud2867642010-04-28 21:12:43 +0000788 def test_echo(self):
789 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000790 if test_support.verbose:
791 sys.stdout.write("\n")
Antoine Pitroud2867642010-04-28 21:12:43 +0000792 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
793 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
794 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000795
Antoine Pitroud2867642010-04-28 21:12:43 +0000796 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000797 if test_support.verbose:
798 sys.stdout.write("\n")
799 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000800 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000801 certreqs=ssl.CERT_NONE,
802 ssl_version=ssl.PROTOCOL_SSLv23,
803 cacerts=CERTFILE,
804 chatty=False)
805 flag = threading.Event()
806 server.start(flag)
807 # wait for it to start
808 flag.wait()
809 # try to connect
810 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000811 s = ssl.wrap_socket(socket.socket(),
812 certfile=CERTFILE,
813 ca_certs=CERTFILE,
814 cert_reqs=ssl.CERT_REQUIRED,
815 ssl_version=ssl.PROTOCOL_SSLv23)
816 s.connect((HOST, server.port))
817 cert = s.getpeercert()
818 self.assertTrue(cert, "Can't get peer certificate.")
819 cipher = s.cipher()
820 if test_support.verbose:
821 sys.stdout.write(pprint.pformat(cert) + '\n')
822 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
823 if 'subject' not in cert:
824 self.fail("No subject field in certificate: %s." %
825 pprint.pformat(cert))
826 if ((('organizationName', 'Python Software Foundation'),)
827 not in cert['subject']):
828 self.fail(
829 "Missing or invalid 'organizationName' field in certificate subject; "
830 "should be 'Python Software Foundation'.")
831 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000832 finally:
833 server.stop()
834 server.join()
835
Antoine Pitroud2867642010-04-28 21:12:43 +0000836 def test_empty_cert(self):
837 """Connecting with an empty cert file"""
838 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
839 "nullcert.pem"))
840 def test_malformed_cert(self):
841 """Connecting with a badly formatted certificate (syntax error)"""
842 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
843 "badcert.pem"))
844 def test_nonexisting_cert(self):
845 """Connecting with a non-existing cert file"""
846 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
847 "wrongcert.pem"))
848 def test_malformed_key(self):
849 """Connecting with a badly formatted key (syntax error)"""
850 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
851 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000852
Antoine Pitroud2867642010-04-28 21:12:43 +0000853 def test_protocol_sslv2(self):
854 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000855 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000856 sys.stdout.write("\ntest_protocol_sslv2 disabled, "
857 "as it fails on OpenSSL 1.0.0+")
858 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000859 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
860 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
861 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
862 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
863 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
864 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000865
Antoine Pitroud2867642010-04-28 21:12:43 +0000866 def test_protocol_sslv23(self):
867 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000868 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000869 sys.stdout.write("\ntest_protocol_sslv23 disabled, "
870 "as it fails on OpenSSL 1.0.0+")
871 return
Bill Janssen98d19da2007-09-10 21:51:02 +0000872 try:
Antoine Pitroud2867642010-04-28 21:12:43 +0000873 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000874 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000875 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
876 if test_support.verbose:
877 sys.stdout.write(
878 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
879 % str(x))
Antoine Pitroud2867642010-04-28 21:12:43 +0000880 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
881 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
882 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000883
Antoine Pitroud2867642010-04-28 21:12:43 +0000884 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
885 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
886 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000887
Antoine Pitroud2867642010-04-28 21:12:43 +0000888 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
889 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
890 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000891
Antoine Pitroud2867642010-04-28 21:12:43 +0000892 def test_protocol_sslv3(self):
893 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000894 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000895 sys.stdout.write("\ntest_protocol_sslv3 disabled, "
896 "as it fails on OpenSSL 1.0.0+")
897 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000898 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
899 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
900 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
901 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
902 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
903 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000904
Antoine Pitroud2867642010-04-28 21:12:43 +0000905 def test_protocol_tlsv1(self):
906 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000907 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000908 sys.stdout.write("\ntest_protocol_tlsv1 disabled, "
909 "as it fails on OpenSSL 1.0.0+")
910 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000911 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
912 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
913 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
914 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
915 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
916 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000917
Antoine Pitroud2867642010-04-28 21:12:43 +0000918 def test_starttls(self):
919 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000920 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000921
Trent Nelsone41b0062008-04-08 23:47:30 +0000922 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000923 ssl_version=ssl.PROTOCOL_TLSv1,
924 starttls_server=True,
925 chatty=True,
926 connectionchatty=True)
927 flag = threading.Event()
928 server.start(flag)
929 # wait for it to start
930 flag.wait()
931 # try to connect
932 wrapped = False
933 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000934 s = socket.socket()
935 s.setblocking(1)
936 s.connect((HOST, server.port))
937 if test_support.verbose:
938 sys.stdout.write("\n")
939 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000940 if test_support.verbose:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000941 sys.stdout.write(
942 " client: sending %s...\n" % repr(indata))
943 if wrapped:
944 conn.write(indata)
945 outdata = conn.read()
946 else:
947 s.send(indata)
948 outdata = s.recv(1024)
949 if (indata == "STARTTLS" and
950 outdata.strip().lower().startswith("ok")):
Antoine Pitroud2867642010-04-28 21:12:43 +0000951 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +0000952 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000953 sys.stdout.write(
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000954 " client: read %s from server, starting TLS...\n"
955 % repr(outdata))
956 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
957 wrapped = True
958 elif (indata == "ENDTLS" and
959 outdata.strip().lower().startswith("ok")):
Antoine Pitroud2867642010-04-28 21:12:43 +0000960 # ENDTLS ok, switch back to clear text
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000961 if test_support.verbose:
962 sys.stdout.write(
963 " client: read %s from server, ending TLS...\n"
964 % repr(outdata))
965 s = conn.unwrap()
966 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000967 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000968 if test_support.verbose:
969 sys.stdout.write(
970 " client: read %s from server\n" % repr(outdata))
971 if test_support.verbose:
972 sys.stdout.write(" client: closing connection.\n")
973 if wrapped:
974 conn.write("over\n")
975 else:
976 s.send("over\n")
977 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000978 finally:
979 server.stop()
980 server.join()
981
Antoine Pitroud2867642010-04-28 21:12:43 +0000982 def test_socketserver(self):
983 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +0000984 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000985 flag = threading.Event()
986 server.start(flag)
987 # wait for it to start
988 flag.wait()
989 # try to connect
990 try:
991 if test_support.verbose:
992 sys.stdout.write('\n')
Antoine Pitroud2867642010-04-28 21:12:43 +0000993 with open(CERTFILE, 'rb') as f:
994 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000995 d2 = ''
996 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +0000997 url = 'https://127.0.0.1:%d/%s' % (
998 server.port, os.path.split(CERTFILE)[1])
Ezio Melottia65e2af2010-08-02 19:56:05 +0000999 with test_support._check_py3k_warnings():
1000 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001001 dlen = f.info().getheader("content-length")
1002 if dlen and (int(dlen) > 0):
1003 d2 = f.read(int(dlen))
1004 if test_support.verbose:
1005 sys.stdout.write(
1006 " client: read %d bytes from remote server '%s'\n"
1007 % (len(d2), server))
1008 f.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001009 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001010 finally:
1011 server.stop()
1012 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001013
Antoine Pitroud2867642010-04-28 21:12:43 +00001014 def test_wrapped_accept(self):
1015 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001016 if test_support.verbose:
1017 sys.stdout.write("\n")
Antoine Pitroud2867642010-04-28 21:12:43 +00001018 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1019 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1020 chatty=True, connectionchatty=True,
1021 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001022
Antoine Pitroud2867642010-04-28 21:12:43 +00001023 def test_asyncore_server(self):
1024 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001025 indata = "TEST MESSAGE of mixed case\n"
1026
1027 if test_support.verbose:
1028 sys.stdout.write("\n")
1029 server = AsyncoreEchoServer(CERTFILE)
1030 flag = threading.Event()
1031 server.start(flag)
1032 # wait for it to start
1033 flag.wait()
1034 # try to connect
1035 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001036 s = ssl.wrap_socket(socket.socket())
1037 s.connect(('127.0.0.1', server.port))
1038 if test_support.verbose:
1039 sys.stdout.write(
1040 " client: sending %s...\n" % (repr(indata)))
1041 s.write(indata)
1042 outdata = s.read()
1043 if test_support.verbose:
1044 sys.stdout.write(" client: read %s\n" % repr(outdata))
1045 if outdata != indata.lower():
1046 self.fail(
1047 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1048 % (outdata[:min(len(outdata),20)], len(outdata),
1049 indata[:min(len(indata),20)].lower(), len(indata)))
1050 s.write("over\n")
1051 if test_support.verbose:
1052 sys.stdout.write(" client: closing connection.\n")
1053 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001054 finally:
1055 server.stop()
1056 # wait for server thread to end
1057 server.join()
1058
Antoine Pitroud2867642010-04-28 21:12:43 +00001059 def test_recv_send(self):
1060 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001061 if test_support.verbose:
1062 sys.stdout.write("\n")
1063
1064 server = ThreadedEchoServer(CERTFILE,
1065 certreqs=ssl.CERT_NONE,
1066 ssl_version=ssl.PROTOCOL_TLSv1,
1067 cacerts=CERTFILE,
1068 chatty=True,
1069 connectionchatty=False)
1070 flag = threading.Event()
1071 server.start(flag)
1072 # wait for it to start
1073 flag.wait()
1074 # try to connect
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001075 s = ssl.wrap_socket(socket.socket(),
1076 server_side=False,
1077 certfile=CERTFILE,
1078 ca_certs=CERTFILE,
1079 cert_reqs=ssl.CERT_NONE,
1080 ssl_version=ssl.PROTOCOL_TLSv1)
1081 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001082 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001083 # helper methods for standardising recv* method signatures
1084 def _recv_into():
1085 b = bytearray("\0"*100)
1086 count = s.recv_into(b)
1087 return b[:count]
1088
1089 def _recvfrom_into():
1090 b = bytearray("\0"*100)
1091 count, addr = s.recvfrom_into(b)
1092 return b[:count]
1093
1094 # (name, method, whether to expect success, *args)
1095 send_methods = [
1096 ('send', s.send, True, []),
1097 ('sendto', s.sendto, False, ["some.address"]),
1098 ('sendall', s.sendall, True, []),
1099 ]
1100 recv_methods = [
1101 ('recv', s.recv, True, []),
1102 ('recvfrom', s.recvfrom, False, ["some.address"]),
1103 ('recv_into', _recv_into, True, []),
1104 ('recvfrom_into', _recvfrom_into, False, []),
1105 ]
1106 data_prefix = u"PREFIX_"
1107
1108 for meth_name, send_meth, expect_success, args in send_methods:
1109 indata = data_prefix + meth_name
1110 try:
1111 send_meth(indata.encode('ASCII', 'strict'), *args)
1112 outdata = s.read()
1113 outdata = outdata.decode('ASCII', 'strict')
1114 if outdata != indata.lower():
1115 raise support.TestFailed(
1116 "While sending with <<%s>> bad data "
1117 "<<%r>> (%d) received; "
1118 "expected <<%r>> (%d)\n" % (
1119 meth_name, outdata[:20], len(outdata),
1120 indata[:20], len(indata)
1121 )
1122 )
1123 except ValueError as e:
1124 if expect_success:
1125 raise support.TestFailed(
1126 "Failed to send with method <<%s>>; "
1127 "expected to succeed.\n" % (meth_name,)
1128 )
1129 if not str(e).startswith(meth_name):
1130 raise support.TestFailed(
1131 "Method <<%s>> failed with unexpected "
1132 "exception message: %s\n" % (
1133 meth_name, e
1134 )
1135 )
1136
1137 for meth_name, recv_meth, expect_success, args in recv_methods:
1138 indata = data_prefix + meth_name
1139 try:
1140 s.send(indata.encode('ASCII', 'strict'))
1141 outdata = recv_meth(*args)
1142 outdata = outdata.decode('ASCII', 'strict')
1143 if outdata != indata.lower():
1144 raise support.TestFailed(
1145 "While receiving with <<%s>> bad data "
1146 "<<%r>> (%d) received; "
1147 "expected <<%r>> (%d)\n" % (
1148 meth_name, outdata[:20], len(outdata),
1149 indata[:20], len(indata)
1150 )
1151 )
1152 except ValueError as e:
1153 if expect_success:
1154 raise support.TestFailed(
1155 "Failed to receive with method <<%s>>; "
1156 "expected to succeed.\n" % (meth_name,)
1157 )
1158 if not str(e).startswith(meth_name):
1159 raise support.TestFailed(
1160 "Method <<%s>> failed with unexpected "
1161 "exception message: %s\n" % (
1162 meth_name, e
1163 )
1164 )
1165 # consume data
1166 s.read()
1167
1168 s.write("over\n".encode("ASCII", "strict"))
1169 s.close()
1170 finally:
1171 server.stop()
1172 server.join()
1173
Antoine Pitrouc689d962010-04-24 20:13:37 +00001174 def test_handshake_timeout(self):
1175 # Issue #5103: SSL handshake must respect the socket timeout
1176 server = socket.socket(socket.AF_INET)
1177 host = "127.0.0.1"
1178 port = test_support.bind_port(server)
1179 started = threading.Event()
1180 finish = False
1181
1182 def serve():
1183 server.listen(5)
1184 started.set()
1185 conns = []
1186 while not finish:
1187 r, w, e = select.select([server], [], [], 0.1)
1188 if server in r:
1189 # Let the socket hang around rather than having
1190 # it closed by garbage collection.
1191 conns.append(server.accept()[0])
1192
1193 t = threading.Thread(target=serve)
1194 t.start()
1195 started.wait()
1196
1197 try:
1198 try:
1199 c = socket.socket(socket.AF_INET)
1200 c.settimeout(0.2)
1201 c.connect((host, port))
1202 # Will attempt handshake and time out
1203 try:
1204 ssl.wrap_socket(c)
1205 except ssl.SSLError, e:
1206 self.assertTrue("timed out" in str(e), str(e))
1207 else:
1208 self.fail("SSLError wasn't raised")
1209 finally:
1210 c.close()
1211 try:
1212 c = socket.socket(socket.AF_INET)
1213 c.settimeout(0.2)
1214 c = ssl.wrap_socket(c)
1215 # Will attempt handshake and time out
1216 try:
1217 c.connect((host, port))
1218 except ssl.SSLError, e:
1219 self.assertTrue("timed out" in str(e), str(e))
1220 else:
1221 self.fail("SSLError wasn't raised")
1222 finally:
1223 c.close()
1224 finally:
1225 finish = True
1226 t.join()
1227 server.close()
1228
Bill Janssen61c001a2008-09-08 16:37:24 +00001229
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001230def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001231 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001232 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001233
Barry Warsaw82f88282013-08-23 13:26:49 -04001234 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NULLBYTECERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001235 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001236 "keycert.pem")
1237 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1238 os.path.dirname(__file__) or os.curdir,
1239 "https_svn_python_org_root.pem")
Barry Warsaw82f88282013-08-23 13:26:49 -04001240 NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1241 "nullbytecert.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001242
1243 if (not os.path.exists(CERTFILE) or
Barry Warsaw82f88282013-08-23 13:26:49 -04001244 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
1245 not os.path.exists(NULLBYTECERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001246 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001247
1248 tests = [BasicTests]
1249
Bill Janssen296a59d2007-09-16 22:06:00 +00001250 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001251 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001252
Bill Janssen98d19da2007-09-10 21:51:02 +00001253 if _have_threads:
1254 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001255 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001256 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001257
Antoine Pitroud2867642010-04-28 21:12:43 +00001258 try:
1259 test_support.run_unittest(*tests)
1260 finally:
1261 if _have_threads:
1262 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001263
1264if __name__ == "__main__":
1265 test_main()