PageRenderTime 20ms CodeModel.GetById 8ms app.highlight 77ms RepoModel.GetById 2ms app.codeStats 0ms

/Lib/test/test_ssl.py

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

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