def test_via_direct_connection_but_server_rejected_connection(self): # Given a server location for a server that's offline server_location = ServerNetworkLocation(hostname="localhost", port=1234) # When testing connectivity, it fails with the right error with pytest.raises(ServerRejectedConnection): check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), )
def test_via_direct_connection_but_server_tls_config_not_supported(self): # Given a server location for a server that only supports DH settings that SSLyze can't use server_location = ServerNetworkLocation(hostname="dh480.badssl.com", port=443) # When testing connectivity, it fails with the right error with pytest.raises(ServerTlsConfigurationNotSupported): check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), )
def test_via_direct_connection_but_server_timed_out(self): # Given a server location for a server that's offline server_location = ServerNetworkLocation( hostname="notarealdomain.not.real.notreal.not", port=1234, ip_address="123.123.123.123") # When testing connectivity, it fails with the right error with pytest.raises(ConnectionToServerTimedOut): check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), )
def test_via_http_proxy_but_proxy_rejected_connection(self): # Given a server location server_location = ServerNetworkLocation( hostname="www.google.com", port=443, # Configured with a proxy that's offline http_proxy_settings=HttpProxySettings("localhost", 1234), ) # When testing connectivity, it fails with the right error with pytest.raises(HttpProxyRejectedConnection): check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), )
def test_via_http_proxy(self): # Given an HTTP proxy proxy_port = 8123 proxy_server = ThreadingHTTPServer(("", proxy_port), ProxyHandler) proxy_server_thread = threading.Thread( target=proxy_server.serve_forever) proxy_server_thread.start() # And a server location server_location = ServerNetworkLocation( hostname="www.google.com", port=443, # Configured with this proxy http_proxy_settings=HttpProxySettings("localhost", proxy_port), ) # When testing connectivity try: tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) finally: proxy_server.shutdown() # It succeeds assert tls_probing_result.cipher_suite_supported assert tls_probing_result.highest_tls_version_supported assert tls_probing_result.client_auth_requirement # And the result can be converted to JSON tls_probing_result_as_json = _ServerTlsProbingResultAsJson.from_orm( tls_probing_result) assert tls_probing_result_as_json.json()
def test_via_http_proxy_but_proxy_rejected_http_connect(self): # Given a server location server_location = ServerNetworkLocation( hostname="www.google.com", port=443, # Configured with a proxy that is going to reject the HTTP CONNECT request http_proxy_settings=HttpProxySettings("www.hotmail.com", 443), ) # When testing connectivity, it fails with the right error with pytest.raises(HttpProxyRejectedConnection): check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), )
def test_via_http_proxy_but_proxy_timed_out(self): # Given a server location server_location = ServerNetworkLocation( hostname="www.google.com", port=443, # Configured with a proxy that will time out http_proxy_settings=HttpProxySettings("1.2.3.4", 80), ) # When testing connectivity, it fails with the right error with pytest.raises(ConnectionToHttpProxyTimedOut): check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), )
def test_via_http_proxy_but_proxy_dns_error(self): # Given a server location server_location = ServerNetworkLocation( hostname="www.google.com", port=443, # Configured with a proxy that cannot be looked up via DNS http_proxy_settings=HttpProxySettings( "notarealdomain.not.real.notreal.not", 443), ) # When testing connectivity, it fails with the right error with pytest.raises(ConnectionToHttpProxyFailed): check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), )
def test_xmpp_but_server_rejected_opportunistic_tls(self): # Given an XMPP server hostname = "jabber.org" server_location = ServerNetworkLocation(hostname=hostname, port=5222) network_configuration = ServerNetworkConfiguration( # But we provide a wrong XMPP setting xmpp_to_hostname="lol.lol", tls_server_name_indication=hostname, tls_opportunistic_encryption=ProtocolWithOpportunisticTlsEnum.XMPP, ) # When testing connectivity, it fails with the right error with pytest.raises(ServerRejectedOpportunisticTlsNegotiation): check_connectivity_to_server( server_location=server_location, network_configuration=network_configuration, )
def test_server_triggers_unexpected_connection_error(self): # Test for https://github.com/nabla-c0d3/sslyze/issues/430 # Given a server that will trigger an unexpected / non-normal error during connectivity testing with LegacyOpenSslServer( # We test this behavior using the following error: the server requires the right SNI to be sent... require_server_name_indication_value="server.com") as server: server_location = ServerNetworkLocation( # ... but SSLyze will send a different value for SNI hostname="not_the_right_value.com", ip_address=server.ip_address, port=server.port, ) # When testing connectivity against it # It fails and return the generic "connection failed" error, instead of crashing with pytest.raises(ConnectionToServerFailed) as e: check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) # And the actual error / root cause is mentioned in the message assert "unrecognized name" in e.error_message
def test_optional_client_auth(self): # Given a server that supports optional client authentication with ModernOpenSslServer( client_auth_config=ClientAuthConfigEnum.OPTIONAL) as server: server_location = ServerNetworkLocation( hostname=server.hostname, port=server.port, ip_address=server.ip_address) tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) # SSLyze correctly detects that client auth is optional assert tls_probing_result.client_auth_requirement == ClientAuthRequirementEnum.OPTIONAL
def test_required_client_auth_tls_1_3(self): # Given a TLS 1.3 server that requires client authentication with ModernOpenSslServer( client_auth_config=ClientAuthConfigEnum.REQUIRED) as server: server_location = ServerNetworkLocation( hostname=server.hostname, port=server.port, ip_address=server.ip_address) tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) # SSLyze correctly detects that client auth is required assert tls_probing_result.client_auth_requirement == ClientAuthRequirementEnum.REQUIRED
def test_ipv6(self): # Given a server accessible via IPv6 server_location = ServerNetworkLocation( hostname="www.google.com", port=443, ip_address="2607:f8b0:4005:804::2004") # When testing connectivity against it tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) # It succeeds assert tls_probing_result assert tls_probing_result.client_auth_requirement assert tls_probing_result.highest_tls_version_supported assert tls_probing_result.cipher_suite_supported
def test_tls_1_only(self): # Given a server that only supports TLS 1.0 server_location = ServerNetworkLocation(hostname="tls-v1-0.badssl.com", port=1010) # When testing connectivity against it tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) # It succeeds assert tls_probing_result assert tls_probing_result.client_auth_requirement assert tls_probing_result.cipher_suite_supported # And it detected that only TLS 1.0 is supported assert tls_probing_result.highest_tls_version_supported == TlsVersionEnum.TLS_1_0
def test_via_direct_connection(self): # Given a server location server_location = ServerNetworkLocation("www.google.com", 443) # When testing connectivity tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) # It succeeds assert tls_probing_result.cipher_suite_supported assert tls_probing_result.highest_tls_version_supported assert tls_probing_result.client_auth_requirement assert tls_probing_result.supports_ecdh_key_exchange # And the result can be converted to JSON tls_probing_result_as_json = _ServerTlsProbingResultAsJson.from_orm( tls_probing_result) assert tls_probing_result_as_json.json()
def run(self) -> None: while True: scan_request = self._scan_requests_queue_in.get(block=True) # If there are no more jobs to complete, notify the parent and shutdown the thread if isinstance(scan_request, _NoMoreWorkSentinel): self._results_queue_out.put( _NoMoreWorkSentinel()) # type: ignore self._scan_requests_queue_in.task_done() return # Otherwise process the job try: tls_probing_result = check_connectivity_to_server( server_location=scan_request.server_location, network_configuration=scan_request.network_configuration, ) self._results_queue_out.put((scan_request, tls_probing_result)) except ConnectionToServerFailed as e: self._results_queue_out.put((scan_request, e)) self._scan_requests_queue_in.task_done()
def test_international_hostname(self): # Given a server with non-ascii characters in its hostname server_location = ServerNetworkLocation(hostname="www.société.com", port=443) # When testing connectivity against it tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) # It succeeds assert tls_probing_result assert tls_probing_result.client_auth_requirement assert tls_probing_result.highest_tls_version_supported assert tls_probing_result.cipher_suite_supported # And the result can be converted to JSON tls_probing_result_as_json = _ServerTlsProbingResultAsJson.from_orm( tls_probing_result) assert tls_probing_result_as_json.json()
def test(self, hostname, port, protocol): # Given some server using a non-HTTP protocol with Opportunistic TLS server_location = ServerNetworkLocation(hostname, port) network_configuration = ServerNetworkConfiguration( tls_server_name_indication=hostname, tls_opportunistic_encryption=protocol) # When testing connectivity against it tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=network_configuration, ) # It succeeds assert tls_probing_result assert tls_probing_result.client_auth_requirement assert tls_probing_result.highest_tls_version_supported assert tls_probing_result.cipher_suite_supported # And the result can be converted to JSON tls_probing_result_as_json = _ServerTlsProbingResultAsJson.from_orm( tls_probing_result) assert tls_probing_result_as_json.json()
def test_optional_client_authentication(self): # Given a server that requires a client certificate server_location = ServerNetworkLocation(hostname="client.badssl.com", port=443) # When testing connectivity against it tls_probing_result = check_connectivity_to_server( server_location=server_location, network_configuration=ServerNetworkConfiguration. default_for_server_location(server_location), ) # It succeeds assert tls_probing_result assert tls_probing_result.highest_tls_version_supported assert tls_probing_result.cipher_suite_supported # And it detected the client authentication assert tls_probing_result.client_auth_requirement == ClientAuthRequirementEnum.OPTIONAL # And the result can be converted to JSON server_info_as_json = _ServerTlsProbingResultAsJson.from_orm( tls_probing_result) assert server_info_as_json.json()