PageRenderTime 91ms CodeModel.GetById 3ms app.highlight 74ms RepoModel.GetById 2ms app.codeStats 0ms

/site/tests/unittests/test/test_ssl.py

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

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