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