def test_ssl_wrap_socket_loads_verify_locations(self): socket = object() mock_context = Mock() ssl_wrap_socket(ssl_context=mock_context, ca_certs="/path/to/pem", sock=socket) mock_context.load_verify_locations.assert_called_once_with( "/path/to/pem", None, None )
def test_ssl_wrap_socket_loads_certificate_directories(self): socket = object() mock_context = Mock() ssl_wrap_socket(ssl_context=mock_context, ca_cert_dir='/path/to/pems', sock=socket) mock_context.load_verify_locations.assert_called_once_with( None, '/path/to/pems')
def test_ssl_wrap_socket_creates_new_context(self, create_urllib3_context): socket = object() ssl_wrap_socket(sock=socket, cert_reqs="CERT_REQUIRED") create_urllib3_context.assert_called_once_with(None, "CERT_REQUIRED", ciphers=None)
def test_ssl_wrap_socket_loads_verify_locations(self): socket = object() mock_context = Mock() ssl_wrap_socket(ssl_context=mock_context, ca_certs='/path/to/pem', sock=socket) mock_context.load_verify_locations.assert_called_once_with( '/path/to/pem', None)
def test_ssl_wrap_socket_loads_the_cert_chain(self): socket = object() mock_context = Mock() ssl_wrap_socket( ssl_context=mock_context, sock=socket, certfile="/path/to/certfile" ) mock_context.load_cert_chain.assert_called_once_with("/path/to/certfile", None)
def test_ssl_wrap_socket_creates_new_context(self, create_urllib3_context): socket = object() ssl_wrap_socket(sock=socket, cert_reqs='CERT_REQUIRED') create_urllib3_context.assert_called_once_with( None, 'CERT_REQUIRED', ciphers=None )
def test_ssl_wrap_socket_loads_certificate_directories(self): socket = object() mock_context = Mock() ssl_wrap_socket(ssl_context=mock_context, ca_cert_dir="/path/to/pems", sock=socket) mock_context.load_verify_locations.assert_called_once_with( None, "/path/to/pems", None)
def test_ssl_wrap_socket_loads_certificate_data(self): socket = object() mock_context = Mock() ssl_wrap_socket(ssl_context=mock_context, ca_cert_data="TOTALLY PEM DATA", sock=socket) mock_context.load_verify_locations.assert_called_once_with( None, None, "TOTALLY PEM DATA")
def test_wrap_socket_given_context_no_load_default_certs(): context = mock.create_autospec(ssl_.SSLContext) context.load_default_certs = mock.Mock() sock = mock.Mock() ssl_.ssl_wrap_socket(sock, ssl_context=context) context.load_default_certs.assert_not_called()
def test_ssl_wrap_socket_loads_the_cert_chain(self): socket = object() mock_context = Mock() ssl_wrap_socket(ssl_context=mock_context, sock=socket, certfile='/path/to/certfile') mock_context.load_cert_chain.assert_called_once_with( '/path/to/certfile', None)
def test_ssl_wrap_socket_with_no_sni(self): socket = object() mock_context = Mock() # Ugly preservation of original value HAS_SNI = ssl_.HAS_SNI ssl_.HAS_SNI = False ssl_wrap_socket(ssl_context=mock_context, sock=socket) mock_context.wrap_socket.assert_called_once_with(socket) ssl_.HAS_SNI = HAS_SNI
def _wrap_socket_and_mock_warn(self, sock, server_hostname): mock_context = Mock() with patch("warnings.warn") as warn: ssl_wrap_socket( ssl_context=mock_context, sock=sock, server_hostname=server_hostname, ) return mock_context, warn
def test_wrap_socket_default_loads_default_certs(monkeypatch): context = mock.create_autospec(ssl_.SSLContext) context.load_default_certs = mock.Mock() context.options = 0 monkeypatch.setattr(ssl_, "SSLContext", lambda *_, **__: context) sock = mock.Mock() ssl_.ssl_wrap_socket(sock) context.load_default_certs.assert_called_with()
def _wrap_socket_and_mock_warn( self, sock: socket.socket, server_hostname: Optional[str]) -> Tuple[Mock, MagicMock]: mock_context = Mock() with patch("warnings.warn") as warn: ssl_wrap_socket( ssl_context=mock_context, sock=sock, server_hostname=server_hostname, ) return mock_context, warn
def test_wrap_socket_given_ca_certs_no_load_default_certs(monkeypatch): context = mock.create_autospec(ssl_.SSLContext) context.load_default_certs = mock.Mock() context.options = 0 monkeypatch.setattr(ssl_, "SSLContext", lambda *_, **__: context) sock = mock.Mock() ssl_.ssl_wrap_socket(sock, ca_certs="/tmp/fake-file") context.load_default_certs.assert_not_called() context.load_verify_locations.assert_called_with("/tmp/fake-file", None)
def test_context_sni_with_ip_address(monkeypatch, has_sni, server_hostname, uses_sni): monkeypatch.setattr(ssl_, "HAS_SNI", has_sni) sock = mock.Mock() context = mock.create_autospec(ssl_.SSLContext) ssl_.ssl_wrap_socket(sock, server_hostname=server_hostname, ssl_context=context) if uses_sni: context.wrap_socket.assert_called_with(sock, server_hostname=server_hostname) else: context.wrap_socket.assert_called_with(sock)
def test_context_sni_with_ip_address(monkeypatch, has_sni, server_hostname, uses_sni): monkeypatch.setattr(ssl_, 'HAS_SNI', has_sni) sock = mock.Mock() context = mock.create_autospec(ssl_.SSLContext) ssl_.ssl_wrap_socket(sock, server_hostname=server_hostname, ssl_context=context) if uses_sni: context.wrap_socket.assert_called_with(sock, server_hostname=server_hostname) else: context.wrap_socket.assert_called_with(sock)
def test_ssl_wrap_socket_with_no_sni_warns(self): socket = object() mock_context = Mock() # Ugly preservation of original value HAS_SNI = ssl_.HAS_SNI ssl_.HAS_SNI = False with patch('warnings.warn') as warn: ssl_wrap_socket(ssl_context=mock_context, sock=socket) mock_context.wrap_socket.assert_called_once_with(socket) ssl_.HAS_SNI = HAS_SNI self.assertTrue(warn.call_count >= 1) warnings = [call[0][1] for call in warn.call_args_list] self.assertTrue(SNIMissingWarning in warnings)
def test_wrap_socket_given_ca_certs_no_load_default_certs(monkeypatch): if platform.python_implementation() == "PyPy" and sys.version_info[0] == 2: # https://github.com/testing-cabal/mock/issues/438 pytest.xfail("fails with PyPy for Python 2 dues to funcsigs bug") context = mock.create_autospec(ssl_.SSLContext) context.load_default_certs = mock.Mock() context.options = 0 monkeypatch.setattr(ssl_, "SSLContext", lambda *_, **__: context) sock = mock.Mock() ssl_.ssl_wrap_socket(sock, ca_certs="/tmp/fake-file") context.load_default_certs.assert_not_called() context.load_verify_locations.assert_called_with("/tmp/fake-file", None)
def test_sni_missing_warning_with_ip_addresses(monkeypatch, has_sni, server_hostname, should_warn): monkeypatch.setattr(ssl_, 'HAS_SNI', has_sni) sock = mock.Mock() context = mock.create_autospec(ssl_.SSLContext) with mock.patch('warnings.warn') as warn: ssl_.ssl_wrap_socket(sock, server_hostname=server_hostname, ssl_context=context) if should_warn: assert warn.call_count >= 1 warnings = [call[0][1] for call in warn.call_args_list] assert SNIMissingWarning in warnings else: assert warn.call_count == 0
def supported_tls_versions(): # We have to create an actual TLS connection # to test if the TLS version is not disabled by # OpenSSL config. Ubuntu 20.04 specifically # disables TLSv1 and TLSv1.1. tls_versions = set() _server = HTTPSDummyServerTestCase() _server._start_server() for _ssl_version_name in ( "PROTOCOL_TLSv1", "PROTOCOL_TLSv1_1", "PROTOCOL_TLSv1_2", "PROTOCOL_TLS", ): _ssl_version = getattr(ssl, _ssl_version_name, 0) if _ssl_version == 0: continue _sock = socket.create_connection((_server.host, _server.port)) try: _sock = ssl_.ssl_wrap_socket(_sock, cert_reqs=ssl.CERT_NONE, ssl_version=_ssl_version) except ssl.SSLError: pass else: tls_versions.add(_sock.version()) _sock.close() _server._stop_server() return tls_versions
def test_ssl_wrap_socket_with_no_sni_warns(self): socket = object() mock_context = Mock() # Ugly preservation of original value HAS_SNI = ssl_.HAS_SNI ssl_.HAS_SNI = False try: with patch('warnings.warn') as warn: ssl_wrap_socket(ssl_context=mock_context, sock=socket, server_hostname='www.google.com') mock_context.wrap_socket.assert_called_once_with(socket) assert warn.call_count >= 1 warnings = [call[0][1] for call in warn.call_args_list] assert SNIMissingWarning in warnings finally: ssl_.HAS_SNI = HAS_SNI
def connect(self): # Add certificate verification conn = self._new_conn() resolved_cert_reqs = ssl_.resolve_cert_reqs(self.cert_reqs) resolved_ssl_version = ssl_.resolve_ssl_version(self.ssl_version) hostname = self.host if getattr(self, '_tunnel_host', None): # _tunnel_host was added in Python 2.6.3 # (See: # http://hg.python.org/cpython/rev/0f57b30a152f) # # However this check is still necessary in 2.7.x self.sock = conn # Calls self._set_hostport(), so self.host is # self._tunnel_host below. self._tunnel() # Mark this connection as not reusable self.auto_open = 0 # Override the host with the one we're requesting data from. hostname = self._tunnel_host # Wrap socket using verification with the root certs in trusted_root_certs self.sock = ssl_.ssl_wrap_socket( conn, self.key_file, self.cert_file, cert_reqs=resolved_cert_reqs, ca_certs=self.ca_certs, server_hostname=hostname, ssl_version=resolved_ssl_version, ciphers=self.ciphers, ) if self.assert_fingerprint: ssl_.assert_fingerprint(self.sock.getpeercert(binary_form=True), self.assert_fingerprint) elif resolved_cert_reqs != ssl.CERT_NONE and self.assert_hostname is not False: cert = self.sock.getpeercert() if not cert.get('subjectAltName', ()): warnings.warn( ('Certificate has no `subjectAltName`, falling back to check for a `commonName` for now. ' 'This feature is being removed by major browsers and deprecated by RFC 2818. ' '(See https://github.com/shazow/urllib3/issues/497 for details.)' ), SecurityWarning, ) match_hostname(cert, self.assert_hostname or hostname) self.is_verified = resolved_cert_reqs == ssl.CERT_REQUIRED or self.assert_fingerprint is not None
def test_sni_missing_warning_with_ip_addresses( self, monkeypatch: pytest.MonkeyPatch, has_sni: bool, server_hostname: Optional[str], should_warn: bool, ) -> None: monkeypatch.setattr(ssl_, "HAS_SNI", has_sni) sock = mock.Mock() context = mock.create_autospec(ssl_.SSLContext) with mock.patch("warnings.warn") as warn: ssl_.ssl_wrap_socket(sock, server_hostname=server_hostname, ssl_context=context) if should_warn: assert warn.call_count >= 1 warnings = [call[0][1] for call in warn.call_args_list] assert SNIMissingWarning in warnings else: assert warn.call_count == 0
def connect(self): conn = self._new_conn() self._prepare_conn(conn) if self.ssl_context is None: self.ssl_context = create_urllib3_context( ssl_version=resolve_ssl_version(None), cert_reqs=resolve_cert_reqs(None), ) self.sock = ssl_wrap_socket(sock=conn, keyfile=self.key_file, certfile=self.cert_file, ssl_context=self.ssl_context, server_hostname=self.server_hostname)
def connect(self): # Add certificate verification conn = self._new_conn() hostname = self.host if self._tunnel_host: self.sock = conn # Calls self._set_hostport(), so self.host is # self._tunnel_host below. self._tunnel() # Mark this connection as not reusable self.auto_open = 0 # Override the host with the one we're requesting data from. hostname = self._tunnel_host server_hostname = hostname if self.server_hostname is not None: server_hostname = self.server_hostname is_time_off = datetime.date.today() < RECENT_DATE if is_time_off: warnings.warn( ('System time is way off (before {0}). This will probably ' 'lead to SSL verification errors').format(RECENT_DATE), SystemTimeWarning) # Wrap socket using verification with the root certs in # trusted_root_certs if self.ssl_context is None: self.ssl_context = create_urllib3_context( ssl_version=resolve_ssl_version(self.ssl_version), cert_reqs=resolve_cert_reqs(self.cert_reqs), ) context = self.ssl_context context.verify_mode = resolve_cert_reqs(self.cert_reqs) self.sock = ssl_wrap_socket(sock=conn, keyfile=self.key_file, certfile=self.cert_file, ca_certs=self.ca_certs, ca_cert_dir=self.ca_cert_dir, server_hostname=server_hostname, ssl_context=context) if self.assert_fingerprint: assert_fingerprint(self.sock.getpeercert(binary_form=True), self.assert_fingerprint) elif context.verify_mode != ssl.CERT_NONE \ and not getattr(context, 'check_hostname', False) \ and self.assert_hostname is not False: # While urllib3 attempts to always turn off hostname matching from # the TLS library, this cannot always be done. So we check whether # the TLS Library still thinks it's matching hostnames. cert = self.sock.getpeercert() if not cert.get('subjectAltName', ()): warnings.warn(( 'Certificate for {0} has no `subjectAltName`, falling back to check for a ' '`commonName` for now. This feature is being removed by major browsers and ' 'deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 ' 'for details.)'.format(hostname)), SubjectAltNameWarning) _match_hostname(cert, self.assert_hostname or server_hostname) self.is_verified = (context.verify_mode == ssl.CERT_REQUIRED or self.assert_fingerprint is not None)
def test_wrap_socket_no_ssltransport(self) -> None: with mock.patch("urllib3.util.ssl_.SSLTransport", None): with pytest.raises(ProxySchemeUnsupported): sock = mock.Mock() ssl_.ssl_wrap_socket(sock, tls_in_tls=True)
def test_ssl_wrap_socket_creates_new_context( self, create_urllib3_context: mock.MagicMock) -> None: socket = Mock() ssl_wrap_socket(socket, cert_reqs=ssl.CERT_REQUIRED) create_urllib3_context.assert_called_once_with(None, 2, ciphers=None)