PageRenderTime 11ms CodeModel.GetById 3ms app.highlight 81ms RepoModel.GetById 1ms app.codeStats 1ms

/Lib/test/test_ssl.py

https://bitbucket.org/benoitbryon/cpython
Python | 1951 lines | 1792 code | 83 blank | 76 comment | 96 complexity | 1de9b5b6db345d12637aabb1e07c9e20 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1# Test the support for SSL and sockets
   2
   3import sys
   4import unittest
   5from test import support
   6import socket
   7import select
   8import time
   9import gc
  10import os
  11import errno
  12import pprint
  13import tempfile
  14import urllib.request
  15import traceback
  16import asyncore
  17import weakref
  18import platform
  19import functools
  20
  21ssl = support.import_module("ssl")
  22
  23PROTOCOLS = [
  24    ssl.PROTOCOL_SSLv3,
  25    ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
  26]
  27if hasattr(ssl, 'PROTOCOL_SSLv2'):
  28    PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
  29
  30HOST = support.HOST
  31
  32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
  33
  34# The custom key and certificate files used in test_ssl are generated
  35# using Lib/test/make_ssl_certs.py.
  36# Other certificates are simply fetched from the Internet servers they
  37# are meant to authenticate.
  38
  39CERTFILE = data_file("keycert.pem")
  40BYTES_CERTFILE = os.fsencode(CERTFILE)
  41ONLYCERT = data_file("ssl_cert.pem")
  42ONLYKEY = data_file("ssl_key.pem")
  43BYTES_ONLYCERT = os.fsencode(ONLYCERT)
  44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
  45CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
  46ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
  47KEY_PASSWORD = "somepass"
  48CAPATH = data_file("capath")
  49BYTES_CAPATH = os.fsencode(CAPATH)
  50
  51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
  52
  53EMPTYCERT = data_file("nullcert.pem")
  54BADCERT = data_file("badcert.pem")
  55WRONGCERT = data_file("XXXnonexisting.pem")
  56BADKEY = data_file("badkey.pem")
  57NOKIACERT = data_file("nokia.pem")
  58
  59DHFILE = data_file("dh512.pem")
  60BYTES_DHFILE = os.fsencode(DHFILE)
  61
  62def handle_error(prefix):
  63    exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
  64    if support.verbose:
  65        sys.stdout.write(prefix + exc_format)
  66
  67def can_clear_options():
  68    # 0.9.8m or higher
  69    return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
  70
  71def no_sslv2_implies_sslv3_hello():
  72    # 0.9.7h or higher
  73    return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
  74
  75
  76# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
  77def skip_if_broken_ubuntu_ssl(func):
  78    if hasattr(ssl, 'PROTOCOL_SSLv2'):
  79        @functools.wraps(func)
  80        def f(*args, **kwargs):
  81            try:
  82                ssl.SSLContext(ssl.PROTOCOL_SSLv2)
  83            except ssl.SSLError:
  84                if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
  85                    platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
  86                    raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
  87            return func(*args, **kwargs)
  88        return f
  89    else:
  90        return func
  91
  92
  93class BasicSocketTests(unittest.TestCase):
  94
  95    def test_constants(self):
  96        #ssl.PROTOCOL_SSLv2
  97        ssl.PROTOCOL_SSLv23
  98        ssl.PROTOCOL_SSLv3
  99        ssl.PROTOCOL_TLSv1
 100        ssl.CERT_NONE
 101        ssl.CERT_OPTIONAL
 102        ssl.CERT_REQUIRED
 103        ssl.OP_CIPHER_SERVER_PREFERENCE
 104        ssl.OP_SINGLE_DH_USE
 105        if ssl.HAS_ECDH:
 106            ssl.OP_SINGLE_ECDH_USE
 107        if ssl.OPENSSL_VERSION_INFO >= (1, 0):
 108            ssl.OP_NO_COMPRESSION
 109        self.assertIn(ssl.HAS_SNI, {True, False})
 110        self.assertIn(ssl.HAS_ECDH, {True, False})
 111
 112    def test_random(self):
 113        v = ssl.RAND_status()
 114        if support.verbose:
 115            sys.stdout.write("\n RAND_status is %d (%s)\n"
 116                             % (v, (v and "sufficient randomness") or
 117                                "insufficient randomness"))
 118
 119        data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
 120        self.assertEqual(len(data), 16)
 121        self.assertEqual(is_cryptographic, v == 1)
 122        if v:
 123            data = ssl.RAND_bytes(16)
 124            self.assertEqual(len(data), 16)
 125        else:
 126            self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
 127
 128        try:
 129            ssl.RAND_egd(1)
 130        except TypeError:
 131            pass
 132        else:
 133            print("didn't raise TypeError")
 134        ssl.RAND_add("this is a random string", 75.0)
 135
 136    def test_parse_cert(self):
 137        # note that this uses an 'unofficial' function in _ssl.c,
 138        # provided solely for this test, to exercise the certificate
 139        # parsing code
 140        p = ssl._ssl._test_decode_cert(CERTFILE)
 141        if support.verbose:
 142            sys.stdout.write("\n" + pprint.pformat(p) + "\n")
 143        self.assertEqual(p['issuer'],
 144                         ((('countryName', 'XY'),),
 145                          (('localityName', 'Castle Anthrax'),),
 146                          (('organizationName', 'Python Software Foundation'),),
 147                          (('commonName', 'localhost'),))
 148                        )
 149        self.assertEqual(p['notAfter'], 'Oct  5 23:01:56 2020 GMT')
 150        self.assertEqual(p['notBefore'], 'Oct  8 23:01:56 2010 GMT')
 151        self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
 152        self.assertEqual(p['subject'],
 153                         ((('countryName', 'XY'),),
 154                          (('localityName', 'Castle Anthrax'),),
 155                          (('organizationName', 'Python Software Foundation'),),
 156                          (('commonName', 'localhost'),))
 157                        )
 158        self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
 159        # Issue #13034: the subjectAltName in some certificates
 160        # (notably projects.developer.nokia.com:443) wasn't parsed
 161        p = ssl._ssl._test_decode_cert(NOKIACERT)
 162        if support.verbose:
 163            sys.stdout.write("\n" + pprint.pformat(p) + "\n")
 164        self.assertEqual(p['subjectAltName'],
 165                         (('DNS', 'projects.developer.nokia.com'),
 166                          ('DNS', 'projects.forum.nokia.com'))
 167                        )
 168
 169    def test_DER_to_PEM(self):
 170        with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
 171            pem = f.read()
 172        d1 = ssl.PEM_cert_to_DER_cert(pem)
 173        p2 = ssl.DER_cert_to_PEM_cert(d1)
 174        d2 = ssl.PEM_cert_to_DER_cert(p2)
 175        self.assertEqual(d1, d2)
 176        if not p2.startswith(ssl.PEM_HEADER + '\n'):
 177            self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
 178        if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
 179            self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
 180
 181    def test_openssl_version(self):
 182        n = ssl.OPENSSL_VERSION_NUMBER
 183        t = ssl.OPENSSL_VERSION_INFO
 184        s = ssl.OPENSSL_VERSION
 185        self.assertIsInstance(n, int)
 186        self.assertIsInstance(t, tuple)
 187        self.assertIsInstance(s, str)
 188        # Some sanity checks follow
 189        # >= 0.9
 190        self.assertGreaterEqual(n, 0x900000)
 191        # < 2.0
 192        self.assertLess(n, 0x20000000)
 193        major, minor, fix, patch, status = t
 194        self.assertGreaterEqual(major, 0)
 195        self.assertLess(major, 2)
 196        self.assertGreaterEqual(minor, 0)
 197        self.assertLess(minor, 256)
 198        self.assertGreaterEqual(fix, 0)
 199        self.assertLess(fix, 256)
 200        self.assertGreaterEqual(patch, 0)
 201        self.assertLessEqual(patch, 26)
 202        self.assertGreaterEqual(status, 0)
 203        self.assertLessEqual(status, 15)
 204        # Version string as returned by OpenSSL, the format might change
 205        self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
 206                        (s, t))
 207
 208    @support.cpython_only
 209    def test_refcycle(self):
 210        # Issue #7943: an SSL object doesn't create reference cycles with
 211        # itself.
 212        s = socket.socket(socket.AF_INET)
 213        ss = ssl.wrap_socket(s)
 214        wr = weakref.ref(ss)
 215        del ss
 216        self.assertEqual(wr(), None)
 217
 218    def test_wrapped_unconnected(self):
 219        # Methods on an unconnected SSLSocket propagate the original
 220        # socket.error raise by the underlying socket object.
 221        s = socket.socket(socket.AF_INET)
 222        ss = ssl.wrap_socket(s)
 223        self.assertRaises(socket.error, ss.recv, 1)
 224        self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
 225        self.assertRaises(socket.error, ss.recvfrom, 1)
 226        self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
 227        self.assertRaises(socket.error, ss.send, b'x')
 228        self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
 229
 230    def test_timeout(self):
 231        # Issue #8524: when creating an SSL socket, the timeout of the
 232        # original socket should be retained.
 233        for timeout in (None, 0.0, 5.0):
 234            s = socket.socket(socket.AF_INET)
 235            s.settimeout(timeout)
 236            ss = ssl.wrap_socket(s)
 237            self.assertEqual(timeout, ss.gettimeout())
 238
 239    def test_errors(self):
 240        sock = socket.socket()
 241        self.assertRaisesRegex(ValueError,
 242                        "certfile must be specified",
 243                        ssl.wrap_socket, sock, keyfile=CERTFILE)
 244        self.assertRaisesRegex(ValueError,
 245                        "certfile must be specified for server-side operations",
 246                        ssl.wrap_socket, sock, server_side=True)
 247        self.assertRaisesRegex(ValueError,
 248                        "certfile must be specified for server-side operations",
 249                        ssl.wrap_socket, sock, server_side=True, certfile="")
 250        s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
 251        self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
 252                                s.connect, (HOST, 8080))
 253        with self.assertRaises(IOError) as cm:
 254            with socket.socket() as sock:
 255                ssl.wrap_socket(sock, certfile=WRONGCERT)
 256        self.assertEqual(cm.exception.errno, errno.ENOENT)
 257        with self.assertRaises(IOError) as cm:
 258            with socket.socket() as sock:
 259                ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
 260        self.assertEqual(cm.exception.errno, errno.ENOENT)
 261        with self.assertRaises(IOError) as cm:
 262            with socket.socket() as sock:
 263                ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
 264        self.assertEqual(cm.exception.errno, errno.ENOENT)
 265
 266    def test_match_hostname(self):
 267        def ok(cert, hostname):
 268            ssl.match_hostname(cert, hostname)
 269        def fail(cert, hostname):
 270            self.assertRaises(ssl.CertificateError,
 271                              ssl.match_hostname, cert, hostname)
 272
 273        cert = {'subject': ((('commonName', 'example.com'),),)}
 274        ok(cert, 'example.com')
 275        ok(cert, 'ExAmple.cOm')
 276        fail(cert, 'www.example.com')
 277        fail(cert, '.example.com')
 278        fail(cert, 'example.org')
 279        fail(cert, 'exampleXcom')
 280
 281        cert = {'subject': ((('commonName', '*.a.com'),),)}
 282        ok(cert, 'foo.a.com')
 283        fail(cert, 'bar.foo.a.com')
 284        fail(cert, 'a.com')
 285        fail(cert, 'Xa.com')
 286        fail(cert, '.a.com')
 287
 288        cert = {'subject': ((('commonName', 'a.*.com'),),)}
 289        ok(cert, 'a.foo.com')
 290        fail(cert, 'a..com')
 291        fail(cert, 'a.com')
 292
 293        cert = {'subject': ((('commonName', 'f*.com'),),)}
 294        ok(cert, 'foo.com')
 295        ok(cert, 'f.com')
 296        fail(cert, 'bar.com')
 297        fail(cert, 'foo.a.com')
 298        fail(cert, 'bar.foo.com')
 299
 300        # Slightly fake real-world example
 301        cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
 302                'subject': ((('commonName', 'linuxfrz.org'),),),
 303                'subjectAltName': (('DNS', 'linuxfr.org'),
 304                                   ('DNS', 'linuxfr.com'),
 305                                   ('othername', '<unsupported>'))}
 306        ok(cert, 'linuxfr.org')
 307        ok(cert, 'linuxfr.com')
 308        # Not a "DNS" entry
 309        fail(cert, '<unsupported>')
 310        # When there is a subjectAltName, commonName isn't used
 311        fail(cert, 'linuxfrz.org')
 312
 313        # A pristine real-world example
 314        cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
 315                'subject': ((('countryName', 'US'),),
 316                            (('stateOrProvinceName', 'California'),),
 317                            (('localityName', 'Mountain View'),),
 318                            (('organizationName', 'Google Inc'),),
 319                            (('commonName', 'mail.google.com'),))}
 320        ok(cert, 'mail.google.com')
 321        fail(cert, 'gmail.com')
 322        # Only commonName is considered
 323        fail(cert, 'California')
 324
 325        # Neither commonName nor subjectAltName
 326        cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
 327                'subject': ((('countryName', 'US'),),
 328                            (('stateOrProvinceName', 'California'),),
 329                            (('localityName', 'Mountain View'),),
 330                            (('organizationName', 'Google Inc'),))}
 331        fail(cert, 'mail.google.com')
 332
 333        # No DNS entry in subjectAltName but a commonName
 334        cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
 335                'subject': ((('countryName', 'US'),),
 336                            (('stateOrProvinceName', 'California'),),
 337                            (('localityName', 'Mountain View'),),
 338                            (('commonName', 'mail.google.com'),)),
 339                'subjectAltName': (('othername', 'blabla'), )}
 340        ok(cert, 'mail.google.com')
 341
 342        # No DNS entry subjectAltName and no commonName
 343        cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
 344                'subject': ((('countryName', 'US'),),
 345                            (('stateOrProvinceName', 'California'),),
 346                            (('localityName', 'Mountain View'),),
 347                            (('organizationName', 'Google Inc'),)),
 348                'subjectAltName': (('othername', 'blabla'),)}
 349        fail(cert, 'google.com')
 350
 351        # Empty cert / no cert
 352        self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
 353        self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
 354
 355    def test_server_side(self):
 356        # server_hostname doesn't work for server sockets
 357        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 358        with socket.socket() as sock:
 359            self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
 360                              server_hostname="some.hostname")
 361
 362    def test_unknown_channel_binding(self):
 363        # should raise ValueError for unknown type
 364        s = socket.socket(socket.AF_INET)
 365        ss = ssl.wrap_socket(s)
 366        with self.assertRaises(ValueError):
 367            ss.get_channel_binding("unknown-type")
 368
 369    @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
 370                         "'tls-unique' channel binding not available")
 371    def test_tls_unique_channel_binding(self):
 372        # unconnected should return None for known type
 373        s = socket.socket(socket.AF_INET)
 374        ss = ssl.wrap_socket(s)
 375        self.assertIsNone(ss.get_channel_binding("tls-unique"))
 376        # the same for server-side
 377        s = socket.socket(socket.AF_INET)
 378        ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
 379        self.assertIsNone(ss.get_channel_binding("tls-unique"))
 380
 381class ContextTests(unittest.TestCase):
 382
 383    @skip_if_broken_ubuntu_ssl
 384    def test_constructor(self):
 385        if hasattr(ssl, 'PROTOCOL_SSLv2'):
 386            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
 387        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 388        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
 389        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 390        self.assertRaises(TypeError, ssl.SSLContext)
 391        self.assertRaises(ValueError, ssl.SSLContext, -1)
 392        self.assertRaises(ValueError, ssl.SSLContext, 42)
 393
 394    @skip_if_broken_ubuntu_ssl
 395    def test_protocol(self):
 396        for proto in PROTOCOLS:
 397            ctx = ssl.SSLContext(proto)
 398            self.assertEqual(ctx.protocol, proto)
 399
 400    def test_ciphers(self):
 401        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 402        ctx.set_ciphers("ALL")
 403        ctx.set_ciphers("DEFAULT")
 404        with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
 405            ctx.set_ciphers("^$:,;?*'dorothyx")
 406
 407    @skip_if_broken_ubuntu_ssl
 408    def test_options(self):
 409        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 410        # OP_ALL is the default value
 411        self.assertEqual(ssl.OP_ALL, ctx.options)
 412        ctx.options |= ssl.OP_NO_SSLv2
 413        self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
 414                         ctx.options)
 415        ctx.options |= ssl.OP_NO_SSLv3
 416        self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
 417                         ctx.options)
 418        if can_clear_options():
 419            ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
 420            self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
 421                             ctx.options)
 422            ctx.options = 0
 423            self.assertEqual(0, ctx.options)
 424        else:
 425            with self.assertRaises(ValueError):
 426                ctx.options = 0
 427
 428    def test_verify(self):
 429        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 430        # Default value
 431        self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
 432        ctx.verify_mode = ssl.CERT_OPTIONAL
 433        self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
 434        ctx.verify_mode = ssl.CERT_REQUIRED
 435        self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
 436        ctx.verify_mode = ssl.CERT_NONE
 437        self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
 438        with self.assertRaises(TypeError):
 439            ctx.verify_mode = None
 440        with self.assertRaises(ValueError):
 441            ctx.verify_mode = 42
 442
 443    def test_load_cert_chain(self):
 444        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 445        # Combined key and cert in a single file
 446        ctx.load_cert_chain(CERTFILE)
 447        ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
 448        self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
 449        with self.assertRaises(IOError) as cm:
 450            ctx.load_cert_chain(WRONGCERT)
 451        self.assertEqual(cm.exception.errno, errno.ENOENT)
 452        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 453            ctx.load_cert_chain(BADCERT)
 454        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 455            ctx.load_cert_chain(EMPTYCERT)
 456        # Separate key and cert
 457        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 458        ctx.load_cert_chain(ONLYCERT, ONLYKEY)
 459        ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
 460        ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
 461        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 462            ctx.load_cert_chain(ONLYCERT)
 463        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 464            ctx.load_cert_chain(ONLYKEY)
 465        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 466            ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
 467        # Mismatching key and cert
 468        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 469        with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
 470            ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
 471        # Password protected key and cert
 472        ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
 473        ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
 474        ctx.load_cert_chain(CERTFILE_PROTECTED,
 475                            password=bytearray(KEY_PASSWORD.encode()))
 476        ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
 477        ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
 478        ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
 479                            bytearray(KEY_PASSWORD.encode()))
 480        with self.assertRaisesRegex(TypeError, "should be a string"):
 481            ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
 482        with self.assertRaises(ssl.SSLError):
 483            ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
 484        with self.assertRaisesRegex(ValueError, "cannot be longer"):
 485            # openssl has a fixed limit on the password buffer.
 486            # PEM_BUFSIZE is generally set to 1kb.
 487            # Return a string larger than this.
 488            ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
 489        # Password callback
 490        def getpass_unicode():
 491            return KEY_PASSWORD
 492        def getpass_bytes():
 493            return KEY_PASSWORD.encode()
 494        def getpass_bytearray():
 495            return bytearray(KEY_PASSWORD.encode())
 496        def getpass_badpass():
 497            return "badpass"
 498        def getpass_huge():
 499            return b'a' * (1024 * 1024)
 500        def getpass_bad_type():
 501            return 9
 502        def getpass_exception():
 503            raise Exception('getpass error')
 504        class GetPassCallable:
 505            def __call__(self):
 506                return KEY_PASSWORD
 507            def getpass(self):
 508                return KEY_PASSWORD
 509        ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
 510        ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
 511        ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
 512        ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
 513        ctx.load_cert_chain(CERTFILE_PROTECTED,
 514                            password=GetPassCallable().getpass)
 515        with self.assertRaises(ssl.SSLError):
 516            ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
 517        with self.assertRaisesRegex(ValueError, "cannot be longer"):
 518            ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
 519        with self.assertRaisesRegex(TypeError, "must return a string"):
 520            ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
 521        with self.assertRaisesRegex(Exception, "getpass error"):
 522            ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
 523        # Make sure the password function isn't called if it isn't needed
 524        ctx.load_cert_chain(CERTFILE, password=getpass_exception)
 525
 526    def test_load_verify_locations(self):
 527        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 528        ctx.load_verify_locations(CERTFILE)
 529        ctx.load_verify_locations(cafile=CERTFILE, capath=None)
 530        ctx.load_verify_locations(BYTES_CERTFILE)
 531        ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
 532        self.assertRaises(TypeError, ctx.load_verify_locations)
 533        self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
 534        with self.assertRaises(IOError) as cm:
 535            ctx.load_verify_locations(WRONGCERT)
 536        self.assertEqual(cm.exception.errno, errno.ENOENT)
 537        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 538            ctx.load_verify_locations(BADCERT)
 539        ctx.load_verify_locations(CERTFILE, CAPATH)
 540        ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
 541
 542        # Issue #10989: crash if the second argument type is invalid
 543        self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
 544
 545    def test_load_dh_params(self):
 546        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 547        ctx.load_dh_params(DHFILE)
 548        if os.name != 'nt':
 549            ctx.load_dh_params(BYTES_DHFILE)
 550        self.assertRaises(TypeError, ctx.load_dh_params)
 551        self.assertRaises(TypeError, ctx.load_dh_params, None)
 552        with self.assertRaises(FileNotFoundError) as cm:
 553            ctx.load_dh_params(WRONGCERT)
 554        self.assertEqual(cm.exception.errno, errno.ENOENT)
 555        with self.assertRaisesRegex(ssl.SSLError, "PEM routines"):
 556            ctx.load_dh_params(CERTFILE)
 557
 558    @skip_if_broken_ubuntu_ssl
 559    def test_session_stats(self):
 560        for proto in PROTOCOLS:
 561            ctx = ssl.SSLContext(proto)
 562            self.assertEqual(ctx.session_stats(), {
 563                'number': 0,
 564                'connect': 0,
 565                'connect_good': 0,
 566                'connect_renegotiate': 0,
 567                'accept': 0,
 568                'accept_good': 0,
 569                'accept_renegotiate': 0,
 570                'hits': 0,
 571                'misses': 0,
 572                'timeouts': 0,
 573                'cache_full': 0,
 574            })
 575
 576    def test_set_default_verify_paths(self):
 577        # There's not much we can do to test that it acts as expected,
 578        # so just check it doesn't crash or raise an exception.
 579        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 580        ctx.set_default_verify_paths()
 581
 582    @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
 583    def test_set_ecdh_curve(self):
 584        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 585        ctx.set_ecdh_curve("prime256v1")
 586        ctx.set_ecdh_curve(b"prime256v1")
 587        self.assertRaises(TypeError, ctx.set_ecdh_curve)
 588        self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
 589        self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
 590        self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
 591
 592
 593class NetworkedTests(unittest.TestCase):
 594
 595    def test_connect(self):
 596        with support.transient_internet("svn.python.org"):
 597            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 598                                cert_reqs=ssl.CERT_NONE)
 599            try:
 600                s.connect(("svn.python.org", 443))
 601                self.assertEqual({}, s.getpeercert())
 602            finally:
 603                s.close()
 604
 605            # this should fail because we have no verification certs
 606            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 607                                cert_reqs=ssl.CERT_REQUIRED)
 608            self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
 609                                   s.connect, ("svn.python.org", 443))
 610            s.close()
 611
 612            # this should succeed because we specify the root cert
 613            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 614                                cert_reqs=ssl.CERT_REQUIRED,
 615                                ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
 616            try:
 617                s.connect(("svn.python.org", 443))
 618                self.assertTrue(s.getpeercert())
 619            finally:
 620                s.close()
 621
 622    def test_connect_ex(self):
 623        # Issue #11326: check connect_ex() implementation
 624        with support.transient_internet("svn.python.org"):
 625            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 626                                cert_reqs=ssl.CERT_REQUIRED,
 627                                ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
 628            try:
 629                self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
 630                self.assertTrue(s.getpeercert())
 631            finally:
 632                s.close()
 633
 634    def test_non_blocking_connect_ex(self):
 635        # Issue #11326: non-blocking connect_ex() should allow handshake
 636        # to proceed after the socket gets ready.
 637        with support.transient_internet("svn.python.org"):
 638            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 639                                cert_reqs=ssl.CERT_REQUIRED,
 640                                ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
 641                                do_handshake_on_connect=False)
 642            try:
 643                s.setblocking(False)
 644                rc = s.connect_ex(('svn.python.org', 443))
 645                # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
 646                self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
 647                # Wait for connect to finish
 648                select.select([], [s], [], 5.0)
 649                # Non-blocking handshake
 650                while True:
 651                    try:
 652                        s.do_handshake()
 653                        break
 654                    except ssl.SSLWantReadError:
 655                        select.select([s], [], [], 5.0)
 656                    except ssl.SSLWantWriteError:
 657                        select.select([], [s], [], 5.0)
 658                # SSL established
 659                self.assertTrue(s.getpeercert())
 660            finally:
 661                s.close()
 662
 663    def test_timeout_connect_ex(self):
 664        # Issue #12065: on a timeout, connect_ex() should return the original
 665        # errno (mimicking the behaviour of non-SSL sockets).
 666        with support.transient_internet("svn.python.org"):
 667            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 668                                cert_reqs=ssl.CERT_REQUIRED,
 669                                ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
 670                                do_handshake_on_connect=False)
 671            try:
 672                s.settimeout(0.0000001)
 673                rc = s.connect_ex(('svn.python.org', 443))
 674                if rc == 0:
 675                    self.skipTest("svn.python.org responded too quickly")
 676                self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
 677            finally:
 678                s.close()
 679
 680    def test_connect_with_context(self):
 681        with support.transient_internet("svn.python.org"):
 682            # Same as test_connect, but with a separately created context
 683            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 684            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 685            s.connect(("svn.python.org", 443))
 686            try:
 687                self.assertEqual({}, s.getpeercert())
 688            finally:
 689                s.close()
 690            # Same with a server hostname
 691            s = ctx.wrap_socket(socket.socket(socket.AF_INET),
 692                                server_hostname="svn.python.org")
 693            if ssl.HAS_SNI:
 694                s.connect(("svn.python.org", 443))
 695                s.close()
 696            else:
 697                self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
 698            # This should fail because we have no verification certs
 699            ctx.verify_mode = ssl.CERT_REQUIRED
 700            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 701            self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
 702                                    s.connect, ("svn.python.org", 443))
 703            s.close()
 704            # This should succeed because we specify the root cert
 705            ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
 706            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 707            s.connect(("svn.python.org", 443))
 708            try:
 709                cert = s.getpeercert()
 710                self.assertTrue(cert)
 711            finally:
 712                s.close()
 713
 714    def test_connect_capath(self):
 715        # Verify server certificates using the `capath` argument
 716        # NOTE: the subject hashing algorithm has been changed between
 717        # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
 718        # contain both versions of each certificate (same content, different
 719        # filename) for this test to be portable across OpenSSL releases.
 720        with support.transient_internet("svn.python.org"):
 721            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 722            ctx.verify_mode = ssl.CERT_REQUIRED
 723            ctx.load_verify_locations(capath=CAPATH)
 724            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 725            s.connect(("svn.python.org", 443))
 726            try:
 727                cert = s.getpeercert()
 728                self.assertTrue(cert)
 729            finally:
 730                s.close()
 731            # Same with a bytes `capath` argument
 732            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 733            ctx.verify_mode = ssl.CERT_REQUIRED
 734            ctx.load_verify_locations(capath=BYTES_CAPATH)
 735            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 736            s.connect(("svn.python.org", 443))
 737            try:
 738                cert = s.getpeercert()
 739                self.assertTrue(cert)
 740            finally:
 741                s.close()
 742
 743    @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
 744    def test_makefile_close(self):
 745        # Issue #5238: creating a file-like object with makefile() shouldn't
 746        # delay closing the underlying "real socket" (here tested with its
 747        # file descriptor, hence skipping the test under Windows).
 748        with support.transient_internet("svn.python.org"):
 749            ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
 750            ss.connect(("svn.python.org", 443))
 751            fd = ss.fileno()
 752            f = ss.makefile()
 753            f.close()
 754            # The fd is still open
 755            os.read(fd, 0)
 756            # Closing the SSL socket should close the fd too
 757            ss.close()
 758            gc.collect()
 759            with self.assertRaises(OSError) as e:
 760                os.read(fd, 0)
 761            self.assertEqual(e.exception.errno, errno.EBADF)
 762
 763    def test_non_blocking_handshake(self):
 764        with support.transient_internet("svn.python.org"):
 765            s = socket.socket(socket.AF_INET)
 766            s.connect(("svn.python.org", 443))
 767            s.setblocking(False)
 768            s = ssl.wrap_socket(s,
 769                                cert_reqs=ssl.CERT_NONE,
 770                                do_handshake_on_connect=False)
 771            count = 0
 772            while True:
 773                try:
 774                    count += 1
 775                    s.do_handshake()
 776                    break
 777                except ssl.SSLWantReadError:
 778                    select.select([s], [], [])
 779                except ssl.SSLWantWriteError:
 780                    select.select([], [s], [])
 781            s.close()
 782            if support.verbose:
 783                sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
 784
 785    def test_get_server_certificate(self):
 786        def _test_get_server_certificate(host, port, cert=None):
 787            with support.transient_internet(host):
 788                pem = ssl.get_server_certificate((host, port))
 789                if not pem:
 790                    self.fail("No server certificate on %s:%s!" % (host, port))
 791
 792                try:
 793                    pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
 794                except ssl.SSLError as x:
 795                    #should fail
 796                    if support.verbose:
 797                        sys.stdout.write("%s\n" % x)
 798                else:
 799                    self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
 800
 801                pem = ssl.get_server_certificate((host, port), ca_certs=cert)
 802                if not pem:
 803                    self.fail("No server certificate on %s:%s!" % (host, port))
 804                if support.verbose:
 805                    sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
 806
 807        _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
 808        if support.IPV6_ENABLED:
 809            _test_get_server_certificate('ipv6.google.com', 443)
 810
 811    def test_ciphers(self):
 812        remote = ("svn.python.org", 443)
 813        with support.transient_internet(remote[0]):
 814            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 815                                cert_reqs=ssl.CERT_NONE, ciphers="ALL")
 816            s.connect(remote)
 817            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 818                                cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
 819            s.connect(remote)
 820            # Error checking can happen at instantiation or when connecting
 821            with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
 822                with socket.socket(socket.AF_INET) as sock:
 823                    s = ssl.wrap_socket(sock,
 824                                        cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
 825                    s.connect(remote)
 826
 827    def test_algorithms(self):
 828        # Issue #8484: all algorithms should be available when verifying a
 829        # certificate.
 830        # SHA256 was added in OpenSSL 0.9.8
 831        if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
 832            self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
 833        # sha256.tbs-internet.com needs SNI to use the correct certificate
 834        if not ssl.HAS_SNI:
 835            self.skipTest("SNI needed for this test")
 836        # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
 837        remote = ("sha256.tbs-internet.com", 443)
 838        sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
 839        with support.transient_internet("sha256.tbs-internet.com"):
 840            ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 841            ctx.verify_mode = ssl.CERT_REQUIRED
 842            ctx.load_verify_locations(sha256_cert)
 843            s = ctx.wrap_socket(socket.socket(socket.AF_INET),
 844                                server_hostname="sha256.tbs-internet.com")
 845            try:
 846                s.connect(remote)
 847                if support.verbose:
 848                    sys.stdout.write("\nCipher with %r is %r\n" %
 849                                     (remote, s.cipher()))
 850                    sys.stdout.write("Certificate is:\n%s\n" %
 851                                     pprint.pformat(s.getpeercert()))
 852            finally:
 853                s.close()
 854
 855
 856try:
 857    import threading
 858except ImportError:
 859    _have_threads = False
 860else:
 861    _have_threads = True
 862
 863    from test.ssl_servers import make_https_server
 864
 865    class ThreadedEchoServer(threading.Thread):
 866
 867        class ConnectionHandler(threading.Thread):
 868
 869            """A mildly complicated class, because we want it to work both
 870            with and without the SSL wrapper around the socket connection, so
 871            that we can test the STARTTLS functionality."""
 872
 873            def __init__(self, server, connsock, addr):
 874                self.server = server
 875                self.running = False
 876                self.sock = connsock
 877                self.addr = addr
 878                self.sock.setblocking(1)
 879                self.sslconn = None
 880                threading.Thread.__init__(self)
 881                self.daemon = True
 882
 883            def wrap_conn(self):
 884                try:
 885                    self.sslconn = self.server.context.wrap_socket(
 886                        self.sock, server_side=True)
 887                    self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
 888                except ssl.SSLError as e:
 889                    # XXX Various errors can have happened here, for example
 890                    # a mismatching protocol version, an invalid certificate,
 891                    # or a low-level bug. This should be made more discriminating.
 892                    self.server.conn_errors.append(e)
 893                    if self.server.chatty:
 894                        handle_error("\n server:  bad connection attempt from " + repr(self.addr) + ":\n")
 895                    self.running = False
 896                    self.server.stop()
 897                    self.close()
 898                    return False
 899                else:
 900                    if self.server.context.verify_mode == ssl.CERT_REQUIRED:
 901                        cert = self.sslconn.getpeercert()
 902                        if support.verbose and self.server.chatty:
 903                            sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
 904                        cert_binary = self.sslconn.getpeercert(True)
 905                        if support.verbose and self.server.chatty:
 906                            sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
 907                    cipher = self.sslconn.cipher()
 908                    if support.verbose and self.server.chatty:
 909                        sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
 910                        sys.stdout.write(" server: selected protocol is now "
 911                                + str(self.sslconn.selected_npn_protocol()) + "\n")
 912                    return True
 913
 914            def read(self):
 915                if self.sslconn:
 916                    return self.sslconn.read()
 917                else:
 918                    return self.sock.recv(1024)
 919
 920            def write(self, bytes):
 921                if self.sslconn:
 922                    return self.sslconn.write(bytes)
 923                else:
 924                    return self.sock.send(bytes)
 925
 926            def close(self):
 927                if self.sslconn:
 928                    self.sslconn.close()
 929                else:
 930                    self.sock.close()
 931
 932            def run(self):
 933                self.running = True
 934                if not self.server.starttls_server:
 935                    if not self.wrap_conn():
 936                        return
 937                while self.running:
 938                    try:
 939                        msg = self.read()
 940                        stripped = msg.strip()
 941                        if not stripped:
 942                            # eof, so quit this handler
 943                            self.running = False
 944                            self.close()
 945                        elif stripped == b'over':
 946                            if support.verbose and self.server.connectionchatty:
 947                                sys.stdout.write(" server: client closed connection\n")
 948                            self.close()
 949                            return
 950                        elif (self.server.starttls_server and
 951                              stripped == b'STARTTLS'):
 952                            if support.verbose and self.server.connectionchatty:
 953                                sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
 954                            self.write(b"OK\n")
 955                            if not self.wrap_conn():
 956                                return
 957                        elif (self.server.starttls_server and self.sslconn
 958                              and stripped == b'ENDTLS'):
 959                            if support.verbose and self.server.connectionchatty:
 960                                sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
 961                            self.write(b"OK\n")
 962                            self.sock = self.sslconn.unwrap()
 963                            self.sslconn = None
 964                            if support.verbose and self.server.connectionchatty:
 965                                sys.stdout.write(" server: connection is now unencrypted...\n")
 966                        elif stripped == b'CB tls-unique':
 967                            if support.verbose and self.server.connectionchatty:
 968                                sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
 969                            data = self.sslconn.get_channel_binding("tls-unique")
 970                            self.write(repr(data).encode("us-ascii") + b"\n")
 971                        else:
 972                            if (support.verbose and
 973                                self.server.connectionchatty):
 974                                ctype = (self.sslconn and "encrypted") or "unencrypted"
 975                                sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
 976                                                 % (msg, ctype, msg.lower(), ctype))
 977                            self.write(msg.lower())
 978                    except socket.error:
 979                        if self.server.chatty:
 980                            handle_error("Test server failure:\n")
 981                        self.close()
 982                        self.running = False
 983                        # normally, we'd just stop here, but for the test
 984                        # harness, we want to stop the server
 985                        self.server.stop()
 986
 987        def __init__(self, certificate=None, ssl_version=None,
 988                     certreqs=None, cacerts=None,
 989                     chatty=True, connectionchatty=False, starttls_server=False,
 990                     npn_protocols=None, ciphers=None, context=None):
 991            if context:
 992                self.context = context
 993            else:
 994                self.context = ssl.SSLContext(ssl_version
 995                                              if ssl_version is not None
 996                                              else ssl.PROTOCOL_TLSv1)
 997                self.context.verify_mode = (certreqs if certreqs is not None
 998                                            else ssl.CERT_NONE)
 999                if cacerts:
1000                    self.context.load_verify_locations(cacerts)
1001                if certificate:
1002                    self.context.load_cert_chain(certificate)
1003                if npn_protocols:
1004                    self.context.set_npn_protocols(npn_protocols)
1005                if ciphers:
1006                    self.context.set_ciphers(ciphers)
1007            self.chatty = chatty
1008            self.connectionchatty = connectionchatty
1009            self.starttls_server = starttls_server
1010            self.sock = socket.socket()
1011            self.port = support.bind_port(self.sock)
1012            self.flag = None
1013            self.active = False
1014            self.selected_protocols = []
1015            self.conn_errors = []
1016            threading.Thread.__init__(self)
1017            self.daemon = True
1018
1019        def __enter__(self):
1020            self.start(threading.Event())
1021            self.flag.wait()
1022            return self
1023
1024        def __exit__(self, *args):
1025            self.stop()
1026            self.join()
1027
1028        def start(self, flag=None):
1029            self.flag = flag
1030            threading.Thread.start(self)
1031
1032        def run(self):
1033            self.sock.settimeout(0.05)
1034            self.sock.listen(5)
1035            self.active = True
1036            if self.flag:
1037                # signal an event
1038                self.flag.set()
1039            while self.active:
1040                try:
1041                    newconn, connaddr = self.sock.accept()
1042                    if support.verbose and self.chatty:
1043                        sys.stdout.write(' server:  new connection from '
1044                                         + repr(connaddr) + '\n')
1045                    handler = self.ConnectionHandler(self, newconn, connaddr)
1046                    handler.start()
1047                    handler.join()
1048                except socket.timeout:
1049                    pass
1050                except KeyboardInterrupt:
1051                    self.stop()
1052            self.sock.close()
1053
1054        def stop(self):
1055            self.active = False
1056
1057    class AsyncoreEchoServer(threading.Thread):
1058
1059        # this one's based on asyncore.dispatcher
1060
1061        class EchoServer (asyncore.dispatcher):
1062
1063            class ConnectionHandler (asyncore.dispatcher_with_send):
1064
1065                def __init__(self, conn, certfile):
1066                    self.socket = ssl.wrap_socket(conn, server_side=True,
1067                                                  certfile=certfile,
1068                                                  do_handshake_on_connect=False)
1069                    asyncore.dispatcher_with_send.__init__(self, self.socket)
1070                    self._ssl_accepting = True
1071                    self._do_ssl_handshake()
1072
1073                def readable(self):
1074                    if isinstance(self.socket, ssl.SSLSocket):
1075                        while self.socket.pending() > 0:
1076                            self.handle_read_event()
1077                    return True
1078
1079                def _do_ssl_handshake(self):
1080                    try:
1081                        self.socket.do_handshake()
1082                    except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1083                        return
1084                    except ssl.SSLEOFError:
1085                        return self.handle_close()
1086                    except ssl.SSLError:
1087                        raise
1088                    except socket.error as err:
1089                        if err.args[0] == errno.ECONNABORTED:
1090                            return self.handle_close()
1091                    else:
1092                        self._ssl_accepting = False
1093
1094                def handle_read(self):
1095                    if self._ssl_accepting:
1096                        self._do_ssl_handshake()
1097                    else:
1098                        data = self.recv(1024)
1099                        if support.verbose:
1100                            sys.stdout.write(" server:  read %s from client\n" % repr(data))
1101                        if not data:
1102                            self.close()
1103                        else:
1104                            self.send(data.lower())
1105
1106                def handle_close(self):
1107                    self.close()
1108                    if support.verbose:
1109                        sys.stdout.write(" server:  closed connection %s\n" % self.socket)
1110
1111                def handle_error(self):
1112                    raise
1113
1114            def __init__(self, certfile):
1115                self.certfile = certfile
1116                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1117                self.port = support.bind_port(sock, '')
1118                asyncore.dispatcher.__init__(self, sock)
1119                self.listen(5)
1120
1121            def handle_accepted(self, sock_obj, addr):
1122                if support.verbose:
1123                    sys.stdout.write(" server:  new connection from %s:%s\n" %addr)
1124                self.ConnectionHandler(sock_obj, self.certfile)
1125
1126            def handle_error(self):
1127                raise
1128
1129        def __init__(self, certfile):
1130            self.flag = None
1131            self.active = False
1132            self.server = self.EchoServer(certfile)
1133            self.port = self.server.port
1134            threading.Thread.__init__(self)
1135            self.daemon = True
1136
1137        def __str__(self):
1138            return "<%s %s>" % (self.__class__.__name__, self.server)
1139
1140        def __enter__(self):
1141            self.start(threading.Event())
1142            self.flag.wait()
1143            return self
1144
1145        def __exit__(self, *args):
1146            if support.verbose:
1147                sys.stdout.write(" cleanup: stopping server.\n")
1148            self.stop()
1149            if support.verbose:
1150                sys.stdout.write(" cleanup: joining server thread.\n")
1151            self.join()
1152            if support.verbose:
1153                sys.stdout.write(" cleanup: successfully joined.\n")
1154
1155        def start (self, flag=None):
1156            self.flag = flag
1157            threading.Thread.start(self)
1158
1159        def run(self):
1160            self.active = True
1161            if self.flag:
1162                s

Large files files are truncated, but you can click here to view the full file