PageRenderTime 165ms CodeModel.GetById 4ms app.highlight 145ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_ssl.py

https://bitbucket.org/ndelrosario/cpython
Python | 2024 lines | 1838 code | 94 blank | 92 comment | 101 complexity | a7892e9171856055314ab68d6eaaa436 MD5 | raw file
   1# Test the support for SSL and sockets
   2
   3import sys
   4import unittest
   5from test import support
   6import socket
   7import select
   8import time
   9import gc
  10import os
  11import errno
  12import pprint
  13import tempfile
  14import urllib.request
  15import traceback
  16import asyncore
  17import weakref
  18import platform
  19import functools
  20
  21ssl = support.import_module("ssl")
  22
  23PROTOCOLS = [
  24    ssl.PROTOCOL_SSLv3,
  25    ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
  26]
  27if hasattr(ssl, 'PROTOCOL_SSLv2'):
  28    PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
  29
  30HOST = support.HOST
  31
  32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
  33
  34# The custom key and certificate files used in test_ssl are generated
  35# using Lib/test/make_ssl_certs.py.
  36# Other certificates are simply fetched from the Internet servers they
  37# are meant to authenticate.
  38
  39CERTFILE = data_file("keycert.pem")
  40BYTES_CERTFILE = os.fsencode(CERTFILE)
  41ONLYCERT = data_file("ssl_cert.pem")
  42ONLYKEY = data_file("ssl_key.pem")
  43BYTES_ONLYCERT = os.fsencode(ONLYCERT)
  44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
  45CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
  46ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
  47KEY_PASSWORD = "somepass"
  48CAPATH = data_file("capath")
  49BYTES_CAPATH = os.fsencode(CAPATH)
  50
  51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
  52
  53EMPTYCERT = data_file("nullcert.pem")
  54BADCERT = data_file("badcert.pem")
  55WRONGCERT = data_file("XXXnonexisting.pem")
  56BADKEY = data_file("badkey.pem")
  57NOKIACERT = data_file("nokia.pem")
  58
  59DHFILE = data_file("dh512.pem")
  60BYTES_DHFILE = os.fsencode(DHFILE)
  61
  62def handle_error(prefix):
  63    exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
  64    if support.verbose:
  65        sys.stdout.write(prefix + exc_format)
  66
  67def can_clear_options():
  68    # 0.9.8m or higher
  69    return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
  70
  71def no_sslv2_implies_sslv3_hello():
  72    # 0.9.7h or higher
  73    return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
  74
  75
  76# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
  77def skip_if_broken_ubuntu_ssl(func):
  78    if hasattr(ssl, 'PROTOCOL_SSLv2'):
  79        @functools.wraps(func)
  80        def f(*args, **kwargs):
  81            try:
  82                ssl.SSLContext(ssl.PROTOCOL_SSLv2)
  83            except ssl.SSLError:
  84                if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
  85                    platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
  86                    raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
  87            return func(*args, **kwargs)
  88        return f
  89    else:
  90        return func
  91
  92
  93class BasicSocketTests(unittest.TestCase):
  94
  95    def test_constants(self):
  96        #ssl.PROTOCOL_SSLv2
  97        ssl.PROTOCOL_SSLv23
  98        ssl.PROTOCOL_SSLv3
  99        ssl.PROTOCOL_TLSv1
 100        ssl.CERT_NONE
 101        ssl.CERT_OPTIONAL
 102        ssl.CERT_REQUIRED
 103        ssl.OP_CIPHER_SERVER_PREFERENCE
 104        ssl.OP_SINGLE_DH_USE
 105        if ssl.HAS_ECDH:
 106            ssl.OP_SINGLE_ECDH_USE
 107        if ssl.OPENSSL_VERSION_INFO >= (1, 0):
 108            ssl.OP_NO_COMPRESSION
 109        self.assertIn(ssl.HAS_SNI, {True, False})
 110        self.assertIn(ssl.HAS_ECDH, {True, False})
 111
 112    def test_random(self):
 113        v = ssl.RAND_status()
 114        if support.verbose:
 115            sys.stdout.write("\n RAND_status is %d (%s)\n"
 116                             % (v, (v and "sufficient randomness") or
 117                                "insufficient randomness"))
 118
 119        data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
 120        self.assertEqual(len(data), 16)
 121        self.assertEqual(is_cryptographic, v == 1)
 122        if v:
 123            data = ssl.RAND_bytes(16)
 124            self.assertEqual(len(data), 16)
 125        else:
 126            self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
 127
 128        self.assertRaises(TypeError, ssl.RAND_egd, 1)
 129        self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
 130        ssl.RAND_add("this is a random string", 75.0)
 131
 132    def test_parse_cert(self):
 133        # note that this uses an 'unofficial' function in _ssl.c,
 134        # provided solely for this test, to exercise the certificate
 135        # parsing code
 136        p = ssl._ssl._test_decode_cert(CERTFILE)
 137        if support.verbose:
 138            sys.stdout.write("\n" + pprint.pformat(p) + "\n")
 139        self.assertEqual(p['issuer'],
 140                         ((('countryName', 'XY'),),
 141                          (('localityName', 'Castle Anthrax'),),
 142                          (('organizationName', 'Python Software Foundation'),),
 143                          (('commonName', 'localhost'),))
 144                        )
 145        self.assertEqual(p['notAfter'], 'Oct  5 23:01:56 2020 GMT')
 146        self.assertEqual(p['notBefore'], 'Oct  8 23:01:56 2010 GMT')
 147        self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
 148        self.assertEqual(p['subject'],
 149                         ((('countryName', 'XY'),),
 150                          (('localityName', 'Castle Anthrax'),),
 151                          (('organizationName', 'Python Software Foundation'),),
 152                          (('commonName', 'localhost'),))
 153                        )
 154        self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
 155        # Issue #13034: the subjectAltName in some certificates
 156        # (notably projects.developer.nokia.com:443) wasn't parsed
 157        p = ssl._ssl._test_decode_cert(NOKIACERT)
 158        if support.verbose:
 159            sys.stdout.write("\n" + pprint.pformat(p) + "\n")
 160        self.assertEqual(p['subjectAltName'],
 161                         (('DNS', 'projects.developer.nokia.com'),
 162                          ('DNS', 'projects.forum.nokia.com'))
 163                        )
 164
 165    def test_DER_to_PEM(self):
 166        with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
 167            pem = f.read()
 168        d1 = ssl.PEM_cert_to_DER_cert(pem)
 169        p2 = ssl.DER_cert_to_PEM_cert(d1)
 170        d2 = ssl.PEM_cert_to_DER_cert(p2)
 171        self.assertEqual(d1, d2)
 172        if not p2.startswith(ssl.PEM_HEADER + '\n'):
 173            self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
 174        if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
 175            self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
 176
 177    def test_openssl_version(self):
 178        n = ssl.OPENSSL_VERSION_NUMBER
 179        t = ssl.OPENSSL_VERSION_INFO
 180        s = ssl.OPENSSL_VERSION
 181        self.assertIsInstance(n, int)
 182        self.assertIsInstance(t, tuple)
 183        self.assertIsInstance(s, str)
 184        # Some sanity checks follow
 185        # >= 0.9
 186        self.assertGreaterEqual(n, 0x900000)
 187        # < 2.0
 188        self.assertLess(n, 0x20000000)
 189        major, minor, fix, patch, status = t
 190        self.assertGreaterEqual(major, 0)
 191        self.assertLess(major, 2)
 192        self.assertGreaterEqual(minor, 0)
 193        self.assertLess(minor, 256)
 194        self.assertGreaterEqual(fix, 0)
 195        self.assertLess(fix, 256)
 196        self.assertGreaterEqual(patch, 0)
 197        self.assertLessEqual(patch, 26)
 198        self.assertGreaterEqual(status, 0)
 199        self.assertLessEqual(status, 15)
 200        # Version string as returned by OpenSSL, the format might change
 201        self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
 202                        (s, t))
 203
 204    @support.cpython_only
 205    def test_refcycle(self):
 206        # Issue #7943: an SSL object doesn't create reference cycles with
 207        # itself.
 208        s = socket.socket(socket.AF_INET)
 209        ss = ssl.wrap_socket(s)
 210        wr = weakref.ref(ss)
 211        del ss
 212        self.assertEqual(wr(), None)
 213
 214    def test_wrapped_unconnected(self):
 215        # Methods on an unconnected SSLSocket propagate the original
 216        # socket.error raise by the underlying socket object.
 217        s = socket.socket(socket.AF_INET)
 218        ss = ssl.wrap_socket(s)
 219        self.assertRaises(socket.error, ss.recv, 1)
 220        self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
 221        self.assertRaises(socket.error, ss.recvfrom, 1)
 222        self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
 223        self.assertRaises(socket.error, ss.send, b'x')
 224        self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
 225
 226    def test_timeout(self):
 227        # Issue #8524: when creating an SSL socket, the timeout of the
 228        # original socket should be retained.
 229        for timeout in (None, 0.0, 5.0):
 230            s = socket.socket(socket.AF_INET)
 231            s.settimeout(timeout)
 232            ss = ssl.wrap_socket(s)
 233            self.assertEqual(timeout, ss.gettimeout())
 234
 235    def test_errors(self):
 236        sock = socket.socket()
 237        self.assertRaisesRegex(ValueError,
 238                        "certfile must be specified",
 239                        ssl.wrap_socket, sock, keyfile=CERTFILE)
 240        self.assertRaisesRegex(ValueError,
 241                        "certfile must be specified for server-side operations",
 242                        ssl.wrap_socket, sock, server_side=True)
 243        self.assertRaisesRegex(ValueError,
 244                        "certfile must be specified for server-side operations",
 245                        ssl.wrap_socket, sock, server_side=True, certfile="")
 246        s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
 247        self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
 248                                s.connect, (HOST, 8080))
 249        with self.assertRaises(IOError) as cm:
 250            with socket.socket() as sock:
 251                ssl.wrap_socket(sock, certfile=WRONGCERT)
 252        self.assertEqual(cm.exception.errno, errno.ENOENT)
 253        with self.assertRaises(IOError) as cm:
 254            with socket.socket() as sock:
 255                ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
 256        self.assertEqual(cm.exception.errno, errno.ENOENT)
 257        with self.assertRaises(IOError) as cm:
 258            with socket.socket() as sock:
 259                ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
 260        self.assertEqual(cm.exception.errno, errno.ENOENT)
 261
 262    def test_match_hostname(self):
 263        def ok(cert, hostname):
 264            ssl.match_hostname(cert, hostname)
 265        def fail(cert, hostname):
 266            self.assertRaises(ssl.CertificateError,
 267                              ssl.match_hostname, cert, hostname)
 268
 269        cert = {'subject': ((('commonName', 'example.com'),),)}
 270        ok(cert, 'example.com')
 271        ok(cert, 'ExAmple.cOm')
 272        fail(cert, 'www.example.com')
 273        fail(cert, '.example.com')
 274        fail(cert, 'example.org')
 275        fail(cert, 'exampleXcom')
 276
 277        cert = {'subject': ((('commonName', '*.a.com'),),)}
 278        ok(cert, 'foo.a.com')
 279        fail(cert, 'bar.foo.a.com')
 280        fail(cert, 'a.com')
 281        fail(cert, 'Xa.com')
 282        fail(cert, '.a.com')
 283
 284        cert = {'subject': ((('commonName', 'a.*.com'),),)}
 285        ok(cert, 'a.foo.com')
 286        fail(cert, 'a..com')
 287        fail(cert, 'a.com')
 288
 289        cert = {'subject': ((('commonName', 'f*.com'),),)}
 290        ok(cert, 'foo.com')
 291        ok(cert, 'f.com')
 292        fail(cert, 'bar.com')
 293        fail(cert, 'foo.a.com')
 294        fail(cert, 'bar.foo.com')
 295
 296        # Slightly fake real-world example
 297        cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
 298                'subject': ((('commonName', 'linuxfrz.org'),),),
 299                'subjectAltName': (('DNS', 'linuxfr.org'),
 300                                   ('DNS', 'linuxfr.com'),
 301                                   ('othername', '<unsupported>'))}
 302        ok(cert, 'linuxfr.org')
 303        ok(cert, 'linuxfr.com')
 304        # Not a "DNS" entry
 305        fail(cert, '<unsupported>')
 306        # When there is a subjectAltName, commonName isn't used
 307        fail(cert, 'linuxfrz.org')
 308
 309        # A pristine real-world example
 310        cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
 311                'subject': ((('countryName', 'US'),),
 312                            (('stateOrProvinceName', 'California'),),
 313                            (('localityName', 'Mountain View'),),
 314                            (('organizationName', 'Google Inc'),),
 315                            (('commonName', 'mail.google.com'),))}
 316        ok(cert, 'mail.google.com')
 317        fail(cert, 'gmail.com')
 318        # Only commonName is considered
 319        fail(cert, 'California')
 320
 321        # Neither commonName nor subjectAltName
 322        cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
 323                'subject': ((('countryName', 'US'),),
 324                            (('stateOrProvinceName', 'California'),),
 325                            (('localityName', 'Mountain View'),),
 326                            (('organizationName', 'Google Inc'),))}
 327        fail(cert, 'mail.google.com')
 328
 329        # No DNS entry in subjectAltName but a commonName
 330        cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
 331                'subject': ((('countryName', 'US'),),
 332                            (('stateOrProvinceName', 'California'),),
 333                            (('localityName', 'Mountain View'),),
 334                            (('commonName', 'mail.google.com'),)),
 335                'subjectAltName': (('othername', 'blabla'), )}
 336        ok(cert, 'mail.google.com')
 337
 338        # No DNS entry subjectAltName and no commonName
 339        cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
 340                'subject': ((('countryName', 'US'),),
 341                            (('stateOrProvinceName', 'California'),),
 342                            (('localityName', 'Mountain View'),),
 343                            (('organizationName', 'Google Inc'),)),
 344                'subjectAltName': (('othername', 'blabla'),)}
 345        fail(cert, 'google.com')
 346
 347        # Empty cert / no cert
 348        self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
 349        self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
 350
 351    def test_server_side(self):
 352        # server_hostname doesn't work for server sockets
 353        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 354        with socket.socket() as sock:
 355            self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
 356                              server_hostname="some.hostname")
 357
 358    def test_unknown_channel_binding(self):
 359        # should raise ValueError for unknown type
 360        s = socket.socket(socket.AF_INET)
 361        ss = ssl.wrap_socket(s)
 362        with self.assertRaises(ValueError):
 363            ss.get_channel_binding("unknown-type")
 364
 365    @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
 366                         "'tls-unique' channel binding not available")
 367    def test_tls_unique_channel_binding(self):
 368        # unconnected should return None for known type
 369        s = socket.socket(socket.AF_INET)
 370        ss = ssl.wrap_socket(s)
 371        self.assertIsNone(ss.get_channel_binding("tls-unique"))
 372        # the same for server-side
 373        s = socket.socket(socket.AF_INET)
 374        ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
 375        self.assertIsNone(ss.get_channel_binding("tls-unique"))
 376
 377class ContextTests(unittest.TestCase):
 378
 379    @skip_if_broken_ubuntu_ssl
 380    def test_constructor(self):
 381        if hasattr(ssl, 'PROTOCOL_SSLv2'):
 382            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
 383        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 384        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
 385        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 386        self.assertRaises(TypeError, ssl.SSLContext)
 387        self.assertRaises(ValueError, ssl.SSLContext, -1)
 388        self.assertRaises(ValueError, ssl.SSLContext, 42)
 389
 390    @skip_if_broken_ubuntu_ssl
 391    def test_protocol(self):
 392        for proto in PROTOCOLS:
 393            ctx = ssl.SSLContext(proto)
 394            self.assertEqual(ctx.protocol, proto)
 395
 396    def test_ciphers(self):
 397        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 398        ctx.set_ciphers("ALL")
 399        ctx.set_ciphers("DEFAULT")
 400        with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
 401            ctx.set_ciphers("^$:,;?*'dorothyx")
 402
 403    @skip_if_broken_ubuntu_ssl
 404    def test_options(self):
 405        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 406        # OP_ALL is the default value
 407        self.assertEqual(ssl.OP_ALL, ctx.options)
 408        ctx.options |= ssl.OP_NO_SSLv2
 409        self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
 410                         ctx.options)
 411        ctx.options |= ssl.OP_NO_SSLv3
 412        self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
 413                         ctx.options)
 414        if can_clear_options():
 415            ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
 416            self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
 417                             ctx.options)
 418            ctx.options = 0
 419            self.assertEqual(0, ctx.options)
 420        else:
 421            with self.assertRaises(ValueError):
 422                ctx.options = 0
 423
 424    def test_verify(self):
 425        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 426        # Default value
 427        self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
 428        ctx.verify_mode = ssl.CERT_OPTIONAL
 429        self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
 430        ctx.verify_mode = ssl.CERT_REQUIRED
 431        self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
 432        ctx.verify_mode = ssl.CERT_NONE
 433        self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
 434        with self.assertRaises(TypeError):
 435            ctx.verify_mode = None
 436        with self.assertRaises(ValueError):
 437            ctx.verify_mode = 42
 438
 439    def test_load_cert_chain(self):
 440        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 441        # Combined key and cert in a single file
 442        ctx.load_cert_chain(CERTFILE)
 443        ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
 444        self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
 445        with self.assertRaises(IOError) as cm:
 446            ctx.load_cert_chain(WRONGCERT)
 447        self.assertEqual(cm.exception.errno, errno.ENOENT)
 448        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 449            ctx.load_cert_chain(BADCERT)
 450        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 451            ctx.load_cert_chain(EMPTYCERT)
 452        # Separate key and cert
 453        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 454        ctx.load_cert_chain(ONLYCERT, ONLYKEY)
 455        ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
 456        ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
 457        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 458            ctx.load_cert_chain(ONLYCERT)
 459        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 460            ctx.load_cert_chain(ONLYKEY)
 461        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 462            ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
 463        # Mismatching key and cert
 464        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 465        with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
 466            ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
 467        # Password protected key and cert
 468        ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
 469        ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
 470        ctx.load_cert_chain(CERTFILE_PROTECTED,
 471                            password=bytearray(KEY_PASSWORD.encode()))
 472        ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
 473        ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
 474        ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
 475                            bytearray(KEY_PASSWORD.encode()))
 476        with self.assertRaisesRegex(TypeError, "should be a string"):
 477            ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
 478        with self.assertRaises(ssl.SSLError):
 479            ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
 480        with self.assertRaisesRegex(ValueError, "cannot be longer"):
 481            # openssl has a fixed limit on the password buffer.
 482            # PEM_BUFSIZE is generally set to 1kb.
 483            # Return a string larger than this.
 484            ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
 485        # Password callback
 486        def getpass_unicode():
 487            return KEY_PASSWORD
 488        def getpass_bytes():
 489            return KEY_PASSWORD.encode()
 490        def getpass_bytearray():
 491            return bytearray(KEY_PASSWORD.encode())
 492        def getpass_badpass():
 493            return "badpass"
 494        def getpass_huge():
 495            return b'a' * (1024 * 1024)
 496        def getpass_bad_type():
 497            return 9
 498        def getpass_exception():
 499            raise Exception('getpass error')
 500        class GetPassCallable:
 501            def __call__(self):
 502                return KEY_PASSWORD
 503            def getpass(self):
 504                return KEY_PASSWORD
 505        ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
 506        ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
 507        ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
 508        ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
 509        ctx.load_cert_chain(CERTFILE_PROTECTED,
 510                            password=GetPassCallable().getpass)
 511        with self.assertRaises(ssl.SSLError):
 512            ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
 513        with self.assertRaisesRegex(ValueError, "cannot be longer"):
 514            ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
 515        with self.assertRaisesRegex(TypeError, "must return a string"):
 516            ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
 517        with self.assertRaisesRegex(Exception, "getpass error"):
 518            ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
 519        # Make sure the password function isn't called if it isn't needed
 520        ctx.load_cert_chain(CERTFILE, password=getpass_exception)
 521
 522    def test_load_verify_locations(self):
 523        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 524        ctx.load_verify_locations(CERTFILE)
 525        ctx.load_verify_locations(cafile=CERTFILE, capath=None)
 526        ctx.load_verify_locations(BYTES_CERTFILE)
 527        ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
 528        self.assertRaises(TypeError, ctx.load_verify_locations)
 529        self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
 530        with self.assertRaises(IOError) as cm:
 531            ctx.load_verify_locations(WRONGCERT)
 532        self.assertEqual(cm.exception.errno, errno.ENOENT)
 533        with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
 534            ctx.load_verify_locations(BADCERT)
 535        ctx.load_verify_locations(CERTFILE, CAPATH)
 536        ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
 537
 538        # Issue #10989: crash if the second argument type is invalid
 539        self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
 540
 541    def test_load_dh_params(self):
 542        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 543        ctx.load_dh_params(DHFILE)
 544        if os.name != 'nt':
 545            ctx.load_dh_params(BYTES_DHFILE)
 546        self.assertRaises(TypeError, ctx.load_dh_params)
 547        self.assertRaises(TypeError, ctx.load_dh_params, None)
 548        with self.assertRaises(FileNotFoundError) as cm:
 549            ctx.load_dh_params(WRONGCERT)
 550        self.assertEqual(cm.exception.errno, errno.ENOENT)
 551        with self.assertRaises(ssl.SSLError) as cm:
 552            ctx.load_dh_params(CERTFILE)
 553
 554    @skip_if_broken_ubuntu_ssl
 555    def test_session_stats(self):
 556        for proto in PROTOCOLS:
 557            ctx = ssl.SSLContext(proto)
 558            self.assertEqual(ctx.session_stats(), {
 559                'number': 0,
 560                'connect': 0,
 561                'connect_good': 0,
 562                'connect_renegotiate': 0,
 563                'accept': 0,
 564                'accept_good': 0,
 565                'accept_renegotiate': 0,
 566                'hits': 0,
 567                'misses': 0,
 568                'timeouts': 0,
 569                'cache_full': 0,
 570            })
 571
 572    def test_set_default_verify_paths(self):
 573        # There's not much we can do to test that it acts as expected,
 574        # so just check it doesn't crash or raise an exception.
 575        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 576        ctx.set_default_verify_paths()
 577
 578    @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
 579    def test_set_ecdh_curve(self):
 580        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 581        ctx.set_ecdh_curve("prime256v1")
 582        ctx.set_ecdh_curve(b"prime256v1")
 583        self.assertRaises(TypeError, ctx.set_ecdh_curve)
 584        self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
 585        self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
 586        self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
 587
 588
 589class SSLErrorTests(unittest.TestCase):
 590
 591    def test_str(self):
 592        # The str() of a SSLError doesn't include the errno
 593        e = ssl.SSLError(1, "foo")
 594        self.assertEqual(str(e), "foo")
 595        self.assertEqual(e.errno, 1)
 596        # Same for a subclass
 597        e = ssl.SSLZeroReturnError(1, "foo")
 598        self.assertEqual(str(e), "foo")
 599        self.assertEqual(e.errno, 1)
 600
 601    def test_lib_reason(self):
 602        # Test the library and reason attributes
 603        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 604        with self.assertRaises(ssl.SSLError) as cm:
 605            ctx.load_dh_params(CERTFILE)
 606        self.assertEqual(cm.exception.library, 'PEM')
 607        self.assertEqual(cm.exception.reason, 'NO_START_LINE')
 608        s = str(cm.exception)
 609        self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
 610
 611    def test_subclass(self):
 612        # Check that the appropriate SSLError subclass is raised
 613        # (this only tests one of them)
 614        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 615        with socket.socket() as s:
 616            s.bind(("127.0.0.1", 0))
 617            s.listen(5)
 618            with socket.socket() as c:
 619                c.connect(s.getsockname())
 620                c.setblocking(False)
 621                c = ctx.wrap_socket(c, False, do_handshake_on_connect=False)
 622                with self.assertRaises(ssl.SSLWantReadError) as cm:
 623                    c.do_handshake()
 624                s = str(cm.exception)
 625                self.assertTrue(s.startswith("The operation did not complete (read)"), s)
 626                # For compatibility
 627                self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
 628
 629
 630class NetworkedTests(unittest.TestCase):
 631
 632    def test_connect(self):
 633        with support.transient_internet("svn.python.org"):
 634            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 635                                cert_reqs=ssl.CERT_NONE)
 636            try:
 637                s.connect(("svn.python.org", 443))
 638                self.assertEqual({}, s.getpeercert())
 639            finally:
 640                s.close()
 641
 642            # this should fail because we have no verification certs
 643            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 644                                cert_reqs=ssl.CERT_REQUIRED)
 645            self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
 646                                   s.connect, ("svn.python.org", 443))
 647            s.close()
 648
 649            # this should succeed because we specify the root cert
 650            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 651                                cert_reqs=ssl.CERT_REQUIRED,
 652                                ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
 653            try:
 654                s.connect(("svn.python.org", 443))
 655                self.assertTrue(s.getpeercert())
 656            finally:
 657                s.close()
 658
 659    def test_connect_ex(self):
 660        # Issue #11326: check connect_ex() implementation
 661        with support.transient_internet("svn.python.org"):
 662            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 663                                cert_reqs=ssl.CERT_REQUIRED,
 664                                ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
 665            try:
 666                self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
 667                self.assertTrue(s.getpeercert())
 668            finally:
 669                s.close()
 670
 671    def test_non_blocking_connect_ex(self):
 672        # Issue #11326: non-blocking connect_ex() should allow handshake
 673        # to proceed after the socket gets ready.
 674        with support.transient_internet("svn.python.org"):
 675            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 676                                cert_reqs=ssl.CERT_REQUIRED,
 677                                ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
 678                                do_handshake_on_connect=False)
 679            try:
 680                s.setblocking(False)
 681                rc = s.connect_ex(('svn.python.org', 443))
 682                # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
 683                self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
 684                # Wait for connect to finish
 685                select.select([], [s], [], 5.0)
 686                # Non-blocking handshake
 687                while True:
 688                    try:
 689                        s.do_handshake()
 690                        break
 691                    except ssl.SSLWantReadError:
 692                        select.select([s], [], [], 5.0)
 693                    except ssl.SSLWantWriteError:
 694                        select.select([], [s], [], 5.0)
 695                # SSL established
 696                self.assertTrue(s.getpeercert())
 697            finally:
 698                s.close()
 699
 700    def test_timeout_connect_ex(self):
 701        # Issue #12065: on a timeout, connect_ex() should return the original
 702        # errno (mimicking the behaviour of non-SSL sockets).
 703        with support.transient_internet("svn.python.org"):
 704            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 705                                cert_reqs=ssl.CERT_REQUIRED,
 706                                ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
 707                                do_handshake_on_connect=False)
 708            try:
 709                s.settimeout(0.0000001)
 710                rc = s.connect_ex(('svn.python.org', 443))
 711                if rc == 0:
 712                    self.skipTest("svn.python.org responded too quickly")
 713                self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
 714            finally:
 715                s.close()
 716
 717    def test_connect_with_context(self):
 718        with support.transient_internet("svn.python.org"):
 719            # Same as test_connect, but with a separately created context
 720            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 721            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 722            s.connect(("svn.python.org", 443))
 723            try:
 724                self.assertEqual({}, s.getpeercert())
 725            finally:
 726                s.close()
 727            # Same with a server hostname
 728            s = ctx.wrap_socket(socket.socket(socket.AF_INET),
 729                                server_hostname="svn.python.org")
 730            if ssl.HAS_SNI:
 731                s.connect(("svn.python.org", 443))
 732                s.close()
 733            else:
 734                self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
 735            # This should fail because we have no verification certs
 736            ctx.verify_mode = ssl.CERT_REQUIRED
 737            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 738            self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
 739                                    s.connect, ("svn.python.org", 443))
 740            s.close()
 741            # This should succeed because we specify the root cert
 742            ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
 743            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 744            s.connect(("svn.python.org", 443))
 745            try:
 746                cert = s.getpeercert()
 747                self.assertTrue(cert)
 748            finally:
 749                s.close()
 750
 751    def test_connect_capath(self):
 752        # Verify server certificates using the `capath` argument
 753        # NOTE: the subject hashing algorithm has been changed between
 754        # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
 755        # contain both versions of each certificate (same content, different
 756        # filename) for this test to be portable across OpenSSL releases.
 757        with support.transient_internet("svn.python.org"):
 758            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 759            ctx.verify_mode = ssl.CERT_REQUIRED
 760            ctx.load_verify_locations(capath=CAPATH)
 761            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 762            s.connect(("svn.python.org", 443))
 763            try:
 764                cert = s.getpeercert()
 765                self.assertTrue(cert)
 766            finally:
 767                s.close()
 768            # Same with a bytes `capath` argument
 769            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 770            ctx.verify_mode = ssl.CERT_REQUIRED
 771            ctx.load_verify_locations(capath=BYTES_CAPATH)
 772            s = ctx.wrap_socket(socket.socket(socket.AF_INET))
 773            s.connect(("svn.python.org", 443))
 774            try:
 775                cert = s.getpeercert()
 776                self.assertTrue(cert)
 777            finally:
 778                s.close()
 779
 780    @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
 781    def test_makefile_close(self):
 782        # Issue #5238: creating a file-like object with makefile() shouldn't
 783        # delay closing the underlying "real socket" (here tested with its
 784        # file descriptor, hence skipping the test under Windows).
 785        with support.transient_internet("svn.python.org"):
 786            ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
 787            ss.connect(("svn.python.org", 443))
 788            fd = ss.fileno()
 789            f = ss.makefile()
 790            f.close()
 791            # The fd is still open
 792            os.read(fd, 0)
 793            # Closing the SSL socket should close the fd too
 794            ss.close()
 795            gc.collect()
 796            with self.assertRaises(OSError) as e:
 797                os.read(fd, 0)
 798            self.assertEqual(e.exception.errno, errno.EBADF)
 799
 800    def test_non_blocking_handshake(self):
 801        with support.transient_internet("svn.python.org"):
 802            s = socket.socket(socket.AF_INET)
 803            s.connect(("svn.python.org", 443))
 804            s.setblocking(False)
 805            s = ssl.wrap_socket(s,
 806                                cert_reqs=ssl.CERT_NONE,
 807                                do_handshake_on_connect=False)
 808            count = 0
 809            while True:
 810                try:
 811                    count += 1
 812                    s.do_handshake()
 813                    break
 814                except ssl.SSLWantReadError:
 815                    select.select([s], [], [])
 816                except ssl.SSLWantWriteError:
 817                    select.select([], [s], [])
 818            s.close()
 819            if support.verbose:
 820                sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
 821
 822    def test_get_server_certificate(self):
 823        def _test_get_server_certificate(host, port, cert=None):
 824            with support.transient_internet(host):
 825                pem = ssl.get_server_certificate((host, port))
 826                if not pem:
 827                    self.fail("No server certificate on %s:%s!" % (host, port))
 828
 829                try:
 830                    pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
 831                except ssl.SSLError as x:
 832                    #should fail
 833                    if support.verbose:
 834                        sys.stdout.write("%s\n" % x)
 835                else:
 836                    self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
 837
 838                pem = ssl.get_server_certificate((host, port), ca_certs=cert)
 839                if not pem:
 840                    self.fail("No server certificate on %s:%s!" % (host, port))
 841                if support.verbose:
 842                    sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
 843
 844        _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
 845        if support.IPV6_ENABLED:
 846            _test_get_server_certificate('ipv6.google.com', 443)
 847
 848    def test_ciphers(self):
 849        remote = ("svn.python.org", 443)
 850        with support.transient_internet(remote[0]):
 851            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 852                                cert_reqs=ssl.CERT_NONE, ciphers="ALL")
 853            s.connect(remote)
 854            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 855                                cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
 856            s.connect(remote)
 857            # Error checking can happen at instantiation or when connecting
 858            with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
 859                with socket.socket(socket.AF_INET) as sock:
 860                    s = ssl.wrap_socket(sock,
 861                                        cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
 862                    s.connect(remote)
 863
 864    def test_algorithms(self):
 865        # Issue #8484: all algorithms should be available when verifying a
 866        # certificate.
 867        # SHA256 was added in OpenSSL 0.9.8
 868        if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
 869            self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
 870        # sha256.tbs-internet.com needs SNI to use the correct certificate
 871        if not ssl.HAS_SNI:
 872            self.skipTest("SNI needed for this test")
 873        # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
 874        remote = ("sha256.tbs-internet.com", 443)
 875        sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
 876        with support.transient_internet("sha256.tbs-internet.com"):
 877            ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 878            ctx.verify_mode = ssl.CERT_REQUIRED
 879            ctx.load_verify_locations(sha256_cert)
 880            s = ctx.wrap_socket(socket.socket(socket.AF_INET),
 881                                server_hostname="sha256.tbs-internet.com")
 882            try:
 883                s.connect(remote)
 884                if support.verbose:
 885                    sys.stdout.write("\nCipher with %r is %r\n" %
 886                                     (remote, s.cipher()))
 887                    sys.stdout.write("Certificate is:\n%s\n" %
 888                                     pprint.pformat(s.getpeercert()))
 889            finally:
 890                s.close()
 891
 892
 893try:
 894    import threading
 895except ImportError:
 896    _have_threads = False
 897else:
 898    _have_threads = True
 899
 900    from test.ssl_servers import make_https_server
 901
 902    class ThreadedEchoServer(threading.Thread):
 903
 904        class ConnectionHandler(threading.Thread):
 905
 906            """A mildly complicated class, because we want it to work both
 907            with and without the SSL wrapper around the socket connection, so
 908            that we can test the STARTTLS functionality."""
 909
 910            def __init__(self, server, connsock, addr):
 911                self.server = server
 912                self.running = False
 913                self.sock = connsock
 914                self.addr = addr
 915                self.sock.setblocking(1)
 916                self.sslconn = None
 917                threading.Thread.__init__(self)
 918                self.daemon = True
 919
 920            def wrap_conn(self):
 921                try:
 922                    self.sslconn = self.server.context.wrap_socket(
 923                        self.sock, server_side=True)
 924                    self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
 925                except ssl.SSLError as e:
 926                    # XXX Various errors can have happened here, for example
 927                    # a mismatching protocol version, an invalid certificate,
 928                    # or a low-level bug. This should be made more discriminating.
 929                    self.server.conn_errors.append(e)
 930                    if self.server.chatty:
 931                        handle_error("\n server:  bad connection attempt from " + repr(self.addr) + ":\n")
 932                    self.running = False
 933                    self.server.stop()
 934                    self.close()
 935                    return False
 936                else:
 937                    if self.server.context.verify_mode == ssl.CERT_REQUIRED:
 938                        cert = self.sslconn.getpeercert()
 939                        if support.verbose and self.server.chatty:
 940                            sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
 941                        cert_binary = self.sslconn.getpeercert(True)
 942                        if support.verbose and self.server.chatty:
 943                            sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
 944                    cipher = self.sslconn.cipher()
 945                    if support.verbose and self.server.chatty:
 946                        sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
 947                        sys.stdout.write(" server: selected protocol is now "
 948                                + str(self.sslconn.selected_npn_protocol()) + "\n")
 949                    return True
 950
 951            def read(self):
 952                if self.sslconn:
 953                    return self.sslconn.read()
 954                else:
 955                    return self.sock.recv(1024)
 956
 957            def write(self, bytes):
 958                if self.sslconn:
 959                    return self.sslconn.write(bytes)
 960                else:
 961                    return self.sock.send(bytes)
 962
 963            def close(self):
 964                if self.sslconn:
 965                    self.sslconn.close()
 966                else:
 967                    self.sock.close()
 968
 969            def run(self):
 970                self.running = True
 971                if not self.server.starttls_server:
 972                    if not self.wrap_conn():
 973                        return
 974                while self.running:
 975                    try:
 976                        msg = self.read()
 977                        stripped = msg.strip()
 978                        if not stripped:
 979                            # eof, so quit this handler
 980                            self.running = False
 981                            self.close()
 982                        elif stripped == b'over':
 983                            if support.verbose and self.server.connectionchatty:
 984                                sys.stdout.write(" server: client closed connection\n")
 985                            self.close()
 986                            return
 987                        elif (self.server.starttls_server and
 988                              stripped == b'STARTTLS'):
 989                            if support.verbose and self.server.connectionchatty:
 990                                sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
 991                            self.write(b"OK\n")
 992                            if not self.wrap_conn():
 993                                return
 994                        elif (self.server.starttls_server and self.sslconn
 995                              and stripped == b'ENDTLS'):
 996                            if support.verbose and self.server.connectionchatty:
 997                                sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
 998                            self.write(b"OK\n")
 999                            self.sock = self.sslconn.unwrap()
1000                            self.sslconn = None
1001                            if support.verbose and self.server.connectionchatty:
1002                                sys.stdout.write(" server: connection is now unencrypted...\n")
1003                        elif stripped == b'CB tls-unique':
1004                            if support.verbose and self.server.connectionchatty:
1005                                sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1006                            data = self.sslconn.get_channel_binding("tls-unique")
1007                            self.write(repr(data).encode("us-ascii") + b"\n")
1008                        else:
1009                            if (support.verbose and
1010                                self.server.connectionchatty):
1011                                ctype = (self.sslconn and "encrypted") or "unencrypted"
1012                                sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1013                                                 % (msg, ctype, msg.lower(), ctype))
1014                            self.write(msg.lower())
1015                    except socket.error:
1016                        if self.server.chatty:
1017                            handle_error("Test server failure:\n")
1018                        self.close()
1019                        self.running = False
1020                        # normally, we'd just stop here, but for the test
1021                        # harness, we want to stop the server
1022                        self.server.stop()
1023
1024        def __init__(self, certificate=None, ssl_version=None,
1025                     certreqs=None, cacerts=None,
1026                     chatty=True, connectionchatty=False, starttls_server=False,
1027                     npn_protocols=None, ciphers=None, context=None):
1028            if context:
1029                self.context = context
1030            else:
1031                self.context = ssl.SSLContext(ssl_version
1032                                              if ssl_version is not None
1033                                              else ssl.PROTOCOL_TLSv1)
1034                self.context.verify_mode = (certreqs if certreqs is not None
1035                                            else ssl.CERT_NONE)
1036                if cacerts:
1037                    self.context.load_verify_locations(cacerts)
1038                if certificate:
1039                    self.context.load_cert_chain(certificate)
1040                if npn_protocols:
1041                    self.context.set_npn_protocols(npn_protocols)
1042                if ciphers:
1043                    self.context.set_ciphers(ciphers)
1044            self.chatty = chatty
1045            self.connectionchatty = connectionchatty
1046            self.starttls_server = starttls_server
1047            self.sock = socket.socket()
1048            self.port = support.bind_port(self.sock)
1049            self.flag = None
1050            self.active = False
1051            self.selected_protocols = []
1052            self.conn_errors = []
1053            threading.Thread.__init__(self)
1054            self.daemon = True
1055
1056        def __enter__(self):
1057            self.start(threading.Event())
1058            self.flag.wait()
1059            return self
1060
1061        def __exit__(self, *args):
1062            self.stop()
1063            self.join()
1064
1065        def start(self, flag=None):
1066            self.flag = flag
1067            threading.Thread.start(self)
1068
1069        def run(self):
1070            self.sock.settimeout(0.05)
1071            self.sock.listen(5)
1072            self.active = True
1073            if self.flag:
1074                # signal an event
1075                self.flag.set()
1076            while self.active:
1077                try:
1078                    newconn, connaddr = self.sock.accept()
1079                    if support.verbose and self.chatty:
1080                        sys.stdout.write(' server:  new connection from '
1081                                         + repr(connaddr) + '\n')
1082                    handler = self.ConnectionHandler(self, newconn, connaddr)
1083                    handler.start()
1084                    handler.join()
1085                except socket.timeout:
1086                    pass
1087                except KeyboardInterrupt:
1088                    self.stop()
1089            self.sock.close()
1090
1091        def stop(self):
1092            self.active = False
1093
1094    class AsyncoreEchoServer(threading.Thread):
1095
1096        # this one's based on asyncore.dispatcher
1097
1098        class EchoServer (asyncore.dispatcher):
1099
1100            class ConnectionHandler (asyncore.dispatcher_with_send):
1101
1102                def __init__(self, conn, certfile):
1103                    self.socket = ssl.wrap_socket(conn, server_side=True,
1104                                                  certfile=certfile,
1105                                                  do_handshake_on_connect=False)
1106                    asyncore.dispatcher_with_send.__init__(self, self.socket)
1107                    self._ssl_accepting = True
1108                    self._do_ssl_handshake()
1109
1110                def readable(self):
1111                    if isinstance(self.socket, ssl.SSLSocket):
1112                        while self.socket.pending() > 0:
1113                            self.handle_read_event()
1114                    return True
1115
1116                def _do_ssl_handshake(self):
1117                    try:
1118                        self.socket.do_handshake()
1119                    except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1120                        return
1121                    except ssl.SSLEOFError:
1122                        return self.handle_close()
1123                    except ssl.SSLError:
1124                        raise
1125                    except socket.error as err:
1126                        if err.args[0] == errno.ECONNABORTED:
1127                            return self.handle_close()
1128                    else:
1129                        self._ssl_accepting = False
1130
1131                def handle_read(self):
1132                    if self._ssl_accepting:
1133                        self._do_ssl_handshake()
1134                    else:
1135                        data = self.recv(1024)
1136                        if support.verbose:
1137                            sys.stdout.write(" server:  read %s from client\n" % repr(data))
1138                        if not data:
1139                            self.close()
1140                        else:
1141                            self.send(data.lower())
1142
1143                def handle_close(self):
1144                    self.close()
1145                    if support.verbose:
1146                        sys.stdout.write(" server:  closed connection %s\n" % self.socket)
1147
1148                def handle_error(self):
1149                    raise
1150
1151            def __init__(self, certfile):
1152                self.certfile = certfile
1153                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1154                self.port = support.bind_port(sock, '')
1155                asyncore.dispatcher.__init__(self, sock)
1156                self.listen(5)
1157
1158            def handle_accepted(self, sock_obj, addr):
1159                if support.verbose:
1160                    sys.stdout.write(" server:  new connection from %s:%s\n" %addr)
1161                self.ConnectionHandler(sock_obj, self.certfile)
1162
1163            def handle_error(self):
1164                raise
1165
1166        def __init__(self, certfile):
1167            self.flag = None
1168            self.active = False
1169            self.server = self.EchoServer(certfile)
1170            self.port = self.server.port
1171            threading.Thread.__init__(self)
1172            self.daemon = True
1173
1174        def __str__(self):
1175            return "<%s %s>" % (self.__class__.__name__, self.server)
1176
1177        def __enter__(self):
1178            self.start(threading.Event())
1179            self.flag.wait()
1180            return self
1181
1182        def __exit__(self, *args):
1183            if support.verbose:
1184                sys.stdout.write(" cleanup: stopping server.\n")
1185            self.stop()
1186            if support.verbose:
1187                sys.stdout.write(" cleanup: joining server thread.\n")
1188            self.join()
1189            if support.verbose:
1190                sys.stdout.write(" cleanup: successfully joined.\n")
1191
1192        def start (self, flag=None):
1193            self.flag = flag
1194            threading.Thread.start(self)
1195
1196        def run(self):
1197            self.active = True
1198            if self.flag:
1199                self.flag.set()
1200            while self.active:
1201                try:
1202                    asyncore.loop(1)
1203                except:
1204                    pass
1205
1206        def stop(self):
1207            self.active = False
1208            self.server.close()
1209
1210    def bad_cert_test(certfile):
1211        """
1212        Launch a server with CERT_REQUIRED, and check that trying to
1213        connect to it with the given client certificate fails.
1214        """
1215        server = ThreadedEchoServer(CERTFILE,
1216                                    certreqs=ssl.CERT_REQUIRED,
1217                                    cacerts=CERTFILE, chatty=False,
1218                                    connectionchatty=False)
1219        with server:
1220            try:
1221                with socket.socket() as sock:
1222                    s = ssl.wrap_socket(sock,
1223                                        certfile=certfile,
1224                                        ssl_version=ssl.PROTOCOL_TLSv1)
1225                    s.connect((HOST, server.port))
1226            except ssl.SSLError as x:
1227                if support.verbose:
1228                    sys.stdout.write("\nSSLError is %s\n" % x.args[1])
1229            except socket.error as x:
1230                if support.verbose:
1231                    sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
1232            except IOError as x:
1233                if x.errno != errno.ENOENT:
1234                    raise
1235                if support.verbose:
1236                    sys.stdout.write("\IOError is %s\n" % str(x))
1237            else:
1238                raise AssertionError("Use of invalid cert should have failed!")
1239
1240    def server_params_test(client_context, server_context, indata=b"FOO\n",
1241                           chatty=True, connectionchatty=False):
1242        """
1243        Launch a server, connect a client to it and try various reads
1244        and writes.
1245        """
1246        stats = {}
1247        server = ThreadedEchoServer(context=server_context,
1248                                    chatty=chatty,
1249                                    connectionchatty=False)
1250        with server:
1251            with client_context.wrap_socket(socket.socket()) as s:
1252                s.connect((HOST, server.port))
1253                for arg in [indata, bytearray(indata), memoryview(indata)]:
1254                    if connectionchatty:
1255                        if support.verbose:
1256                            sys.stdout.write(
1257                                " client:  sending %r...\n" % indata)
1258                    s.write(arg)
1259                    outdata = s.read()
1260                    if connectionchatty:
1261                        if support.verbose:
1262                            sys.stdout.write(" client:  read %r\n" % outdata)
1263                    if outdata != indata.lower():
1264                        raise AssertionError(
1265                            "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1266                            % (outdata[:20], len(outdata),
1267                               indata[:20].lower(), len(indata)))
1268                s.write(b"over\n")
1269                if connectionchatty:
1270                    if support.verbose:
1271                        sys.stdout.write(" client:  closing connection.\n")
1272                stats.update({
1273                    'compression': s.compression(),
1274                    'cipher': s.cipher(),
1275                    'client_npn_protocol': s.selected_npn_protocol()
1276                })
1277                s.close()
1278            stats['server_npn_protocols'] = server.selected_protocols
1279        return stats
1280
1281    def try_protocol_combo(server_protocol, client_protocol, expect_success,
1282                           certsreqs=None, server_options=0, client_options=0):
1283        if certsreqs is None:
1284            certsreqs = ssl.CERT_NONE
1285        certtype = {
1286            ssl.CERT_NONE: "CERT_NONE",
1287            ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1288            ssl.CERT_REQUIRED: "CERT_REQUIRED",
1289        }[certsreqs]
1290        if support.verbose:
1291            formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
1292            sys.stdout.write(formatstr %
1293                             (ssl.get_protocol_name(client_protocol),
1294                              ssl.get_protocol_name(server_protocol),
1295                              certtype))
1296        client_context = ssl.SSLContext(client_protocol)
1297        client_context.options = ssl.OP_ALL | client_options
1298        server_context = ssl.SSLContext(server_protocol)
1299        server_context.options = ssl.OP_ALL | server_options
1300        for ctx in (client_context, server_context):
1301            ctx.verify_mode = certsreqs
1302            # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1303            # will send an SSLv3 hello (rather than SSLv2) starting from
1304            # OpenSSL 1.0.0 (see issue #8322).
1305            ctx.set_ciphers("ALL")
1306            ctx.load_cert_chain(CERTFILE)
1307            ctx.load_verify_locations(CERTFILE)
1308        try:
1309            server_params_test(client_context, server_context,
1310                               chatty=False, connectionchatty=False)
1311        # Protocol mismatch can result in either an SSLError, or a
1312        # "Connection reset by peer" error.
1313        except ssl.SSLError:
1314            if expect_success:
1315                raise
1316        except socket.error as e:
1317            if expect_success or e.errno != errno.ECONNRESET:
1318                raise
1319        else:
1320            if not expect_success:
1321                raise AssertionError(
1322                    "Client protocol %s succeeded with server protocol %s!"
1323                    % (ssl.get_protocol_name(client_protocol),
1324                       ssl.get_protocol_name(server_protocol)))
1325
1326
1327    class ThreadedTests(unittest.TestCase):
1328
1329        @skip_if_broken_ubuntu_ssl
1330        def test_echo(self):
1331            """Basic test of an SSL client connecting to a server"""
1332            if support.verbose:
1333                sys.stdout.write("\n")
1334            for protocol in PROTOCOLS:
1335                context = ssl.SSLContext(protocol)
1336                context.load_cert_chain(CERTFILE)
1337                server_params_test(context, context,
1338                                   chatty=True, connectionchatty=True)
1339
1340        def test_getpeercert(self):
1341            if support.verbose:
1342                sys.stdout.write("\n")
1343            context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1344            context.verify_mode = ssl.CERT_REQUIRED
1345            context.load_verify_locations(CERTFILE)
1346            context.load_cert_chain(CERTFILE)
1347            server = ThreadedEchoServer(context=context, chatty=False)
1348            with server:
1349                s = context.wrap_socket(socket.socket())
1350                s.connect((HOST, server.port))
1351                cert = s.getpeercert()
1352                self.assertTrue(cert, "Can't get peer certificate.")
1353                cipher = s.cipher()
1354                if support.verbose:
1355                    sys.stdout.write(pprint.pformat(cert) + '\n')
1356                    sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1357                if 'subject' not in cert:
1358                    self.fail("No subject field in certificate: %s." %
1359                              pprint.pformat(cert))
1360                if ((('organizationName', 'Python Software Foundation'),)
1361                    not in cert['subject']):
1362                    self.fail(
1363                        "Missing or invalid 'organizationName' field in certificate subject; "
1364                        "should be 'Python Software Foundation'.")
1365                self.assertIn('notBefore', cert)
1366                self.assertIn('notAfter', cert)
1367                before = ssl.cert_time_to_seconds(cert['notBefore'])
1368                after = ssl.cert_time_to_seconds(cert['notAfter'])
1369                self.assertLess(before, after)
1370                s.close()
1371
1372        def test_empty_cert(self):
1373            """Connecting with an empty cert file"""
1374            bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1375                                      "nullcert.pem"))
1376        def test_malformed_cert(self):
1377            """Connecting with a badly formatted certificate (syntax error)"""
1378            bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1379                                       "badcert.pem"))
1380        def test_nonexisting_cert(self):
1381            """Connecting with a non-existing cert file"""
1382            bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1383                                       "wrongcert.pem"))
1384        def test_malformed_key(self):
1385            """Connecting with a badly formatted key (syntax error)"""
1386            bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1387                                       "badkey.pem"))
1388
1389        def test_rude_shutdown(self):
1390            """A brutal shutdown of an SSL server should raise an IOError
1391            in the client when attempting handshake.
1392            """
1393            listener_ready = threading.Event()
1394            listener_gone = threading.Event()
1395
1396            s = socket.socket()
1397            port = support.bind_port(s, HOST)
1398
1399            # `listener` runs in a thread.  It sits in an accept() until
1400            # the main thread connects.  Then it rudely closes the socket,
1401            # and sets Event `listener_gone` to let the main thread know
1402            # the socket is gone.
1403            def listener():
1404                s.listen(5)
1405                listener_ready.set()
1406                newsock, addr = s.accept()
1407                newsock.close()
1408                s.close()
1409                listener_gone.set()
1410
1411            def connector():
1412                listener_ready.wait()
1413                with socket.socket() as c:
1414                    c.connect((HOST, port))
1415                    listener_gone.wait()
1416                    try:
1417                        ssl_sock = ssl.wrap_socket(c)
1418                    except IOError:
1419                        pass
1420                    else:
1421                        self.fail('connecting to closed SSL socket should have failed')
1422
1423            t = threading.Thread(target=listener)
1424            t.start()
1425            try:
1426                connector()
1427            finally:
1428                t.join()
1429
1430        @skip_if_broken_ubuntu_ssl
1431        @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1432                             "OpenSSL is compiled without SSLv2 support")
1433        def test_protocol_sslv2(self):
1434            """Connecting to an SSLv2 server with various client options"""
1435            if support.verbose:
1436                sys.stdout.write("\n")
1437            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1438            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1439            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1440            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1441            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1442            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
1443            # SSLv23 client with specific SSL options
1444            if no_sslv2_implies_sslv3_hello():
1445                # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1446                try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1447                                   client_options=ssl.OP_NO_SSLv2)
1448            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1449                               client_options=ssl.OP_NO_SSLv3)
1450            try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1451                               client_options=ssl.OP_NO_TLSv1)
1452
1453        @skip_if_broken_ubuntu_ssl
1454        def test_protocol_sslv23(self):
1455            """Connecting to an SSLv23 server with various client options"""
1456            if support.verbose:
1457                sys.stdout.write("\n")
1458            if hasattr(ssl, 'PROTOCOL_SSLv2'):
1459                try:
1460                    try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1461                except (ssl.SSLError, socket.error) as x:
1462                    # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1463                    if support.verbose:
1464                        sys.stdout.write(
1465                            " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1466                            % str(x))
1467            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1468            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1469            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
1470
1471            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1472            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1473            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1474
1475            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1476            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1477            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1478
1479            # Server with specific SSL options
1480            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1481                               server_options=ssl.OP_NO_SSLv3)
1482            # Will choose TLSv1
1483            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1484                               server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1485            try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1486                               server_options=ssl.OP_NO_TLSv1)
1487
1488
1489        @skip_if_broken_ubuntu_ssl
1490        def test_protocol_sslv3(self):
1491            """Connecting to an SSLv3 server with various client options"""
1492            if support.verbose:
1493                sys.stdout.write("\n")
1494            try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1495            try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1496            try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1497            if hasattr(ssl, 'PROTOCOL_SSLv2'):
1498                try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1499            try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1500                               client_options=ssl.OP_NO_SSLv3)
1501            try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
1502            if no_sslv2_implies_sslv3_hello():
1503                # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1504                try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1505                                   client_options=ssl.OP_NO_SSLv2)
1506
1507        @skip_if_broken_ubuntu_ssl
1508        def test_protocol_tlsv1(self):
1509            """Connecting to a TLSv1 server with various client options"""
1510            if support.verbose:
1511                sys.stdout.write("\n")
1512            try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1513            try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1514            try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1515            if hasattr(ssl, 'PROTOCOL_SSLv2'):
1516                try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1517            try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1518            try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1519                               client_options=ssl.OP_NO_TLSv1)
1520
1521        def test_starttls(self):
1522            """Switching from clear text to encrypted and back again."""
1523            msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
1524
1525            server = ThreadedEchoServer(CERTFILE,
1526                                        ssl_version=ssl.PROTOCOL_TLSv1,
1527                                        starttls_server=True,
1528                                        chatty=True,
1529                                        connectionchatty=True)
1530            wrapped = False
1531            with server:
1532                s = socket.socket()
1533                s.setblocking(1)
1534                s.connect((HOST, server.port))
1535                if support.verbose:
1536                    sys.stdout.write("\n")
1537                for indata in msgs:
1538                    if support.verbose:
1539                        sys.stdout.write(
1540                            " client:  sending %r...\n" % indata)
1541                    if wrapped:
1542                        conn.write(indata)
1543                        outdata = conn.read()
1544                    else:
1545                        s.send(indata)
1546                        outdata = s.recv(1024)
1547                    msg = outdata.strip().lower()
1548                    if indata == b"STARTTLS" and msg.startswith(b"ok"):
1549                        # STARTTLS ok, switch to secure mode
1550                        if support.verbose:
1551                            sys.stdout.write(
1552                                " client:  read %r from server, starting TLS...\n"
1553                                % msg)
1554                        conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1555                        wrapped = True
1556                    elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1557                        # ENDTLS ok, switch back to clear text
1558                        if support.verbose:
1559                            sys.stdout.write(
1560                                " client:  read %r from server, ending TLS...\n"
1561                                % msg)
1562                        s = conn.unwrap()
1563                        wrapped = False
1564                    else:
1565                        if support.verbose:
1566                            sys.stdout.write(
1567                                " client:  read %r from server\n" % msg)
1568                if support.verbose:
1569                    sys.stdout.write(" client:  closing connection.\n")
1570                if wrapped:
1571                    conn.write(b"over\n")
1572                else:
1573                    s.send(b"over\n")
1574                if wrapped:
1575                    conn.close()
1576                else:
1577                    s.close()
1578
1579        def test_socketserver(self):
1580            """Using a SocketServer to create and manage SSL connections."""
1581            server = make_https_server(self, CERTFILE)
1582            # try to connect
1583            if support.verbose:
1584                sys.stdout.write('\n')
1585            with open(CERTFILE, 'rb') as f:
1586                d1 = f.read()
1587            d2 = ''
1588            # now fetch the same data from the HTTPS server
1589            url = 'https://%s:%d/%s' % (
1590                HOST, server.port, os.path.split(CERTFILE)[1])
1591            f = urllib.request.urlopen(url)
1592            try:
1593                dlen = f.info().get("content-length")
1594                if dlen and (int(dlen) > 0):
1595                    d2 = f.read(int(dlen))
1596                    if support.verbose:
1597                        sys.stdout.write(
1598                            " client: read %d bytes from remote server '%s'\n"
1599                            % (len(d2), server))
1600            finally:
1601                f.close()
1602            self.assertEqual(d1, d2)
1603
1604        def test_asyncore_server(self):
1605            """Check the example asyncore integration."""
1606            indata = "TEST MESSAGE of mixed case\n"
1607
1608            if support.verbose:
1609                sys.stdout.write("\n")
1610
1611            indata = b"FOO\n"
1612            server = AsyncoreEchoServer(CERTFILE)
1613            with server:
1614                s = ssl.wrap_socket(socket.socket())
1615                s.connect(('127.0.0.1', server.port))
1616                if support.verbose:
1617                    sys.stdout.write(
1618                        " client:  sending %r...\n" % indata)
1619                s.write(indata)
1620                outdata = s.read()
1621                if support.verbose:
1622                    sys.stdout.write(" client:  read %r\n" % outdata)
1623                if outdata != indata.lower():
1624                    self.fail(
1625                        "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1626                        % (outdata[:20], len(outdata),
1627                           indata[:20].lower(), len(indata)))
1628                s.write(b"over\n")
1629                if support.verbose:
1630                    sys.stdout.write(" client:  closing connection.\n")
1631                s.close()
1632                if support.verbose:
1633                    sys.stdout.write(" client:  connection closed.\n")
1634
1635        def test_recv_send(self):
1636            """Test recv(), send() and friends."""
1637            if support.verbose:
1638                sys.stdout.write("\n")
1639
1640            server = ThreadedEchoServer(CERTFILE,
1641                                        certreqs=ssl.CERT_NONE,
1642                                        ssl_version=ssl.PROTOCOL_TLSv1,
1643                                        cacerts=CERTFILE,
1644                                        chatty=True,
1645                                        connectionchatty=False)
1646            with server:
1647                s = ssl.wrap_socket(socket.socket(),
1648                                    server_side=False,
1649                                    certfile=CERTFILE,
1650                                    ca_certs=CERTFILE,
1651                                    cert_reqs=ssl.CERT_NONE,
1652                                    ssl_version=ssl.PROTOCOL_TLSv1)
1653                s.connect((HOST, server.port))
1654                # helper methods for standardising recv* method signatures
1655                def _recv_into():
1656                    b = bytearray(b"\0"*100)
1657                    count = s.recv_into(b)
1658                    return b[:count]
1659
1660                def _recvfrom_into():
1661                    b = bytearray(b"\0"*100)
1662                    count, addr = s.recvfrom_into(b)
1663                    return b[:count]
1664
1665                # (name, method, whether to expect success, *args)
1666                send_methods = [
1667                    ('send', s.send, True, []),
1668                    ('sendto', s.sendto, False, ["some.address"]),
1669                    ('sendall', s.sendall, True, []),
1670                ]
1671                recv_methods = [
1672                    ('recv', s.recv, True, []),
1673                    ('recvfrom', s.recvfrom, False, ["some.address"]),
1674                    ('recv_into', _recv_into, True, []),
1675                    ('recvfrom_into', _recvfrom_into, False, []),
1676                ]
1677                data_prefix = "PREFIX_"
1678
1679                for meth_name, send_meth, expect_success, args in send_methods:
1680                    indata = (data_prefix + meth_name).encode('ascii')
1681                    try:
1682                        send_meth(indata, *args)
1683                        outdata = s.read()
1684                        if outdata != indata.lower():
1685                            self.fail(
1686                                "While sending with <<{name:s}>> bad data "
1687                                "<<{outdata:r}>> ({nout:d}) received; "
1688                                "expected <<{indata:r}>> ({nin:d})\n".format(
1689                                    name=meth_name, outdata=outdata[:20],
1690                                    nout=len(outdata),
1691                                    indata=indata[:20], nin=len(indata)
1692                                )
1693                            )
1694                    except ValueError as e:
1695                        if expect_success:
1696                            self.fail(
1697                                "Failed to send with method <<{name:s}>>; "
1698                                "expected to succeed.\n".format(name=meth_name)
1699                            )
1700                        if not str(e).startswith(meth_name):
1701                            self.fail(
1702                                "Method <<{name:s}>> failed with unexpected "
1703                                "exception message: {exp:s}\n".format(
1704                                    name=meth_name, exp=e
1705                                )
1706                            )
1707
1708                for meth_name, recv_meth, expect_success, args in recv_methods:
1709                    indata = (data_prefix + meth_name).encode('ascii')
1710                    try:
1711                        s.send(indata)
1712                        outdata = recv_meth(*args)
1713                        if outdata != indata.lower():
1714                            self.fail(
1715                                "While receiving with <<{name:s}>> bad data "
1716                                "<<{outdata:r}>> ({nout:d}) received; "
1717                                "expected <<{indata:r}>> ({nin:d})\n".format(
1718                                    name=meth_name, outdata=outdata[:20],
1719                                    nout=len(outdata),
1720                                    indata=indata[:20], nin=len(indata)
1721                                )
1722                            )
1723                    except ValueError as e:
1724                        if expect_success:
1725                            self.fail(
1726                                "Failed to receive with method <<{name:s}>>; "
1727                                "expected to succeed.\n".format(name=meth_name)
1728                            )
1729                        if not str(e).startswith(meth_name):
1730                            self.fail(
1731                                "Method <<{name:s}>> failed with unexpected "
1732                                "exception message: {exp:s}\n".format(
1733                                    name=meth_name, exp=e
1734                                )
1735                            )
1736                        # consume data
1737                        s.read()
1738
1739                # Make sure sendmsg et al are disallowed to avoid
1740                # inadvertent disclosure of data and/or corruption
1741                # of the encrypted data stream
1742                self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1743                self.assertRaises(NotImplementedError, s.recvmsg, 100)
1744                self.assertRaises(NotImplementedError,
1745                                  s.recvmsg_into, bytearray(100))
1746
1747                s.write(b"over\n")
1748                s.close()
1749
1750        def test_handshake_timeout(self):
1751            # Issue #5103: SSL handshake must respect the socket timeout
1752            server = socket.socket(socket.AF_INET)
1753            host = "127.0.0.1"
1754            port = support.bind_port(server)
1755            started = threading.Event()
1756            finish = False
1757
1758            def serve():
1759                server.listen(5)
1760                started.set()
1761                conns = []
1762                while not finish:
1763                    r, w, e = select.select([server], [], [], 0.1)
1764                    if server in r:
1765                        # Let the socket hang around rather than having
1766                        # it closed by garbage collection.
1767                        conns.append(server.accept()[0])
1768                for sock in conns:
1769                    sock.close()
1770
1771            t = threading.Thread(target=serve)
1772            t.start()
1773            started.wait()
1774
1775            try:
1776                try:
1777                    c = socket.socket(socket.AF_INET)
1778                    c.settimeout(0.2)
1779                    c.connect((host, port))
1780                    # Will attempt handshake and time out
1781                    self.assertRaisesRegex(socket.timeout, "timed out",
1782                                           ssl.wrap_socket, c)
1783                finally:
1784                    c.close()
1785                try:
1786                    c = socket.socket(socket.AF_INET)
1787                    c = ssl.wrap_socket(c)
1788                    c.settimeout(0.2)
1789                    # Will attempt handshake and time out
1790                    self.assertRaisesRegex(socket.timeout, "timed out",
1791                                           c.connect, (host, port))
1792                finally:
1793                    c.close()
1794            finally:
1795                finish = True
1796                t.join()
1797                server.close()
1798
1799        def test_server_accept(self):
1800            # Issue #16357: accept() on a SSLSocket created through
1801            # SSLContext.wrap_socket().
1802            context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1803            context.verify_mode = ssl.CERT_REQUIRED
1804            context.load_verify_locations(CERTFILE)
1805            context.load_cert_chain(CERTFILE)
1806            server = socket.socket(socket.AF_INET)
1807            host = "127.0.0.1"
1808            port = support.bind_port(server)
1809            server = context.wrap_socket(server, server_side=True)
1810
1811            evt = threading.Event()
1812            remote = None
1813            peer = None
1814            def serve():
1815                nonlocal remote, peer
1816                server.listen(5)
1817                # Block on the accept and wait on the connection to close.
1818                evt.set()
1819                remote, peer = server.accept()
1820                remote.recv(1)
1821
1822            t = threading.Thread(target=serve)
1823            t.start()
1824            # Client wait until server setup and perform a connect.
1825            evt.wait()
1826            client = context.wrap_socket(socket.socket())
1827            client.connect((host, port))
1828            client_addr = client.getsockname()
1829            client.close()
1830            t.join()
1831            # Sanity checks.
1832            self.assertIsInstance(remote, ssl.SSLSocket)
1833            self.assertEqual(peer, client_addr)
1834
1835        def test_default_ciphers(self):
1836            context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1837            try:
1838                # Force a set of weak ciphers on our client context
1839                context.set_ciphers("DES")
1840            except ssl.SSLError:
1841                self.skipTest("no DES cipher available")
1842            with ThreadedEchoServer(CERTFILE,
1843                                    ssl_version=ssl.PROTOCOL_SSLv23,
1844                                    chatty=False) as server:
1845                with socket.socket() as sock:
1846                    s = context.wrap_socket(sock)
1847                    with self.assertRaises((OSError, ssl.SSLError)):
1848                        s.connect((HOST, server.port))
1849            self.assertIn("no shared cipher", str(server.conn_errors[0]))
1850
1851        @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1852                             "'tls-unique' channel binding not available")
1853        def test_tls_unique_channel_binding(self):
1854            """Test tls-unique channel binding."""
1855            if support.verbose:
1856                sys.stdout.write("\n")
1857
1858            server = ThreadedEchoServer(CERTFILE,
1859                                        certreqs=ssl.CERT_NONE,
1860                                        ssl_version=ssl.PROTOCOL_TLSv1,
1861                                        cacerts=CERTFILE,
1862                                        chatty=True,
1863                                        connectionchatty=False)
1864            with server:
1865                s = ssl.wrap_socket(socket.socket(),
1866                                    server_side=False,
1867                                    certfile=CERTFILE,
1868                                    ca_certs=CERTFILE,
1869                                    cert_reqs=ssl.CERT_NONE,
1870                                    ssl_version=ssl.PROTOCOL_TLSv1)
1871                s.connect((HOST, server.port))
1872                # get the data
1873                cb_data = s.get_channel_binding("tls-unique")
1874                if support.verbose:
1875                    sys.stdout.write(" got channel binding data: {0!r}\n"
1876                                     .format(cb_data))
1877
1878                # check if it is sane
1879                self.assertIsNotNone(cb_data)
1880                self.assertEqual(len(cb_data), 12) # True for TLSv1
1881
1882                # and compare with the peers version
1883                s.write(b"CB tls-unique\n")
1884                peer_data_repr = s.read().strip()
1885                self.assertEqual(peer_data_repr,
1886                                 repr(cb_data).encode("us-ascii"))
1887                s.close()
1888
1889                # now, again
1890                s = ssl.wrap_socket(socket.socket(),
1891                                    server_side=False,
1892                                    certfile=CERTFILE,
1893                                    ca_certs=CERTFILE,
1894                                    cert_reqs=ssl.CERT_NONE,
1895                                    ssl_version=ssl.PROTOCOL_TLSv1)
1896                s.connect((HOST, server.port))
1897                new_cb_data = s.get_channel_binding("tls-unique")
1898                if support.verbose:
1899                    sys.stdout.write(" got another channel binding data: {0!r}\n"
1900                                     .format(new_cb_data))
1901                # is it really unique
1902                self.assertNotEqual(cb_data, new_cb_data)
1903                self.assertIsNotNone(cb_data)
1904                self.assertEqual(len(cb_data), 12) # True for TLSv1
1905                s.write(b"CB tls-unique\n")
1906                peer_data_repr = s.read().strip()
1907                self.assertEqual(peer_data_repr,
1908                                 repr(new_cb_data).encode("us-ascii"))
1909                s.close()
1910
1911        def test_compression(self):
1912            context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1913            context.load_cert_chain(CERTFILE)
1914            stats = server_params_test(context, context,
1915                                       chatty=True, connectionchatty=True)
1916            if support.verbose:
1917                sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1918            self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1919
1920        @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1921                             "ssl.OP_NO_COMPRESSION needed for this test")
1922        def test_compression_disabled(self):
1923            context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1924            context.load_cert_chain(CERTFILE)
1925            context.options |= ssl.OP_NO_COMPRESSION
1926            stats = server_params_test(context, context,
1927                                       chatty=True, connectionchatty=True)
1928            self.assertIs(stats['compression'], None)
1929
1930        def test_dh_params(self):
1931            # Check we can get a connection with ephemeral Diffie-Hellman
1932            context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1933            context.load_cert_chain(CERTFILE)
1934            context.load_dh_params(DHFILE)
1935            context.set_ciphers("kEDH")
1936            stats = server_params_test(context, context,
1937                                       chatty=True, connectionchatty=True)
1938            cipher = stats["cipher"][0]
1939            parts = cipher.split("-")
1940            if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1941                self.fail("Non-DH cipher: " + cipher[0])
1942
1943        def test_selected_npn_protocol(self):
1944            # selected_npn_protocol() is None unless NPN is used
1945            context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1946            context.load_cert_chain(CERTFILE)
1947            stats = server_params_test(context, context,
1948                                       chatty=True, connectionchatty=True)
1949            self.assertIs(stats['client_npn_protocol'], None)
1950
1951        @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1952        def test_npn_protocols(self):
1953            server_protocols = ['http/1.1', 'spdy/2']
1954            protocol_tests = [
1955                (['http/1.1', 'spdy/2'], 'http/1.1'),
1956                (['spdy/2', 'http/1.1'], 'http/1.1'),
1957                (['spdy/2', 'test'], 'spdy/2'),
1958                (['abc', 'def'], 'abc')
1959            ]
1960            for client_protocols, expected in protocol_tests:
1961                server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1962                server_context.load_cert_chain(CERTFILE)
1963                server_context.set_npn_protocols(server_protocols)
1964                client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1965                client_context.load_cert_chain(CERTFILE)
1966                client_context.set_npn_protocols(client_protocols)
1967                stats = server_params_test(client_context, server_context,
1968                                           chatty=True, connectionchatty=True)
1969
1970                msg = "failed trying %s (s) and %s (c).\n" \
1971                      "was expecting %s, but got %%s from the %%s" \
1972                          % (str(server_protocols), str(client_protocols),
1973                             str(expected))
1974                client_result = stats['client_npn_protocol']
1975                self.assertEqual(client_result, expected, msg % (client_result, "client"))
1976                server_result = stats['server_npn_protocols'][-1] \
1977                    if len(stats['server_npn_protocols']) else 'nothing'
1978                self.assertEqual(server_result, expected, msg % (server_result, "server"))
1979
1980
1981def test_main(verbose=False):
1982    if support.verbose:
1983        plats = {
1984            'Linux': platform.linux_distribution,
1985            'Mac': platform.mac_ver,
1986            'Windows': platform.win32_ver,
1987        }
1988        for name, func in plats.items():
1989            plat = func()
1990            if plat and plat[0]:
1991                plat = '%s %r' % (name, plat)
1992                break
1993        else:
1994            plat = repr(platform.platform())
1995        print("test_ssl: testing with %r %r" %
1996            (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1997        print("          under %s" % plat)
1998        print("          HAS_SNI = %r" % ssl.HAS_SNI)
1999
2000    for filename in [
2001        CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2002        ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2003        BADCERT, BADKEY, EMPTYCERT]:
2004        if not os.path.exists(filename):
2005            raise support.TestFailed("Can't read certificate file %r" % filename)
2006
2007    tests = [ContextTests, BasicSocketTests, SSLErrorTests]
2008
2009    if support.is_resource_enabled('network'):
2010        tests.append(NetworkedTests)
2011
2012    if _have_threads:
2013        thread_info = support.threading_setup()
2014        if thread_info and support.is_resource_enabled('network'):
2015            tests.append(ThreadedTests)
2016
2017    try:
2018        support.run_unittest(*tests)
2019    finally:
2020        if _have_threads:
2021            support.threading_cleanup(*thread_info)
2022
2023if __name__ == "__main__":
2024    test_main()