/Lib/test/test_ssl.py
Python | 2035 lines | 1848 code | 95 blank | 92 comment | 101 complexity | 466e3a8b8c1b233f8a75e2fdbb7b06b7 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1# Test the support for SSL and sockets 2 3import sys 4import unittest 5from test import support 6import socket 7import select 8import time 9import gc 10import os 11import errno 12import pprint 13import tempfile 14import urllib.request 15import traceback 16import asyncore 17import weakref 18import platform 19import functools 20 21ssl = support.import_module("ssl") 22 23PROTOCOLS = [ 24 ssl.PROTOCOL_SSLv3, 25 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1 26] 27if hasattr(ssl, 'PROTOCOL_SSLv2'): 28 PROTOCOLS.append(ssl.PROTOCOL_SSLv2) 29 30HOST = support.HOST 31 32data_file = lambda name: os.path.join(os.path.dirname(__file__), name) 33 34# The custom key and certificate files used in test_ssl are generated 35# using Lib/test/make_ssl_certs.py. 36# Other certificates are simply fetched from the Internet servers they 37# are meant to authenticate. 38 39CERTFILE = data_file("keycert.pem") 40BYTES_CERTFILE = os.fsencode(CERTFILE) 41ONLYCERT = data_file("ssl_cert.pem") 42ONLYKEY = data_file("ssl_key.pem") 43BYTES_ONLYCERT = os.fsencode(ONLYCERT) 44BYTES_ONLYKEY = os.fsencode(ONLYKEY) 45CERTFILE_PROTECTED = data_file("keycert.passwd.pem") 46ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem") 47KEY_PASSWORD = "somepass" 48CAPATH = data_file("capath") 49BYTES_CAPATH = os.fsencode(CAPATH) 50 51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem") 52 53EMPTYCERT = data_file("nullcert.pem") 54BADCERT = data_file("badcert.pem") 55WRONGCERT = data_file("XXXnonexisting.pem") 56BADKEY = data_file("badkey.pem") 57NOKIACERT = data_file("nokia.pem") 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 # OSError raise by the underlying socket object. 217 s = socket.socket(socket.AF_INET) 218 ss = ssl.wrap_socket(s) 219 self.assertRaises(OSError, ss.recv, 1) 220 self.assertRaises(OSError, ss.recv_into, bytearray(b'x')) 221 self.assertRaises(OSError, ss.recvfrom, 1) 222 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1) 223 self.assertRaises(OSError, ss.send, b'x') 224 self.assertRaises(OSError, 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(OSError) 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(OSError) 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(OSError) 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(OSError) 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(OSError) 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_ex_error(self): 718 with support.transient_internet("svn.python.org"): 719 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 720 cert_reqs=ssl.CERT_REQUIRED, 721 ca_certs=SVN_PYTHON_ORG_ROOT_CERT) 722 try: 723 self.assertEqual(errno.ECONNREFUSED, 724 s.connect_ex(("svn.python.org", 444))) 725 finally: 726 s.close() 727 728 def test_connect_with_context(self): 729 with support.transient_internet("svn.python.org"): 730 # Same as test_connect, but with a separately created context 731 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) 732 s = ctx.wrap_socket(socket.socket(socket.AF_INET)) 733 s.connect(("svn.python.org", 443)) 734 try: 735 self.assertEqual({}, s.getpeercert()) 736 finally: 737 s.close() 738 # Same with a server hostname 739 s = ctx.wrap_socket(socket.socket(socket.AF_INET), 740 server_hostname="svn.python.org") 741 if ssl.HAS_SNI: 742 s.connect(("svn.python.org", 443)) 743 s.close() 744 else: 745 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443)) 746 # This should fail because we have no verification certs 747 ctx.verify_mode = ssl.CERT_REQUIRED 748 s = ctx.wrap_socket(socket.socket(socket.AF_INET)) 749 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed", 750 s.connect, ("svn.python.org", 443)) 751 s.close() 752 # This should succeed because we specify the root cert 753 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT) 754 s = ctx.wrap_socket(socket.socket(socket.AF_INET)) 755 s.connect(("svn.python.org", 443)) 756 try: 757 cert = s.getpeercert() 758 self.assertTrue(cert) 759 finally: 760 s.close() 761 762 def test_connect_capath(self): 763 # Verify server certificates using the `capath` argument 764 # NOTE: the subject hashing algorithm has been changed between 765 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must 766 # contain both versions of each certificate (same content, different 767 # filename) for this test to be portable across OpenSSL releases. 768 with support.transient_internet("svn.python.org"): 769 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) 770 ctx.verify_mode = ssl.CERT_REQUIRED 771 ctx.load_verify_locations(capath=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 # Same with a bytes `capath` argument 780 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) 781 ctx.verify_mode = ssl.CERT_REQUIRED 782 ctx.load_verify_locations(capath=BYTES_CAPATH) 783 s = ctx.wrap_socket(socket.socket(socket.AF_INET)) 784 s.connect(("svn.python.org", 443)) 785 try: 786 cert = s.getpeercert() 787 self.assertTrue(cert) 788 finally: 789 s.close() 790 791 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows") 792 def test_makefile_close(self): 793 # Issue #5238: creating a file-like object with makefile() shouldn't 794 # delay closing the underlying "real socket" (here tested with its 795 # file descriptor, hence skipping the test under Windows). 796 with support.transient_internet("svn.python.org"): 797 ss = ssl.wrap_socket(socket.socket(socket.AF_INET)) 798 ss.connect(("svn.python.org", 443)) 799 fd = ss.fileno() 800 f = ss.makefile() 801 f.close() 802 # The fd is still open 803 os.read(fd, 0) 804 # Closing the SSL socket should close the fd too 805 ss.close() 806 gc.collect() 807 with self.assertRaises(OSError) as e: 808 os.read(fd, 0) 809 self.assertEqual(e.exception.errno, errno.EBADF) 810 811 def test_non_blocking_handshake(self): 812 with support.transient_internet("svn.python.org"): 813 s = socket.socket(socket.AF_INET) 814 s.connect(("svn.python.org", 443)) 815 s.setblocking(False) 816 s = ssl.wrap_socket(s, 817 cert_reqs=ssl.CERT_NONE, 818 do_handshake_on_connect=False) 819 count = 0 820 while True: 821 try: 822 count += 1 823 s.do_handshake() 824 break 825 except ssl.SSLWantReadError: 826 select.select([s], [], []) 827 except ssl.SSLWantWriteError: 828 select.select([], [s], []) 829 s.close() 830 if support.verbose: 831 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count) 832 833 def test_get_server_certificate(self): 834 def _test_get_server_certificate(host, port, cert=None): 835 with support.transient_internet(host): 836 pem = ssl.get_server_certificate((host, port)) 837 if not pem: 838 self.fail("No server certificate on %s:%s!" % (host, port)) 839 840 try: 841 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE) 842 except ssl.SSLError as x: 843 #should fail 844 if support.verbose: 845 sys.stdout.write("%s\n" % x) 846 else: 847 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port)) 848 849 pem = ssl.get_server_certificate((host, port), ca_certs=cert) 850 if not pem: 851 self.fail("No server certificate on %s:%s!" % (host, port)) 852 if support.verbose: 853 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem)) 854 855 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT) 856 if support.IPV6_ENABLED: 857 _test_get_server_certificate('ipv6.google.com', 443) 858 859 def test_ciphers(self): 860 remote = ("svn.python.org", 443) 861 with support.transient_internet(remote[0]): 862 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 863 cert_reqs=ssl.CERT_NONE, ciphers="ALL") 864 s.connect(remote) 865 s = ssl.wrap_socket(socket.socket(socket.AF_INET), 866 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") 867 s.connect(remote) 868 # Error checking can happen at instantiation or when connecting 869 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"): 870 with socket.socket(socket.AF_INET) as sock: 871 s = ssl.wrap_socket(sock, 872 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx") 873 s.connect(remote) 874 875 def test_algorithms(self): 876 # Issue #8484: all algorithms should be available when verifying a 877 # certificate. 878 # SHA256 was added in OpenSSL 0.9.8 879 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15): 880 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION) 881 # sha256.tbs-internet.com needs SNI to use the correct certificate 882 if not ssl.HAS_SNI: 883 self.skipTest("SNI needed for this test") 884 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host) 885 remote = ("sha256.tbs-internet.com", 443) 886 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem") 887 with support.transient_internet("sha256.tbs-internet.com"): 888 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 889 ctx.verify_mode = ssl.CERT_REQUIRED 890 ctx.load_verify_locations(sha256_cert) 891 s = ctx.wrap_socket(socket.socket(socket.AF_INET), 892 server_hostname="sha256.tbs-internet.com") 893 try: 894 s.connect(remote) 895 if support.verbose: 896 sys.stdout.write("\nCipher with %r is %r\n" % 897 (remote, s.cipher())) 898 sys.stdout.write("Certificate is:\n%s\n" % 899 pprint.pformat(s.getpeercert())) 900 finally: 901 s.close() 902 903 904try: 905 import threading 906except ImportError: 907 _have_threads = False 908else: 909 _have_threads = True 910 911 from test.ssl_servers import make_https_server 912 913 class ThreadedEchoServer(threading.Thread): 914 915 class ConnectionHandler(threading.Thread): 916 917 """A mildly complicated class, because we want it to work both 918 with and without the SSL wrapper around the socket connection, so 919 that we can test the STARTTLS functionality.""" 920 921 def __init__(self, server, connsock, addr): 922 self.server = server 923 self.running = False 924 self.sock = connsock 925 self.addr = addr 926 self.sock.setblocking(1) 927 self.sslconn = None 928 threading.Thread.__init__(self) 929 self.daemon = True 930 931 def wrap_conn(self): 932 try: 933 self.sslconn = self.server.context.wrap_socket( 934 self.sock, server_side=True) 935 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol()) 936 except ssl.SSLError as e: 937 # XXX Various errors can have happened here, for example 938 # a mismatching protocol version, an invalid certificate, 939 # or a low-level bug. This should be made more discriminating. 940 self.server.conn_errors.append(e) 941 if self.server.chatty: 942 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n") 943 self.running = False 944 self.server.stop() 945 self.close() 946 return False 947 else: 948 if self.server.context.verify_mode == ssl.CERT_REQUIRED: 949 cert = self.sslconn.getpeercert() 950 if support.verbose and self.server.chatty: 951 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n") 952 cert_binary = self.sslconn.getpeercert(True) 953 if support.verbose and self.server.chatty: 954 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n") 955 cipher = self.sslconn.cipher() 956 if support.verbose and self.server.chatty: 957 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n") 958 sys.stdout.write(" server: selected protocol is now " 959 + str(self.sslconn.selected_npn_protocol()) + "\n") 960 return True 961 962 def read(self): 963 if self.sslconn: 964 return self.sslconn.read() 965 else: 966 return self.sock.recv(1024) 967 968 def write(self, bytes): 969 if self.sslconn: 970 return self.sslconn.write(bytes) 971 else: 972 return self.sock.send(bytes) 973 974 def close(self): 975 if self.sslconn: 976 self.sslconn.close() 977 else: 978 self.sock.close() 979 980 def run(self): 981 self.running = True 982 if not self.server.starttls_server: 983 if not self.wrap_conn(): 984 return 985 while self.running: 986 try: 987 msg = self.read() 988 stripped = msg.strip() 989 if not stripped: 990 # eof, so quit this handler 991 self.running = False 992 self.close() 993 elif stripped == b'over': 994 if support.verbose and self.server.connectionchatty: 995 sys.stdout.write(" server: client closed connection\n") 996 self.close() 997 return 998 elif (self.server.starttls_server and 999 stripped == b'STARTTLS'): 1000 if support.verbose and self.server.connectionchatty: 1001 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n") 1002 self.write(b"OK\n") 1003 if not self.wrap_conn(): 1004 return 1005 elif (self.server.starttls_server and self.sslconn 1006 and stripped == b'ENDTLS'): 1007 if support.verbose and self.server.connectionchatty: 1008 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n") 1009 self.write(b"OK\n") 1010 self.sock = self.sslconn.unwrap() 1011 self.sslconn = None 1012 if support.verbose and self.server.connectionchatty: 1013 sys.stdout.write(" server: connection is now unencrypted...\n") 1014 elif stripped == b'CB tls-unique': 1015 if support.verbose and self.server.connectionchatty: 1016 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n") 1017 data = self.sslconn.get_channel_binding("tls-unique") 1018 self.write(repr(data).encode("us-ascii") + b"\n") 1019 else: 1020 if (support.verbose and 1021 self.server.connectionchatty): 1022 ctype = (self.sslconn and "encrypted") or "unencrypted" 1023 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n" 1024 % (msg, ctype, msg.lower(), ctype)) 1025 self.write(msg.lower()) 1026 except OSError: 1027 if self.server.chatty: 1028 handle_error("Test server failure:\n") 1029 self.close() 1030 self.running = False 1031 # normally, we'd just stop here, but for the test 1032 # harness, we want to stop the server 1033 self.server.stop() 1034 1035 def __init__(self, certificate=None, ssl_version=None, 1036 certreqs=None, cacerts=None, 1037 chatty=True, connectionchatty=False, starttls_server=False, 1038 npn_protocols=None, ciphers=None, context=None): 1039 if context: 1040 self.context = context 1041 else: 1042 self.context = ssl.SSLContext(ssl_version 1043 if ssl_version is not None 1044 else ssl.PROTOCOL_TLSv1) 1045 self.context.verify_mode = (certreqs if certreqs is not None 1046 else ssl.CERT_NONE) 1047 if cacerts: 1048 self.context.load_verify_locations(cacerts) 1049 if certificate: 1050 self.context.load_cert_chain(certificate) 1051 if npn_protocols: 1052 self.context.set_npn_protocols(npn_protocols) 1053 if ciphers: 1054 self.context.set_ciphers(ciphers) 1055 self.chatty = chatty 1056 self.connectionchatty = connectionchatty 1057 self.starttls_server = starttls_server 1058 self.sock = socket.socket() 1059 self.port = support.bind_port(self.sock) 1060 self.flag = None 1061 self.active = False 1062 self.selected_protocols = [] 1063 self.conn_errors = [] 1064 threading.Thread.__init__(self) 1065 self.daemon = True 1066 1067 def __enter__(self): 1068 self.start(threading.Event()) 1069 self.flag.wait() 1070 return self 1071 1072 def __exit__(self, *args): 1073 self.stop() 1074 self.join() 1075 1076 def start(self, flag=None): 1077 self.flag = flag 1078 threading.Thread.start(self) 1079 1080 def run(self): 1081 self.sock.settimeout(0.05) 1082 self.sock.listen(5) 1083 self.active = True 1084 if self.flag: 1085 # signal an event 1086 self.flag.set() 1087 while self.active: 1088 try: 1089 newconn, connaddr = self.sock.accept() 1090 if support.verbose and self.chatty: 1091 sys.stdout.write(' server: new connection from ' 1092 + repr(connaddr) + '\n') 1093 handler = self.ConnectionHandler(self, newconn, connaddr) 1094 handler.start() 1095 handler.join() 1096 except socket.timeout: 1097 pass 1098 except KeyboardInterrupt: 1099 self.stop() 1100 self.sock.close() 1101 1102 def stop(self): 1103 self.active = False 1104 1105 class AsyncoreEchoServer(threading.Thread): 1106 1107 # this one's based on asyncore.dispatcher 1108 1109 class EchoServer (asyncore.dispatcher): 1110 1111 class ConnectionHandler (asyncore.dispatcher_with_send): 1112 1113 def __init__(self, conn, certfile): 1114 self.socket = ssl.wrap_socket(conn, server_side=True, 1115 certfile=certfile, 1116 do_handshake_on_connect=False) 1117 asyncore.dispatcher_with_send.__init__(self, self.socket) 1118 self._ssl_accepting = True 1119 self._do_ssl_handshake() 1120 1121 def readable(self): 1122 if isinstance(self.socket, ssl.SSLSocket): 1123 while self.socket.pending() > 0: 1124 self.handle_read_event() 1125 return True 1126 1127 def _do_ssl_handshake(self): 1128 try: 1129 self.socket.do_handshake() 1130 except (ssl.SSLWantReadError, ssl.SSLWantWriteError): 1131 return 1132 except ssl.SSLEOFError: 1133 return self.handle_close() 1134 except ssl.SSLError: 1135 raise 1136 except OSError as err: 1137 if err.args[0] == errno.ECONNABORTED: 1138 return self.handle_close() 1139 else: 1140 self._ssl_accepting = False 1141 1142 def handle_read(self): 1143 if self._ssl_accepting: 1144 self._do_ssl_handshake() 1145 else: 1146 data = self.recv(1024) 1147 if support.verbose: 1148 sys.stdout.write(" server: read %s from client\n" % repr(data)) 1149 if not data: 1150 …
Large files files are truncated, but you can click here to view the full file