PageRenderTime 89ms CodeModel.GetById 4ms app.highlight 73ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_ssl.py

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

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