blob: f779dbae2260aef767a9c18544f3ee6ded9032bd [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 Heimes8f65ef82013-08-25 14:12:41 +0200105 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
106 san = (('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 else:
112 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
113 san = (('DNS', 'altnull.python.org\x00example.com'),
114 ('email', 'null@python.org\x00user@example.org'),
115 ('URI', 'http://null.python.org\x00http://example.org'),
116 ('IP Address', '192.0.2.1'),
117 ('IP Address', '<invalid>'))
118
119 self.assertEqual(p['subjectAltName'], san)
Barry Warsaw82f88282013-08-23 13:26:49 -0400120
Antoine Pitroud2867642010-04-28 21:12:43 +0000121 def test_DER_to_PEM(self):
122 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
123 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000124 d1 = ssl.PEM_cert_to_DER_cert(pem)
125 p2 = ssl.DER_cert_to_PEM_cert(d1)
126 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000127 self.assertEqual(d1, d2)
Antoine Pitrou12cb1292010-04-27 22:05:18 +0000128 if not p2.startswith(ssl.PEM_HEADER + '\n'):
129 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
130 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
131 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000132
Antoine Pitrou3df58d12010-04-23 23:07:37 +0000133 def test_refcycle(self):
134 # Issue #7943: an SSL object doesn't create reference cycles with
135 # itself.
136 s = socket.socket(socket.AF_INET)
137 ss = ssl.wrap_socket(s)
138 wr = weakref.ref(ss)
139 del ss
140 self.assertEqual(wr(), None)
141
Antoine Pitroud4030da2010-04-23 23:35:01 +0000142
Bill Janssen934b16d2008-06-28 22:19:33 +0000143class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000144
Antoine Pitroud2867642010-04-28 21:12:43 +0000145 def test_connect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000146 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
147 cert_reqs=ssl.CERT_NONE)
148 s.connect(("svn.python.org", 443))
149 c = s.getpeercert()
150 if c:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000151 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000152 s.close()
153
154 # this should fail because we have no verification certs
155 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
156 cert_reqs=ssl.CERT_REQUIRED)
157 try:
158 s.connect(("svn.python.org", 443))
159 except ssl.SSLError:
160 pass
161 finally:
162 s.close()
163
164 # this should succeed because we specify the root cert
165 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
166 cert_reqs=ssl.CERT_REQUIRED,
167 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
168 try:
169 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000170 finally:
171 s.close()
172
Antoine Pitrou0753d942010-04-24 11:09:52 +0000173 def test_makefile_close(self):
174 # Issue #5238: creating a file-like object with makefile() shouldn't
175 # delay closing the underlying "real socket" (here tested with its
176 # file descriptor, hence skipping the test under Windows).
177 if os.name == "nt":
178 if test_support.verbose:
179 print "Skipped: can't use a socket as a file under Windows"
180 return
181 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
182 ss.connect(("svn.python.org", 443))
183 fd = ss.fileno()
184 f = ss.makefile()
185 f.close()
186 # The fd is still open
187 os.read(fd, 0)
188 # Closing the SSL socket should close the fd too
189 ss.close()
190 gc.collect()
191 try:
192 os.read(fd, 0)
193 except OSError, e:
194 self.assertEqual(e.errno, errno.EBADF)
195 else:
196 self.fail("OSError wasn't raised")
Bill Janssen934b16d2008-06-28 22:19:33 +0000197
Antoine Pitroud2867642010-04-28 21:12:43 +0000198 def test_non_blocking_handshake(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000199 s = socket.socket(socket.AF_INET)
200 s.connect(("svn.python.org", 443))
201 s.setblocking(False)
202 s = ssl.wrap_socket(s,
203 cert_reqs=ssl.CERT_NONE,
204 do_handshake_on_connect=False)
205 count = 0
206 while True:
207 try:
208 count += 1
209 s.do_handshake()
210 break
211 except ssl.SSLError, err:
212 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
213 select.select([s], [], [])
214 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
215 select.select([], [s], [])
216 else:
217 raise
218 s.close()
219 if test_support.verbose:
220 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
221
Antoine Pitroud2867642010-04-28 21:12:43 +0000222 def test_get_server_certificate(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000223 pem = ssl.get_server_certificate(("svn.python.org", 443))
224 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000225 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000226
227 try:
228 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
229 except ssl.SSLError:
230 #should fail
231 pass
232 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000233 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000234
235 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
236 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000237 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000238 if test_support.verbose:
239 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
240
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000241 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000242 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000243 if test_support.verbose:
244 sys.stdout.write("test_algorithms disabled, "
245 "as it fails on some old OpenSSL versions")
246 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000247 # Issue #8484: all algorithms should be available when verifying a
248 # certificate.
249 # NOTE: https://sha256.tbs-internet.com is another possible test host
250 remote = ("sha2.hboeck.de", 443)
251 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
252 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
253 cert_reqs=ssl.CERT_REQUIRED,
254 ca_certs=sha256_cert,)
255 with test_support.transient_internet():
256 try:
257 s.connect(remote)
258 if test_support.verbose:
259 sys.stdout.write("\nCipher with %r is %r\n" %
260 (remote, s.cipher()))
261 sys.stdout.write("Certificate is:\n%s\n" %
262 pprint.pformat(s.getpeercert()))
263 finally:
264 s.close()
265
Bill Janssen296a59d2007-09-16 22:06:00 +0000266
Bill Janssen98d19da2007-09-10 21:51:02 +0000267try:
268 import threading
269except ImportError:
270 _have_threads = False
271else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000272 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000273
Bill Janssen98d19da2007-09-10 21:51:02 +0000274 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000275
Bill Janssen98d19da2007-09-10 21:51:02 +0000276 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000277
Bill Janssen98d19da2007-09-10 21:51:02 +0000278 """A mildly complicated class, because we want it to work both
279 with and without the SSL wrapper around the socket connection, so
280 that we can test the STARTTLS functionality."""
281
282 def __init__(self, server, connsock):
283 self.server = server
284 self.running = False
285 self.sock = connsock
286 self.sock.setblocking(1)
287 self.sslconn = None
288 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000289 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000290
Bill Janssen934b16d2008-06-28 22:19:33 +0000291 def show_conn_details(self):
292 if self.server.certreqs == ssl.CERT_REQUIRED:
293 cert = self.sslconn.getpeercert()
294 if test_support.verbose and self.server.chatty:
295 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
296 cert_binary = self.sslconn.getpeercert(True)
297 if test_support.verbose and self.server.chatty:
298 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
299 cipher = self.sslconn.cipher()
300 if test_support.verbose and self.server.chatty:
301 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
302
Antoine Pitroud2867642010-04-28 21:12:43 +0000303 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000304 try:
305 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
306 certfile=self.server.certificate,
307 ssl_version=self.server.protocol,
308 ca_certs=self.server.cacerts,
309 cert_reqs=self.server.certreqs)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000310 except ssl.SSLError:
311 # XXX Various errors can have happened here, for example
312 # a mismatching protocol version, an invalid certificate,
313 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000314 if self.server.chatty:
315 handle_error("\n server: bad connection attempt from " +
316 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000317 self.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000318 self.running = False
319 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000320 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000321 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000322 return True
323
324 def read(self):
325 if self.sslconn:
326 return self.sslconn.read()
327 else:
328 return self.sock.recv(1024)
329
330 def write(self, bytes):
331 if self.sslconn:
332 return self.sslconn.write(bytes)
333 else:
334 return self.sock.send(bytes)
335
336 def close(self):
337 if self.sslconn:
338 self.sslconn.close()
339 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000340 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000341
Antoine Pitroud2867642010-04-28 21:12:43 +0000342 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000343 self.running = True
344 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000345 if isinstance(self.sock, ssl.SSLSocket):
346 self.sslconn = self.sock
347 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000348 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000349 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000350 while self.running:
351 try:
352 msg = self.read()
353 if not msg:
354 # eof, so quit this handler
355 self.running = False
356 self.close()
357 elif msg.strip() == 'over':
358 if test_support.verbose and self.server.connectionchatty:
359 sys.stdout.write(" server: client closed connection\n")
360 self.close()
361 return
362 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
363 if test_support.verbose and self.server.connectionchatty:
364 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
365 self.write("OK\n")
366 if not self.wrap_conn():
367 return
Bill Janssen39295c22008-08-12 16:31:21 +0000368 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
369 if test_support.verbose and self.server.connectionchatty:
370 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
371 self.write("OK\n")
372 self.sslconn.unwrap()
373 self.sslconn = None
374 if test_support.verbose and self.server.connectionchatty:
375 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000376 else:
377 if (test_support.verbose and
378 self.server.connectionchatty):
379 ctype = (self.sslconn and "encrypted") or "unencrypted"
380 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
381 % (repr(msg), ctype, repr(msg.lower()), ctype))
382 self.write(msg.lower())
383 except ssl.SSLError:
384 if self.server.chatty:
385 handle_error("Test server failure:\n")
386 self.close()
387 self.running = False
388 # normally, we'd just stop here, but for the test
389 # harness, we want to stop the server
390 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000391
Trent Nelsone41b0062008-04-08 23:47:30 +0000392 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000393 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000394 chatty=True, connectionchatty=False, starttls_server=False,
395 wrap_accepting_socket=False):
396
Bill Janssen98d19da2007-09-10 21:51:02 +0000397 if ssl_version is None:
398 ssl_version = ssl.PROTOCOL_TLSv1
399 if certreqs is None:
400 certreqs = ssl.CERT_NONE
401 self.certificate = certificate
402 self.protocol = ssl_version
403 self.certreqs = certreqs
404 self.cacerts = cacerts
Bill Janssen98d19da2007-09-10 21:51:02 +0000405 self.chatty = chatty
406 self.connectionchatty = connectionchatty
407 self.starttls_server = starttls_server
408 self.sock = socket.socket()
409 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000410 if wrap_accepting_socket:
411 self.sock = ssl.wrap_socket(self.sock, server_side=True,
412 certfile=self.certificate,
413 cert_reqs = self.certreqs,
414 ca_certs = self.cacerts,
415 ssl_version = self.protocol)
416 if test_support.verbose and self.chatty:
417 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
418 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000419 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000420 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000421 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000422
Antoine Pitroud2867642010-04-28 21:12:43 +0000423 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000424 self.flag = flag
425 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000426
Antoine Pitroud2867642010-04-28 21:12:43 +0000427 def run(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000428 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000429 self.sock.listen(5)
430 self.active = True
431 if self.flag:
432 # signal an event
433 self.flag.set()
434 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000435 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000436 newconn, connaddr = self.sock.accept()
437 if test_support.verbose and self.chatty:
438 sys.stdout.write(' server: new connection from '
439 + str(connaddr) + '\n')
440 handler = self.ConnectionHandler(self, newconn)
441 handler.start()
442 except socket.timeout:
443 pass
444 except KeyboardInterrupt:
445 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000446 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000447
Antoine Pitroud2867642010-04-28 21:12:43 +0000448 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000449 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000450
Bill Janssen934b16d2008-06-28 22:19:33 +0000451 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000452
Antoine Pitroud2867642010-04-28 21:12:43 +0000453 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000454
Antoine Pitroud2867642010-04-28 21:12:43 +0000455 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000456
457 def __init__(self, conn, certfile):
458 asyncore.dispatcher_with_send.__init__(self, conn)
459 self.socket = ssl.wrap_socket(conn, server_side=True,
460 certfile=certfile,
Antoine Pitrouc689d962010-04-24 20:13:37 +0000461 do_handshake_on_connect=False)
462 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000463
464 def readable(self):
465 if isinstance(self.socket, ssl.SSLSocket):
466 while self.socket.pending() > 0:
467 self.handle_read_event()
468 return True
469
Antoine Pitrouc689d962010-04-24 20:13:37 +0000470 def _do_ssl_handshake(self):
471 try:
472 self.socket.do_handshake()
473 except ssl.SSLError, err:
474 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
475 ssl.SSL_ERROR_WANT_WRITE):
476 return
477 elif err.args[0] == ssl.SSL_ERROR_EOF:
478 return self.handle_close()
479 raise
480 except socket.error, err:
481 if err.args[0] == errno.ECONNABORTED:
482 return self.handle_close()
483 else:
484 self._ssl_accepting = False
485
Bill Janssen934b16d2008-06-28 22:19:33 +0000486 def handle_read(self):
Antoine Pitrouc689d962010-04-24 20:13:37 +0000487 if self._ssl_accepting:
488 self._do_ssl_handshake()
489 else:
490 data = self.recv(1024)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000491 if data and data.strip() != 'over':
492 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000493
494 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000495 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000496 if test_support.verbose:
497 sys.stdout.write(" server: closed connection %s\n" % self.socket)
498
499 def handle_error(self):
500 raise
501
502 def __init__(self, certfile):
503 self.certfile = certfile
504 asyncore.dispatcher.__init__(self)
505 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
506 self.port = test_support.bind_port(self.socket)
507 self.listen(5)
508
509 def handle_accept(self):
510 sock_obj, addr = self.accept()
511 if test_support.verbose:
512 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
513 self.ConnectionHandler(sock_obj, self.certfile)
514
515 def handle_error(self):
516 raise
517
518 def __init__(self, certfile):
519 self.flag = None
520 self.active = False
521 self.server = self.EchoServer(certfile)
522 self.port = self.server.port
523 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000524 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000525
526 def __str__(self):
527 return "<%s %s>" % (self.__class__.__name__, self.server)
528
Antoine Pitroud2867642010-04-28 21:12:43 +0000529 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000530 self.flag = flag
531 threading.Thread.start(self)
532
Antoine Pitroud2867642010-04-28 21:12:43 +0000533 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000534 self.active = True
535 if self.flag:
536 self.flag.set()
537 while self.active:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000538 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000539
Antoine Pitroud2867642010-04-28 21:12:43 +0000540 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000541 self.active = False
542 self.server.close()
543
544 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000545
546 class HTTPSServer(HTTPServer):
547
548 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000549 HTTPServer.__init__(self, server_address, RequestHandlerClass)
550 # we assume the certfile contains both private key and certificate
551 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000552 self.allow_reuse_address = True
553
Bill Janssen934b16d2008-06-28 22:19:33 +0000554 def __str__(self):
555 return ('<%s %s:%s>' %
556 (self.__class__.__name__,
557 self.server_name,
558 self.server_port))
559
Antoine Pitroud2867642010-04-28 21:12:43 +0000560 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000561 # override this to wrap socket with SSL
562 sock, addr = self.socket.accept()
563 sslconn = ssl.wrap_socket(sock, server_side=True,
564 certfile=self.certfile)
565 return sslconn, addr
566
Bill Janssen296a59d2007-09-16 22:06:00 +0000567 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000568 # need to override translate_path to get a known root,
569 # instead of using os.curdir, since the test could be
570 # run from anywhere
571
572 server_version = "TestHTTPS/1.0"
573
574 root = None
575
576 def translate_path(self, path):
577 """Translate a /-separated PATH to the local filename syntax.
578
579 Components that mean special things to the local file system
580 (e.g. drive or directory names) are ignored. (XXX They should
581 probably be diagnosed.)
582
583 """
584 # abandon query parameters
585 path = urlparse.urlparse(path)[2]
586 path = os.path.normpath(urllib.unquote(path))
587 words = path.split('/')
588 words = filter(None, words)
589 path = self.root
590 for word in words:
591 drive, word = os.path.splitdrive(word)
592 head, word = os.path.split(word)
593 if word in self.root: continue
594 path = os.path.join(path, word)
595 return path
596
597 def log_message(self, format, *args):
598
599 # we override this to suppress logging unless "verbose"
600
601 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000602 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
603 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000604 self.server.server_port,
605 self.request.cipher(),
606 self.log_date_time_string(),
607 format%args))
608
609
Trent Nelsone41b0062008-04-08 23:47:30 +0000610 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000611 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000612 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
613 self.server = self.HTTPSServer(
Antoine Pitrou6535b312010-04-27 08:43:11 +0000614 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
615 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000616 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000617 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000618
619 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000620 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000621
Antoine Pitroud2867642010-04-28 21:12:43 +0000622 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000623 self.flag = flag
624 threading.Thread.start(self)
625
Antoine Pitroud2867642010-04-28 21:12:43 +0000626 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000627 if self.flag:
628 self.flag.set()
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000629 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000630
Antoine Pitroud2867642010-04-28 21:12:43 +0000631 def stop(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000632 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000633
634
Antoine Pitroud2867642010-04-28 21:12:43 +0000635 def bad_cert_test(certfile):
636 """
637 Launch a server with CERT_REQUIRED, and check that trying to
638 connect to it with the given client certificate fails.
639 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000640 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000641 certreqs=ssl.CERT_REQUIRED,
642 cacerts=CERTFILE, chatty=False)
643 flag = threading.Event()
644 server.start(flag)
645 # wait for it to start
646 flag.wait()
647 # try to connect
648 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000649 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000650 s = ssl.wrap_socket(socket.socket(),
651 certfile=certfile,
652 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000653 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000654 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000655 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000656 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000657 except socket.error, x:
658 if test_support.verbose:
659 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000660 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000661 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000662 finally:
663 server.stop()
664 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000665
Antoine Pitroud2867642010-04-28 21:12:43 +0000666 def server_params_test(certfile, protocol, certreqs, cacertsfile,
667 client_certfile, client_protocol=None, indata="FOO\n",
668 chatty=True, connectionchatty=False,
669 wrap_accepting_socket=False):
670 """
671 Launch a server, connect a client to it and try various reads
672 and writes.
673 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000674 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000675 certreqs=certreqs,
676 ssl_version=protocol,
677 cacerts=cacertsfile,
678 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000679 connectionchatty=connectionchatty,
680 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000681 flag = threading.Event()
682 server.start(flag)
683 # wait for it to start
684 flag.wait()
685 # try to connect
686 if client_protocol is None:
687 client_protocol = protocol
688 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000689 s = ssl.wrap_socket(socket.socket(),
690 certfile=client_certfile,
691 ca_certs=cacertsfile,
692 cert_reqs=certreqs,
693 ssl_version=client_protocol)
694 s.connect((HOST, server.port))
695 if connectionchatty:
696 if test_support.verbose:
697 sys.stdout.write(
698 " client: sending %s...\n" % (repr(indata)))
699 s.write(indata)
700 outdata = s.read()
701 if connectionchatty:
702 if test_support.verbose:
703 sys.stdout.write(" client: read %s\n" % repr(outdata))
704 if outdata != indata.lower():
705 self.fail(
706 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
707 % (outdata[:min(len(outdata),20)], len(outdata),
708 indata[:min(len(indata),20)].lower(), len(indata)))
709 s.write("over\n")
710 if connectionchatty:
711 if test_support.verbose:
712 sys.stdout.write(" client: closing connection.\n")
713 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000714 finally:
715 server.stop()
716 server.join()
717
Antoine Pitroud2867642010-04-28 21:12:43 +0000718 def try_protocol_combo(server_protocol,
719 client_protocol,
720 expect_success,
721 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000722 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000723 certsreqs = ssl.CERT_NONE
Antoine Pitroud2867642010-04-28 21:12:43 +0000724 certtype = {
725 ssl.CERT_NONE: "CERT_NONE",
726 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
727 ssl.CERT_REQUIRED: "CERT_REQUIRED",
728 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000729 if test_support.verbose:
Antoine Pitroud2867642010-04-28 21:12:43 +0000730 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000731 sys.stdout.write(formatstr %
732 (ssl.get_protocol_name(client_protocol),
733 ssl.get_protocol_name(server_protocol),
734 certtype))
735 try:
Antoine Pitroud2867642010-04-28 21:12:43 +0000736 server_params_test(CERTFILE, server_protocol, certsreqs,
737 CERTFILE, CERTFILE, client_protocol,
738 chatty=False)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000739 # Protocol mismatch can result in either an SSLError, or a
740 # "Connection reset by peer" error.
741 except ssl.SSLError:
Antoine Pitroud2867642010-04-28 21:12:43 +0000742 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000743 raise
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000744 except socket.error as e:
Antoine Pitroud2867642010-04-28 21:12:43 +0000745 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000746 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000747 else:
Antoine Pitroud2867642010-04-28 21:12:43 +0000748 if not expect_success:
Antoine Pitrou12226692010-05-06 13:49:10 +0000749 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000750 "Client protocol %s succeeded with server protocol %s!"
751 % (ssl.get_protocol_name(client_protocol),
752 ssl.get_protocol_name(server_protocol)))
753
754
Bill Janssen934b16d2008-06-28 22:19:33 +0000755 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000756
Antoine Pitroud2867642010-04-28 21:12:43 +0000757 def test_rude_shutdown(self):
758 """A brutal shutdown of an SSL server should raise an IOError
759 in the client when attempting handshake.
760 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000761 listener_ready = threading.Event()
762 listener_gone = threading.Event()
763
Antoine Pitrou6535b312010-04-27 08:43:11 +0000764 s = socket.socket()
765 port = test_support.bind_port(s, HOST)
766
767 # `listener` runs in a thread. It sits in an accept() until
768 # the main thread connects. Then it rudely closes the socket,
769 # and sets Event `listener_gone` to let the main thread know
770 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000771 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000772 s.listen(5)
773 listener_ready.set()
774 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000775 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000776 listener_gone.set()
777
778 def connector():
779 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000780 c = socket.socket()
781 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000782 listener_gone.wait()
783 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000784 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000785 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000786 pass
787 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000788 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000789
790 t = threading.Thread(target=listener)
791 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000792 try:
793 connector()
794 finally:
795 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000796
Antoine Pitroud2867642010-04-28 21:12:43 +0000797 def test_echo(self):
798 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000799 if test_support.verbose:
800 sys.stdout.write("\n")
Antoine Pitroud2867642010-04-28 21:12:43 +0000801 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
802 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
803 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000804
Antoine Pitroud2867642010-04-28 21:12:43 +0000805 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000806 if test_support.verbose:
807 sys.stdout.write("\n")
808 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000809 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000810 certreqs=ssl.CERT_NONE,
811 ssl_version=ssl.PROTOCOL_SSLv23,
812 cacerts=CERTFILE,
813 chatty=False)
814 flag = threading.Event()
815 server.start(flag)
816 # wait for it to start
817 flag.wait()
818 # try to connect
819 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000820 s = ssl.wrap_socket(socket.socket(),
821 certfile=CERTFILE,
822 ca_certs=CERTFILE,
823 cert_reqs=ssl.CERT_REQUIRED,
824 ssl_version=ssl.PROTOCOL_SSLv23)
825 s.connect((HOST, server.port))
826 cert = s.getpeercert()
827 self.assertTrue(cert, "Can't get peer certificate.")
828 cipher = s.cipher()
829 if test_support.verbose:
830 sys.stdout.write(pprint.pformat(cert) + '\n')
831 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
832 if 'subject' not in cert:
833 self.fail("No subject field in certificate: %s." %
834 pprint.pformat(cert))
835 if ((('organizationName', 'Python Software Foundation'),)
836 not in cert['subject']):
837 self.fail(
838 "Missing or invalid 'organizationName' field in certificate subject; "
839 "should be 'Python Software Foundation'.")
840 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000841 finally:
842 server.stop()
843 server.join()
844
Antoine Pitroud2867642010-04-28 21:12:43 +0000845 def test_empty_cert(self):
846 """Connecting with an empty cert file"""
847 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
848 "nullcert.pem"))
849 def test_malformed_cert(self):
850 """Connecting with a badly formatted certificate (syntax error)"""
851 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
852 "badcert.pem"))
853 def test_nonexisting_cert(self):
854 """Connecting with a non-existing cert file"""
855 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
856 "wrongcert.pem"))
857 def test_malformed_key(self):
858 """Connecting with a badly formatted key (syntax error)"""
859 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
860 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000861
Antoine Pitroud2867642010-04-28 21:12:43 +0000862 def test_protocol_sslv2(self):
863 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000864 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000865 sys.stdout.write("\ntest_protocol_sslv2 disabled, "
866 "as it fails on OpenSSL 1.0.0+")
867 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000868 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
869 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
870 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
871 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
872 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
873 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000874
Antoine Pitroud2867642010-04-28 21:12:43 +0000875 def test_protocol_sslv23(self):
876 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000877 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000878 sys.stdout.write("\ntest_protocol_sslv23 disabled, "
879 "as it fails on OpenSSL 1.0.0+")
880 return
Bill Janssen98d19da2007-09-10 21:51:02 +0000881 try:
Antoine Pitroud2867642010-04-28 21:12:43 +0000882 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000883 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000884 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
885 if test_support.verbose:
886 sys.stdout.write(
887 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
888 % str(x))
Antoine Pitroud2867642010-04-28 21:12:43 +0000889 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
890 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
891 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000892
Antoine Pitroud2867642010-04-28 21:12:43 +0000893 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
894 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
895 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000896
Antoine Pitroud2867642010-04-28 21:12:43 +0000897 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
898 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
899 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000900
Antoine Pitroud2867642010-04-28 21:12:43 +0000901 def test_protocol_sslv3(self):
902 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000903 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000904 sys.stdout.write("\ntest_protocol_sslv3 disabled, "
905 "as it fails on OpenSSL 1.0.0+")
906 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000907 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
908 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
909 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
910 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
911 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
912 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000913
Antoine Pitroud2867642010-04-28 21:12:43 +0000914 def test_protocol_tlsv1(self):
915 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000916 if test_support.verbose:
Antoine Pitrou12226692010-05-06 13:49:10 +0000917 sys.stdout.write("\ntest_protocol_tlsv1 disabled, "
918 "as it fails on OpenSSL 1.0.0+")
919 return
Antoine Pitroud2867642010-04-28 21:12:43 +0000920 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
921 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
922 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
923 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
924 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
925 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000926
Antoine Pitroud2867642010-04-28 21:12:43 +0000927 def test_starttls(self):
928 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000929 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000930
Trent Nelsone41b0062008-04-08 23:47:30 +0000931 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000932 ssl_version=ssl.PROTOCOL_TLSv1,
933 starttls_server=True,
934 chatty=True,
935 connectionchatty=True)
936 flag = threading.Event()
937 server.start(flag)
938 # wait for it to start
939 flag.wait()
940 # try to connect
941 wrapped = False
942 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000943 s = socket.socket()
944 s.setblocking(1)
945 s.connect((HOST, server.port))
946 if test_support.verbose:
947 sys.stdout.write("\n")
948 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000949 if test_support.verbose:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000950 sys.stdout.write(
951 " client: sending %s...\n" % repr(indata))
952 if wrapped:
953 conn.write(indata)
954 outdata = conn.read()
955 else:
956 s.send(indata)
957 outdata = s.recv(1024)
958 if (indata == "STARTTLS" and
959 outdata.strip().lower().startswith("ok")):
Antoine Pitroud2867642010-04-28 21:12:43 +0000960 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +0000961 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000962 sys.stdout.write(
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000963 " client: read %s from server, starting TLS...\n"
964 % repr(outdata))
965 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
966 wrapped = True
967 elif (indata == "ENDTLS" and
968 outdata.strip().lower().startswith("ok")):
Antoine Pitroud2867642010-04-28 21:12:43 +0000969 # ENDTLS ok, switch back to clear text
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000970 if test_support.verbose:
971 sys.stdout.write(
972 " client: read %s from server, ending TLS...\n"
973 % repr(outdata))
974 s = conn.unwrap()
975 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000976 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000977 if test_support.verbose:
978 sys.stdout.write(
979 " client: read %s from server\n" % repr(outdata))
980 if test_support.verbose:
981 sys.stdout.write(" client: closing connection.\n")
982 if wrapped:
983 conn.write("over\n")
984 else:
985 s.send("over\n")
986 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000987 finally:
988 server.stop()
989 server.join()
990
Antoine Pitroud2867642010-04-28 21:12:43 +0000991 def test_socketserver(self):
992 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +0000993 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000994 flag = threading.Event()
995 server.start(flag)
996 # wait for it to start
997 flag.wait()
998 # try to connect
999 try:
1000 if test_support.verbose:
1001 sys.stdout.write('\n')
Antoine Pitroud2867642010-04-28 21:12:43 +00001002 with open(CERTFILE, 'rb') as f:
1003 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001004 d2 = ''
1005 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001006 url = 'https://127.0.0.1:%d/%s' % (
1007 server.port, os.path.split(CERTFILE)[1])
Ezio Melottia65e2af2010-08-02 19:56:05 +00001008 with test_support._check_py3k_warnings():
1009 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001010 dlen = f.info().getheader("content-length")
1011 if dlen and (int(dlen) > 0):
1012 d2 = f.read(int(dlen))
1013 if test_support.verbose:
1014 sys.stdout.write(
1015 " client: read %d bytes from remote server '%s'\n"
1016 % (len(d2), server))
1017 f.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001018 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001019 finally:
1020 server.stop()
1021 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001022
Antoine Pitroud2867642010-04-28 21:12:43 +00001023 def test_wrapped_accept(self):
1024 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001025 if test_support.verbose:
1026 sys.stdout.write("\n")
Antoine Pitroud2867642010-04-28 21:12:43 +00001027 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1028 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1029 chatty=True, connectionchatty=True,
1030 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001031
Antoine Pitroud2867642010-04-28 21:12:43 +00001032 def test_asyncore_server(self):
1033 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001034 indata = "TEST MESSAGE of mixed case\n"
1035
1036 if test_support.verbose:
1037 sys.stdout.write("\n")
1038 server = AsyncoreEchoServer(CERTFILE)
1039 flag = threading.Event()
1040 server.start(flag)
1041 # wait for it to start
1042 flag.wait()
1043 # try to connect
1044 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001045 s = ssl.wrap_socket(socket.socket())
1046 s.connect(('127.0.0.1', server.port))
1047 if test_support.verbose:
1048 sys.stdout.write(
1049 " client: sending %s...\n" % (repr(indata)))
1050 s.write(indata)
1051 outdata = s.read()
1052 if test_support.verbose:
1053 sys.stdout.write(" client: read %s\n" % repr(outdata))
1054 if outdata != indata.lower():
1055 self.fail(
1056 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1057 % (outdata[:min(len(outdata),20)], len(outdata),
1058 indata[:min(len(indata),20)].lower(), len(indata)))
1059 s.write("over\n")
1060 if test_support.verbose:
1061 sys.stdout.write(" client: closing connection.\n")
1062 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001063 finally:
1064 server.stop()
1065 # wait for server thread to end
1066 server.join()
1067
Antoine Pitroud2867642010-04-28 21:12:43 +00001068 def test_recv_send(self):
1069 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001070 if test_support.verbose:
1071 sys.stdout.write("\n")
1072
1073 server = ThreadedEchoServer(CERTFILE,
1074 certreqs=ssl.CERT_NONE,
1075 ssl_version=ssl.PROTOCOL_TLSv1,
1076 cacerts=CERTFILE,
1077 chatty=True,
1078 connectionchatty=False)
1079 flag = threading.Event()
1080 server.start(flag)
1081 # wait for it to start
1082 flag.wait()
1083 # try to connect
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001084 s = ssl.wrap_socket(socket.socket(),
1085 server_side=False,
1086 certfile=CERTFILE,
1087 ca_certs=CERTFILE,
1088 cert_reqs=ssl.CERT_NONE,
1089 ssl_version=ssl.PROTOCOL_TLSv1)
1090 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001091 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001092 # helper methods for standardising recv* method signatures
1093 def _recv_into():
1094 b = bytearray("\0"*100)
1095 count = s.recv_into(b)
1096 return b[:count]
1097
1098 def _recvfrom_into():
1099 b = bytearray("\0"*100)
1100 count, addr = s.recvfrom_into(b)
1101 return b[:count]
1102
1103 # (name, method, whether to expect success, *args)
1104 send_methods = [
1105 ('send', s.send, True, []),
1106 ('sendto', s.sendto, False, ["some.address"]),
1107 ('sendall', s.sendall, True, []),
1108 ]
1109 recv_methods = [
1110 ('recv', s.recv, True, []),
1111 ('recvfrom', s.recvfrom, False, ["some.address"]),
1112 ('recv_into', _recv_into, True, []),
1113 ('recvfrom_into', _recvfrom_into, False, []),
1114 ]
1115 data_prefix = u"PREFIX_"
1116
1117 for meth_name, send_meth, expect_success, args in send_methods:
1118 indata = data_prefix + meth_name
1119 try:
1120 send_meth(indata.encode('ASCII', 'strict'), *args)
1121 outdata = s.read()
1122 outdata = outdata.decode('ASCII', 'strict')
1123 if outdata != indata.lower():
1124 raise support.TestFailed(
1125 "While sending with <<%s>> bad data "
1126 "<<%r>> (%d) received; "
1127 "expected <<%r>> (%d)\n" % (
1128 meth_name, outdata[:20], len(outdata),
1129 indata[:20], len(indata)
1130 )
1131 )
1132 except ValueError as e:
1133 if expect_success:
1134 raise support.TestFailed(
1135 "Failed to send with method <<%s>>; "
1136 "expected to succeed.\n" % (meth_name,)
1137 )
1138 if not str(e).startswith(meth_name):
1139 raise support.TestFailed(
1140 "Method <<%s>> failed with unexpected "
1141 "exception message: %s\n" % (
1142 meth_name, e
1143 )
1144 )
1145
1146 for meth_name, recv_meth, expect_success, args in recv_methods:
1147 indata = data_prefix + meth_name
1148 try:
1149 s.send(indata.encode('ASCII', 'strict'))
1150 outdata = recv_meth(*args)
1151 outdata = outdata.decode('ASCII', 'strict')
1152 if outdata != indata.lower():
1153 raise support.TestFailed(
1154 "While receiving with <<%s>> bad data "
1155 "<<%r>> (%d) received; "
1156 "expected <<%r>> (%d)\n" % (
1157 meth_name, outdata[:20], len(outdata),
1158 indata[:20], len(indata)
1159 )
1160 )
1161 except ValueError as e:
1162 if expect_success:
1163 raise support.TestFailed(
1164 "Failed to receive with method <<%s>>; "
1165 "expected to succeed.\n" % (meth_name,)
1166 )
1167 if not str(e).startswith(meth_name):
1168 raise support.TestFailed(
1169 "Method <<%s>> failed with unexpected "
1170 "exception message: %s\n" % (
1171 meth_name, e
1172 )
1173 )
1174 # consume data
1175 s.read()
1176
1177 s.write("over\n".encode("ASCII", "strict"))
1178 s.close()
1179 finally:
1180 server.stop()
1181 server.join()
1182
Antoine Pitrouc689d962010-04-24 20:13:37 +00001183 def test_handshake_timeout(self):
1184 # Issue #5103: SSL handshake must respect the socket timeout
1185 server = socket.socket(socket.AF_INET)
1186 host = "127.0.0.1"
1187 port = test_support.bind_port(server)
1188 started = threading.Event()
1189 finish = False
1190
1191 def serve():
1192 server.listen(5)
1193 started.set()
1194 conns = []
1195 while not finish:
1196 r, w, e = select.select([server], [], [], 0.1)
1197 if server in r:
1198 # Let the socket hang around rather than having
1199 # it closed by garbage collection.
1200 conns.append(server.accept()[0])
1201
1202 t = threading.Thread(target=serve)
1203 t.start()
1204 started.wait()
1205
1206 try:
1207 try:
1208 c = socket.socket(socket.AF_INET)
1209 c.settimeout(0.2)
1210 c.connect((host, port))
1211 # Will attempt handshake and time out
1212 try:
1213 ssl.wrap_socket(c)
1214 except ssl.SSLError, e:
1215 self.assertTrue("timed out" in str(e), str(e))
1216 else:
1217 self.fail("SSLError wasn't raised")
1218 finally:
1219 c.close()
1220 try:
1221 c = socket.socket(socket.AF_INET)
1222 c.settimeout(0.2)
1223 c = ssl.wrap_socket(c)
1224 # Will attempt handshake and time out
1225 try:
1226 c.connect((host, port))
1227 except ssl.SSLError, e:
1228 self.assertTrue("timed out" in str(e), str(e))
1229 else:
1230 self.fail("SSLError wasn't raised")
1231 finally:
1232 c.close()
1233 finally:
1234 finish = True
1235 t.join()
1236 server.close()
1237
Bill Janssen61c001a2008-09-08 16:37:24 +00001238
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001239def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001240 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001241 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001242
Barry Warsaw82f88282013-08-23 13:26:49 -04001243 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NULLBYTECERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001244 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001245 "keycert.pem")
1246 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1247 os.path.dirname(__file__) or os.curdir,
1248 "https_svn_python_org_root.pem")
Barry Warsaw82f88282013-08-23 13:26:49 -04001249 NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir,
1250 "nullbytecert.pem")
Bill Janssen296a59d2007-09-16 22:06:00 +00001251
1252 if (not os.path.exists(CERTFILE) or
Barry Warsaw82f88282013-08-23 13:26:49 -04001253 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or
1254 not os.path.exists(NULLBYTECERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001255 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001256
1257 tests = [BasicTests]
1258
Bill Janssen296a59d2007-09-16 22:06:00 +00001259 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001260 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001261
Bill Janssen98d19da2007-09-10 21:51:02 +00001262 if _have_threads:
1263 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001264 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001265 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001266
Antoine Pitroud2867642010-04-28 21:12:43 +00001267 try:
1268 test_support.run_unittest(*tests)
1269 finally:
1270 if _have_threads:
1271 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001272
1273if __name__ == "__main__":
1274 test_main()