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