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