def test_ca_file_bad_file(self):
        # Given a server to scan
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.hotmail.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When trying to enable a custom CA file but the path is wrong, it fails
        with pytest.raises(ValueError):
            CertificateInfoImplementation.scan_server(
                server_info,
                CertificateInfoExtraArguments(
                    custom_ca_file=Path("doesntexist")))
    def test_invalid_certificate_bad_name(self, certificate_name_field):
        # Given a server to scan
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.cloudflare.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # And the server has a certificate with an invalid Subject field
        with mock.patch.object(
                hazmat.backends.openssl.x509._Certificate,
                certificate_name_field,
                new_callable=PropertyMock) as mock_certificate_name:
            # https://github.com/nabla-c0d3/sslyze/issues/495
            mock_certificate_name.side_effect = ValueError(
                "Country name must be a 2 character country code")

            # When running the scan, it succeeds
            scan_result = CertificateInfoImplementation.scan_server(
                server_info)

            # And the result can be converted to console output
            result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
                scan_result)
            assert result_as_txt

            # And the result can be converted to JSON
            result_as_json = json.dumps(asdict(scan_result), cls=JsonEncoder)
            assert result_as_json
    def test_ed25519_certificate(self):
        # Given a server that is configured with an ED25519 certificate
        with ModernOpenSslServer(
                server_certificate_path=Path(__file__).parent.absolute() /
                "server-ed25519-cert.pem",
                server_key_path=Path(__file__).parent.absolute() /
                "server-ed25519-key.pem",
        ) as server:
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                port=server.port,
                ip_address=server.ip_address)
            server_info = check_connectivity_to_server_and_return_info(
                server_location)

            # When running the scan, it succeeds
            scan_result = CertificateInfoImplementation.scan_server(
                server_info)
            assert scan_result.certificate_deployments[
                0].received_certificate_chain

            # And the result can be converted to JSON
            result_as_json = CertificateInfoScanResultAsJson.from_orm(
                scan_result).json()
            assert result_as_json

            # And the result can be converted to console output
            result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
                scan_result)
            assert result_as_txt
    def test_invalid_chain(self):
        # Given a server to scan that has a self-signed certificate
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "self-signed.badssl.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # A verified chain cannot be built
        assert not plugin_result.certificate_deployments[
            0].verified_certificate_chain
        assert plugin_result.certificate_deployments[
            0].verified_chain_has_sha1_signature is None

        # And the result has other details about the certificate chain
        assert plugin_result.certificate_deployments[0].ocsp_response is None
        assert len(plugin_result.certificate_deployments[0].
                   received_certificate_chain) == 1

        assert len(plugin_result.certificate_deployments[0].
                   path_validation_results) >= 5
        for path_validation_result in plugin_result.certificate_deployments[
                0].path_validation_results:
            assert not path_validation_result.was_validation_successful

        assert plugin_result.certificate_deployments[
            0].leaf_certificate_signed_certificate_timestamps_count == 0

        assert plugin_result.certificate_deployments[
            0].leaf_certificate_subject_matches_hostname
        assert plugin_result.certificate_deployments[
            0].received_chain_has_valid_order
        assert plugin_result.certificate_deployments[
            0].received_chain_contains_anchor_certificate is None
Esempio n. 5
0
    def test_json_serializer_functions(self):
        # Given a completed scan for a server with the CERTIFICATE_INFO scan command
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.hotmail.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)
        plugin_result = CertificateInfoImplementation.perform(server_info)
        scan_results = {ScanCommandEnum.CERTIFICATE_INFO: plugin_result}
        scan_result = ServerScanResultFactory.create(
            scan_commands_results=scan_results)

        # When generating the JSON output for this server scan
        with StringIO() as file_out:
            json_generator = JsonOutputGenerator(file_to=file_out)
            json_generator.server_scan_completed(scan_result)

            # We call scans_completed() because this is when the output actually gets written to the file
            json_generator.scans_completed(0.2)
            final_output = file_out.getvalue()

        # It succeeds
        assert final_output

        # And complex object like certificates were properly serialized
        assert "notBefore" in final_output
        assert "issuer" in final_output
        assert "subject" in final_output
    def test_valid_chain_with_ev_cert(self):
        # Given a server to scan that has an EV certificate
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.digicert.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # The result returns that the certificate is EV
        assert plugin_result.certificate_deployments[0].leaf_certificate_is_ev

        # And the result has other details about the certificate chain
        assert len(plugin_result.certificate_deployments[0].
                   received_certificate_chain)
        assert len(plugin_result.certificate_deployments[0].
                   verified_certificate_chain)
        assert not plugin_result.certificate_deployments[
            0].received_chain_contains_anchor_certificate

        assert len(plugin_result.certificate_deployments[0].
                   path_validation_results) == 5
        for path_validation_result in plugin_result.certificate_deployments[
                0].path_validation_results:
            assert path_validation_result.was_validation_successful

        assert plugin_result.certificate_deployments[
            0].leaf_certificate_subject_matches_hostname
        assert plugin_result.certificate_deployments[
            0].received_chain_has_valid_order
    def test_ca_file(self):
        # Given a server to scan
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.hotmail.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # And a valid path to a custom CA file
        ca_file_path = Path(
            __file__
        ).parent / ".." / ".." / "certificates" / "wildcard-self-signed.pem"

        # When running the scan with the custom CA file enabled
        plugin_result = CertificateInfoImplementation.scan_server(
            server_info,
            CertificateInfoExtraArguments(custom_ca_file=ca_file_path))

        # It succeeds
        assert len(plugin_result.certificate_deployments[0].
                   path_validation_results) >= 6
        for path_validation_result in plugin_result.certificate_deployments[
                0].path_validation_results:
            if path_validation_result.trust_store.path == ca_file_path:
                assert not path_validation_result.was_validation_successful
            else:
                assert path_validation_result.was_validation_successful
    def test_invalid_certificate_bad_name(self, certificate_name_field):
        # Given a server to scan
        server_location = ServerNetworkLocation("www.cloudflare.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # And the server has a certificate with an invalid Subject field
        with mock.patch.object(
                cryptography.x509.Certificate,
                certificate_name_field,
                new_callable=PropertyMock) as mock_certificate_name:
            # https://github.com/nabla-c0d3/sslyze/issues/495
            mock_certificate_name.side_effect = ValueError(
                "Country name must be a 2 character country code")

            # When running the scan, it succeeds
            scan_result = CertificateInfoImplementation.scan_server(
                server_info)

            # And the result can be converted to console output
            result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
                scan_result)
            assert result_as_txt

            # And the result can be converted to JSON
            result_as_json = CertificateInfoScanResultAsJson.from_orm(
                scan_result).json()
            assert result_as_json
    def test_certificate_with_no_subject(self):
        # Given a server to scan that has a certificate with no Subject
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("no-subject.badssl.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan, it succeeds
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        assert plugin_result.certificate_deployments[0].verified_certificate_chain
    def test_multiple_certificates(self):
        # Given a server to scan that exposes multiple certificates for maximum compatibility
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("www.facebook.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan, it succeeds
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # And multiple certificates were detected
        assert len(plugin_result.certificate_deployments) > 1
    def test_certificate_with_scts(self):
        # Given a server to scan that has a certificate with SCTS
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("www.apple.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan, it succeeds
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # And the SCTS were detected
        assert plugin_result.certificate_deployments[0].leaf_certificate_signed_certificate_timestamps_count > 1
    def test_chain_with_anchor(self):
        # Given a server to scan that has its anchor certificate returned in its chain
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("www.verizon.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan, it succeeds
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # And the anchor certificate was detected
        assert plugin_result.certificate_deployments[0].received_chain_contains_anchor_certificate
    def test_sha256_chain(self):
        # Given a server to scan that has a SHA256-signed certificate
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("sha256.badssl.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # No SHA1 signature is detected
        assert not plugin_result.certificate_deployments[0].verified_chain_has_sha1_signature
Esempio n. 14
0
    def test(self):
        # Given a completed scan for a CERTIFICATE_INFO scan command
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.facebook.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # When generating the CLI output for this result, it succeeds
        result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
            plugin_result)
        assert result_as_txt
Esempio n. 15
0
    def test(self):
        # Given a completed scan for a CERTIFICATE_INFO scan command
        server_location = ServerNetworkLocation("www.facebook.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # When generating the CLI output for this result, it succeeds
        result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
            plugin_result)
        assert result_as_txt
    def test_succeeds_when_client_auth_failed(self):
        # Given a server that requires client authentication
        with ModernOpenSslServer(client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            # And the client does NOT provide a client certificate
            server_location = ServerNetworkLocationViaDirectConnection(
                hostname=server.hostname, port=server.port, ip_address=server.ip_address
            )
            server_info = ServerConnectivityTester().perform(server_location)

            # When running the scan, it succeeds
            plugin_result = CertificateInfoImplementation.scan_server(server_info)
            assert plugin_result.certificate_deployments[0].received_certificate_chain
    def test_valid_chain_with_ocsp_stapling(self):
        # Given a server to scan that supports OCSP stapling
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("www.apple.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # The result contains details about the server's OCSP config
        assert plugin_result.certificate_deployments[0].ocsp_response
        assert plugin_result.certificate_deployments[0].ocsp_response.status == OcspResponseStatusEnum.SUCCESSFUL
        assert plugin_result.certificate_deployments[0].ocsp_response_is_trusted
        assert not plugin_result.certificate_deployments[0].leaf_certificate_has_must_staple_extension
Esempio n. 18
0
    def test_ecdsa_certificate(self):
        # Given a server to scan that has an ECDSA certificate
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.cloudflare.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan, it succeeds
        scan_result = CertificateInfoImplementation.scan_server(server_info)

        # And the result can be converted to JSON
        result_as_json = json.dumps(asdict(scan_result), cls=JsonEncoder)
        assert result_as_json

        # And the result can be converted to console output
        result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
            scan_result)
        assert result_as_txt
Esempio n. 19
0
    def test(self):
        # Given a completed scan for a server with the CERTIFICATE_INFO scan command
        server_location = ServerNetworkLocation("www.facebook.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # When converting it to JSON
        result_as_json = CertificateInfoScanResultAsJson.from_orm(
            plugin_result).json()

        # It succeeds
        assert result_as_json

        # And complex object like certificates were properly serialized
        assert "issuer" in result_as_json
        assert "subject" in result_as_json
    def test_not_trusted_by_mozilla_but_trusted_by_microsoft(self):
        # Given a server to scan that has a certificate chain valid for the Microsoft but not the Mozilla trust stores
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "webmail.russia.nasa.gov", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan, it succeeds
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # And the chain was correctly identified as valid with the Microsoft store
        found_microsoft_store = False
        for validation_result in plugin_result.certificate_deployments[
                0].path_validation_results:
            if validation_result.trust_store.name == "Windows":
                found_microsoft_store = True
                assert validation_result.was_validation_successful
                break
        assert found_microsoft_store
    def test_ecdsa_certificate(self):
        # Given a server to scan that has an ECDSA certificate
        server_location = ServerNetworkLocation("www.cloudflare.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When running the scan, it succeeds
        scan_result = CertificateInfoImplementation.scan_server(server_info)

        # And the result can be converted to JSON
        result_as_json = CertificateInfoScanResultAsJson.from_orm(
            scan_result).json()
        assert result_as_json

        # And the result can be converted to console output
        result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
            scan_result)
        assert result_as_txt
Esempio n. 22
0
    def test(self):
        # Given a completed scan for a server with the CERTIFICATE_INFO scan command
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.facebook.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)
        plugin_result = CertificateInfoImplementation.scan_server(server_info)
        scan_results = {ScanCommand.CERTIFICATE_INFO: plugin_result}
        scan_result = ServerScanResultFactory.create(
            scan_commands_results=scan_results)

        # When converting it into to JSON
        result_as_json = json.dumps(asdict(scan_result),
                                    cls=sslyze.JsonEncoder)

        # It succeeds
        assert result_as_json

        # And complex object like certificates were properly serialized
        assert "issuer" in result_as_json
        assert "subject" in result_as_json
Esempio n. 23
0
    def test_rsa_certificate(self):
        # Given a server that is configured with an RSA certificate
        with ModernOpenSslServer() as server:
            server_location = ServerNetworkLocationViaDirectConnection(
                hostname=server.hostname,
                port=server.port,
                ip_address=server.ip_address)
            server_info = ServerConnectivityTester().perform(server_location)

            # When running the scan, it succeeds
            scan_result = CertificateInfoImplementation.scan_server(
                server_info)
            assert scan_result.certificate_deployments[
                0].received_certificate_chain

            # And the result can be converted to JSON
            result_as_json = json.dumps(asdict(scan_result), cls=JsonEncoder)
            assert result_as_json

            # And the result can be converted to console output
            result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
                scan_result)
            assert result_as_txt