PageRenderTime 97ms CodeModel.GetById 3ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_ssl.py

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

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