class ClientAuthenticationTestCase(unittest.TestCase):
    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_optional_client_auth(self):
        # Given a server that supports optional client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                OPTIONAL) as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

        # SSLyze correctly detects that client auth is optional
        self.assertEqual(server_info.client_auth_requirement,
                         ClientAuthenticationServerConfigurationEnum.OPTIONAL)

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_required_client_auth(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

        # SSLyze correctly detects that client auth is required
        self.assertEqual(server_info.client_auth_requirement,
                         ClientAuthenticationServerConfigurationEnum.REQUIRED)
Esempio n. 2
0
class HeartbleedPluginTestCase(unittest.TestCase):

    def test_heartbleed_good(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = HeartbleedPlugin()
        plugin_result = plugin.process_task(server_info, HeartbleedScanCommand())

        self.assertFalse(plugin_result.is_vulnerable_to_heartbleed)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(), 'Not on Linux 64')
    def test_heartbleed_bad(self):
        with VulnerableOpenSslServer() as server:
            server_test = ServerConnectivityTester(hostname=server.hostname, ip_address=server.ip_address,
                                                 port=server.port)
            server_info = server_test.perform()

            plugin = HeartbleedPlugin()
            plugin_result = plugin.process_task(server_info, HeartbleedScanCommand())

        self.assertTrue(plugin_result.is_vulnerable_to_heartbleed)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(), 'Not on Linux 64')
    def test_succeeds_when_client_auth_failed(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.REQUIRED
        ) as server:
            # And the client does NOT provide a client certificate
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port
            )
            server_info = server_test.perform()

            # The plugin works even when a client cert was not supplied
            plugin = HeartbleedPlugin()
            plugin_result = plugin.process_task(server_info, HeartbleedScanCommand())

        self.assertTrue(plugin_result.is_vulnerable_to_heartbleed)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
class OpenSslCcsInjectionPluginTestCase(unittest.TestCase):
    def test_ccs_injection_good(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCcsInjectionPlugin()
        plugin_result = plugin.process_task(server_info,
                                            OpenSslCcsInjectionScanCommand())

        self.assertFalse(plugin_result.is_vulnerable_to_ccs_injection)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_ccs_injection_bad(self):
        with VulnerableOpenSslServer() as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            plugin = OpenSslCcsInjectionPlugin()
            plugin_result = plugin.process_task(
                server_info, OpenSslCcsInjectionScanCommand())

        self.assertTrue(plugin_result.is_vulnerable_to_ccs_injection)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_succeeds_when_client_auth_failed(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client does NOT provide a client certificate
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            # OpenSslCcsInjectionPlugin works even when a client cert was not supplied
            plugin = OpenSslCcsInjectionPlugin()
            plugin_result = plugin.process_task(
                server_info, OpenSslCcsInjectionScanCommand())

        self.assertTrue(plugin_result.is_vulnerable_to_ccs_injection)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Esempio n. 4
0
class RobotPluginPluginTestCase(unittest.TestCase):
    def test_robot_attack_good(self):
        # Validate the bug fix for https://github.com/nabla-c0d3/sslyze/issues/282
        server_test = ServerConnectivityTester(hostname='guide.duo.com')
        server_info = server_test.perform()

        plugin = RobotPlugin()
        plugin_result = plugin.process_task(server_info, RobotScanCommand())

        # On Travis CI we sometimes get inconsistent results
        if IS_RUNNING_ON_TRAVIS:
            self.assertIn(plugin_result.robot_result_enum, [
                RobotScanResultEnum.NOT_VULNERABLE_NO_ORACLE,
                RobotScanResultEnum.UNKNOWN_INCONSISTENT_RESULTS
            ])
        else:
            self.assertEqual(plugin_result.robot_result_enum,
                             RobotScanResultEnum.NOT_VULNERABLE_NO_ORACLE)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

    @unittest.skip('Not implemented')
    def test_robot_attack_bad(self):
        # TODO(AD): Find a vulnerable server?
        pass

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_fails_when_client_auth_failed(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client does NOT provide a client certificate
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            # The plugin fails when a client cert was not supplied
            plugin = RobotPlugin()
            with self.assertRaises(ClientCertificateRequested):
                plugin.process_task(server_info, RobotScanCommand())
Esempio n. 5
0
class SessionRenegotiationPluginTestCase(unittest.TestCase):
    def test_renegotiation_good(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = SessionRenegotiationPlugin()
        plugin_result = plugin.process_task(server_info,
                                            SessionRenegotiationScanCommand())

        self.assertFalse(plugin_result.accepts_client_renegotiation)
        self.assertTrue(plugin_result.supports_secure_renegotiation)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_fails_when_client_auth_failed_session(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client does NOT provide a client certificate
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            # The plugin fails when a client cert was not supplied
            plugin = SessionRenegotiationPlugin()
            with self.assertRaises(ClientCertificateRequested):
                plugin.process_task(server_info,
                                    SessionRenegotiationScanCommand())

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_works_when_client_auth_succeeded(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client provides a client certificate
            client_creds = ClientAuthenticationCredentials(
                client_certificate_chain_path=server.
                get_client_certificate_path(),
                client_key_path=server.get_client_key_path(),
            )

            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port,
                client_auth_credentials=client_creds,
            )
            server_info = server_test.perform()

            # The plugin works fine
            plugin = SessionRenegotiationPlugin()
            plugin_result = plugin.process_task(
                server_info, SessionRenegotiationScanCommand())

        self.assertTrue(plugin_result.accepts_client_renegotiation)
        self.assertTrue(plugin_result.supports_secure_renegotiation)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
class OpenSslCipherSuitesPluginTestCase(unittest.TestCase):
    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_sslv2_enabled(self):
        with VulnerableOpenSslServer() as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            plugin = OpenSslCipherSuitesPlugin()
            plugin_result = plugin.process_task(server_info,
                                                Sslv20ScanCommand())

        # The embedded server does not have a preference
        self.assertFalse(plugin_result.preferred_cipher)

        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {
                'SSL_CK_RC4_128_EXPORT40_WITH_MD5',
                'SSL_CK_IDEA_128_CBC_WITH_MD5',
                'SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5',
                'SSL_CK_DES_192_EDE3_CBC_WITH_MD5',
                'SSL_CK_DES_192_EDE3_CBC_WITH_MD5', 'SSL_CK_RC4_128_WITH_MD5',
                'SSL_CK_RC2_128_CBC_WITH_MD5', 'SSL_CK_DES_64_CBC_WITH_MD5'
            }, set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.accepted_cipher_list)
        self.assertFalse(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_sslv2_disabled(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Sslv20ScanCommand())

        self.assertIsNone(plugin_result.preferred_cipher)
        self.assertFalse(plugin_result.accepted_cipher_list)
        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_sslv3_enabled(self):
        with VulnerableOpenSslServer() as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            plugin = OpenSslCipherSuitesPlugin()
            plugin_result = plugin.process_task(server_info,
                                                Sslv30ScanCommand())

        # The embedded server does not have a preference
        self.assertFalse(plugin_result.preferred_cipher)
        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {
                'TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA',
                'TLS_RSA_WITH_3DES_EDE_CBC_SHA',
                'TLS_DH_anon_WITH_AES_128_CBC_SHA',
                'TLS_ECDH_anon_WITH_AES_128_CBC_SHA',
                'TLS_DH_anon_WITH_SEED_CBC_SHA',
                'TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5',
                'TLS_ECDHE_RSA_WITH_NULL_SHA',
                'TLS_ECDHE_RSA_WITH_RC4_128_SHA',
                'TLS_DH_anon_WITH_AES_256_CBC_SHA',
                'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA',
                'TLS_ECDH_anon_WITH_RC4_128_SHA',
                'TLS_DH_anon_WITH_3DES_EDE_CBC_SHA',
                'TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA',
                'TLS_DH_anon_EXPORT_WITH_RC4_40_MD5',
                'TLS_RSA_EXPORT_WITH_DES40_CBC_SHA',
                'TLS_ECDH_anon_WITH_NULL_SHA',
                'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA',
                'TLS_RSA_WITH_RC4_128_SHA', 'TLS_RSA_EXPORT_WITH_RC4_40_MD5',
                'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', 'TLS_RSA_WITH_NULL_MD5',
                'TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA',
                'TLS_DH_anon_WITH_DES_CBC_SHA', 'TLS_RSA_WITH_SEED_CBC_SHA',
                'TLS_RSA_WITH_DES_CBC_SHA',
                'TLS_ECDH_anon_WITH_AES_256_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA',
                'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA',
                'TLS_RSA_WITH_AES_256_CBC_SHA', 'TLS_RSA_WITH_RC4_128_MD5',
                'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', 'TLS_RSA_WITH_NULL_SHA',
                'TLS_RSA_WITH_IDEA_CBC_SHA', 'TLS_RSA_WITH_AES_128_CBC_SHA',
                'TLS_DH_anon_WITH_RC4_128_MD5'
            }, set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.accepted_cipher_list)
        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_sslv3_disabled(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Sslv30ScanCommand())

        self.assertIsNone(plugin_result.preferred_cipher)
        self.assertFalse(plugin_result.accepted_cipher_list)
        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_tlsv1_0_enabled(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv10ScanCommand())

        self.assertTrue(plugin_result.preferred_cipher)
        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {
                'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA',
                'TLS_RSA_WITH_AES_256_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA',
                'TLS_RSA_WITH_AES_128_CBC_SHA', 'TLS_RSA_WITH_3DES_EDE_CBC_SHA'
            }, set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.accepted_cipher_list)
        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_tlsv1_0_disabled(self):
        server_test = ServerConnectivityTester(
            hostname='success.trendmicro.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv10ScanCommand())

        self.assertIsNone(plugin_result.preferred_cipher)
        self.assertFalse(plugin_result.accepted_cipher_list)
        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_tlsv1_1_enabled(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv11ScanCommand())

        self.assertTrue(plugin_result.preferred_cipher)
        self.assertTrue(plugin_result.accepted_cipher_list)
        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {
                'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA',
                'TLS_RSA_WITH_AES_256_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA',
                'TLS_RSA_WITH_AES_128_CBC_SHA', 'TLS_RSA_WITH_3DES_EDE_CBC_SHA'
            }, set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_tlsv1_2_enabled(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        # Also do full HTTP connections
        plugin_result = plugin.process_task(server_info,
                                            Tlsv12ScanCommand(http_get=True))

        self.assertTrue(plugin_result.preferred_cipher)
        self.assertTrue(plugin_result.accepted_cipher_list)
        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]

        self.assertEqual(
            {
                'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',
                'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA',
                'TLS_RSA_WITH_AES_256_GCM_SHA384',
                'TLS_RSA_WITH_AES_256_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256',
                'TLS_RSA_WITH_AES_128_GCM_SHA256',
                'TLS_RSA_WITH_AES_128_CBC_SHA',
                'TLS_RSA_WITH_3DES_EDE_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
                'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256'
            }, set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_null_cipher_suites(self):
        server_test = ServerConnectivityTester(hostname='null.badssl.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {
                'TLS_ECDH_anon_WITH_AES_256_CBC_SHA',
                'TLS_DH_anon_WITH_AES_256_CBC_SHA256',
                'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA',
                'TLS_DH_anon_WITH_AES_256_GCM_SHA384',
                'TLS_DH_anon_WITH_AES_256_CBC_SHA',
                'TLS_ECDH_anon_WITH_AES_128_CBC_SHA',
                'TLS_DH_anon_WITH_AES_128_CBC_SHA256',
                'TLS_DH_anon_WITH_AES_128_CBC_SHA',
                'TLS_DH_anon_WITH_AES_128_GCM_SHA256',
                'TLS_DH_anon_WITH_SEED_CBC_SHA',
                'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_NULL_SHA', 'TLS_ECDH_anon_WITH_NULL_SHA',
                'TLS_RSA_WITH_NULL_SHA256', 'TLS_RSA_WITH_NULL_SHA'
            }, set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_rc4_cipher_suites(self):
        server_test = ServerConnectivityTester(hostname='rc4.badssl.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {'TLS_ECDHE_RSA_WITH_RC4_128_SHA', 'TLS_RSA_WITH_RC4_128_SHA'},
            set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_rc4_md5_cipher_suites(self):
        server_test = ServerConnectivityTester(hostname='rc4-md5.badssl.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual({'TLS_RSA_WITH_RC4_128_MD5'},
                         set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_follows_client_cipher_suite_preference(self):
        # Google.com does not follow client cipher suite preference
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        self.assertTrue(plugin_result.preferred_cipher)
        self.assertTrue(plugin_result.accepted_cipher_list)

        # Sogou.com follows client cipher suite preference
        server_test = ServerConnectivityTester(hostname='www.sogou.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        self.assertIsNone(plugin_result.preferred_cipher)
        self.assertTrue(plugin_result.accepted_cipher_list)

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_smtp_post_handshake_response(self):
        server_test = ServerConnectivityTester(
            hostname='smtp.gmail.com',
            port=587,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP)
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

    def test_tls_1_3_cipher_suites(self):
        server_test = ServerConnectivityTester(hostname='www.cloudflare.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv13ScanCommand())

        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {
                'TLS_CHACHA20_POLY1305_SHA256', 'TLS_AES_256_GCM_SHA384',
                'TLS_AES_128_GCM_SHA256'
            }, set(accepted_cipher_name_list))

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_succeeds_when_client_auth_failed(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client does NOT provide a client certificate
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            # OpenSslCipherSuitesPlugin works even when a client cert was not supplied
            plugin = OpenSslCipherSuitesPlugin()
            plugin_result = plugin.process_task(server_info,
                                                Sslv30ScanCommand())

        self.assertTrue(plugin_result.accepted_cipher_list)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
class HttpHeadersPluginTestCase(unittest.TestCase):
    def test_hsts_enabled(self):
        server_test = ServerConnectivityTester(hostname='hsts.badssl.com')
        server_info = server_test.perform()

        plugin = HttpHeadersPlugin()
        plugin_result = plugin.process_task(server_info,
                                            HttpHeadersScanCommand())

        self.assertTrue(plugin_result.hsts_header)
        self.assertFalse(plugin_result.hpkp_header)
        self.assertIsNone(plugin_result.is_valid_pin_configured)
        self.assertIsNone(plugin_result.is_backup_pin_configured)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_hsts_and_hpkp_disabled(self):
        server_test = ServerConnectivityTester(hostname='expired.badssl.com')
        server_info = server_test.perform()

        plugin = HttpHeadersPlugin()
        plugin_result = plugin.process_task(server_info,
                                            HttpHeadersScanCommand())

        self.assertFalse(plugin_result.hsts_header)
        self.assertFalse(plugin_result.hpkp_header)
        self.assertIsNone(plugin_result.is_valid_pin_configured)
        self.assertIsNone(plugin_result.is_backup_pin_configured)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_hpkp_enabled(self):
        # HPKP is being deprecated in Chrome - I couldn't find a website with the header set
        pass

    def test_expect_ct_disabled(self):
        server_test = ServerConnectivityTester(hostname='hsts.badssl.com')
        server_info = server_test.perform()

        plugin = HttpHeadersPlugin()
        plugin_result = plugin.process_task(server_info,
                                            HttpHeadersScanCommand())

        self.assertFalse(plugin_result.expect_ct_header)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        self.assertTrue(pickle.dumps(plugin_result))

    def test_expect_ct_enabled(self):
        # Github was the only server I could find with expect-ct header set
        server_test = ServerConnectivityTester(hostname='github.com')
        server_info = server_test.perform()

        plugin = HttpHeadersPlugin()
        plugin_result = plugin.process_task(server_info,
                                            HttpHeadersScanCommand())

        self.assertTrue(plugin_result.expect_ct_header)
        self.assertTrue(plugin_result.expect_ct_header.max_age >= 0)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        self.assertTrue(pickle.dumps(plugin_result))

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_fails_when_client_auth_failed(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client does NOT provide a client certificate
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            # The plugin fails when a client cert was not supplied
            plugin = HttpHeadersPlugin()
            with self.assertRaises(ClientCertificateRequested):
                plugin.process_task(server_info, HttpHeadersScanCommand())

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_works_when_client_auth_succeeded(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client provides a client certificate
            client_creds = ClientAuthenticationCredentials(
                client_certificate_chain_path=server.
                get_client_certificate_path(),
                client_key_path=server.get_client_key_path(),
            )

            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port,
                client_auth_credentials=client_creds,
            )
            server_info = server_test.perform()

            # The plugin works fine
            plugin = HttpHeadersPlugin()
            plugin_result = plugin.process_task(server_info,
                                                HttpHeadersScanCommand())

        self.assertIsNone(plugin_result.expect_ct_header)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
class CertificateInfoPluginTestCase(unittest.TestCase):
    def test_ca_file_bad_file(self):
        server_test = ServerConnectivityTester(hostname='www.hotmail.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        with self.assertRaises(ValueError):
            plugin.process_task(
                server_info, CertificateInfoScanCommand(ca_file='doesntexist'))

    def test_ca_file(self):
        server_test = ServerConnectivityTester(hostname='www.hotmail.com')
        server_info = server_test.perform()

        ca_file_path = os.path.join(os.path.dirname(__file__), '..', 'utils',
                                    'wildcard-self-signed.pem')
        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(
            server_info, CertificateInfoScanCommand(ca_file=ca_file_path))

        self.assertGreaterEqual(len(plugin_result.path_validation_result_list),
                                6)
        for path_validation_result in plugin_result.path_validation_result_list:
            if path_validation_result.trust_store.name == 'Custom --ca_file':
                self.assertFalse(path_validation_result.is_certificate_trusted)
            else:
                self.assertTrue(path_validation_result.is_certificate_trusted)

    @unittest.skip('Not implemented - find a server that has must-staple')
    def test_valid_chain_with_ocsp_stapling_and_must_staple(self):
        server_test = ServerConnectivityTester(hostname='www.scotthelme.co.uk')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertTrue(plugin_result.ocsp_response)
        self.assertEqual(plugin_result.ocsp_response_status,
                         OcspResponseStatusEnum.SUCCESSFUL)
        self.assertTrue(plugin_result.is_ocsp_response_trusted)
        self.assertTrue(plugin_result.certificate_has_must_staple_extension)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_valid_chain_with_ev_cert(self):
        server_test = ServerConnectivityTester(hostname='www.comodo.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertTrue(plugin_result.is_leaf_certificate_ev)

        self.assertEqual(len(plugin_result.certificate_chain), 4)
        self.assertEqual(len(plugin_result.verified_certificate_chain), 3)
        self.assertFalse(plugin_result.has_anchor_in_certificate_chain)

        self.assertGreaterEqual(len(plugin_result.path_validation_result_list),
                                5)
        for path_validation_result in plugin_result.path_validation_result_list:
            self.assertTrue(path_validation_result.is_certificate_trusted)

        self.assertEqual(len(plugin_result.path_validation_error_list), 0)
        self.assertEqual(plugin_result.certificate_matches_hostname, True)
        self.assertTrue(plugin_result.is_certificate_chain_order_valid)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_invalid_chain(self):
        server_test = ServerConnectivityTester(
            hostname='self-signed.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertIsNone(plugin_result.ocsp_response)
        self.assertEqual(len(plugin_result.certificate_chain), 1)

        self.assertGreaterEqual(len(plugin_result.path_validation_result_list),
                                5)
        for path_validation_result in plugin_result.path_validation_result_list:
            self.assertFalse(path_validation_result.is_certificate_trusted)

        self.assertEqual(plugin_result.certificate_included_scts_count, 0)

        self.assertEqual(len(plugin_result.path_validation_error_list), 0)
        self.assertEqual(plugin_result.certificate_matches_hostname, True)
        self.assertTrue(plugin_result.is_certificate_chain_order_valid)
        self.assertIsNone(plugin_result.has_anchor_in_certificate_chain)
        self.assertIsNone(plugin_result.has_sha1_in_certificate_chain)
        self.assertFalse(plugin_result.verified_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_1000_sans_chain(self):
        # Ensure SSLyze can process a leaf cert with 1000 SANs
        server_test = ServerConnectivityTester(hostname='1000-sans.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin.process_task(server_info, CertificateInfoScanCommand())

    def test_sha1_chain(self):
        server_test = ServerConnectivityTester(
            hostname='sha1-intermediate.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertTrue(plugin_result.has_sha1_in_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

    def test_sha256_chain(self):
        server_test = ServerConnectivityTester(hostname='sha256.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertFalse(plugin_result.has_sha1_in_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_unicode_certificate(self):
        server_test = ServerConnectivityTester(hostname='เพย์สบาย.th')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertGreaterEqual(len(plugin_result.certificate_chain), 1)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_ecdsa_certificate(self):
        server_test = ServerConnectivityTester(hostname='www.cloudflare.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertGreaterEqual(len(plugin_result.certificate_chain), 1)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_chain_with_anchor(self):
        server_test = ServerConnectivityTester(hostname='www.verizon.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertTrue(plugin_result.has_anchor_in_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_not_trusted_by_mozilla_but_trusted_by_microsoft(self):
        server_test = ServerConnectivityTester(
            hostname='webmail.russia.nasa.gov')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertEqual(plugin_result.successful_trust_store.name, 'Windows')

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_only_trusted_by_custom_ca_file(self):
        server_test = ServerConnectivityTester(
            hostname='self-signed.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        ca_file_path = os.path.join(os.path.dirname(__file__), '..', 'utils',
                                    'self-signed.badssl.com.pem')
        plugin_result = plugin.process_task(
            server_info, CertificateInfoScanCommand(ca_file=ca_file_path))

        self.assertEqual(plugin_result.successful_trust_store.name,
                         'Custom --ca_file')
        self.assertTrue(plugin_result.verified_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_certificate_with_no_cn(self):
        server_test = ServerConnectivityTester(
            hostname='no-common-name.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertTrue(plugin_result.verified_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_certificate_with_no_subject(self):
        server_test = ServerConnectivityTester(
            hostname='no-subject.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertTrue(plugin_result.verified_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_certificate_with_scts(self):
        server_test = ServerConnectivityTester(hostname='www.apple.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info,
                                            CertificateInfoScanCommand())

        self.assertGreater(plugin_result.certificate_included_scts_count, 1)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_succeeds_when_client_auth_failed(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client does NOT provide a client certificate
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            # CertificateInfoPlugin works even when a client cert was not supplied
            plugin = CertificateInfoPlugin()
            plugin_result = plugin.process_task(server_info,
                                                CertificateInfoScanCommand())

        self.assertTrue(plugin_result.certificate_chain)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
class SessionResumptionPluginTestCase(unittest.TestCase):
    def test_resumption_support(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = SessionResumptionPlugin()
        plugin_result = plugin.process_task(
            server_info, SessionResumptionSupportScanCommand())

        self.assertTrue(plugin_result.is_ticket_resumption_supported)
        self.assertTrue(plugin_result.attempted_resumptions_nb)
        self.assertTrue(plugin_result.successful_resumptions_nb)
        self.assertFalse(plugin_result.errored_resumptions_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    def test_resumption_rate(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = SessionResumptionPlugin()
        plugin_result = plugin.process_task(server_info,
                                            SessionResumptionRateScanCommand())

        self.assertTrue(plugin_result.attempted_resumptions_nb)
        self.assertTrue(plugin_result.successful_resumptions_nb)
        self.assertFalse(plugin_result.errored_resumptions_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_fails_when_client_auth_failed_session(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client does NOT provide a client certificate
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            # SessionResumptionPlugin fails even when a client cert was not supplied
            plugin = SessionResumptionPlugin()
            plugin_result = plugin.process_task(
                server_info, SessionResumptionSupportScanCommand())

        # All session resumption attempts returned an error because of client authentication
        self.assertEqual(len(plugin_result.errored_resumptions_list), 5)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

    @unittest.skipIf(not VulnerableOpenSslServer.is_platform_supported(),
                     'Not on Linux 64')
    def test_works_when_client_auth_succeeded(self):
        # Given a server that requires client authentication
        with VulnerableOpenSslServer(
                client_auth_config=ClientAuthenticationServerConfigurationEnum.
                REQUIRED) as server:
            # And the client provides a client certificate
            client_creds = ClientAuthenticationCredentials(
                client_certificate_chain_path=server.
                get_client_certificate_path(),
                client_key_path=server.get_client_key_path(),
            )

            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port,
                client_auth_credentials=client_creds,
            )
            server_info = server_test.perform()

            # SessionResumptionPlugin works fine
            plugin = SessionResumptionPlugin()
            plugin_result = plugin.process_task(
                server_info, SessionResumptionSupportScanCommand())

        self.assertEqual(plugin_result.successful_resumptions_nb, 5)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())