blob: 012b8bf8fa45811de3985a9f7b16cc08633568ed [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Jeremy Hylton1afc1692008-06-18 20:49:58 +000013import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000014import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000015import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000016import weakref
Thomas Woutersed03b412007-08-28 21:37:11 +000017
Georg Brandl24420152008-05-26 16:32:26 +000018from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000019
Thomas Woutersed03b412007-08-28 21:37:11 +000020# Optionally test SSL support, if we have it in the tested platform
21skip_expected = False
22try:
23 import ssl
24except ImportError:
25 skip_expected = True
26
Benjamin Petersonee8712c2008-05-20 21:35:26 +000027HOST = support.HOST
Thomas Woutersed03b412007-08-28 21:37:11 +000028CERTFILE = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +000029SVN_PYTHON_ORG_ROOT_CERT = None
Thomas Woutersed03b412007-08-28 21:37:11 +000030
Thomas Woutersed03b412007-08-28 21:37:11 +000031def handle_error(prefix):
32 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000033 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000034 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000035
36
37class BasicTests(unittest.TestCase):
38
Georg Brandlfceab5a2008-01-19 20:08:23 +000039 def testSSLconnect(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000040 if not support.is_resource_enabled('network'):
Georg Brandlfceab5a2008-01-19 20:08:23 +000041 return
42 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
43 cert_reqs=ssl.CERT_NONE)
44 s.connect(("svn.python.org", 443))
45 c = s.getpeercert()
46 if c:
Antoine Pitrou18c913e2010-04-27 10:59:39 +000047 self.fail("Peer cert %s shouldn't be here!")
Georg Brandlfceab5a2008-01-19 20:08:23 +000048 s.close()
49
50 # this should fail because we have no verification certs
51 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
52 cert_reqs=ssl.CERT_REQUIRED)
53 try:
54 s.connect(("svn.python.org", 443))
55 except ssl.SSLError:
56 pass
57 finally:
58 s.close()
59
Thomas Wouters1b7f8912007-09-19 03:06:30 +000060 def testCrucialConstants(self):
61 ssl.PROTOCOL_SSLv2
62 ssl.PROTOCOL_SSLv23
63 ssl.PROTOCOL_SSLv3
64 ssl.PROTOCOL_TLSv1
65 ssl.CERT_NONE
66 ssl.CERT_OPTIONAL
67 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000068
Thomas Wouters1b7f8912007-09-19 03:06:30 +000069 def testRAND(self):
70 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000071 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000072 sys.stdout.write("\n RAND_status is %d (%s)\n"
73 % (v, (v and "sufficient randomness") or
74 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000075 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000076 ssl.RAND_egd(1)
77 except TypeError:
78 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000079 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000080 print("didn't raise TypeError")
81 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000082
Thomas Wouters1b7f8912007-09-19 03:06:30 +000083 def testParseCert(self):
84 # note that this uses an 'unofficial' function in _ssl.c,
85 # provided solely for this test, to exercise the certificate
86 # parsing code
87 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000088 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000089 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +000090
Thomas Wouters1b7f8912007-09-19 03:06:30 +000091 def testDERtoPEM(self):
92
93 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
94 d1 = ssl.PEM_cert_to_DER_cert(pem)
95 p2 = ssl.DER_cert_to_PEM_cert(d1)
96 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +000097 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +000098 if not p2.startswith(ssl.PEM_HEADER + '\n'):
99 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
100 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
101 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000103 def test_openssl_version(self):
104 n = ssl.OPENSSL_VERSION_NUMBER
105 t = ssl.OPENSSL_VERSION_INFO
106 s = ssl.OPENSSL_VERSION
107 self.assertIsInstance(n, int)
108 self.assertIsInstance(t, tuple)
109 self.assertIsInstance(s, str)
110 # Some sanity checks follow
111 # >= 0.9
112 self.assertGreaterEqual(n, 0x900000)
113 # < 2.0
114 self.assertLess(n, 0x20000000)
115 major, minor, fix, patch, status = t
116 self.assertGreaterEqual(major, 0)
117 self.assertLess(major, 2)
118 self.assertGreaterEqual(minor, 0)
119 self.assertLess(minor, 256)
120 self.assertGreaterEqual(fix, 0)
121 self.assertLess(fix, 256)
122 self.assertGreaterEqual(patch, 0)
123 self.assertLessEqual(patch, 26)
124 self.assertGreaterEqual(status, 0)
125 self.assertLessEqual(status, 15)
126 # Version string as returned by OpenSSL, the format might change
127 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
128 (s, t))
129
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000130 def test_ciphers(self):
131 if not support.is_resource_enabled('network'):
132 return
133 remote = ("svn.python.org", 443)
134 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
135 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
136 s.connect(remote)
137 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
138 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
139 s.connect(remote)
140 # Error checking occurs when connecting, because the SSL context
141 # isn't created before.
142 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
143 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
144 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
145 s.connect(remote)
146
Antoine Pitrou9d543662010-04-23 23:10:32 +0000147 @support.cpython_only
148 def test_refcycle(self):
149 # Issue #7943: an SSL object doesn't create reference cycles with
150 # itself.
151 s = socket.socket(socket.AF_INET)
152 ss = ssl.wrap_socket(s)
153 wr = weakref.ref(ss)
154 del ss
155 self.assertEqual(wr(), None)
156
Antoine Pitrou40f08742010-04-24 22:04:40 +0000157 def test_timeout(self):
158 # Issue #8524: when creating an SSL socket, the timeout of the
159 # original socket should be retained.
160 for timeout in (None, 0.0, 5.0):
161 s = socket.socket(socket.AF_INET)
162 s.settimeout(timeout)
163 ss = ssl.wrap_socket(s)
164 self.assertEqual(timeout, ss.gettimeout())
165
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000166
Bill Janssen6e027db2007-11-15 22:23:56 +0000167class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000168
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000169 def testConnect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000170 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
171 cert_reqs=ssl.CERT_NONE)
172 s.connect(("svn.python.org", 443))
173 c = s.getpeercert()
174 if c:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000175 self.fail("Peer cert %s shouldn't be here!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000176 s.close()
177
178 # this should fail because we have no verification certs
179 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
180 cert_reqs=ssl.CERT_REQUIRED)
Thomas Woutersed03b412007-08-28 21:37:11 +0000181 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000182 s.connect(("svn.python.org", 443))
183 except ssl.SSLError:
184 pass
185 finally:
186 s.close()
187
188 # this should succeed because we specify the root cert
189 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
190 cert_reqs=ssl.CERT_REQUIRED,
191 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
192 try:
193 s.connect(("svn.python.org", 443))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000194 finally:
195 s.close()
196
Antoine Pitroue3220242010-04-24 11:13:53 +0000197 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
198 def test_makefile_close(self):
199 # Issue #5238: creating a file-like object with makefile() shouldn't
200 # delay closing the underlying "real socket" (here tested with its
201 # file descriptor, hence skipping the test under Windows).
202 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
203 ss.connect(("svn.python.org", 443))
204 fd = ss.fileno()
205 f = ss.makefile()
206 f.close()
207 # The fd is still open
208 os.read(fd, 0)
209 # Closing the SSL socket should close the fd too
210 ss.close()
211 gc.collect()
212 with self.assertRaises(OSError) as e:
213 os.read(fd, 0)
214 self.assertEqual(e.exception.errno, errno.EBADF)
215
Bill Janssen6e027db2007-11-15 22:23:56 +0000216 def testNonBlockingHandshake(self):
217 s = socket.socket(socket.AF_INET)
218 s.connect(("svn.python.org", 443))
219 s.setblocking(False)
220 s = ssl.wrap_socket(s,
221 cert_reqs=ssl.CERT_NONE,
222 do_handshake_on_connect=False)
223 count = 0
224 while True:
225 try:
226 count += 1
227 s.do_handshake()
228 break
229 except ssl.SSLError as err:
230 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
231 select.select([s], [], [])
232 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
233 select.select([], [s], [])
234 else:
235 raise
236 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000237 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000238 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000239
Bill Janssen54cc54c2007-12-14 22:08:56 +0000240 def testFetchServerCert(self):
241
242 pem = ssl.get_server_certificate(("svn.python.org", 443))
243 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000244 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000245
246 return
247
248 try:
249 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
250 except ssl.SSLError as x:
251 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000252 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000253 sys.stdout.write("%s\n" % x)
254 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000255 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000256
257 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
258 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000259 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000260 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000261 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
262
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000263 def test_algorithms(self):
264 # Issue #8484: all algorithms should be available when verifying a
265 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000266 # SHA256 was added in OpenSSL 0.9.8
267 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
268 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000269 # NOTE: https://sha256.tbs-internet.com is another possible test host
270 remote = ("sha2.hboeck.de", 443)
271 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
272 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
273 cert_reqs=ssl.CERT_REQUIRED,
274 ca_certs=sha256_cert,)
275 with support.transient_internet():
276 try:
277 s.connect(remote)
278 if support.verbose:
279 sys.stdout.write("\nCipher with %r is %r\n" %
280 (remote, s.cipher()))
281 sys.stdout.write("Certificate is:\n%s\n" %
282 pprint.pformat(s.getpeercert()))
283 finally:
284 s.close()
285
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000286
287try:
288 import threading
289except ImportError:
290 _have_threads = False
291else:
292
293 _have_threads = True
294
295 class ThreadedEchoServer(threading.Thread):
296
297 class ConnectionHandler(threading.Thread):
298
299 """A mildly complicated class, because we want it to work both
300 with and without the SSL wrapper around the socket connection, so
301 that we can test the STARTTLS functionality."""
302
Bill Janssen6e027db2007-11-15 22:23:56 +0000303 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000304 self.server = server
305 self.running = False
306 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000307 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000308 self.sock.setblocking(1)
309 self.sslconn = None
310 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000311 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000312
313 def wrap_conn (self):
314 try:
315 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
316 certfile=self.server.certificate,
317 ssl_version=self.server.protocol,
318 ca_certs=self.server.cacerts,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000319 cert_reqs=self.server.certreqs,
320 ciphers=self.server.ciphers)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000321 except ssl.SSLError:
322 # XXX Various errors can have happened here, for example
323 # a mismatching protocol version, an invalid certificate,
324 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000325 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000326 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000327 self.running = False
328 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000329 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000330 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000331 else:
332 if self.server.certreqs == ssl.CERT_REQUIRED:
333 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000334 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000335 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
336 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000337 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000338 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
339 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000340 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000341 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
342 return True
343
344 def read(self):
345 if self.sslconn:
346 return self.sslconn.read()
347 else:
348 return self.sock.recv(1024)
349
350 def write(self, bytes):
351 if self.sslconn:
352 return self.sslconn.write(bytes)
353 else:
354 return self.sock.send(bytes)
355
356 def close(self):
357 if self.sslconn:
358 self.sslconn.close()
359 else:
360 self.sock.close()
361
362 def run (self):
363 self.running = True
364 if not self.server.starttls_server:
365 if not self.wrap_conn():
366 return
367 while self.running:
368 try:
369 msg = self.read()
Bill Janssen6e027db2007-11-15 22:23:56 +0000370 amsg = (msg and str(msg, 'ASCII', 'strict')) or ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000371 if not msg:
372 # eof, so quit this handler
373 self.running = False
374 self.close()
Bill Janssen6e027db2007-11-15 22:23:56 +0000375 elif amsg.strip() == 'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000376 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000377 sys.stdout.write(" server: client closed connection\n")
378 self.close()
379 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000380 elif (self.server.starttls_server and
381 amsg.strip() == 'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000382 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000383 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000384 self.write("OK\n".encode("ASCII", "strict"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000385 if not self.wrap_conn():
386 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000387 elif (self.server.starttls_server and self.sslconn
388 and amsg.strip() == 'ENDTLS'):
389 if support.verbose and self.server.connectionchatty:
390 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
391 self.write("OK\n".encode("ASCII", "strict"))
392 self.sock = self.sslconn.unwrap()
393 self.sslconn = None
394 if support.verbose and self.server.connectionchatty:
395 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000396 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000397 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000398 self.server.connectionchatty):
399 ctype = (self.sslconn and "encrypted") or "unencrypted"
400 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
401 % (repr(msg), ctype, repr(msg.lower()), ctype))
Bill Janssen6e027db2007-11-15 22:23:56 +0000402 self.write(amsg.lower().encode('ASCII', 'strict'))
403 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000404 if self.server.chatty:
405 handle_error("Test server failure:\n")
406 self.close()
407 self.running = False
408 # normally, we'd just stop here, but for the test
409 # harness, we want to stop the server
410 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000411
Trent Nelson78520002008-04-10 20:54:35 +0000412 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000413 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000414 chatty=True, connectionchatty=False, starttls_server=False,
415 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000416 if ssl_version is None:
417 ssl_version = ssl.PROTOCOL_TLSv1
418 if certreqs is None:
419 certreqs = ssl.CERT_NONE
420 self.certificate = certificate
421 self.protocol = ssl_version
422 self.certreqs = certreqs
423 self.cacerts = cacerts
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000424 self.ciphers = ciphers
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000425 self.chatty = chatty
426 self.connectionchatty = connectionchatty
427 self.starttls_server = starttls_server
428 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000429 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000430 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000431 self.active = False
432 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000433 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000434
435 def start (self, flag=None):
436 self.flag = flag
437 threading.Thread.start(self)
438
439 def run (self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000440 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000441 self.sock.listen(5)
442 self.active = True
443 if self.flag:
444 # signal an event
445 self.flag.set()
446 while self.active:
447 try:
448 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000449 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000450 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000451 + repr(connaddr) + '\n')
452 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000453 handler.start()
454 except socket.timeout:
455 pass
456 except KeyboardInterrupt:
457 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000458 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000459
460 def stop (self):
461 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000462
Bill Janssen54cc54c2007-12-14 22:08:56 +0000463 class OurHTTPSServer(threading.Thread):
464
465 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000466
467 class HTTPSServer(HTTPServer):
468
469 def __init__(self, server_address, RequestHandlerClass, certfile):
470
471 HTTPServer.__init__(self, server_address, RequestHandlerClass)
472 # we assume the certfile contains both private key and certificate
473 self.certfile = certfile
474 self.active = False
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000475 self.active_lock = threading.Lock()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000476 self.allow_reuse_address = True
477
Bill Janssen6e027db2007-11-15 22:23:56 +0000478 def __str__(self):
479 return ('<%s %s:%s>' %
480 (self.__class__.__name__,
481 self.server_name,
482 self.server_port))
483
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000484 def get_request (self):
485 # override this to wrap socket with SSL
486 sock, addr = self.socket.accept()
487 sslconn = ssl.wrap_socket(sock, server_side=True,
488 certfile=self.certfile)
489 return sslconn, addr
490
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000491 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
492
493 # need to override translate_path to get a known root,
494 # instead of using os.curdir, since the test could be
495 # run from anywhere
496
497 server_version = "TestHTTPS/1.0"
498
499 root = None
500
501 def translate_path(self, path):
502 """Translate a /-separated PATH to the local filename syntax.
503
504 Components that mean special things to the local file system
505 (e.g. drive or directory names) are ignored. (XXX They should
506 probably be diagnosed.)
507
508 """
509 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000510 path = urllib.parse.urlparse(path)[2]
511 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512 words = path.split('/')
513 words = filter(None, words)
514 path = self.root
515 for word in words:
516 drive, word = os.path.splitdrive(word)
517 head, word = os.path.split(word)
518 if word in self.root: continue
519 path = os.path.join(path, word)
520 return path
521
522 def log_message(self, format, *args):
523
524 # we override this to suppress logging unless "verbose"
525
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000526 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000527 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
528 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000529 self.server.server_port,
530 self.request.cipher(),
531 self.log_date_time_string(),
532 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000533
534
Trent Nelson78520002008-04-10 20:54:35 +0000535 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000536 self.flag = None
537 self.active = False
538 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
539 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000540 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
541 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000542 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000543 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000544
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000545 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000546 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000547
548 def start (self, flag=None):
549 self.flag = flag
550 threading.Thread.start(self)
551
Thomas Woutersed03b412007-08-28 21:37:11 +0000552 def run (self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000553 self.active = True
554 if self.flag:
555 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000556 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000557 self.active = False
558
559 def stop (self):
560 self.active = False
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000561 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000562
563
Bill Janssen54cc54c2007-12-14 22:08:56 +0000564 class AsyncoreEchoServer(threading.Thread):
565
566 # this one's based on asyncore.dispatcher
567
568 class EchoServer (asyncore.dispatcher):
569
570 class ConnectionHandler (asyncore.dispatcher_with_send):
571
572 def __init__(self, conn, certfile):
573 self.socket = ssl.wrap_socket(conn, server_side=True,
574 certfile=certfile,
575 do_handshake_on_connect=False)
576 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000577 self._ssl_accepting = True
578 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000579
580 def readable(self):
581 if isinstance(self.socket, ssl.SSLSocket):
582 while self.socket.pending() > 0:
583 self.handle_read_event()
584 return True
585
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000586 def _do_ssl_handshake(self):
587 try:
588 self.socket.do_handshake()
589 except ssl.SSLError as err:
590 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
591 ssl.SSL_ERROR_WANT_WRITE):
592 return
593 elif err.args[0] == ssl.SSL_ERROR_EOF:
594 return self.handle_close()
595 raise
596 except socket.error as err:
597 if err.args[0] == errno.ECONNABORTED:
598 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000599 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000600 self._ssl_accepting = False
601
602 def handle_read(self):
603 if self._ssl_accepting:
604 self._do_ssl_handshake()
605 else:
606 data = self.recv(1024)
607 if support.verbose:
608 sys.stdout.write(" server: read %s from client\n" % repr(data))
609 if not data:
610 self.close()
611 else:
612 self.send(str(data, 'ASCII', 'strict').lower().encode('ASCII', 'strict'))
Bill Janssen54cc54c2007-12-14 22:08:56 +0000613
614 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000615 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000616 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000617 sys.stdout.write(" server: closed connection %s\n" % self.socket)
618
619 def handle_error(self):
620 raise
621
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000622 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000623 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000624 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
625 self.port = support.bind_port(sock, '')
626 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000627 self.listen(5)
628
629 def handle_accept(self):
630 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000631 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000632 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
633 self.ConnectionHandler(sock_obj, self.certfile)
634
635 def handle_error(self):
636 raise
637
Trent Nelson78520002008-04-10 20:54:35 +0000638 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000639 self.flag = None
640 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000641 self.server = self.EchoServer(certfile)
642 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000643 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000644 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000645
646 def __str__(self):
647 return "<%s %s>" % (self.__class__.__name__, self.server)
648
649 def start (self, flag=None):
650 self.flag = flag
651 threading.Thread.start(self)
652
653 def run (self):
654 self.active = True
655 if self.flag:
656 self.flag.set()
657 while self.active:
658 try:
659 asyncore.loop(1)
660 except:
661 pass
662
663 def stop (self):
664 self.active = False
665 self.server.close()
666
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000667 def badCertTest (certfile):
Trent Nelson78520002008-04-10 20:54:35 +0000668 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000669 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000670 cacerts=CERTFILE, chatty=False,
671 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000672 flag = threading.Event()
673 server.start(flag)
674 # wait for it to start
675 flag.wait()
676 # try to connect
677 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000678 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000679 s = ssl.wrap_socket(socket.socket(),
680 certfile=certfile,
681 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000682 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000683 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000684 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000685 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000686 except socket.error as x:
687 if test_support.verbose:
688 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000689 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000690 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000691 finally:
692 server.stop()
693 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000694
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000695 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
Bill Janssen6e027db2007-11-15 22:23:56 +0000696 client_certfile, client_protocol=None,
697 indata="FOO\n",
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000698 ciphers=None, chatty=False, connectionchatty=False):
Thomas Woutersed03b412007-08-28 21:37:11 +0000699
Trent Nelson78520002008-04-10 20:54:35 +0000700 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000701 certreqs=certreqs,
702 ssl_version=protocol,
703 cacerts=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000704 ciphers=ciphers,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000706 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000707 flag = threading.Event()
708 server.start(flag)
709 # wait for it to start
710 flag.wait()
711 # try to connect
712 if client_protocol is None:
713 client_protocol = protocol
714 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000715 s = ssl.wrap_socket(socket.socket(),
716 certfile=client_certfile,
717 ca_certs=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000718 ciphers=ciphers,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000719 cert_reqs=certreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000720 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000721 s.connect((HOST, server.port))
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000722 bindata = indata.encode('ASCII', 'strict')
723 for arg in [bindata, bytearray(bindata), memoryview(bindata)]:
724 if connectionchatty:
725 if support.verbose:
726 sys.stdout.write(
727 " client: sending %s...\n" % (repr(indata)))
728 s.write(arg)
729 outdata = s.read()
730 if connectionchatty:
731 if support.verbose:
732 sys.stdout.write(" client: read %s\n" % repr(outdata))
733 outdata = str(outdata, 'ASCII', 'strict')
734 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000735 self.fail(
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000736 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
737 % (repr(outdata[:min(len(outdata),20)]), len(outdata),
738 repr(indata[:min(len(indata),20)].lower()), len(indata)))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000739 s.write("over\n".encode("ASCII", "strict"))
Bill Janssen6e027db2007-11-15 22:23:56 +0000740 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000741 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000742 sys.stdout.write(" client: closing connection.\n")
743 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000744 finally:
745 server.stop()
746 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000747
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000748 def tryProtocolCombo (server_protocol,
749 client_protocol,
750 expectedToWork,
751 certsreqs=None):
Thomas Woutersed03b412007-08-28 21:37:11 +0000752
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000753 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000754 certsreqs = ssl.CERT_NONE
Thomas Woutersed03b412007-08-28 21:37:11 +0000755
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756 if certsreqs == ssl.CERT_NONE:
757 certtype = "CERT_NONE"
758 elif certsreqs == ssl.CERT_OPTIONAL:
759 certtype = "CERT_OPTIONAL"
760 elif certsreqs == ssl.CERT_REQUIRED:
761 certtype = "CERT_REQUIRED"
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000762 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
764 sys.stdout.write(formatstr %
765 (ssl.get_protocol_name(client_protocol),
766 ssl.get_protocol_name(server_protocol),
767 certtype))
768 try:
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000769 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
770 # will send an SSLv3 hello (rather than SSLv2) starting from
771 # OpenSSL 1.0.0 (see issue #8322).
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000772 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000773 CERTFILE, CERTFILE, client_protocol,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000774 ciphers="ALL",
Bill Janssen6e027db2007-11-15 22:23:56 +0000775 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000776 # Protocol mismatch can result in either an SSLError, or a
777 # "Connection reset by peer" error.
778 except ssl.SSLError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000779 if expectedToWork:
780 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000781 except socket.error as e:
782 if expectedToWork or e.errno != errno.ECONNRESET:
783 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000784 else:
785 if not expectedToWork:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000786 self.fail(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787 "Client protocol %s succeeded with server protocol %s!"
788 % (ssl.get_protocol_name(client_protocol),
789 ssl.get_protocol_name(server_protocol)))
790
791
Bill Janssen6e027db2007-11-15 22:23:56 +0000792 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000793
Trent Nelson6b240cd2008-04-10 20:12:06 +0000794 def testEcho (self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000795
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000796 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000797 sys.stdout.write("\n")
798 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
799 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
800 chatty=True, connectionchatty=True)
801
802 def testReadCert(self):
803
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000804 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000805 sys.stdout.write("\n")
806 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000807 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000808 certreqs=ssl.CERT_NONE,
809 ssl_version=ssl.PROTOCOL_SSLv23,
810 cacerts=CERTFILE,
811 chatty=False)
812 flag = threading.Event()
813 server.start(flag)
814 # wait for it to start
815 flag.wait()
816 # try to connect
817 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000818 s = ssl.wrap_socket(socket.socket(),
819 certfile=CERTFILE,
820 ca_certs=CERTFILE,
821 cert_reqs=ssl.CERT_REQUIRED,
822 ssl_version=ssl.PROTOCOL_SSLv23)
823 s.connect((HOST, server.port))
824 cert = s.getpeercert()
825 self.assertTrue(cert, "Can't get peer certificate.")
826 cipher = s.cipher()
827 if support.verbose:
828 sys.stdout.write(pprint.pformat(cert) + '\n')
829 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
830 if 'subject' not in cert:
831 self.fail("No subject field in certificate: %s." %
832 pprint.pformat(cert))
833 if ((('organizationName', 'Python Software Foundation'),)
834 not in cert['subject']):
835 self.fail(
836 "Missing or invalid 'organizationName' field in certificate subject; "
837 "should be 'Python Software Foundation'.")
838 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000839 finally:
840 server.stop()
841 server.join()
842
843 def testNULLcert(self):
844 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
845 "nullcert.pem"))
846 def testMalformedCert(self):
847 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
848 "badcert.pem"))
Bill Janssen58afe4c2008-09-08 16:45:19 +0000849 def testWrongCert(self):
850 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
851 "wrongcert.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000852 def testMalformedKey(self):
853 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
854 "badkey.pem"))
855
Trent Nelson6b240cd2008-04-10 20:12:06 +0000856 def testRudeShutdown(self):
857
858 listener_ready = threading.Event()
859 listener_gone = threading.Event()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000860 s = socket.socket()
861 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000862
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000863 # `listener` runs in a thread. It sits in an accept() until
864 # the main thread connects. Then it rudely closes the socket,
865 # and sets Event `listener_gone` to let the main thread know
866 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000867 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000868 s.listen(5)
869 listener_ready.set()
870 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000871 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000872 listener_gone.set()
873
874 def connector():
875 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000876 c = socket.socket()
877 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000878 listener_gone.wait()
879 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000880 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000881 except IOError:
882 pass
883 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000884 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +0000885
886 t = threading.Thread(target=listener)
887 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000888 try:
889 connector()
890 finally:
891 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000892
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000893 def testProtocolSSL2(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000894 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 sys.stdout.write("\n")
896 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
897 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
898 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
899 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
900 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
901 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
902
903 def testProtocolSSL23(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000904 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905 sys.stdout.write("\n")
906 try:
907 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000908 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000910 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911 sys.stdout.write(
912 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
913 % str(x))
914 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
915 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
916 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
917
918 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
919 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
920 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
921
922 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
923 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
924 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
925
926 def testProtocolSSL3(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000927 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000928 sys.stdout.write("\n")
929 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
930 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
931 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
932 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
933 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
934 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
935
936 def testProtocolTLS1(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000937 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938 sys.stdout.write("\n")
939 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
940 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
941 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
942 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
943 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
944 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
945
946 def testSTARTTLS (self):
947
Bill Janssen40a0f662008-08-12 16:56:25 +0000948 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949
Trent Nelson78520002008-04-10 20:54:35 +0000950 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951 ssl_version=ssl.PROTOCOL_TLSv1,
952 starttls_server=True,
953 chatty=True,
954 connectionchatty=True)
955 flag = threading.Event()
956 server.start(flag)
957 # wait for it to start
958 flag.wait()
959 # try to connect
960 wrapped = False
961 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000962 s = socket.socket()
963 s.setblocking(1)
964 s.connect((HOST, server.port))
965 if support.verbose:
966 sys.stdout.write("\n")
967 for indata in msgs:
968 msg = indata.encode('ASCII', 'replace')
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000969 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000970 sys.stdout.write(
971 " client: sending %s...\n" % repr(msg))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000972 if wrapped:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000973 conn.write(msg)
974 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000976 s.send(msg)
977 outdata = s.recv(1024)
978 if (indata == "STARTTLS" and
979 str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")):
980 if support.verbose:
981 msg = str(outdata, 'ASCII', 'replace')
982 sys.stdout.write(
983 " client: read %s from server, starting TLS...\n"
984 % repr(msg))
985 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
986 wrapped = True
987 elif (indata == "ENDTLS" and
988 str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")):
989 if support.verbose:
990 msg = str(outdata, 'ASCII', 'replace')
991 sys.stdout.write(
992 " client: read %s from server, ending TLS...\n"
993 % repr(msg))
994 s = conn.unwrap()
995 wrapped = False
996 else:
997 if support.verbose:
998 msg = str(outdata, 'ASCII', 'replace')
999 sys.stdout.write(
1000 " client: read %s from server\n" % repr(msg))
1001 if support.verbose:
1002 sys.stdout.write(" client: closing connection.\n")
1003 if wrapped:
1004 conn.write("over\n".encode("ASCII", "strict"))
1005 else:
1006 s.send("over\n".encode("ASCII", "strict"))
Bill Janssen6e027db2007-11-15 22:23:56 +00001007 if wrapped:
1008 conn.close()
1009 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001010 s.close()
1011 finally:
1012 server.stop()
1013 server.join()
1014
Bill Janssen54cc54c2007-12-14 22:08:56 +00001015 def testSocketServer(self):
Bill Janssen6e027db2007-11-15 22:23:56 +00001016
Trent Nelson78520002008-04-10 20:54:35 +00001017 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001018 flag = threading.Event()
1019 server.start(flag)
1020 # wait for it to start
1021 flag.wait()
1022 # try to connect
1023 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001024 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001025 sys.stdout.write('\n')
1026 d1 = open(CERTFILE, 'rb').read()
1027 d2 = ''
1028 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001029 url = 'https://%s:%d/%s' % (
1030 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001031 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001032 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001033 if dlen and (int(dlen) > 0):
1034 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001035 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001036 sys.stdout.write(
1037 " client: read %d bytes from remote server '%s'\n"
1038 % (len(d2), server))
1039 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001040 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001041 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001042 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001043 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001044 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001045 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001046 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001047 server.join()
1048
Trent Nelson6b240cd2008-04-10 20:12:06 +00001049 def testAsyncoreServer(self):
1050
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001051 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001052 sys.stdout.write("\n")
1053
1054 indata="FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001055 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001056 flag = threading.Event()
1057 server.start(flag)
1058 # wait for it to start
1059 flag.wait()
1060 # try to connect
1061 try:
1062 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001063 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001064 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001065 sys.stdout.write(
1066 " client: sending %s...\n" % (repr(indata)))
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001067 s.write(indata.encode('ASCII', 'strict'))
1068 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001069 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001070 sys.stdout.write(" client: read %s\n" % repr(outdata))
1071 outdata = str(outdata, 'ASCII', 'strict')
1072 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001073 self.fail(
Trent Nelson6b240cd2008-04-10 20:12:06 +00001074 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001075 % (outdata[:min(len(outdata),20)], len(outdata),
1076 indata[:min(len(indata),20)].lower(), len(indata)))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001077 s.write("over\n".encode("ASCII", "strict"))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001078 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001079 sys.stdout.write(" client: closing connection.\n")
1080 s.close()
1081 finally:
1082 server.stop()
1083 server.join()
1084
Bill Janssen58afe4c2008-09-08 16:45:19 +00001085 def testAllRecvAndSendMethods(self):
1086
1087 if support.verbose:
1088 sys.stdout.write("\n")
1089
1090 server = ThreadedEchoServer(CERTFILE,
1091 certreqs=ssl.CERT_NONE,
1092 ssl_version=ssl.PROTOCOL_TLSv1,
1093 cacerts=CERTFILE,
1094 chatty=True,
1095 connectionchatty=False)
1096 flag = threading.Event()
1097 server.start(flag)
1098 # wait for it to start
1099 flag.wait()
1100 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001101 s = ssl.wrap_socket(socket.socket(),
1102 server_side=False,
1103 certfile=CERTFILE,
1104 ca_certs=CERTFILE,
1105 cert_reqs=ssl.CERT_NONE,
1106 ssl_version=ssl.PROTOCOL_TLSv1)
1107 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001108 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001109 # helper methods for standardising recv* method signatures
1110 def _recv_into():
1111 b = bytearray(b"\0"*100)
1112 count = s.recv_into(b)
1113 return b[:count]
1114
1115 def _recvfrom_into():
1116 b = bytearray(b"\0"*100)
1117 count, addr = s.recvfrom_into(b)
1118 return b[:count]
1119
1120 # (name, method, whether to expect success, *args)
1121 send_methods = [
1122 ('send', s.send, True, []),
1123 ('sendto', s.sendto, False, ["some.address"]),
1124 ('sendall', s.sendall, True, []),
1125 ]
1126 recv_methods = [
1127 ('recv', s.recv, True, []),
1128 ('recvfrom', s.recvfrom, False, ["some.address"]),
1129 ('recv_into', _recv_into, True, []),
1130 ('recvfrom_into', _recvfrom_into, False, []),
1131 ]
1132 data_prefix = "PREFIX_"
1133
1134 for meth_name, send_meth, expect_success, args in send_methods:
1135 indata = data_prefix + meth_name
1136 try:
1137 send_meth(indata.encode('ASCII', 'strict'), *args)
1138 outdata = s.read()
1139 outdata = str(outdata, 'ASCII', 'strict')
1140 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001141 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001142 "While sending with <<{name:s}>> bad data "
1143 "<<{outdata:s}>> ({nout:d}) received; "
1144 "expected <<{indata:s}>> ({nin:d})\n".format(
1145 name=meth_name, outdata=repr(outdata[:20]),
1146 nout=len(outdata),
1147 indata=repr(indata[:20]), nin=len(indata)
1148 )
1149 )
1150 except ValueError as e:
1151 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001152 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001153 "Failed to send with method <<{name:s}>>; "
1154 "expected to succeed.\n".format(name=meth_name)
1155 )
1156 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001157 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001158 "Method <<{name:s}>> failed with unexpected "
1159 "exception message: {exp:s}\n".format(
1160 name=meth_name, exp=e
1161 )
1162 )
1163
1164 for meth_name, recv_meth, expect_success, args in recv_methods:
1165 indata = data_prefix + meth_name
1166 try:
1167 s.send(indata.encode('ASCII', 'strict'))
1168 outdata = recv_meth(*args)
1169 outdata = str(outdata, 'ASCII', 'strict')
1170 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001171 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001172 "While receiving with <<{name:s}>> bad data "
1173 "<<{outdata:s}>> ({nout:d}) received; "
1174 "expected <<{indata:s}>> ({nin:d})\n".format(
1175 name=meth_name, outdata=repr(outdata[:20]),
1176 nout=len(outdata),
1177 indata=repr(indata[:20]), nin=len(indata)
1178 )
1179 )
1180 except ValueError as e:
1181 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001182 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001183 "Failed to receive with method <<{name:s}>>; "
1184 "expected to succeed.\n".format(name=meth_name)
1185 )
1186 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001187 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001188 "Method <<{name:s}>> failed with unexpected "
1189 "exception message: {exp:s}\n".format(
1190 name=meth_name, exp=e
1191 )
1192 )
1193 # consume data
1194 s.read()
1195
1196 s.write("over\n".encode("ASCII", "strict"))
1197 s.close()
1198 finally:
1199 server.stop()
1200 server.join()
1201
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001202 def test_handshake_timeout(self):
1203 # Issue #5103: SSL handshake must respect the socket timeout
1204 server = socket.socket(socket.AF_INET)
1205 host = "127.0.0.1"
1206 port = support.bind_port(server)
1207 started = threading.Event()
1208 finish = False
1209
1210 def serve():
1211 server.listen(5)
1212 started.set()
1213 conns = []
1214 while not finish:
1215 r, w, e = select.select([server], [], [], 0.1)
1216 if server in r:
1217 # Let the socket hang around rather than having
1218 # it closed by garbage collection.
1219 conns.append(server.accept()[0])
1220
1221 t = threading.Thread(target=serve)
1222 t.start()
1223 started.wait()
1224
1225 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001226 try:
1227 c = socket.socket(socket.AF_INET)
1228 c.settimeout(0.2)
1229 c.connect((host, port))
1230 # Will attempt handshake and time out
1231 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1232 ssl.wrap_socket, c)
1233 finally:
1234 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001235 try:
1236 c = socket.socket(socket.AF_INET)
1237 c = ssl.wrap_socket(c)
1238 c.settimeout(0.2)
1239 # Will attempt handshake and time out
1240 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1241 c.connect, (host, port))
1242 finally:
1243 c.close()
1244 finally:
1245 finish = True
1246 t.join()
1247 server.close()
1248
Bill Janssen58afe4c2008-09-08 16:45:19 +00001249
Thomas Woutersed03b412007-08-28 21:37:11 +00001250def test_main(verbose=False):
1251 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001252 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001253
Trent Nelson78520002008-04-10 20:54:35 +00001254 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001255 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1256 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001257 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1258 os.path.dirname(__file__) or os.curdir,
1259 "https_svn_python_org_root.pem")
1260
1261 if (not os.path.exists(CERTFILE) or
1262 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001263 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001264
Thomas Woutersed03b412007-08-28 21:37:11 +00001265 tests = [BasicTests]
1266
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001267 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001268 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001269
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001270 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001271 thread_info = support.threading_setup()
1272 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001273 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001274
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001275 support.run_unittest(*tests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001276
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001277 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001278 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001279
1280if __name__ == "__main__":
1281 test_main()