class TestHTTPS_TLSv1(HTTPSDummyServerTestCase): certs = DEFAULT_CERTS.copy() certs["ssl_version"] = ssl.PROTOCOL_TLSv1 def setUp(self): self._pool = HTTPSConnectionPool(self.host, self.port) def test_set_ssl_version_to_sslv3(self): self._pool.ssl_version = ssl.PROTOCOL_SSLv3 self.assertRaises(SSLError, self._pool.request, "GET", "/") def test_ssl_version_as_string(self): self._pool.ssl_version = "PROTOCOL_SSLv3" self.assertRaises(SSLError, self._pool.request, "GET", "/") def test_ssl_version_as_short_string(self): self._pool.ssl_version = "SSLv3" self.assertRaises(SSLError, self._pool.request, "GET", "/") def test_discards_connection_on_sslerror(self): self._pool.cert_reqs = "CERT_REQUIRED" self.assertRaises(SSLError, self._pool.request, "GET", "/") self._pool.ca_certs = DEFAULT_CA self._pool.request("GET", "/") def test_set_cert_default_cert_required(self): conn = VerifiedHTTPSConnection(self.host, self.port) conn.set_cert(ca_certs="/etc/ssl/certs/custom.pem") self.assertEqual(conn.cert_reqs, "CERT_REQUIRED")
def test_invalid_common_name(self): https_pool = HTTPSConnectionPool("127.0.0.1", self.port, cert_reqs="CERT_REQUIRED", ca_certs=DEFAULT_CA) try: https_pool.request("GET", "/") self.fail("Didn't raise SSL invalid common name") except SSLError as e: self.assertTrue("doesn't match" in str(e))
def test_ssl_verified_with_platform_ca_certs(self): """ We should rely on the platform CA file to validate authenticity of SSL certificates. Since this file is used by many components of the OS, such as curl, apt-get, etc., we decided to not touch it, in order to not compromise the security of the OS running the test suite (typically urllib3 developer's OS). This test assumes that httpbin.org uses a certificate signed by a well known Certificate Authority. """ try: import urllib3.contrib.pyopenssl except ImportError: raise SkipTest('Test requires PyOpenSSL') if (urllib3.connection.ssl_wrap_socket is urllib3.contrib.pyopenssl.orig_connection_ssl_wrap_socket): # Not patched raise SkipTest('Test should only be run after PyOpenSSL ' 'monkey patching') https_pool = HTTPSConnectionPool('httpbin.org', 443, cert_reqs=ssl.CERT_REQUIRED) https_pool.request('HEAD', '/')
def test_assert_fingerprint_sha256(self): https_pool = HTTPSConnectionPool("localhost", self.port, cert_reqs="CERT_REQUIRED", ca_certs=DEFAULT_CA) https_pool.assert_fingerprint = ( "9A:29:9D:4F:47:85:1C:51:23:F5:9A:A3:" "0F:5A:EF:96:F9:2E:3C:22:2E:FC:E8:BC:" "0E:73:90:37:ED:3B:AA:AB" ) https_pool.request("GET", "/")
def test_assert_specific_hostname(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED') https_pool.ca_certs = DEFAULT_CA https_pool.assert_hostname = 'localhost' https_pool.request('GET', '/')
def test_https_timeout(self): timeout = Timeout(connect=0.001) https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port, timeout=timeout, retries=False, cert_reqs='CERT_REQUIRED') self.addCleanup(https_pool.close) timeout = Timeout(total=None, connect=0.001) https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port, timeout=timeout, retries=False, cert_reqs='CERT_REQUIRED') self.addCleanup(https_pool.close) self.assertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/') timeout = Timeout(read=0.001) https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, retries=False, cert_reqs='CERT_REQUIRED') self.addCleanup(https_pool.close) https_pool.ca_certs = DEFAULT_CA https_pool.assert_fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:' \ 'BF:93:CF:F9:71:CC:07:7D:0A' timeout = Timeout(total=None) https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, cert_reqs='CERT_NONE') self.addCleanup(https_pool.close) https_pool.request('GET', '/')
def test_https_timeout(self): timeout = Timeout(connect=0.001) https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port, timeout=timeout, cert_reqs='CERT_REQUIRED') timeout = Timeout(total=None, connect=0.001) https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port, timeout=timeout, cert_reqs='CERT_REQUIRED') self.assertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/') timeout = Timeout(read=0.001) https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, cert_reqs='CERT_REQUIRED') https_pool.ca_certs = DEFAULT_CA https_pool.assert_fingerprint = 'CC:45:6A:90:82:F7FF:C0:8218:8e:' \ '7A:F2:8A:D7:1E:07:33:67:DE' url = '/sleep?seconds=0.005' self.assertRaises(ReadTimeoutError, https_pool.request, 'GET', url) timeout = Timeout(total=None) https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, cert_reqs='CERT_NONE') https_pool.request('GET', '/')
def test_assert_hostname_false(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) https_pool.assert_hostname = False https_pool.request('GET', '/')
class TestHTTPS_TLSv1(HTTPSDummyServerTestCase): certs = DEFAULT_CERTS.copy() certs['ssl_version'] = ssl.PROTOCOL_TLSv1 def setUp(self): self._pool = HTTPSConnectionPool(self.host, self.port) def test_set_ssl_version_to_sslv3(self): self._pool.ssl_version = ssl.PROTOCOL_SSLv3 self.assertRaises(SSLError, self._pool.request, 'GET', '/') def test_ssl_version_as_string(self): self._pool.ssl_version = 'PROTOCOL_SSLv3' self.assertRaises(SSLError, self._pool.request, 'GET', '/') def test_ssl_version_as_short_string(self): self._pool.ssl_version = 'SSLv3' self.assertRaises(SSLError, self._pool.request, 'GET', '/') def test_discards_connection_on_sslerror(self): self._pool.cert_reqs = 'CERT_REQUIRED' self.assertRaises(SSLError, self._pool.request, 'GET', '/') self._pool.ca_certs = DEFAULT_CA self._pool.request('GET', '/') def test_set_cert_default_cert_required(self): conn = VerifiedHTTPSConnection(self.host, self.port) conn.set_cert(ca_certs=DEFAULT_CA) self.assertEqual(conn.cert_reqs, 'CERT_REQUIRED')
def test_verify_none_and_good_fingerprint(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_NONE', ca_certs=DEFAULT_CA_BAD) https_pool.assert_fingerprint = 'CC:45:6A:90:82:F7FF:C0:8218:8e:' \ '7A:F2:8A:D7:1E:07:33:67:DE' https_pool.request('GET', '/')
def test_assert_fingerprint_md5(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED') https_pool.ca_certs = DEFAULT_CA https_pool.assert_fingerprint = 'CA:84:E1:AD0E5a:ef:2f:C3:09' \ ':E7:30:F8:CD:C8:5B' https_pool.request('GET', '/')
def test_assert_fingerprint_sha1(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED') https_pool.ca_certs = DEFAULT_CA https_pool.assert_fingerprint = 'CC:45:6A:90:82:F7FF:C0:8218:8e:' \ '7A:F2:8A:D7:1E:07:33:67:DE' https_pool.request('GET', '/')
def test_assert_specific_hostname(self): https_pool = HTTPSConnectionPool('localhost', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) self.addCleanup(https_pool.close) https_pool.assert_hostname = 'localhost' https_pool.request('GET', '/')
def test_assert_fingerprint_sha1(self): https_pool = HTTPSConnectionPool('localhost', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) https_pool.assert_fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:' \ 'BF:93:CF:F9:71:CC:07:7D:0A' https_pool.request('GET', '/')
def test_verify_none_and_good_fingerprint(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_NONE', ca_certs=DEFAULT_CA_BAD) https_pool.assert_fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:' \ 'BF:93:CF:F9:71:CC:07:7D:0A' https_pool.request('GET', '/')
def test_good_fingerprint_and_hostname_mismatch(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) https_pool.assert_fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:' \ 'BF:93:CF:F9:71:CC:07:7D:0A' https_pool.request('GET', '/')
def test_no_ssl(self): pool = HTTPSConnectionPool(self.host, self.port) pool.ConnectionCls = None self.addCleanup(pool.close) self.assertRaises(SSLError, pool._new_conn) with self.assertRaises(MaxRetryError) as cm: pool.request('GET', '/', retries=0) self.assertIsInstance(cm.exception.reason, SSLError)
class TestHTTPS(HTTPSDummyServerTestCase): def setUp(self): self._pool = HTTPSConnectionPool(self.host, self.port) def test_simple(self): r = self._pool.request('GET', '/specific_method', fields={'method': 'GET'}) self.assertEqual(r.status, 200, r.data) def test_verified(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED') conn = https_pool._new_conn() self.assertEqual(conn.__class__, VerifiedHTTPSConnection) self.assertRaises(SSLError, https_pool.request, 'GET', '/') https_pool.ca_certs = DEFAULT_CA_BAD try: https_pool.request('GET', '/') self.fail("Didn't raise SSL error with wrong CA") except SSLError as e: self.assertTrue('certificate verify failed' in str(e), "Expected 'certificate verify failed', instead got: %r" % e) https_pool.ca_certs = DEFAULT_CA https_pool.request('GET', '/') # Should succeed without exceptions. https_fail_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED') https_fail_pool.ca_certs = DEFAULT_CA try: https_fail_pool.request('GET', '/') self.fail("Didn't raise SSL invalid common name") except SSLError as e: self.assertTrue("doesn't match" in str(e)) def test_no_ssl(self): import urllib3.connectionpool OriginalHTTPSConnection = urllib3.connectionpool.HTTPSConnection OriginalSSL = urllib3.connectionpool.ssl urllib3.connectionpool.HTTPSConnection = None urllib3.connectionpool.ssl = None self.assertRaises(SSLError, self._pool._new_conn) self.assertRaises(SSLError, lambda: self._pool.request('GET', '/specific_method', fields={'method': 'GET'})) # Undo urllib3.HTTPSConnection = OriginalHTTPSConnection urllib3.connectionpool.ssl = OriginalSSL
def test_verified(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) conn = https_pool._new_conn() self.assertEqual(conn.__class__, VerifiedHTTPSConnection) https_pool.request('GET', '/') # Should succeed without exceptions.
def test_assert_fingerprint_sha256(self): https_pool = HTTPSConnectionPool('localhost', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) https_pool.assert_fingerprint = ('C5:4D:0B:83:84:89:2E:AE:B4:58:BB:12:' 'F7:A6:C4:76:05:03:88:D8:57:65:51:F3:' '1E:60:B0:8B:70:18:64:E6') https_pool.request('GET', '/')
def test_assert_fingerprint_md5(self): https_pool = HTTPSConnectionPool('localhost', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) https_pool.assert_fingerprint = 'F2:06:5A:42:10:3F:45:1C:17:FE:E6:' \ '07:1E:8A:86:E5' https_pool.request('GET', '/')
def test_assert_fingerprint_sha256(self): https_pool = HTTPSConnectionPool('localhost', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) https_pool.assert_fingerprint = ('9A:29:9D:4F:47:85:1C:51:23:F5:9A:A3:' '0F:5A:EF:96:F9:2E:3C:22:2E:FC:E8:BC:' '0E:73:90:37:ED:3B:AA:AB') https_pool.request('GET', '/')
def test_verified_with_bad_ca_certs(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs="CERT_REQUIRED", ca_certs=DEFAULT_CA_BAD) try: https_pool.request("GET", "/") self.fail("Didn't raise SSL error with bad CA certs") except SSLError as e: self.assertTrue( "certificate verify failed" in str(e), "Expected 'certificate verify failed'," "instead got: %r" % e )
def test_verified(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs="CERT_REQUIRED") conn = https_pool._new_conn() self.assertEqual(conn.__class__, VerifiedHTTPSConnection) try: https_pool.request("GET", "/") self.fail("Didn't raise SSL error with no CA") except SSLError, e: self.assertIn("No root certificates", str(e))
def test_verify_none_and_bad_fingerprint(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_NONE', ca_certs=DEFAULT_CA_BAD) self.addCleanup(https_pool.close) https_pool.assert_fingerprint = 'AA:AA:AA:AA:AA:AAAA:AA:AAAA:AA:' \ 'AA:AA:AA:AA:AA:AA:AA:AA:AA' with self.assertRaises(MaxRetryError) as cm: https_pool.request('GET', '/', retries=0) self.assertIsInstance(cm.exception.reason, SSLError)
def test_invalid_common_name(self): https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) self.addCleanup(https_pool.close) try: https_pool.request('GET', '/') self.fail("Didn't raise SSL invalid common name") except SSLError as e: self.assertTrue("doesn't match" in str(e))
def test_verified(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED') conn = https_pool._new_conn() self.assertEqual(conn.__class__, VerifiedHTTPSConnection) try: https_pool.request('GET', '/') self.fail("Didn't raise SSL error with no CA") except SSLError, e: self.assertTrue('No root certificates' in str(e))
def test_good_fingerprint_and_hostname_mismatch(self): # This test doesn't run with SecureTransport because we don't turn off # hostname validation without turning off all validation, which this # test doesn't do (deliberately). We should revisit this if we make # new decisions. https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) self.addCleanup(https_pool.close) https_pool.assert_fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:' \ 'BF:93:CF:F9:71:CC:07:7D:0A' https_pool.request('GET', '/')
def test_verified_with_bad_ca_certs(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA_BAD) self.addCleanup(https_pool.close) try: https_pool.request('GET', '/') self.fail("Didn't raise SSL error with bad CA certs") except SSLError as e: self.assertTrue('certificate verify failed' in str(e), "Expected 'certificate verify failed'," "instead got: %r" % e)
def test_client_no_intermediate(self): client_cert, client_key = ( DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS['certfile'], DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS['keyfile'] ) https_pool = HTTPSConnectionPool(self.host, self.port, cert_file=client_cert, key_file=client_key) try: https_pool.request('GET', '/certificate', retries=False) except SSLError as e: self.assertTrue('alert unknown ca' in str(e) or 'invalid certificate chain' in str(e) or 'unknown Cert Authority' in str(e))
def test_strip_square_brackets_before_validating(self): """Test that the fix for #760 works.""" https_pool = HTTPSConnectionPool('[::1]', self.port, cert_reqs='CERT_REQUIRED', ca_certs=IPV6_ADDR_CA) self.addCleanup(https_pool.close) r = https_pool.request('GET', '/') self.assertEqual(r.status, 200)
def test_client_certs_two_files(self): """ Having a client cert in a separate file to its associated key works properly. """ done_receiving = Event() client_certs = [] def socket_handler(listener): sock = listener.accept()[0] sock = self._wrap_in_ssl(sock) client_certs.append(sock.getpeercert()) data = b'' while not data.endswith(b'\r\n\r\n'): data += sock.recv(8192) sock.sendall( b'HTTP/1.1 200 OK\r\n' b'Server: testsocket\r\n' b'Connection: close\r\n' b'Content-Length: 6\r\n' b'\r\n' b'Valid!' ) done_receiving.wait(5) sock.close() self._start_server(socket_handler) pool = HTTPSConnectionPool( self.host, self.port, cert_file=DEFAULT_CERTS['certfile'], key_file=DEFAULT_CERTS['keyfile'], cert_reqs='REQUIRED', ca_certs=DEFAULT_CA, ) self.addCleanup(pool.close) pool.request('GET', '/', retries=0) done_receiving.set() self.assertEqual(len(client_certs), 1)
def test_warning_for_certs_without_a_san(self): """Ensure that a warning is raised when the cert from the server has no Subject Alternative Name.""" with mock.patch('warnings.warn') as warn: https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED', ca_certs=NO_SAN_CA) r = https_pool.request('GET', '/') self.assertEqual(r.status, 200) self.assertTrue(warn.called)
def test_source_address_ignored(self): # source_address is ignored in Python 2.6 and earlier. for addr in INVALID_SOURCE_ADDRESSES: https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED', source_address=addr) https_pool.ca_certs = DEFAULT_CA r = https_pool.request('GET', '/source_address') assert r.status == 200
def test_verified_without_ca_certs(self): # default is cert_reqs=None which is ssl.CERT_NONE https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED') try: https_pool.request('GET', '/') self.fail("Didn't raise SSL error with no CA certs when" "CERT_REQUIRED is set") except SSLError as e: # there is a different error message depending on whether or # not pyopenssl is injected self.assertTrue( 'No root certificates specified' in str(e) or 'certificate verify failed' in str(e), "Expected 'No root certificates specified' or " "'certificate verify failed', " "instead got: %r" % e)
def test_strip_square_brackets_before_validating(self): """Test that the fix for #760 works.""" if not HAS_IPV6: raise SkipTest("Only runs on IPv6 systems") https_pool = HTTPSConnectionPool('[::1]', self.port, cert_reqs='CERT_REQUIRED', ca_certs=IPV6_ADDR_CA) r = https_pool.request('GET', '/') self.assertEqual(r.status, 200)
def test_https_timeout(self): timeout = Timeout(connect=0.001) https_pool = HTTPSConnectionPool( TARPIT_HOST, self.port, timeout=timeout, retries=False, cert_reqs="CERT_REQUIRED", ) self.addCleanup(https_pool.close) timeout = Timeout(total=None, connect=0.001) https_pool = HTTPSConnectionPool( TARPIT_HOST, self.port, timeout=timeout, retries=False, cert_reqs="CERT_REQUIRED", ) self.addCleanup(https_pool.close) with pytest.raises(ConnectTimeoutError): https_pool.request("GET", "/") timeout = Timeout(read=0.01) https_pool = HTTPSConnectionPool( self.host, self.port, timeout=timeout, retries=False, cert_reqs="CERT_REQUIRED", ) self.addCleanup(https_pool.close) https_pool.ca_certs = DEFAULT_CA https_pool.assert_fingerprint = ("92:81:FE:85:F7:0C:26:60:EC:D6:B3:" "BF:93:CF:F9:71:CC:07:7D:0A") timeout = Timeout(total=None) https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, cert_reqs="CERT_NONE") self.addCleanup(https_pool.close) https_pool.request("GET", "/")
def test_ca_dir_verified(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED', ca_cert_dir=DEFAULT_CA_DIR) self.addCleanup(https_pool.close) with mock.patch('warnings.warn') as warn: r = https_pool.request('GET', '/') self.assertEqual(r.status, 200) self.assertFalse(warn.called, warn.call_args_list)
def test_enhanced_ssl_connection(self): fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:BF:93:CF:F9:71:CC:07:7D:0A' https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA, assert_fingerprint=fingerprint) self.addCleanup(https_pool.close) r = https_pool.request('GET', '/') assert r.status == 200
class TestHTTPS_TLSv1(HTTPSDummyServerTestCase): certs = DEFAULT_CERTS.copy() certs['ssl_version'] = ssl.PROTOCOL_TLSv1 def setUp(self): self._pool = HTTPSConnectionPool(self.host, self.port) self.addCleanup(self._pool.close) def test_discards_connection_on_sslerror(self): self._pool.cert_reqs = 'CERT_REQUIRED' with self.assertRaises(MaxRetryError) as cm: self._pool.request('GET', '/', retries=0) self.assertIsInstance(cm.exception.reason, SSLError) self._pool.ca_certs = DEFAULT_CA self._pool.request('GET', '/') def test_set_cert_default_cert_required(self): conn = VerifiedHTTPSConnection(self.host, self.port) conn.set_cert(ca_certs=DEFAULT_CA) self.assertEqual(conn.cert_reqs, 'CERT_REQUIRED')
def test_client_intermediate(self): client_cert, client_key, client_subject = ( DEFAULT_CLIENT_CERTS['certfile'], DEFAULT_CLIENT_CERTS['keyfile'], DEFAULT_CLIENT_CERTS['subject']) https_pool = HTTPSConnectionPool(self.host, self.port, key_file=client_key, cert_file=client_cert) r = https_pool.request('GET', '/certificate') self.assertDictEqual(json.loads(r.data.decode('utf-8')), client_subject, r.data)
def test_client_intermediate(self): client_cert, client_key = ( DEFAULT_CLIENT_CERTS['certfile'], DEFAULT_CLIENT_CERTS['keyfile'], ) https_pool = HTTPSConnectionPool(self.host, self.port, key_file=client_key, cert_file=client_cert) r = https_pool.request('GET', '/certificate') subject = json.loads(r.data.decode('utf-8')) assert subject['organizationalUnitName'].startswith( 'Testing server cert')
def test_verified(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) conn = https_pool._new_conn() self.assertEqual(conn.__class__, VerifiedHTTPSConnection) with mock.patch('warnings.warn') as warn: r = https_pool.request('GET', '/') self.assertEqual(r.status, 200) self.assertFalse(warn.called, warn.call_args_list)
def test_warning_for_certs_without_a_san(self): """Ensure that a warning is raised when the cert from the server has no Subject Alternative Name.""" with mock.patch("warnings.warn") as warn: https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs="CERT_REQUIRED", ca_certs=NO_SAN_CA) self.addCleanup(https_pool.close) r = https_pool.request("GET", "/") assert r.status == 200 assert warn.called
def test_verified(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_REQUIRED') conn = https_pool._new_conn() self.assertEqual(conn.__class__, VerifiedHTTPSConnection) self.assertRaises(SSLError, https_pool.request, 'GET', '/') https_pool.ca_certs = DEFAULT_CA_BAD try: https_pool.request('GET', '/') self.fail("Didn't raise SSL error with wrong CA") except SSLError as e: self.assertTrue( 'certificate verify failed' in str(e), "Expected 'certificate verify failed'," "instead got: %r" % e) https_pool.ca_certs = DEFAULT_CA https_pool.request('GET', '/') # Should succeed without exceptions. https_fail_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED') https_fail_pool.ca_certs = DEFAULT_CA try: https_fail_pool.request('GET', '/') self.fail("Didn't raise SSL invalid common name") except SSLError as e: self.assertTrue("doesn't match" in str(e))
def test_https_connect_timeout(self): url = '/' host, port = self.host, self.port timeout = Timeout(connect=SHORT_TIMEOUT) # Pool-global timeout pool = HTTPSConnectionPool(host, port, timeout=timeout) conn = pool._get_conn() exc = ReadTimeoutError # Until we fix it to be ConnectTimeoutError pos = 0 # Will be 1 once we fix ConnectTimeoutError with self.assertRaises(exc) as cmgr: pool._make_request(conn, 'GET', url) self.assertEqual(cmgr.exception.args[pos].split()[-1], 'timeout=%s)' % timeout.connect_timeout) # Retries retries = Retry(connect=0) self.assertRaises(MaxRetryError, pool.request, 'GET', url, retries=retries, timeout=timeout) # Request-specific connection timeouts timeout2 = Timeout(read=LONG_TIMEOUT, connect=SHORT_TIMEOUT / 100) pool = HTTPSConnectionPool(host, port, timeout=timeout2, retries=False) conn = pool._get_conn() with self.assertRaises(exc) as cmgr: pool._make_request(conn, 'GET', url, timeout=timeout2) self.assertEqual(cmgr.exception.args[pos].split()[-1], 'timeout=%s)' % timeout2.connect_timeout) pool._put_conn(conn) timeout = Timeout(connect=SHORT_TIMEOUT) with self.assertRaises(exc) as cmgr: pool.request('GET', url, timeout=timeout) self.assertEqual(cmgr.exception.args[pos].split()[-1], 'timeout=%s)' % timeout.connect_timeout)
def test_ssl_unverified_with_ca_certs(self): pool = HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_NONE', ca_certs=DEFAULT_CA_BAD) with mock.patch('warnings.warn') as warn: r = pool.request('GET', '/') self.assertEqual(r.status, 200) self.assertTrue(warn.called) call, = warn.call_args_list category = call[0][1] self.assertEqual(category, InsecureRequestWarning)
class TestHTTPS_TLSv1(HTTPSDummyServerTestCase): certs = DEFAULT_CERTS.copy() certs['ssl_version'] = ssl.PROTOCOL_TLSv1 def setUp(self): self._pool = HTTPSConnectionPool(self.host, self.port) self.addCleanup(self._pool.close) @onlyPy27OrNewerOrNonWindows def test_discards_connection_on_sslerror(self): # This test is skipped on Windows for Python 2.6 because we suspect there # is an issue with the OpenSSL for Python 2.6 on Windows. self._pool.cert_reqs = 'CERT_REQUIRED' self.assertRaises(SSLError, self._pool.request, 'GET', '/') self._pool.ca_certs = DEFAULT_CA self._pool.request('GET', '/') def test_set_cert_default_cert_required(self): conn = VerifiedHTTPSConnection(self.host, self.port) conn.set_cert(ca_certs=DEFAULT_CA) self.assertEqual(conn.cert_reqs, 'CERT_REQUIRED')
def test_can_validate_ip_san(self): """Ensure that urllib3 can validate SANs with IP addresses in them.""" try: import ipaddress # noqa: F401 except ImportError: pytest.skip("Only runs on systems with an ipaddress module") https_pool = HTTPSConnectionPool('127.0.0.1', self.port, cert_reqs='CERT_REQUIRED', ca_certs=DEFAULT_CA) self.addCleanup(https_pool.close) r = https_pool.request('GET', '/') self.assertEqual(r.status, 200)
def test_client_no_intermediate(self): client_cert, client_key = ( DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS['certfile'], DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS['keyfile']) https_pool = HTTPSConnectionPool(self.host, self.port, cert_file=client_cert, key_file=client_key) try: https_pool.request('GET', '/certificate', retries=False) except SSLError as e: if not ('alert unknown ca' in str(e) or 'invalid certificate chain' in str(e) or 'unknown Cert Authority' in str(e) or # https://github.com/urllib3/urllib3/issues/1422 'connection closed via error' in str(e) or 'WSAECONNRESET' in str(e)): raise except ProtocolError as e: # https://github.com/urllib3/urllib3/issues/1422 if not ('An existing connection was forcibly closed by the remote host' in str(e)): raise
def test_verified_without_ca_certs(self): # default is cert_reqs=None which is ssl.CERT_NONE https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs="CERT_REQUIRED") self.addCleanup(https_pool.close) try: https_pool.request("GET", "/") self.fail("Didn't raise SSL error with no CA certs when" "CERT_REQUIRED is set") except MaxRetryError as e: assert isinstance(e.reason, SSLError) # there is a different error message depending on whether or # not pyopenssl is injected assert ("No root certificates specified" in str(e.reason) or "certificate verify failed" in str(e.reason) or "invalid certificate chain" in str(e.reason)), ( "Expected 'No root certificates specified', " "'certificate verify failed', or " "'invalid certificate chain', " "instead got: %r" % e.reason)
def test_hostname_in_first_request_packet(self): if not util.HAS_SNI: raise SkipTest('SNI-support not available') done_receiving = Event() self.buf = b'' def socket_handler(listener): sock = listener.accept()[0] self.buf = sock.recv(65536) # We only accept one packet done_receiving.set() # let the test know it can proceed self._start_server(socket_handler) pool = HTTPSConnectionPool(self.host, self.port) try: pool.request('GET', '/', retries=0) except SSLError: # We are violating the protocol pass done_receiving.wait() self.assertTrue(self.host.encode() in self.buf, "missing hostname in SSL handshake")
def test_unverified_ssl(self): """ Test that bare HTTPSConnection can connect, make requests """ pool = HTTPSConnectionPool(self.host, self.port) pool.ConnectionCls = UnverifiedHTTPSConnection with mock.patch('warnings.warn') as warn: r = pool.request('GET', '/') self.assertEqual(r.status, 200) self.assertTrue(warn.called) call, = warn.call_args_list category = call[0][1] self.assertEqual(category, InsecureRequestWarning)
def test_client_key_password(self): client_cert, client_key = ( DEFAULT_CLIENT_CERTS['certfile'], PASSWORD_CLIENT_KEYFILE, ) https_pool = HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA, key_file=client_key, cert_file=client_cert, key_password="******") r = https_pool.request('GET', '/certificate') subject = json.loads(r.data.decode('utf-8')) assert subject['organizationalUnitName'].startswith( 'Testing server cert')
def test_ca_dir_verified(self): https_pool = HTTPSConnectionPool(self.host, self.port, cert_reqs="CERT_REQUIRED", ca_cert_dir=DEFAULT_CA_DIR) self.addCleanup(https_pool.close) conn = https_pool._new_conn() assert conn.__class__ == VerifiedHTTPSConnection with mock.patch("warnings.warn") as warn: r = https_pool.request("GET", "/") assert r.status == 200 assert not warn.called, warn.call_args_list
def test_can_validate_ipv6_san(self): """Ensure that urllib3 can validate SANs with IPv6 addresses in them.""" try: import ipaddress # noqa: F401 except ImportError: pytest.skip("Only runs on systems with an ipaddress module") https_pool = HTTPSConnectionPool("[::1]", self.port, cert_reqs="CERT_REQUIRED", ca_certs=IPV6_SAN_CA) self.addCleanup(https_pool.close) r = https_pool.request("GET", "/") assert r.status == 200
def test_reuse_conn(self): # Test pool.request() connection reusal: # 1. Create a new connection. # 2. Perform a request which will succeed. # 3. Reuse the connection - delay the response with original pool settings. # 4. Reuse same connection for a successful read request with delay in response. # 5. Reuse same connection for a timeout read request. # Create the connection pool with default timeouts long enough to connect and read. self.set_block_response(None) timeout = Timeout(connect=1., read=4) headers = make_headers(keep_alive=True) pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, headers=headers, retries=False) # First request - direct with pool._make_request() with delay=conn_timeout+read_timeout-0.5 delay = timeout.connect_timeout + timeout.read_timeout - 0.5 self.set_block_response(delay) conn = pool._get_conn() self.assertIsNone(conn.sock) pool._make_request(conn, 'GET', '/') self.set_block_response(None) # Make a request - it must succeed pool.request('GET', '/') # Reuse the connection - successful read request with delayed response. # * Ensure that new connection is not created by using a short connect timeout with # pool._make_request. # * Use a read timeout which will be larger than the pool's connect timeout but shorter # than the pool's read timeout timeout = Timeout(connect=SHORT_TIMEOUT, read=2.5) delay = 1.1 # Check that the timeouts are as intended self.assertLess(timeout.connect_timeout, pool.timeout.connect_timeout) self.assertLess(pool.timeout.connect_timeout, delay) self.assertLess(delay, timeout.read_timeout) self.assertLess(timeout.read_timeout, pool.timeout.read_timeout) # Make the request self.set_block_response(delay) pool.request('GET', '/', timeout=timeout) # Reuse the connection - timeout read request delay = timeout.read_timeout + 1 self.set_block_response(delay) now = time.time() with self.assertRaises(ReadTimeoutError) as cmgr: pool.request('GET', '/', timeout=timeout) delta = time.time() - now self.assertEqual(cmgr.exception.args[0].split()[-1], 'timeout=%s)' % timeout.read_timeout) self.assertAlmostEqual(delta, timeout.read_timeout, places=1) print('delta={}'.format(delta))
def test_unverified_ssl(self): """ Test that bare HTTPSConnection can connect, make requests """ pool = HTTPSConnectionPool(self.host, self.port) self.addCleanup(pool.close) with mock.patch('warnings.warn') as warn: r = pool.request('GET', '/') self.assertEqual(r.status, 200) self.assertTrue(warn.called) # Modern versions of Python, or systems using PyOpenSSL, only emit # the unverified warning. Older systems may also emit other # warnings, which we want to ignore here. calls = warn.call_args_list self.assertIn(InsecureRequestWarning, [x[0][1] for x in calls])
class TestHTTPS_TLSv1(HTTPSDummyServerTestCase): certs = DEFAULT_CERTS.copy() certs['ssl_version'] = ssl.PROTOCOL_TLSv1 def setUp(self): self._pool = HTTPSConnectionPool(self.host, self.port) def test_set_ssl_version_to_sslv3(self): self._pool.ssl_version = ssl.PROTOCOL_SSLv3 self.assertRaises(SSLError, self._pool.request, 'GET', '/') def test_ssl_version_as_string(self): self._pool.ssl_version = 'PROTOCOL_SSLv3' self.assertRaises(SSLError, self._pool.request, 'GET', '/') def test_ssl_version_as_short_string(self): self._pool.ssl_version = 'SSLv3' self.assertRaises(SSLError, self._pool.request, 'GET', '/') def test_discards_connection_on_sslerror(self): self._pool.cert_reqs = 'CERT_REQUIRED' self.assertRaises(SSLError, self._pool.request, 'GET', '/') self._pool.ca_certs = DEFAULT_CA self._pool.request('GET', '/')