/lib-python/2.7/test/test_ssl.py
Python | 1369 lines | 1177 code | 102 blank | 90 comment | 137 complexity | 11e90867cfb9c3da63c1c8d7c526f31b MD5 | raw file
1# Test the support for SSL and sockets 2 3import sys 4import unittest 5from test import test_support 6import asyncore 7import socket 8import select 9import time 10import gc 11import os 12import errno 13import pprint 14import urllib, urlparse 15import traceback 16import weakref 17import functools 18import platform 19 20from BaseHTTPServer import HTTPServer 21from SimpleHTTPServer import SimpleHTTPRequestHandler 22 23ssl = test_support.import_module("ssl") 24 25HOST = test_support.HOST 26CERTFILE = None 27SVN_PYTHON_ORG_ROOT_CERT = None 28 29def handle_error(prefix): 30 exc_format = ' '.join(traceback.format_exception(*sys.exc_info())) 31 if test_support.verbose: 32 sys.stdout.write(prefix + exc_format) 33 34 35class BasicTests(unittest.TestCase): 36 37 def test_sslwrap_simple(self): 38 # A crude test for the legacy API 39 try: 40 ssl.sslwrap_simple(socket.socket(socket.AF_INET)) 41 except IOError, e: 42 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that 43 pass 44 else: 45 raise 46 try: 47 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock) 48 except IOError, e: 49 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that 50 pass 51 else: 52 raise 53 54# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2 55def skip_if_broken_ubuntu_ssl(func): 56 if hasattr(ssl, 'PROTOCOL_SSLv2'): 57 # We need to access the lower-level wrapper in order to create an 58 # implicit SSL context without trying to connect or listen. 59 try: 60 import _ssl 61 except ImportError: 62 # The returned function won't get executed, just ignore the error 63 pass 64 @functools.wraps(func) 65 def f(*args, **kwargs): 66 try: 67 s = socket.socket(socket.AF_INET) 68 _ssl.sslwrap(s._sock, 0, None, None, 69 ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None) 70 except ssl.SSLError as e: 71 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and 72 platform.linux_distribution() == ('debian', 'squeeze/sid', '') 73 and 'Invalid SSL protocol variant specified' in str(e)): 74 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") 75 return func(*args, **kwargs) 76 return f 77 else: 78 return func 79 80 81class BasicSocketTests(unittest.TestCase): 82 83 def test_constants(self): 84 #ssl.PROTOCOL_SSLv2 85 ssl.PROTOCOL_SSLv23 86 ssl.PROTOCOL_SSLv3 87 ssl.PROTOCOL_TLSv1 88 ssl.CERT_NONE 89 ssl.CERT_OPTIONAL 90 ssl.CERT_REQUIRED 91 92 def test_random(self): 93 v = ssl.RAND_status() 94 if test_support.verbose: 95 sys.stdout.write("\n RAND_status is %d (%s)\n" 96 % (v, (v and "sufficient randomness") or 97 "insufficient randomness")) 98 try: 99 ssl.RAND_egd(1) 100 except TypeError: 101 pass 102 else: 103 print "didn't raise TypeError" 104 ssl.RAND_add("this is a random string", 75.0) 105 106 def test_parse_cert(self): 107 # note that this uses an 'unofficial' function in _ssl.c, 108 # provided solely for this test, to exercise the certificate 109 # parsing code 110 p = ssl._ssl._test_decode_cert(CERTFILE, False) 111 if test_support.verbose: 112 sys.stdout.write("\n" + pprint.pformat(p) + "\n") 113 self.assertEqual(p['subject'], 114 ((('countryName', u'US'),), 115 (('stateOrProvinceName', u'Delaware'),), 116 (('localityName', u'Wilmington'),), 117 (('organizationName', u'Python Software Foundation'),), 118 (('organizationalUnitName', u'SSL'),), 119 (('commonName', u'somemachine.python.org'),)), 120 ) 121 # Issue #13034: the subjectAltName in some certificates 122 # (notably projects.developer.nokia.com:443) wasn't parsed 123 p = ssl._ssl._test_decode_cert(NOKIACERT) 124 if test_support.verbose: 125 sys.stdout.write("\n" + pprint.pformat(p) + "\n") 126 self.assertEqual(p['subjectAltName'], 127 (('DNS', 'projects.developer.nokia.com'), 128 ('DNS', 'projects.forum.nokia.com')) 129 ) 130 131 def test_DER_to_PEM(self): 132 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f: 133 pem = f.read() 134 d1 = ssl.PEM_cert_to_DER_cert(pem) 135 p2 = ssl.DER_cert_to_PEM_cert(d1) 136 d2 = ssl.PEM_cert_to_DER_cert(p2) 137 self.assertEqual(d1, d2) 138 if not p2.startswith(ssl.PEM_HEADER + '\n'): 139 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2) 140 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'): 141 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2) 142 143 def test_openssl_version(self): 144 n = ssl.OPENSSL_VERSION_NUMBER 145 t = ssl.OPENSSL_VERSION_INFO 146 s = ssl.OPENSSL_VERSION 147 self.assertIsInstance(n, (int, long)) 148 self.assertIsInstance(t, tuple) 149 self.assertIsInstance(s, str) 150 # Some sanity checks follow 151 # >= 0.9 152 self.assertGreaterEqual(n, 0x900000) 153 # < 2.0 154 self.assertLess(n, 0x20000000) 155 major, minor, fix, patch, status = t 156 self.assertGreaterEqual(major, 0) 157 self.assertLess(major, 2) 158 self.assertGreaterEqual(minor, 0) 159 self.assertLess(minor, 256) 160 self.assertGreaterEqual(fix, 0) 161 self.assertLess(fix, 256) 162 self.assertGreaterEqual(patch, 0) 163 self.assertLessEqual(patch, 26) 164 self.assertGreaterEqual(status, 0) 165 self.assertLessEqual(status, 15) 166 # Version string as returned by OpenSSL, the format might change 167 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)), 168 (s, t)) 169 170 def test_ciphers(self): 171 if not test_support.is_resource_enabled('network'): 172 return 173 remote = ("svn.python.org", 443) 174 with test_support.transient_internet(remote[0]): 175 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 176 cert_reqs=ssl.CERT_NONE, ciphers="ALL") 177 s.connect(remote) 178 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 179 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") 180 s.connect(remote) 181 # Error checking occurs when connecting, because the SSL context 182 # isn't created before. 183 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 184 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx") 185 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): 186 s.connect(remote) 187 188 @test_support.cpython_only 189 def test_refcycle(self): 190 # Issue #7943: an SSL object doesn't create reference cycles with 191 # itself. 192 s = socket.socket(socket.AF_INET) 193 ss = ssl.wrap_socket(s) 194 wr = weakref.ref(ss) 195 del ss 196 self.assertEqual(wr(), None) 197 198 def test_wrapped_unconnected(self): 199 # The _delegate_methods in socket.py are correctly delegated to by an 200 # unconnected SSLSocket, so they will raise a socket.error rather than 201 # something unexpected like TypeError. 202 s = socket.socket(socket.AF_INET) 203 ss = ssl.wrap_socket(s) 204 self.assertRaises(socket.error, ss.recv, 1) 205 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x')) 206 self.assertRaises(socket.error, ss.recvfrom, 1) 207 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1) 208 self.assertRaises(socket.error, ss.send, b'x') 209 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0)) 210 211 212class NetworkedTests(unittest.TestCase): 213 214 def test_connect(self): 215 with test_support.transient_internet("svn.python.org"): 216 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 217 cert_reqs=ssl.CERT_NONE) 218 s.connect(("svn.python.org", 443)) 219 c = s.getpeercert() 220 if c: 221 self.fail("Peer cert %s shouldn't be here!") 222 s.close() 223 224 # this should fail because we have no verification certs 225 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 226 cert_reqs=ssl.CERT_REQUIRED) 227 try: 228 s.connect(("svn.python.org", 443)) 229 except ssl.SSLError: 230 pass 231 finally: 232 s.close() 233 234 # this should succeed because we specify the root cert 235 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 236 cert_reqs=ssl.CERT_REQUIRED, 237 ca_certs=SVN_PYTHON_ORG_ROOT_CERT) 238 try: 239 s.connect(("svn.python.org", 443)) 240 finally: 241 s.close() 242 243 def test_connect_ex(self): 244 # Issue #11326: check connect_ex() implementation 245 with test_support.transient_internet("svn.python.org"): 246 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 247 cert_reqs=ssl.CERT_REQUIRED, 248 ca_certs=SVN_PYTHON_ORG_ROOT_CERT) 249 try: 250 self.assertEqual(0, s.connect_ex(("svn.python.org", 443))) 251 self.assertTrue(s.getpeercert()) 252 finally: 253 s.close() 254 255 def test_non_blocking_connect_ex(self): 256 # Issue #11326: non-blocking connect_ex() should allow handshake 257 # to proceed after the socket gets ready. 258 with test_support.transient_internet("svn.python.org"): 259 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 260 cert_reqs=ssl.CERT_REQUIRED, 261 ca_certs=SVN_PYTHON_ORG_ROOT_CERT, 262 do_handshake_on_connect=False) 263 try: 264 s.setblocking(False) 265 rc = s.connect_ex(('svn.python.org', 443)) 266 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere 267 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK)) 268 # Wait for connect to finish 269 select.select([], [s], [], 5.0) 270 # Non-blocking handshake 271 while True: 272 try: 273 s.do_handshake() 274 break 275 except ssl.SSLError as err: 276 if err.args[0] == ssl.SSL_ERROR_WANT_READ: 277 select.select([s], [], [], 5.0) 278 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: 279 select.select([], [s], [], 5.0) 280 else: 281 raise 282 # SSL established 283 self.assertTrue(s.getpeercert()) 284 finally: 285 s.close() 286 287 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows") 288 def test_makefile_close(self): 289 # Issue #5238: creating a file-like object with makefile() shouldn't 290 # delay closing the underlying "real socket" (here tested with its 291 # file descriptor, hence skipping the test under Windows). 292 with test_support.transient_internet("svn.python.org"): 293 ss = ssl.wrap_socket(socket.socket(socket.AF_INET)) 294 ss.connect(("svn.python.org", 443)) 295 fd = ss.fileno() 296 f = ss.makefile() 297 f.close() 298 # The fd is still open 299 os.read(fd, 0) 300 # Closing the SSL socket should close the fd too 301 ss.close() 302 gc.collect() 303 with self.assertRaises(OSError) as e: 304 os.read(fd, 0) 305 self.assertEqual(e.exception.errno, errno.EBADF) 306 307 def test_non_blocking_handshake(self): 308 with test_support.transient_internet("svn.python.org"): 309 s = socket.socket(socket.AF_INET) 310 s.connect(("svn.python.org", 443)) 311 s.setblocking(False) 312 s = ssl.wrap_socket(s, 313 cert_reqs=ssl.CERT_NONE, 314 do_handshake_on_connect=False) 315 count = 0 316 while True: 317 try: 318 count += 1 319 s.do_handshake() 320 break 321 except ssl.SSLError, err: 322 if err.args[0] == ssl.SSL_ERROR_WANT_READ: 323 select.select([s], [], []) 324 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: 325 select.select([], [s], []) 326 else: 327 raise 328 s.close() 329 if test_support.verbose: 330 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count) 331 332 def test_get_server_certificate(self): 333 with test_support.transient_internet("svn.python.org"): 334 pem = ssl.get_server_certificate(("svn.python.org", 443)) 335 if not pem: 336 self.fail("No server certificate on svn.python.org:443!") 337 338 try: 339 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE) 340 except ssl.SSLError: 341 #should fail 342 pass 343 else: 344 self.fail("Got server certificate %s for svn.python.org!" % pem) 345 346 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT) 347 if not pem: 348 self.fail("No server certificate on svn.python.org:443!") 349 if test_support.verbose: 350 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem) 351 352 def test_algorithms(self): 353 # Issue #8484: all algorithms should be available when verifying a 354 # certificate. 355 # SHA256 was added in OpenSSL 0.9.8 356 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15): 357 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION) 358 # NOTE: https://sha256.tbs-internet.com is another possible test host 359 remote = ("sha256.tbs-internet.com", 443) 360 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem") 361 with test_support.transient_internet("sha256.tbs-internet.com"): 362 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 363 cert_reqs=ssl.CERT_REQUIRED, 364 ca_certs=sha256_cert,) 365 try: 366 s.connect(remote) 367 if test_support.verbose: 368 sys.stdout.write("\nCipher with %r is %r\n" % 369 (remote, s.cipher())) 370 sys.stdout.write("Certificate is:\n%s\n" % 371 pprint.pformat(s.getpeercert())) 372 finally: 373 s.close() 374 375 376try: 377 import threading 378except ImportError: 379 _have_threads = False 380else: 381 _have_threads = True 382 383 class ThreadedEchoServer(threading.Thread): 384 385 class ConnectionHandler(threading.Thread): 386 387 """A mildly complicated class, because we want it to work both 388 with and without the SSL wrapper around the socket connection, so 389 that we can test the STARTTLS functionality.""" 390 391 def __init__(self, server, connsock): 392 self.server = server 393 self.running = False 394 self.sock = connsock 395 self.sock.setblocking(1) 396 self.sslconn = None 397 threading.Thread.__init__(self) 398 self.daemon = True 399 400 def show_conn_details(self): 401 if self.server.certreqs == ssl.CERT_REQUIRED: 402 cert = self.sslconn.getpeercert() 403 if test_support.verbose and self.server.chatty: 404 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n") 405 cert_binary = self.sslconn.getpeercert(True) 406 if test_support.verbose and self.server.chatty: 407 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n") 408 cipher = self.sslconn.cipher() 409 if test_support.verbose and self.server.chatty: 410 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n") 411 412 def wrap_conn(self): 413 try: 414 self.sslconn = ssl.wrap_socket(self.sock, server_side=True, 415 certfile=self.server.certificate, 416 ssl_version=self.server.protocol, 417 ca_certs=self.server.cacerts, 418 cert_reqs=self.server.certreqs, 419 ciphers=self.server.ciphers) 420 except ssl.SSLError as e: 421 # XXX Various errors can have happened here, for example 422 # a mismatching protocol version, an invalid certificate, 423 # or a low-level bug. This should be made more discriminating. 424 self.server.conn_errors.append(e) 425 if self.server.chatty: 426 handle_error("\n server: bad connection attempt from " + 427 str(self.sock.getpeername()) + ":\n") 428 self.close() 429 self.running = False 430 self.server.stop() 431 return False 432 else: 433 return True 434 435 def read(self): 436 if self.sslconn: 437 return self.sslconn.read() 438 else: 439 return self.sock.recv(1024) 440 441 def write(self, bytes): 442 if self.sslconn: 443 return self.sslconn.write(bytes) 444 else: 445 return self.sock.send(bytes) 446 447 def close(self): 448 if self.sslconn: 449 self.sslconn.close() 450 else: 451 self.sock._sock.close() 452 453 def run(self): 454 self.running = True 455 if not self.server.starttls_server: 456 if isinstance(self.sock, ssl.SSLSocket): 457 self.sslconn = self.sock 458 elif not self.wrap_conn(): 459 return 460 self.show_conn_details() 461 while self.running: 462 try: 463 msg = self.read() 464 if not msg: 465 # eof, so quit this handler 466 self.running = False 467 self.close() 468 elif msg.strip() == 'over': 469 if test_support.verbose and self.server.connectionchatty: 470 sys.stdout.write(" server: client closed connection\n") 471 self.close() 472 return 473 elif self.server.starttls_server and msg.strip() == 'STARTTLS': 474 if test_support.verbose and self.server.connectionchatty: 475 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n") 476 self.write("OK\n") 477 if not self.wrap_conn(): 478 return 479 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS': 480 if test_support.verbose and self.server.connectionchatty: 481 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n") 482 self.write("OK\n") 483 self.sslconn.unwrap() 484 self.sslconn = None 485 if test_support.verbose and self.server.connectionchatty: 486 sys.stdout.write(" server: connection is now unencrypted...\n") 487 else: 488 if (test_support.verbose and 489 self.server.connectionchatty): 490 ctype = (self.sslconn and "encrypted") or "unencrypted" 491 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n" 492 % (repr(msg), ctype, repr(msg.lower()), ctype)) 493 self.write(msg.lower()) 494 except ssl.SSLError: 495 if self.server.chatty: 496 handle_error("Test server failure:\n") 497 self.close() 498 self.running = False 499 # normally, we'd just stop here, but for the test 500 # harness, we want to stop the server 501 self.server.stop() 502 503 def __init__(self, certificate, ssl_version=None, 504 certreqs=None, cacerts=None, 505 chatty=True, connectionchatty=False, starttls_server=False, 506 wrap_accepting_socket=False, ciphers=None): 507 508 if ssl_version is None: 509 ssl_version = ssl.PROTOCOL_TLSv1 510 if certreqs is None: 511 certreqs = ssl.CERT_NONE 512 self.certificate = certificate 513 self.protocol = ssl_version 514 self.certreqs = certreqs 515 self.cacerts = cacerts 516 self.ciphers = ciphers 517 self.chatty = chatty 518 self.connectionchatty = connectionchatty 519 self.starttls_server = starttls_server 520 self.sock = socket.socket() 521 self.flag = None 522 if wrap_accepting_socket: 523 self.sock = ssl.wrap_socket(self.sock, server_side=True, 524 certfile=self.certificate, 525 cert_reqs = self.certreqs, 526 ca_certs = self.cacerts, 527 ssl_version = self.protocol, 528 ciphers = self.ciphers) 529 if test_support.verbose and self.chatty: 530 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock)) 531 self.port = test_support.bind_port(self.sock) 532 self.active = False 533 self.conn_errors = [] 534 threading.Thread.__init__(self) 535 self.daemon = True 536 537 def __enter__(self): 538 self.start(threading.Event()) 539 self.flag.wait() 540 return self 541 542 def __exit__(self, *args): 543 self.stop() 544 self.join() 545 546 def start(self, flag=None): 547 self.flag = flag 548 threading.Thread.start(self) 549 550 def run(self): 551 self.sock.settimeout(0.05) 552 self.sock.listen(5) 553 self.active = True 554 if self.flag: 555 # signal an event 556 self.flag.set() 557 while self.active: 558 try: 559 newconn, connaddr = self.sock.accept() 560 if test_support.verbose and self.chatty: 561 sys.stdout.write(' server: new connection from ' 562 + str(connaddr) + '\n') 563 handler = self.ConnectionHandler(self, newconn) 564 handler.start() 565 handler.join() 566 except socket.timeout: 567 pass 568 except KeyboardInterrupt: 569 self.stop() 570 self.sock.close() 571 572 def stop(self): 573 self.active = False 574 575 class AsyncoreEchoServer(threading.Thread): 576 577 class EchoServer(asyncore.dispatcher): 578 579 class ConnectionHandler(asyncore.dispatcher_with_send): 580 581 def __init__(self, conn, certfile): 582 asyncore.dispatcher_with_send.__init__(self, conn) 583 self.socket = ssl.wrap_socket(conn, server_side=True, 584 certfile=certfile, 585 do_handshake_on_connect=False) 586 self._ssl_accepting = True 587 588 def readable(self): 589 if isinstance(self.socket, ssl.SSLSocket): 590 while self.socket.pending() > 0: 591 self.handle_read_event() 592 return True 593 594 def _do_ssl_handshake(self): 595 try: 596 self.socket.do_handshake() 597 except ssl.SSLError, err: 598 if err.args[0] in (ssl.SSL_ERROR_WANT_READ, 599 ssl.SSL_ERROR_WANT_WRITE): 600 return 601 elif err.args[0] == ssl.SSL_ERROR_EOF: 602 return self.handle_close() 603 raise 604 except socket.error, err: 605 if err.args[0] == errno.ECONNABORTED: 606 return self.handle_close() 607 else: 608 self._ssl_accepting = False 609 610 def handle_read(self): 611 if self._ssl_accepting: 612 self._do_ssl_handshake() 613 else: 614 data = self.recv(1024) 615 if data and data.strip() != 'over': 616 self.send(data.lower()) 617 618 def handle_close(self): 619 self.close() 620 if test_support.verbose: 621 sys.stdout.write(" server: closed connection %s\n" % self.socket) 622 623 def handle_error(self): 624 raise 625 626 def __init__(self, certfile): 627 self.certfile = certfile 628 asyncore.dispatcher.__init__(self) 629 self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 630 self.port = test_support.bind_port(self.socket) 631 self.listen(5) 632 633 def handle_accept(self): 634 sock_obj, addr = self.accept() 635 if test_support.verbose: 636 sys.stdout.write(" server: new connection from %s:%s\n" %addr) 637 self.ConnectionHandler(sock_obj, self.certfile) 638 639 def handle_error(self): 640 raise 641 642 def __init__(self, certfile): 643 self.flag = None 644 self.active = False 645 self.server = self.EchoServer(certfile) 646 self.port = self.server.port 647 threading.Thread.__init__(self) 648 self.daemon = True 649 650 def __str__(self): 651 return "<%s %s>" % (self.__class__.__name__, self.server) 652 653 def __enter__(self): 654 self.start(threading.Event()) 655 self.flag.wait() 656 return self 657 658 def __exit__(self, *args): 659 if test_support.verbose: 660 sys.stdout.write(" cleanup: stopping server.\n") 661 self.stop() 662 if test_support.verbose: 663 sys.stdout.write(" cleanup: joining server thread.\n") 664 self.join() 665 if test_support.verbose: 666 sys.stdout.write(" cleanup: successfully joined.\n") 667 668 def start(self, flag=None): 669 self.flag = flag 670 threading.Thread.start(self) 671 672 def run(self): 673 self.active = True 674 if self.flag: 675 self.flag.set() 676 while self.active: 677 asyncore.loop(0.05) 678 679 def stop(self): 680 self.active = False 681 self.server.close() 682 683 class SocketServerHTTPSServer(threading.Thread): 684 685 class HTTPSServer(HTTPServer): 686 687 def __init__(self, server_address, RequestHandlerClass, certfile): 688 HTTPServer.__init__(self, server_address, RequestHandlerClass) 689 # we assume the certfile contains both private key and certificate 690 self.certfile = certfile 691 self.allow_reuse_address = True 692 693 def __str__(self): 694 return ('<%s %s:%s>' % 695 (self.__class__.__name__, 696 self.server_name, 697 self.server_port)) 698 699 def get_request(self): 700 # override this to wrap socket with SSL 701 sock, addr = self.socket.accept() 702 sslconn = ssl.wrap_socket(sock, server_side=True, 703 certfile=self.certfile) 704 return sslconn, addr 705 706 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler): 707 # need to override translate_path to get a known root, 708 # instead of using os.curdir, since the test could be 709 # run from anywhere 710 711 server_version = "TestHTTPS/1.0" 712 713 root = None 714 715 def translate_path(self, path): 716 """Translate a /-separated PATH to the local filename syntax. 717 718 Components that mean special things to the local file system 719 (e.g. drive or directory names) are ignored. (XXX They should 720 probably be diagnosed.) 721 722 """ 723 # abandon query parameters 724 path = urlparse.urlparse(path)[2] 725 path = os.path.normpath(urllib.unquote(path)) 726 words = path.split('/') 727 words = filter(None, words) 728 path = self.root 729 for word in words: 730 drive, word = os.path.splitdrive(word) 731 head, word = os.path.split(word) 732 if word in self.root: continue 733 path = os.path.join(path, word) 734 return path 735 736 def log_message(self, format, *args): 737 738 # we override this to suppress logging unless "verbose" 739 740 if test_support.verbose: 741 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" % 742 (self.server.server_address, 743 self.server.server_port, 744 self.request.cipher(), 745 self.log_date_time_string(), 746 format%args)) 747 748 749 def __init__(self, certfile): 750 self.flag = None 751 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0] 752 self.server = self.HTTPSServer( 753 (HOST, 0), self.RootedHTTPRequestHandler, certfile) 754 self.port = self.server.server_port 755 threading.Thread.__init__(self) 756 self.daemon = True 757 758 def __str__(self): 759 return "<%s %s>" % (self.__class__.__name__, self.server) 760 761 def start(self, flag=None): 762 self.flag = flag 763 threading.Thread.start(self) 764 765 def run(self): 766 if self.flag: 767 self.flag.set() 768 self.server.serve_forever(0.05) 769 770 def stop(self): 771 self.server.shutdown() 772 773 774 def bad_cert_test(certfile): 775 """ 776 Launch a server with CERT_REQUIRED, and check that trying to 777 connect to it with the given client certificate fails. 778 """ 779 server = ThreadedEchoServer(CERTFILE, 780 certreqs=ssl.CERT_REQUIRED, 781 cacerts=CERTFILE, chatty=False) 782 with server: 783 try: 784 s = ssl.wrap_socket(socket.socket(), 785 certfile=certfile, 786 ssl_version=ssl.PROTOCOL_TLSv1) 787 s.connect((HOST, server.port)) 788 except ssl.SSLError, x: 789 if test_support.verbose: 790 sys.stdout.write("\nSSLError is %s\n" % x[1]) 791 except socket.error, x: 792 if test_support.verbose: 793 sys.stdout.write("\nsocket.error is %s\n" % x[1]) 794 else: 795 raise AssertionError("Use of invalid cert should have failed!") 796 797 def server_params_test(certfile, protocol, certreqs, cacertsfile, 798 client_certfile, client_protocol=None, indata="FOO\n", 799 ciphers=None, chatty=True, connectionchatty=False, 800 wrap_accepting_socket=False): 801 """ 802 Launch a server, connect a client to it and try various reads 803 and writes. 804 """ 805 server = ThreadedEchoServer(certfile, 806 certreqs=certreqs, 807 ssl_version=protocol, 808 cacerts=cacertsfile, 809 ciphers=ciphers, 810 chatty=chatty, 811 connectionchatty=connectionchatty, 812 wrap_accepting_socket=wrap_accepting_socket) 813 with server: 814 # try to connect 815 if client_protocol is None: 816 client_protocol = protocol 817 s = ssl.wrap_socket(socket.socket(), 818 certfile=client_certfile, 819 ca_certs=cacertsfile, 820 ciphers=ciphers, 821 cert_reqs=certreqs, 822 ssl_version=client_protocol) 823 s.connect((HOST, server.port)) 824 for arg in [indata, bytearray(indata), memoryview(indata)]: 825 if connectionchatty: 826 if test_support.verbose: 827 sys.stdout.write( 828 " client: sending %s...\n" % (repr(arg))) 829 s.write(arg) 830 outdata = s.read() 831 if connectionchatty: 832 if test_support.verbose: 833 sys.stdout.write(" client: read %s\n" % repr(outdata)) 834 if outdata != indata.lower(): 835 raise AssertionError( 836 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n" 837 % (outdata[:min(len(outdata),20)], len(outdata), 838 indata[:min(len(indata),20)].lower(), len(indata))) 839 s.write("over\n") 840 if connectionchatty: 841 if test_support.verbose: 842 sys.stdout.write(" client: closing connection.\n") 843 s.close() 844 845 def try_protocol_combo(server_protocol, 846 client_protocol, 847 expect_success, 848 certsreqs=None): 849 if certsreqs is None: 850 certsreqs = ssl.CERT_NONE 851 certtype = { 852 ssl.CERT_NONE: "CERT_NONE", 853 ssl.CERT_OPTIONAL: "CERT_OPTIONAL", 854 ssl.CERT_REQUIRED: "CERT_REQUIRED", 855 }[certsreqs] 856 if test_support.verbose: 857 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n" 858 sys.stdout.write(formatstr % 859 (ssl.get_protocol_name(client_protocol), 860 ssl.get_protocol_name(server_protocol), 861 certtype)) 862 try: 863 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client 864 # will send an SSLv3 hello (rather than SSLv2) starting from 865 # OpenSSL 1.0.0 (see issue #8322). 866 server_params_test(CERTFILE, server_protocol, certsreqs, 867 CERTFILE, CERTFILE, client_protocol, 868 ciphers="ALL", chatty=False) 869 # Protocol mismatch can result in either an SSLError, or a 870 # "Connection reset by peer" error. 871 except ssl.SSLError: 872 if expect_success: 873 raise 874 except socket.error as e: 875 if expect_success or e.errno != errno.ECONNRESET: 876 raise 877 else: 878 if not expect_success: 879 raise AssertionError( 880 "Client protocol %s succeeded with server protocol %s!" 881 % (ssl.get_protocol_name(client_protocol), 882 ssl.get_protocol_name(server_protocol))) 883 884 885 class ThreadedTests(unittest.TestCase): 886 887 def test_rude_shutdown(self): 888 """A brutal shutdown of an SSL server should raise an IOError 889 in the client when attempting handshake. 890 """ 891 listener_ready = threading.Event() 892 listener_gone = threading.Event() 893 894 s = socket.socket() 895 port = test_support.bind_port(s, HOST) 896 897 # `listener` runs in a thread. It sits in an accept() until 898 # the main thread connects. Then it rudely closes the socket, 899 # and sets Event `listener_gone` to let the main thread know 900 # the socket is gone. 901 def listener(): 902 s.listen(5) 903 listener_ready.set() 904 s.accept() 905 s.close() 906 listener_gone.set() 907 908 def connector(): 909 listener_ready.wait() 910 c = socket.socket() 911 c.connect((HOST, port)) 912 listener_gone.wait() 913 # XXX why is it necessary? 914 test_support.gc_collect() 915 try: 916 ssl_sock = ssl.wrap_socket(c) 917 except IOError: 918 pass 919 else: 920 self.fail('connecting to closed SSL socket should have failed') 921 922 t = threading.Thread(target=listener) 923 t.start() 924 try: 925 connector() 926 finally: 927 t.join() 928 929 @skip_if_broken_ubuntu_ssl 930 def test_echo(self): 931 """Basic test of an SSL client connecting to a server""" 932 if test_support.verbose: 933 sys.stdout.write("\n") 934 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE, 935 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1, 936 chatty=True, connectionchatty=True) 937 938 def test_getpeercert(self): 939 if test_support.verbose: 940 sys.stdout.write("\n") 941 s2 = socket.socket() 942 server = ThreadedEchoServer(CERTFILE, 943 certreqs=ssl.CERT_NONE, 944 ssl_version=ssl.PROTOCOL_SSLv23, 945 cacerts=CERTFILE, 946 chatty=False) 947 with server: 948 s = ssl.wrap_socket(socket.socket(), 949 certfile=CERTFILE, 950 ca_certs=CERTFILE, 951 cert_reqs=ssl.CERT_REQUIRED, 952 ssl_version=ssl.PROTOCOL_SSLv23) 953 s.connect((HOST, server.port)) 954 cert = s.getpeercert() 955 self.assertTrue(cert, "Can't get peer certificate.") 956 cipher = s.cipher() 957 if test_support.verbose: 958 sys.stdout.write(pprint.pformat(cert) + '\n') 959 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n') 960 if 'subject' not in cert: 961 self.fail("No subject field in certificate: %s." % 962 pprint.pformat(cert)) 963 if ((('organizationName', 'Python Software Foundation'),) 964 not in cert['subject']): 965 self.fail( 966 "Missing or invalid 'organizationName' field in certificate subject; " 967 "should be 'Python Software Foundation'.") 968 s.close() 969 970 def test_empty_cert(self): 971 """Connecting with an empty cert file""" 972 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, 973 "nullcert.pem")) 974 def test_malformed_cert(self): 975 """Connecting with a badly formatted certificate (syntax error)""" 976 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, 977 "badcert.pem")) 978 def test_nonexisting_cert(self): 979 """Connecting with a non-existing cert file""" 980 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, 981 "wrongcert.pem")) 982 def test_malformed_key(self): 983 """Connecting with a badly formatted key (syntax error)""" 984 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, 985 "badkey.pem")) 986 987 @skip_if_broken_ubuntu_ssl 988 def test_protocol_sslv2(self): 989 """Connecting to an SSLv2 server with various client options""" 990 if test_support.verbose: 991 sys.stdout.write("\n") 992 if not hasattr(ssl, 'PROTOCOL_SSLv2'): 993 self.skipTest("PROTOCOL_SSLv2 needed") 994 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) 995 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) 996 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) 997 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) 998 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) 999 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) 1000 1001 @skip_if_broken_ubuntu_ssl 1002 def test_protocol_sslv23(self): 1003 """Connecting to an SSLv23 server with various client options""" 1004 if test_support.verbose: 1005 sys.stdout.write("\n") 1006 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) 1007 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) 1008 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) 1009 1010 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) 1011 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL) 1012 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) 1013 1014 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) 1015 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED) 1016 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) 1017 1018 @skip_if_broken_ubuntu_ssl 1019 def test_protocol_sslv3(self): 1020 """Connecting to an SSLv3 server with various client options""" 1021 if test_support.verbose: 1022 sys.stdout.write("\n") 1023 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) 1024 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) 1025 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) 1026 if hasattr(ssl, 'PROTOCOL_SSLv2'): 1027 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) 1028 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) 1029 1030 @skip_if_broken_ubuntu_ssl 1031 def test_protocol_tlsv1(self): 1032 """Connecting to a TLSv1 server with various client options""" 1033 if test_support.verbose: 1034 sys.stdout.write("\n") 1035 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) 1036 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) 1037 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) 1038 if hasattr(ssl, 'PROTOCOL_SSLv2'): 1039 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) 1040 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) 1041 1042 def test_starttls(self): 1043 """Switching from clear text to encrypted and back again.""" 1044 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6") 1045 1046 server = ThreadedEchoServer(CERTFILE, 1047 ssl_version=ssl.PROTOCOL_TLSv1, 1048 starttls_server=True, 1049 chatty=True, 1050 connectionchatty=True) 1051 wrapped = False 1052 with server: 1053 s = socket.socket() 1054 s.setblocking(1) 1055 s.connect((HOST, server.port)) 1056 if test_support.verbose: 1057 sys.stdout.write("\n") 1058 for indata in msgs: 1059 if test_support.verbose: 1060 sys.stdout.write( 1061 " client: sending %s...\n" % repr(indata)) 1062 if wrapped: 1063 conn.write(indata) 1064 outdata = conn.read() 1065 else: 1066 s.send(indata) 1067 outdata = s.recv(1024) 1068 if (indata == "STARTTLS" and 1069 outdata.strip().lower().startswith("ok")): 1070 # STARTTLS ok, switch to secure mode 1071 if test_support.verbose: 1072 sys.stdout.write( 1073 " client: read %s from server, starting TLS...\n" 1074 % repr(outdata)) 1075 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) 1076 wrapped = True 1077 elif (indata == "ENDTLS" and 1078 outdata.strip().lower().startswith("ok")): 1079 # ENDTLS ok, switch back to clear text 1080 if test_support.verbose: 1081 sys.stdout.write( 1082 " client: read %s from server, ending TLS...\n" 1083 % repr(outdata)) 1084 s = conn.unwrap() 1085 wrapped = False 1086 else: 1087 if test_support.verbose: 1088 sys.stdout.write( 1089 " client: read %s from server\n" % repr(outdata)) 1090 if test_support.verbose: 1091 sys.stdout.write(" client: closing connection.\n") 1092 if wrapped: 1093 conn.write("over\n") 1094 else: 1095 s.send("over\n") 1096 s.close() 1097 1098 def test_socketserver(self): 1099 """Using a SocketServer to create and manage SSL connections.""" 1100 server = SocketServerHTTPSServer(CERTFILE) 1101 flag = threading.Event() 1102 server.start(flag) 1103 # wait for it to start 1104 flag.wait() 1105 # try to connect 1106 try: 1107 if test_support.verbose: 1108 sys.stdout.write('\n') 1109 with open(CERTFILE, 'rb') as f: 1110 d1 = f.read() 1111 d2 = '' 1112 # now fetch the same data from the HTTPS server 1113 url = 'https://127.0.0.1:%d/%s' % ( 1114 server.port, os.path.split(CERTFILE)[1]) 1115 with test_support.check_py3k_warnings(): 1116 f = urllib.urlopen(url) 1117 dlen = f.info().getheader("content-length") 1118 if dlen and (int(dlen) > 0): 1119 d2 = f.read(int(dlen)) 1120 if test_support.verbose: 1121 sys.stdout.write( 1122 " client: read %d bytes from remote server '%s'\n" 1123 % (len(d2), server)) 1124 f.close() 1125 self.assertEqual(d1, d2) 1126 finally: 1127 server.stop() 1128 server.join() 1129 1130 def test_wrapped_accept(self): 1131 """Check the accept() method on SSL sockets.""" 1132 if test_support.verbose: 1133 sys.stdout.write("\n") 1134 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED, 1135 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23, 1136 chatty=True, connectionchatty=True, 1137 wrap_accepting_socket=True) 1138 1139 def test_asyncore_server(self): 1140 """Check the example asyncore integration.""" 1141 indata = "TEST MESSAGE of mixed case\n" 1142 1143 if test_support.verbose: 1144 sys.stdout.write("\n") 1145 server = AsyncoreEchoServer(CERTFILE) 1146 with server: 1147 s = ssl.wrap_socket(socket.socket()) 1148 s.connect(('127.0.0.1', server.port)) 1149 if test_support.verbose: 1150 sys.stdout.write( 1151 " client: sending %s...\n" % (repr(indata))) 1152 s.write(indata) 1153 outdata = s.read() 1154 if test_support.verbose: 1155 sys.stdout.write(" client: read %s\n" % repr(outdata)) 1156 if outdata != indata.lower(): 1157 self.fail( 1158 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n" 1159 % (outdata[:min(len(outdata),20)], len(outdata), 1160 indata[:min(len(indata),20)].lower(), len(indata))) 1161 s.write("over\n") 1162 if test_support.verbose: 1163 sys.stdout.write(" client: closing connection.\n") 1164 s.close() 1165 1166 def test_recv_send(self): 1167 """Test recv(), send() and friends.""" 1168 if test_support.verbose: 1169 sys.stdout.write("\n") 1170 1171 server = ThreadedEchoServer(CERTFILE, 1172 certreqs=ssl.CERT_NONE, 1173 ssl_version=ssl.PROTOCOL_TLSv1, 1174 cacerts=CERTFILE, 1175 chatty=True, 1176 connectionchatty=False) 1177 with server: 1178 s = ssl.wrap_socket(socket.socket(), 1179 server_side=False, 1180 certfile=CERTFILE, 1181 ca_certs=CERTFILE, 1182 cert_reqs=ssl.CERT_NONE, 1183 ssl_version=ssl.PROTOCOL_TLSv1) 1184 s.connect((HOST, server.port)) 1185 # helper methods for standardising recv* method signatures 1186 def _recv_into(): 1187 b = bytearray("\0"*100) 1188 count = s.recv_into(b) 1189 return b[:count] 1190 1191 def _recvfrom_into(): 1192 b = bytearray("\0"*100) 1193 count, addr = s.recvfrom_into(b) 1194 return b[:count] 1195 1196 # (name, method, whether to expect success, *args) 1197 send_methods = [ 1198 ('send', s.send, True, []), 1199 ('sendto', s.sendto, False, ["some.address"]), 1200 ('sendall', s.sendall, True, []), 1201 ] 1202 recv_methods = [ 1203 ('recv', s.recv, True, []), 1204 ('recvfrom', s.recvfrom, False, ["some.address"]), 1205 ('recv_into', _recv_into, True, []), 1206 ('recvfrom_into', _recvfrom_into, False, []), 1207 ] 1208 data_prefix = u"PREFIX_" 1209 1210 for meth_name, send_meth, expect_success, args in send_methods: 1211 indata = data_prefix + meth_name 1212 try: 1213 send_meth(indata.encode('ASCII', 'strict'), *args) 1214 outdata = s.read() 1215 outdata = outdata.decode('ASCII', 'strict') 1216 if outdata != indata.lower(): 1217 self.fail( 1218 "While sending with <<%s>> bad data " 1219 "<<%r>> (%d) received; " 1220 "expected <<%r>> (%d)\n" % ( 1221 meth_name, outdata[:20], len(outdata), 1222 indata[:20], len(indata) 1223 ) 1224 ) 1225 except ValueError as e: 1226 if expect_success: 1227 self.fail( 1228 "Failed to send with method <<%s>>; " 1229 "expected to succeed.\n" % (meth_name,) 1230 ) 1231 if not str(e).startswith(meth_name): 1232 self.fail( 1233 "Method <<%s>> failed with unexpected " 1234 "exception message: %s\n" % ( 1235 meth_name, e 1236 ) 1237 ) 1238 1239 for meth_name, recv_meth, expect_success, args in recv_methods: 1240 indata = data_prefix + meth_name 1241 try: 1242 s.send(indata.encode('ASCII', 'strict')) 1243 outdata = recv_meth(*args) 1244 outdata = outdata.decode('ASCII', 'strict') 1245 if outdata != indata.lower(): 1246 self.fail( 1247 "While receiving with <<%s>> bad data " 1248 "<<%r>> (%d) received; " 1249 "expected <<%r>> (%d)\n" % ( 1250 meth_name, outdata[:20], len(outdata), 1251 indata[:20], len(indata) 1252 ) 1253 ) 1254 except ValueError as e: 1255 if expect_success: 1256 self.fail( 1257 "Failed to receive with method <<%s>>; " 1258 "expected to succeed.\n" % (meth_name,) 1259 ) 1260 if not str(e).startswith(meth_name): 1261 self.fail( 1262 "Method <<%s>> failed with unexpected " 1263 "exception message: %s\n" % ( 1264 meth_name, e 1265 ) 1266 ) 1267 # consume data 1268 s.read() 1269 1270 s.write("over\n".encode("ASCII", "strict")) 1271 s.close() 1272 1273 def test_handshake_timeout(self): 1274 # Issue #5103: SSL handshake must respect the socket timeout 1275 server = socket.socket(socket.AF_INET) 1276 host = "127.0.0.1" 1277 port = test_support.bind_port(server) 1278 started = threading.Event() 1279 finish = False 1280 1281 def serve(): 1282 server.listen(5) 1283 started.set() 1284 conns = [] 1285 while not finish: 1286 r, w, e = select.select([server], [], [], 0.1) 1287 if server in r: 1288 # Let the socket hang around rather than having 1289 # it closed by garbage collection. 1290 conns.append(server.accept()[0]) 1291 1292 t = threading.Thread(target=serve) 1293 t.start() 1294 started.wait() 1295 1296 try: 1297 try: 1298 c = socket.socket(socket.AF_INET) 1299 c.settimeout(0.2) 1300 c.connect((host, port)) 1301 # Will attempt handshake and time out 1302 self.assertRaisesRegexp(ssl.SSLError, "timed out", 1303 ssl.wrap_socket, c) 1304 finally: 1305 c.close() 1306 try: 1307 c = socket.socket(socket.AF_INET) 1308 c.settimeout(0.2) 1309 c = ssl.wrap_socket(c) 1310 # Will attempt handshake and time out 1311 self.assertRaisesRegexp(ssl.SSLError, "timed out", 1312 c.connect, (host, port)) 1313 finally: 1314 c.close() 1315 finally: 1316 finish = True 1317 t.join() 1318 server.close() 1319 1320 def test_default_ciphers(self): 1321 with ThreadedEchoServer(CERTFILE, 1322 ssl_version=ssl.PROTOCOL_SSLv23, 1323 chatty=False) as server: 1324 sock = socket.socket() 1325 try: 1326 # Force a set of weak ciphers on our client socket 1327 try: 1328 s = ssl.wrap_socket(sock, 1329 ssl_version=ssl.PROTOCOL_SSLv23, 1330 ciphers="DES") 1331 except ssl.SSLError: 1332 self.skipTest("no DES cipher available") 1333 with self.assertRaises((OSError, ssl.SSLError)): 1334 s.connect((HOST, server.port)) 1335 finally: 1336 sock.close() 1337 self.assertIn("no shared cipher", str(server.conn_errors[0])) 1338 1339 1340def test_main(verbose=False): 1341 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT 1342 CERTFILE = test_support.findfile("keycert.pem") 1343 SVN_PYTHON_ORG_ROOT_CERT = test_support.findfile( 1344 "https_svn_python_org_root.pem") 1345 NOKIACERT = test_support.findfile("nokia.pem") 1346 1347 if (not os.path.exists(CERTFILE) or 1348 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or 1349 not os.path.exists(NOKIACERT)): 1350 raise test_support.TestFailed("Can't read certificate files!") 1351 1352 tests = [BasicTests, BasicSocketTests] 1353 1354 if test_support.is_resource_enabled('network'): 1355 tests.append(NetworkedTests) 1356 1357 if _have_threads: 1358 thread_info = test_support.threading_setup() 1359 if thread_info and test_support.is_resource_enabled('network'): 1360 tests.append(ThreadedTests) 1361 1362 try: 1363 test_support.run_unittest(*tests) 1364 finally: 1365 if _have_threads: 1366 test_support.threading_cleanup(*thread_info) 1367 1368if __name__ == "__main__": 1369 test_main()