blob: b03c45fce65ddd9636d97adf8b9c1841f04dedf3 [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
Antoine Pitrou480a1242010-04-28 21:37:09 +000039 def test_connect(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
Antoine Pitrou480a1242010-04-28 21:37:09 +000060 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000061 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
Antoine Pitrou480a1242010-04-28 21:37:09 +000069 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000070 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
Antoine Pitrou480a1242010-04-28 21:37:09 +000083 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000084 # 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
Antoine Pitrou480a1242010-04-28 21:37:09 +000091 def test_DER_to_PEM(self):
92 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
93 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +000094 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
Antoine Pitrou480a1242010-04-28 21:37:09 +0000169 def test_connect(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
Antoine Pitrou480a1242010-04-28 21:37:09 +0000216 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000217 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
Antoine Pitrou480a1242010-04-28 21:37:09 +0000240 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000241 pem = ssl.get_server_certificate(("svn.python.org", 443))
242 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000243 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000244
245 return
246
247 try:
248 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
249 except ssl.SSLError as x:
250 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000251 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000252 sys.stdout.write("%s\n" % x)
253 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000254 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000255
256 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
257 if not pem:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000258 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000259 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000260 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
261
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000262 def test_algorithms(self):
263 # Issue #8484: all algorithms should be available when verifying a
264 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000265 # SHA256 was added in OpenSSL 0.9.8
266 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
267 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000268 # NOTE: https://sha256.tbs-internet.com is another possible test host
269 remote = ("sha2.hboeck.de", 443)
270 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
271 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
272 cert_reqs=ssl.CERT_REQUIRED,
273 ca_certs=sha256_cert,)
274 with support.transient_internet():
275 try:
276 s.connect(remote)
277 if support.verbose:
278 sys.stdout.write("\nCipher with %r is %r\n" %
279 (remote, s.cipher()))
280 sys.stdout.write("Certificate is:\n%s\n" %
281 pprint.pformat(s.getpeercert()))
282 finally:
283 s.close()
284
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000285
286try:
287 import threading
288except ImportError:
289 _have_threads = False
290else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000291 _have_threads = True
292
293 class ThreadedEchoServer(threading.Thread):
294
295 class ConnectionHandler(threading.Thread):
296
297 """A mildly complicated class, because we want it to work both
298 with and without the SSL wrapper around the socket connection, so
299 that we can test the STARTTLS functionality."""
300
Bill Janssen6e027db2007-11-15 22:23:56 +0000301 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000302 self.server = server
303 self.running = False
304 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000305 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000306 self.sock.setblocking(1)
307 self.sslconn = None
308 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000309 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000310
Antoine Pitrou480a1242010-04-28 21:37:09 +0000311 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000312 try:
313 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
314 certfile=self.server.certificate,
315 ssl_version=self.server.protocol,
316 ca_certs=self.server.cacerts,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000317 cert_reqs=self.server.certreqs,
318 ciphers=self.server.ciphers)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000319 except ssl.SSLError:
320 # XXX Various errors can have happened here, for example
321 # a mismatching protocol version, an invalid certificate,
322 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000323 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000324 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000325 self.running = False
326 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000327 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000328 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000329 else:
330 if self.server.certreqs == ssl.CERT_REQUIRED:
331 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000332 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000333 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
334 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000335 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000336 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
337 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000338 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000339 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
340 return True
341
342 def read(self):
343 if self.sslconn:
344 return self.sslconn.read()
345 else:
346 return self.sock.recv(1024)
347
348 def write(self, bytes):
349 if self.sslconn:
350 return self.sslconn.write(bytes)
351 else:
352 return self.sock.send(bytes)
353
354 def close(self):
355 if self.sslconn:
356 self.sslconn.close()
357 else:
358 self.sock.close()
359
Antoine Pitrou480a1242010-04-28 21:37:09 +0000360 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000361 self.running = True
362 if not self.server.starttls_server:
363 if not self.wrap_conn():
364 return
365 while self.running:
366 try:
367 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000368 stripped = msg.strip()
369 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000370 # eof, so quit this handler
371 self.running = False
372 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000373 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000374 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000375 sys.stdout.write(" server: client closed connection\n")
376 self.close()
377 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000378 elif (self.server.starttls_server and
Antoine Pitrou480a1242010-04-28 21:37:09 +0000379 stripped == 'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000380 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000381 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000382 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000383 if not self.wrap_conn():
384 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000385 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou480a1242010-04-28 21:37:09 +0000386 and stripped == 'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000387 if support.verbose and self.server.connectionchatty:
388 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000389 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000390 self.sock = self.sslconn.unwrap()
391 self.sslconn = None
392 if support.verbose and self.server.connectionchatty:
393 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000394 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000395 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000396 self.server.connectionchatty):
397 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000398 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
399 % (msg, ctype, msg.lower(), ctype))
400 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000401 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000402 if self.server.chatty:
403 handle_error("Test server failure:\n")
404 self.close()
405 self.running = False
406 # normally, we'd just stop here, but for the test
407 # harness, we want to stop the server
408 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000409
Trent Nelson78520002008-04-10 20:54:35 +0000410 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000411 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000412 chatty=True, connectionchatty=False, starttls_server=False,
413 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000414 if ssl_version is None:
415 ssl_version = ssl.PROTOCOL_TLSv1
416 if certreqs is None:
417 certreqs = ssl.CERT_NONE
418 self.certificate = certificate
419 self.protocol = ssl_version
420 self.certreqs = certreqs
421 self.cacerts = cacerts
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000422 self.ciphers = ciphers
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000423 self.chatty = chatty
424 self.connectionchatty = connectionchatty
425 self.starttls_server = starttls_server
426 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000427 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000428 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000429 self.active = False
430 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000431 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000432
Antoine Pitrou480a1242010-04-28 21:37:09 +0000433 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000434 self.flag = flag
435 threading.Thread.start(self)
436
Antoine Pitrou480a1242010-04-28 21:37:09 +0000437 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000438 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000439 self.sock.listen(5)
440 self.active = True
441 if self.flag:
442 # signal an event
443 self.flag.set()
444 while self.active:
445 try:
446 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000447 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000448 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000449 + repr(connaddr) + '\n')
450 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000451 handler.start()
452 except socket.timeout:
453 pass
454 except KeyboardInterrupt:
455 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000456 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000457
Antoine Pitrou480a1242010-04-28 21:37:09 +0000458 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000459 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000460
Bill Janssen54cc54c2007-12-14 22:08:56 +0000461 class OurHTTPSServer(threading.Thread):
462
463 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000464
465 class HTTPSServer(HTTPServer):
466
467 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000468 HTTPServer.__init__(self, server_address, RequestHandlerClass)
469 # we assume the certfile contains both private key and certificate
470 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000471 self.allow_reuse_address = True
472
Bill Janssen6e027db2007-11-15 22:23:56 +0000473 def __str__(self):
474 return ('<%s %s:%s>' %
475 (self.__class__.__name__,
476 self.server_name,
477 self.server_port))
478
Antoine Pitrou480a1242010-04-28 21:37:09 +0000479 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000480 # override this to wrap socket with SSL
481 sock, addr = self.socket.accept()
482 sslconn = ssl.wrap_socket(sock, server_side=True,
483 certfile=self.certfile)
484 return sslconn, addr
485
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000486 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000487 # need to override translate_path to get a known root,
488 # instead of using os.curdir, since the test could be
489 # run from anywhere
490
491 server_version = "TestHTTPS/1.0"
492
493 root = None
494
495 def translate_path(self, path):
496 """Translate a /-separated PATH to the local filename syntax.
497
498 Components that mean special things to the local file system
499 (e.g. drive or directory names) are ignored. (XXX They should
500 probably be diagnosed.)
501
502 """
503 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000504 path = urllib.parse.urlparse(path)[2]
505 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000506 words = path.split('/')
507 words = filter(None, words)
508 path = self.root
509 for word in words:
510 drive, word = os.path.splitdrive(word)
511 head, word = os.path.split(word)
512 if word in self.root: continue
513 path = os.path.join(path, word)
514 return path
515
516 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000517 # we override this to suppress logging unless "verbose"
518
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000519 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000520 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
521 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000522 self.server.server_port,
523 self.request.cipher(),
524 self.log_date_time_string(),
525 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000526
527
Trent Nelson78520002008-04-10 20:54:35 +0000528 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000529 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000530 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
531 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000532 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
533 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000534 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000535 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000536
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000537 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000538 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000539
Antoine Pitrou480a1242010-04-28 21:37:09 +0000540 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000541 self.flag = flag
542 threading.Thread.start(self)
543
Antoine Pitrou480a1242010-04-28 21:37:09 +0000544 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000545 if self.flag:
546 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000547 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000548
Antoine Pitrou480a1242010-04-28 21:37:09 +0000549 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000550 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000551
552
Bill Janssen54cc54c2007-12-14 22:08:56 +0000553 class AsyncoreEchoServer(threading.Thread):
554
555 # this one's based on asyncore.dispatcher
556
557 class EchoServer (asyncore.dispatcher):
558
559 class ConnectionHandler (asyncore.dispatcher_with_send):
560
561 def __init__(self, conn, certfile):
562 self.socket = ssl.wrap_socket(conn, server_side=True,
563 certfile=certfile,
564 do_handshake_on_connect=False)
565 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000566 self._ssl_accepting = True
567 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000568
569 def readable(self):
570 if isinstance(self.socket, ssl.SSLSocket):
571 while self.socket.pending() > 0:
572 self.handle_read_event()
573 return True
574
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000575 def _do_ssl_handshake(self):
576 try:
577 self.socket.do_handshake()
578 except ssl.SSLError as err:
579 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
580 ssl.SSL_ERROR_WANT_WRITE):
581 return
582 elif err.args[0] == ssl.SSL_ERROR_EOF:
583 return self.handle_close()
584 raise
585 except socket.error as err:
586 if err.args[0] == errno.ECONNABORTED:
587 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000588 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000589 self._ssl_accepting = False
590
591 def handle_read(self):
592 if self._ssl_accepting:
593 self._do_ssl_handshake()
594 else:
595 data = self.recv(1024)
596 if support.verbose:
597 sys.stdout.write(" server: read %s from client\n" % repr(data))
598 if not data:
599 self.close()
600 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000601 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000602
603 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000604 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000605 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000606 sys.stdout.write(" server: closed connection %s\n" % self.socket)
607
608 def handle_error(self):
609 raise
610
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000611 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000612 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000613 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
614 self.port = support.bind_port(sock, '')
615 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000616 self.listen(5)
617
618 def handle_accept(self):
619 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000620 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000621 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
622 self.ConnectionHandler(sock_obj, self.certfile)
623
624 def handle_error(self):
625 raise
626
Trent Nelson78520002008-04-10 20:54:35 +0000627 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000628 self.flag = None
629 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000630 self.server = self.EchoServer(certfile)
631 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000632 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000633 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000634
635 def __str__(self):
636 return "<%s %s>" % (self.__class__.__name__, self.server)
637
638 def start (self, flag=None):
639 self.flag = flag
640 threading.Thread.start(self)
641
Antoine Pitrou480a1242010-04-28 21:37:09 +0000642 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000643 self.active = True
644 if self.flag:
645 self.flag.set()
646 while self.active:
647 try:
648 asyncore.loop(1)
649 except:
650 pass
651
Antoine Pitrou480a1242010-04-28 21:37:09 +0000652 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000653 self.active = False
654 self.server.close()
655
Antoine Pitrou480a1242010-04-28 21:37:09 +0000656 def bad_cert_test(certfile):
657 """
658 Launch a server with CERT_REQUIRED, and check that trying to
659 connect to it with the given client certificate fails.
660 """
Trent Nelson78520002008-04-10 20:54:35 +0000661 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000663 cacerts=CERTFILE, chatty=False,
664 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665 flag = threading.Event()
666 server.start(flag)
667 # wait for it to start
668 flag.wait()
669 # try to connect
670 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000671 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000672 s = ssl.wrap_socket(socket.socket(),
673 certfile=certfile,
674 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000675 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000676 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000677 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000678 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000679 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000680 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000681 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000682 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000683 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000684 finally:
685 server.stop()
686 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000687
Antoine Pitrou480a1242010-04-28 21:37:09 +0000688 def server_params_test(certfile, protocol, certreqs, cacertsfile,
689 client_certfile, client_protocol=None, indata=b"FOO\n",
690 ciphers=None, chatty=True, connectionchatty=False):
691 """
692 Launch a server, connect a client to it and try various reads
693 and writes.
694 """
Trent Nelson78520002008-04-10 20:54:35 +0000695 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000696 certreqs=certreqs,
697 ssl_version=protocol,
698 cacerts=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000699 ciphers=ciphers,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000700 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000701 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000702 flag = threading.Event()
703 server.start(flag)
704 # wait for it to start
705 flag.wait()
706 # try to connect
707 if client_protocol is None:
708 client_protocol = protocol
709 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000710 s = ssl.wrap_socket(socket.socket(),
711 certfile=client_certfile,
712 ca_certs=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000713 ciphers=ciphers,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000714 cert_reqs=certreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000715 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000716 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000717 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000718 if connectionchatty:
719 if support.verbose:
720 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000721 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000722 s.write(arg)
723 outdata = s.read()
724 if connectionchatty:
725 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000726 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000727 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000728 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000729 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
730 % (outdata[:20], len(outdata),
731 indata[:20].lower(), len(indata)))
732 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000733 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000734 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000735 sys.stdout.write(" client: closing connection.\n")
736 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000737 finally:
738 server.stop()
739 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000740
Antoine Pitrou480a1242010-04-28 21:37:09 +0000741 def try_protocol_combo(server_protocol,
742 client_protocol,
743 expect_success,
744 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000745 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000746 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000747 certtype = {
748 ssl.CERT_NONE: "CERT_NONE",
749 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
750 ssl.CERT_REQUIRED: "CERT_REQUIRED",
751 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000752 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000753 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000754 sys.stdout.write(formatstr %
755 (ssl.get_protocol_name(client_protocol),
756 ssl.get_protocol_name(server_protocol),
757 certtype))
758 try:
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000759 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
760 # will send an SSLv3 hello (rather than SSLv2) starting from
761 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou480a1242010-04-28 21:37:09 +0000762 server_params_test(CERTFILE, server_protocol, certsreqs,
763 CERTFILE, CERTFILE, client_protocol,
764 ciphers="ALL", chatty=False,
765 connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000766 # Protocol mismatch can result in either an SSLError, or a
767 # "Connection reset by peer" error.
768 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000769 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000770 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000771 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000772 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000773 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000774 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000775 if not expect_success:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000776 self.fail(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000777 "Client protocol %s succeeded with server protocol %s!"
778 % (ssl.get_protocol_name(client_protocol),
779 ssl.get_protocol_name(server_protocol)))
780
781
Bill Janssen6e027db2007-11-15 22:23:56 +0000782 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783
Antoine Pitrou480a1242010-04-28 21:37:09 +0000784 def test_echo(self):
785 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000786 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000788 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
789 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
790 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000791
Antoine Pitrou480a1242010-04-28 21:37:09 +0000792 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000793 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000794 sys.stdout.write("\n")
795 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000796 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000797 certreqs=ssl.CERT_NONE,
798 ssl_version=ssl.PROTOCOL_SSLv23,
799 cacerts=CERTFILE,
800 chatty=False)
801 flag = threading.Event()
802 server.start(flag)
803 # wait for it to start
804 flag.wait()
805 # try to connect
806 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000807 s = ssl.wrap_socket(socket.socket(),
808 certfile=CERTFILE,
809 ca_certs=CERTFILE,
810 cert_reqs=ssl.CERT_REQUIRED,
811 ssl_version=ssl.PROTOCOL_SSLv23)
812 s.connect((HOST, server.port))
813 cert = s.getpeercert()
814 self.assertTrue(cert, "Can't get peer certificate.")
815 cipher = s.cipher()
816 if support.verbose:
817 sys.stdout.write(pprint.pformat(cert) + '\n')
818 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
819 if 'subject' not in cert:
820 self.fail("No subject field in certificate: %s." %
821 pprint.pformat(cert))
822 if ((('organizationName', 'Python Software Foundation'),)
823 not in cert['subject']):
824 self.fail(
825 "Missing or invalid 'organizationName' field in certificate subject; "
826 "should be 'Python Software Foundation'.")
827 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000828 finally:
829 server.stop()
830 server.join()
831
Antoine Pitrou480a1242010-04-28 21:37:09 +0000832 def test_empty_cert(self):
833 """Connecting with an empty cert file"""
834 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
835 "nullcert.pem"))
836 def test_malformed_cert(self):
837 """Connecting with a badly formatted certificate (syntax error)"""
838 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
839 "badcert.pem"))
840 def test_nonexisting_cert(self):
841 """Connecting with a non-existing cert file"""
842 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
843 "wrongcert.pem"))
844 def test_malformed_key(self):
845 """Connecting with a badly formatted key (syntax error)"""
846 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
847 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848
Antoine Pitrou480a1242010-04-28 21:37:09 +0000849 def test_rude_shutdown(self):
850 """A brutal shutdown of an SSL server should raise an IOError
851 in the client when attempting handshake.
852 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000853 listener_ready = threading.Event()
854 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000855
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000856 s = socket.socket()
857 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000858
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000859 # `listener` runs in a thread. It sits in an accept() until
860 # the main thread connects. Then it rudely closes the socket,
861 # and sets Event `listener_gone` to let the main thread know
862 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000863 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000864 s.listen(5)
865 listener_ready.set()
866 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000867 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000868 listener_gone.set()
869
870 def connector():
871 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000872 c = socket.socket()
873 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000874 listener_gone.wait()
875 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000876 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000877 except IOError:
878 pass
879 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000880 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +0000881
882 t = threading.Thread(target=listener)
883 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000884 try:
885 connector()
886 finally:
887 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000888
Antoine Pitrou480a1242010-04-28 21:37:09 +0000889 def test_protocol_sslv2(self):
890 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000891 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000893 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
894 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
895 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
896 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
897 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
898 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000899
Antoine Pitrou480a1242010-04-28 21:37:09 +0000900 def test_protocol_sslv23(self):
901 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000902 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903 sys.stdout.write("\n")
904 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000905 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000906 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000907 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000908 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 sys.stdout.write(
910 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
911 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000912 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
913 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
914 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915
Antoine Pitrou480a1242010-04-28 21:37:09 +0000916 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
917 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
918 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919
Antoine Pitrou480a1242010-04-28 21:37:09 +0000920 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
921 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
922 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000923
Antoine Pitrou480a1242010-04-28 21:37:09 +0000924 def test_protocol_sslv3(self):
925 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000926 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000927 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000928 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
929 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
930 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
931 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
932 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
933 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000934
Antoine Pitrou480a1242010-04-28 21:37:09 +0000935 def test_protocol_tlsv1(self):
936 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000937 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000939 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
940 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
941 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
942 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
943 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
944 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000945
Antoine Pitrou480a1242010-04-28 21:37:09 +0000946 def test_starttls(self):
947 """Switching from clear text to encrypted and back again."""
948 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"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:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000968 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000969 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000970 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000971 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000972 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000973 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000974 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000975 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000976 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +0000977 msg = outdata.strip().lower()
978 if indata == b"STARTTLS" and msg.startswith(b"ok"):
979 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000980 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000981 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000982 " client: read %r from server, starting TLS...\n"
983 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000984 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
985 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +0000986 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
987 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000988 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000989 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000990 " client: read %r from server, ending TLS...\n"
991 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000992 s = conn.unwrap()
993 wrapped = False
994 else:
995 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000996 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000997 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000998 if support.verbose:
999 sys.stdout.write(" client: closing connection.\n")
1000 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001002 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001003 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001004 if wrapped:
1005 conn.close()
1006 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007 s.close()
1008 finally:
1009 server.stop()
1010 server.join()
1011
Antoine Pitrou480a1242010-04-28 21:37:09 +00001012 def test_socketserver(self):
1013 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001014 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001015 flag = threading.Event()
1016 server.start(flag)
1017 # wait for it to start
1018 flag.wait()
1019 # try to connect
1020 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001021 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001022 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001023 with open(CERTFILE, 'rb') as f:
1024 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001025 d2 = ''
1026 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001027 url = 'https://%s:%d/%s' % (
1028 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001029 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001030 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001031 if dlen and (int(dlen) > 0):
1032 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001033 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 sys.stdout.write(
1035 " client: read %d bytes from remote server '%s'\n"
1036 % (len(d2), server))
1037 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001038 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001039 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001040 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001041 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001042 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001043 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001044 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001045 server.join()
1046
Antoine Pitrou480a1242010-04-28 21:37:09 +00001047 def test_asyncore_server(self):
1048 """Check the example asyncore integration."""
1049 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001050
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001051 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001052 sys.stdout.write("\n")
1053
Antoine Pitrou480a1242010-04-28 21:37:09 +00001054 indata = b"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(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001066 " client: sending %r...\n" % indata)
1067 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001068 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001069 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001070 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001071 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001072 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001073 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1074 % (outdata[:20], len(outdata),
1075 indata[:20].lower(), len(indata)))
1076 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001077 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001078 sys.stdout.write(" client: closing connection.\n")
1079 s.close()
1080 finally:
1081 server.stop()
1082 server.join()
1083
Antoine Pitrou480a1242010-04-28 21:37:09 +00001084 def test_recv_send(self):
1085 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001086 if support.verbose:
1087 sys.stdout.write("\n")
1088
1089 server = ThreadedEchoServer(CERTFILE,
1090 certreqs=ssl.CERT_NONE,
1091 ssl_version=ssl.PROTOCOL_TLSv1,
1092 cacerts=CERTFILE,
1093 chatty=True,
1094 connectionchatty=False)
1095 flag = threading.Event()
1096 server.start(flag)
1097 # wait for it to start
1098 flag.wait()
1099 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001100 s = ssl.wrap_socket(socket.socket(),
1101 server_side=False,
1102 certfile=CERTFILE,
1103 ca_certs=CERTFILE,
1104 cert_reqs=ssl.CERT_NONE,
1105 ssl_version=ssl.PROTOCOL_TLSv1)
1106 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001107 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001108 # helper methods for standardising recv* method signatures
1109 def _recv_into():
1110 b = bytearray(b"\0"*100)
1111 count = s.recv_into(b)
1112 return b[:count]
1113
1114 def _recvfrom_into():
1115 b = bytearray(b"\0"*100)
1116 count, addr = s.recvfrom_into(b)
1117 return b[:count]
1118
1119 # (name, method, whether to expect success, *args)
1120 send_methods = [
1121 ('send', s.send, True, []),
1122 ('sendto', s.sendto, False, ["some.address"]),
1123 ('sendall', s.sendall, True, []),
1124 ]
1125 recv_methods = [
1126 ('recv', s.recv, True, []),
1127 ('recvfrom', s.recvfrom, False, ["some.address"]),
1128 ('recv_into', _recv_into, True, []),
1129 ('recvfrom_into', _recvfrom_into, False, []),
1130 ]
1131 data_prefix = "PREFIX_"
1132
1133 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001134 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001135 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001136 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001137 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001138 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001139 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001140 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 "<<{outdata:r}>> ({nout:d}) received; "
1142 "expected <<{indata:r}>> ({nin:d})\n".format(
1143 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001144 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001146 )
1147 )
1148 except ValueError as e:
1149 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001150 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001151 "Failed to send with method <<{name:s}>>; "
1152 "expected to succeed.\n".format(name=meth_name)
1153 )
1154 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001155 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001156 "Method <<{name:s}>> failed with unexpected "
1157 "exception message: {exp:s}\n".format(
1158 name=meth_name, exp=e
1159 )
1160 )
1161
1162 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001163 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001164 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001165 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001166 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001167 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001168 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001169 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001170 "<<{outdata:r}>> ({nout:d}) received; "
1171 "expected <<{indata:r}>> ({nin:d})\n".format(
1172 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001173 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001175 )
1176 )
1177 except ValueError as e:
1178 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001179 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001180 "Failed to receive with method <<{name:s}>>; "
1181 "expected to succeed.\n".format(name=meth_name)
1182 )
1183 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001184 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001185 "Method <<{name:s}>> failed with unexpected "
1186 "exception message: {exp:s}\n".format(
1187 name=meth_name, exp=e
1188 )
1189 )
1190 # consume data
1191 s.read()
1192
Antoine Pitrou480a1242010-04-28 21:37:09 +00001193 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001194 s.close()
1195 finally:
1196 server.stop()
1197 server.join()
1198
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001199 def test_handshake_timeout(self):
1200 # Issue #5103: SSL handshake must respect the socket timeout
1201 server = socket.socket(socket.AF_INET)
1202 host = "127.0.0.1"
1203 port = support.bind_port(server)
1204 started = threading.Event()
1205 finish = False
1206
1207 def serve():
1208 server.listen(5)
1209 started.set()
1210 conns = []
1211 while not finish:
1212 r, w, e = select.select([server], [], [], 0.1)
1213 if server in r:
1214 # Let the socket hang around rather than having
1215 # it closed by garbage collection.
1216 conns.append(server.accept()[0])
1217
1218 t = threading.Thread(target=serve)
1219 t.start()
1220 started.wait()
1221
1222 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001223 try:
1224 c = socket.socket(socket.AF_INET)
1225 c.settimeout(0.2)
1226 c.connect((host, port))
1227 # Will attempt handshake and time out
1228 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1229 ssl.wrap_socket, c)
1230 finally:
1231 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001232 try:
1233 c = socket.socket(socket.AF_INET)
1234 c = ssl.wrap_socket(c)
1235 c.settimeout(0.2)
1236 # Will attempt handshake and time out
1237 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1238 c.connect, (host, port))
1239 finally:
1240 c.close()
1241 finally:
1242 finish = True
1243 t.join()
1244 server.close()
1245
Bill Janssen58afe4c2008-09-08 16:45:19 +00001246
Thomas Woutersed03b412007-08-28 21:37:11 +00001247def test_main(verbose=False):
1248 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001249 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001250
Trent Nelson78520002008-04-10 20:54:35 +00001251 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001252 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1253 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001254 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1255 os.path.dirname(__file__) or os.curdir,
1256 "https_svn_python_org_root.pem")
1257
1258 if (not os.path.exists(CERTFILE) or
1259 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001260 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001261
Thomas Woutersed03b412007-08-28 21:37:11 +00001262 tests = [BasicTests]
1263
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001264 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001265 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001266
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001267 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001268 thread_info = support.threading_setup()
1269 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001270 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001271
Antoine Pitrou480a1242010-04-28 21:37:09 +00001272 try:
1273 support.run_unittest(*tests)
1274 finally:
1275 if _have_threads:
1276 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001277
1278if __name__ == "__main__":
1279 test_main()