| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ssl/ssl_error_assistant.h" |
| |
| #include <memory> |
| |
| #include "chrome/browser/ssl/ssl_error_assistant.pb.h" |
| #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| #include "crypto/sha2.h" |
| #include "net/cert/asn1_util.h" |
| #include "net/test/cert_test_util.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "net/test/test_certificate_data.h" |
| #include "net/test/test_data_directory.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| const net::SHA256HashValue kCertPublicKeyHashValue = {{0x01, 0x02}}; |
| |
| const uint32_t kLargeVersionId = 0xFFFFFFu; |
| |
| // These certificates are self signed certificates with relevant issuer common |
| // names generated using the following openssl command: |
| // openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes |
| |
| // Common name: "Misconfig Software" |
| // Organization name: "Test Company" |
| const char kMisconfigSoftwareCert[] = |
| "-----BEGIN CERTIFICATE-----\n" |
| "MIIC5DCCAk2gAwIBAgIJAPYPMpr0AIDBMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV\n" |
| "BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRUwEwYDVQQKEwxUZXN0IENvbXBh\n" |
| "bnkxGzAZBgNVBAMTEk1pc2NvbmZpZyBTb2Z0d2FyZTAeFw0xNzEwMTcxOTQyMzFa\n" |
| "Fw0xODEwMTcxOTQyMzFaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0\n" |
| "YXRlMRUwEwYDVQQKEwxUZXN0IENvbXBhbnkxGzAZBgNVBAMTEk1pc2NvbmZpZyBT\n" |
| "b2Z0d2FyZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyZWnLvuD19iG5PSi\n" |
| "8dSVhLeuZDBtwcWBOMzga3hx7HDMd+395gstRLc1VhpMePmxUdyEpStHDiYjNF/k\n" |
| "GRsIXfXWpO82L7r+Fm6eym4BOw2sjX1aounljETYasREvXhEB/8WaLJfMcstUwsT\n" |
| "PoXgUWYkIBi/76EiWHXvYEiXV2kCAwEAAaOBuTCBtjAdBgNVHQ4EFgQUtakrb0wU\n" |
| "gZVXyus1vlj6T5aDEnYwgYYGA1UdIwR/MH2AFLWpK29MFIGVV8rrNb5Y+k+WgxJ2\n" |
| "oVqkWDBWMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEVMBMGA1UE\n" |
| "ChMMVGVzdCBDb21wYW55MRswGQYDVQQDExJNaXNjb25maWcgU29mdHdhcmWCCQD2\n" |
| "DzKa9ACAwTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFAFlPO3HEWQ\n" |
| "0XdRbeIQPVva72VFyF+ESFC6ky7GLDoaSAwRlE1i5qWfxnLbEA0b7CWjyO1tC8Uw\n" |
| "OMB5U9qmQouAqf5medr2pECSDimb7qBCz3kKjgZWt1Xv8w0PsW6lFVPmMsO4Zv7F\n" |
| "Podf1biETWgaYoT6PrUTtWG3jeSU2r9M\n" |
| "-----END CERTIFICATE-----"; |
| |
| // Common name: "ijklmn opqrs" |
| // Organization name: "abc defgh co" |
| const char kMisconfigSoftwareRegexCheckCert[] = |
| "-----BEGIN CERTIFICATE-----\n" |
| "MIIC0jCCAjugAwIBAgIJAOyyORCXGxvDMA0GCSqGSIb3DQEBBQUAMFAxCzAJBgNV\n" |
| "BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRUwEwYDVQQKEwxhYmMgZGVmZ2gg\n" |
| "Y28xFTATBgNVBAMTDGlqa2xtbiBvcHFyczAeFw0xNzEwMTcyMjM4MzJaFw0xODEw\n" |
| "MTcyMjM4MzJaMFAxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRUw\n" |
| "EwYDVQQKEwxhYmMgZGVmZ2ggY28xFTATBgNVBAMTDGlqa2xtbiBvcHFyczCBnzAN\n" |
| "BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsnuBPW2k4+eFazC8lq7rLRNjpZ5yqEwX\n" |
| "LBE8fxbvjXSSZAaJz/iTn+Zg/UMJz9IpulbcA/xf36JuhFYv7aClFrtg5DHaqrPf\n" |
| "kt7g9AM3hEIjGsdHtyAqFp/+CpySGzVpTLyT1NtHkqtkiD6HCSpWqL+m/6ibpUhy\n" |
| "oy9y/ZV1vVUCAwEAAaOBszCBsDAdBgNVHQ4EFgQUBk+vtSjNipTcWh3NIbtsjVN0\n" |
| "uJswgYAGA1UdIwR5MHeAFAZPr7UozYqU3FodzSG7bI1TdLiboVSkUjBQMQswCQYD\n" |
| "VQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEVMBMGA1UEChMMYWJjIGRlZmdo\n" |
| "IGNvMRUwEwYDVQQDEwxpamtsbW4gb3BxcnOCCQDssjkQlxsbwzAMBgNVHRMEBTAD\n" |
| "AQH/MA0GCSqGSIb3DQEBBQUAA4GBACv8KnNmaOqHD8QsmvaD2Yvc7dAFkCgsdQb/\n" |
| "Tkyw0sJN8ZH+bummkgGZLw4gzdmhVg8kGIbiDvCYgOVaIg+2H3PtkdIrW2KhyXrN\n" |
| "2qIa9nBvuv8LC1TAdB65DDheLh0PuTGcIwfJ7kcKi+Eo8fPbYYdyHGRw+rVWXVPz\n" |
| "SgZO4ZYq\n" |
| "-----END CERTIFICATE-----"; |
| |
| } // namespace |
| |
| class SSLErrorAssistantTest : public ChromeRenderViewHostTestHarness { |
| public: |
| void SetUp() override { |
| ChromeRenderViewHostTestHarness::SetUp(); |
| error_assistant_.reset(new SSLErrorAssistant()); |
| |
| ssl_info_.cert = net::ImportCertFromFile( |
| net::GetTestCertsDirectory(), "subjectAltName_www_example_com.pem"); |
| ssl_info_.cert_status = net::CERT_STATUS_COMMON_NAME_INVALID; |
| ssl_info_.public_key_hashes.push_back( |
| net::HashValue(kCertPublicKeyHashValue)); |
| } |
| |
| void TearDown() override { |
| error_assistant_.reset(); |
| ChromeRenderViewHostTestHarness::TearDown(); |
| } |
| |
| void TestMITMSoftwareMatchFromString(const std::string& cert, |
| const std::string& match_result) { |
| net::CertificateList certs = |
| net::X509Certificate::CreateCertificateListFromBytes( |
| cert.data(), cert.size(), net::X509Certificate::FORMAT_AUTO); |
| ASSERT_FALSE(certs.empty()); |
| EXPECT_EQ(match_result, |
| error_assistant()->MatchKnownMITMSoftware(certs[0])); |
| } |
| |
| protected: |
| SSLErrorAssistantTest() { |
| embedded_test_server_ = std::make_unique<net::EmbeddedTestServer>(); |
| } |
| |
| ~SSLErrorAssistantTest() override {} |
| |
| SSLErrorAssistant* error_assistant() const { return error_assistant_.get(); } |
| |
| net::EmbeddedTestServer* embedded_test_server() const { |
| return embedded_test_server_.get(); |
| } |
| |
| const net::SSLInfo& ssl_info() const { return ssl_info_; } |
| |
| const std::string& issuer_common_name() const { |
| return ssl_info_.cert->issuer().common_name; |
| } |
| |
| const std::string& issuer_organization_name() const { |
| DCHECK(!ssl_info_.cert->issuer().organization_names.empty()); |
| return ssl_info_.cert->issuer().organization_names.front(); |
| } |
| |
| private: |
| net::SSLInfo ssl_info_; |
| |
| std::unique_ptr<SSLErrorAssistant> error_assistant_; |
| std::unique_ptr<net::EmbeddedTestServer> embedded_test_server_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SSLErrorAssistantTest); |
| }; |
| |
| // Test to see if IsKnownCaptivePortalCertificate() returns the correct value. |
| TEST_F(SSLErrorAssistantTest, CaptivePortalCertificateList) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| // Test without the known captive portal certificate in config_proto. |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| config_proto->add_captive_portal_cert()->set_sha256_hash("sha256/boxfish"); |
| config_proto->add_captive_portal_cert()->set_sha256_hash( |
| "sha256/treecreeper"); |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| EXPECT_FALSE(error_assistant()->IsKnownCaptivePortalCertificate(ssl_info())); |
| |
| error_assistant()->ResetForTesting(); |
| |
| // Test with the known captive portal certificate in config_proto. |
| config_proto.reset(new chrome_browser_ssl::SSLErrorAssistantConfig()); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| config_proto->add_captive_portal_cert()->set_sha256_hash("sha256/boxfish"); |
| config_proto->add_captive_portal_cert()->set_sha256_hash( |
| ssl_info().public_key_hashes[0].ToString()); |
| config_proto->add_captive_portal_cert()->set_sha256_hash( |
| "sha256/treecreeper"); |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| EXPECT_TRUE(error_assistant()->IsKnownCaptivePortalCertificate(ssl_info())); |
| } |
| |
| // Test to see if the MitM Software gets matched correctly. |
| TEST_F(SSLErrorAssistantTest, MitMSoftwareMatching) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| // Tests for a basic and more complex regex match. |
| chrome_browser_ssl::MITMSoftware* filter = config_proto->add_mitm_software(); |
| filter->set_name("Basic Check"); |
| filter->set_issuer_common_name_regex("Misconfig Software"); |
| filter->set_issuer_organization_regex("Test Company"); |
| |
| filter = config_proto->add_mitm_software(); |
| filter->set_name("Regex Check"); |
| filter->set_issuer_common_name_regex("ij[a-z]+n opqrs"); |
| filter->set_issuer_organization_regex("abc de[a-z0-9]gh [a-z]+"); |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| TestMITMSoftwareMatchFromString(kMisconfigSoftwareCert, "Basic Check"); |
| TestMITMSoftwareMatchFromString(kMisconfigSoftwareRegexCheckCert, |
| "Regex Check"); |
| |
| error_assistant()->ResetForTesting(); |
| |
| // Tests for no matches. |
| config_proto.reset(new chrome_browser_ssl::SSLErrorAssistantConfig()); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| filter = config_proto->add_mitm_software(); |
| filter->set_name("Incorrect common name"); |
| filter->set_issuer_common_name_regex("Misconfig Sotware"); |
| filter->set_issuer_organization_regex("Test Company"); |
| |
| filter = config_proto->add_mitm_software(); |
| filter->set_name("Incorrect company name"); |
| filter->set_issuer_common_name_regex("Misconfig Software"); |
| filter->set_issuer_organization_regex("Tst Company"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| TestMITMSoftwareMatchFromString(kMisconfigSoftwareCert, ""); |
| } |
| |
| // Test to see if the dynamic interstitial is matched with more complex regex |
| // fields. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListMatch) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| // Add a dynamic interstitial that will mismatch. |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type(chrome_browser_ssl::DynamicInterstitial:: |
| INTERSTITIAL_PAGE_CAPTIVE_PORTAL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| filter->add_sha256_hash("sha256/nightjar"); |
| filter->add_sha256_hash("sha256/frogmouth"); |
| filter->add_sha256_hash("sha256/poorwill"); |
| |
| filter->set_mitm_software_name("UwS"); |
| filter->set_issuer_common_name_regex("whippoorwill"); |
| |
| // Add a matching dynamic interstitial. |
| filter = config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::ERR_CERT_COMMON_NAME_INVALID); |
| filter->add_sha256_hash("sha256/nuthatch"); |
| filter->add_sha256_hash(ssl_info().public_key_hashes[0].ToString()); |
| filter->add_sha256_hash("sha256/treecreeper"); |
| |
| filter->set_mitm_software_name("UwS"); |
| filter->set_issuer_common_name_regex(issuer_common_name()); |
| filter->set_issuer_organization_regex(issuer_organization_name()); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| base::Optional<DynamicInterstitialInfo> dynamic_interstitial = |
| error_assistant()->MatchDynamicInterstitial(ssl_info()); |
| ASSERT_TRUE(dynamic_interstitial); |
| EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL, |
| dynamic_interstitial->interstitial_type); |
| } |
| |
| // Test to see if the dynamic interstitial is matched. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListComplexRegexMatch) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| // Add a dynamic interstitial that will mismatch. |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type(chrome_browser_ssl::DynamicInterstitial:: |
| INTERSTITIAL_PAGE_CAPTIVE_PORTAL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| filter->add_sha256_hash("sha256/nightjar"); |
| filter->add_sha256_hash("sha256/frogmouth"); |
| filter->add_sha256_hash("sha256/poorwill"); |
| |
| filter->set_mitm_software_name("UwS"); |
| filter->set_issuer_common_name_regex("whippoorwill"); |
| |
| // Add a dynamic interstitial that will match. |
| filter = config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::ERR_CERT_COMMON_NAME_INVALID); |
| filter->add_sha256_hash("sha256/nuthatch"); |
| filter->add_sha256_hash(ssl_info().public_key_hashes[0].ToString()); |
| filter->add_sha256_hash("sha256/treecreeper"); |
| |
| filter->set_mitm_software_name("UwS"); |
| filter->set_issuer_common_name_regex("[0-9]+.0.[0-9]+.1"); |
| filter->set_issuer_organization_regex("T[a-z]+t CA"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| base::Optional<DynamicInterstitialInfo> dynamic_interstitial = |
| error_assistant()->MatchDynamicInterstitial(ssl_info()); |
| ASSERT_TRUE(dynamic_interstitial); |
| EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL, |
| dynamic_interstitial->interstitial_type); |
| } |
| |
| // Test to see if the dynamic interstitial is matched when the certificate |
| // error is set to UNKNOWN_CERT_ERROR. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListMatchUnknownCertError) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| // Add a dynamic interstitial that will mismatch. |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type(chrome_browser_ssl::DynamicInterstitial:: |
| INTERSTITIAL_PAGE_CAPTIVE_PORTAL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| filter->add_sha256_hash("sha256/nightjar"); |
| filter->add_sha256_hash("sha256/frogmouth"); |
| filter->add_sha256_hash("sha256/poorwill"); |
| |
| // Add a dynamic interstitial that will match. |
| filter = config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| filter->add_sha256_hash("sha256/nuthatch"); |
| filter->add_sha256_hash(ssl_info().public_key_hashes[0].ToString()); |
| filter->add_sha256_hash("sha256/treecreeper"); |
| |
| filter->set_issuer_common_name_regex(issuer_common_name()); |
| filter->set_issuer_organization_regex(issuer_organization_name()); |
| filter->set_mitm_software_name("UwS"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| base::Optional<DynamicInterstitialInfo> dynamic_interstitial = |
| error_assistant()->MatchDynamicInterstitial(ssl_info()); |
| EXPECT_TRUE(dynamic_interstitial); |
| EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL, |
| dynamic_interstitial->interstitial_type); |
| } |
| |
| // Test to see if the dynamic interstitial is matched if an empty issuer |
| // common name regex is set. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListNoCommonName) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| // Add a dynamic interstitial that will mismatch. |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type(chrome_browser_ssl::DynamicInterstitial:: |
| INTERSTITIAL_PAGE_CAPTIVE_PORTAL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| filter->add_sha256_hash("sha256/nightjar"); |
| filter->add_sha256_hash("sha256/frogmouth"); |
| filter->add_sha256_hash("sha256/poorwill"); |
| |
| // Add a matching dynamic interstitial with an empty issuer common name |
| // regex. |
| filter = config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::ERR_CERT_COMMON_NAME_INVALID); |
| filter->add_sha256_hash("sha256/nuthatch"); |
| filter->add_sha256_hash(ssl_info().public_key_hashes[0].ToString()); |
| filter->add_sha256_hash("sha256/treecreeper"); |
| |
| filter->set_issuer_common_name_regex(std::string()); |
| filter->set_issuer_organization_regex(issuer_organization_name()); |
| filter->set_mitm_software_name("UwS"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| base::Optional<DynamicInterstitialInfo> dynamic_interstitial = |
| error_assistant()->MatchDynamicInterstitial(ssl_info()); |
| ASSERT_TRUE(dynamic_interstitial); |
| EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL, |
| dynamic_interstitial->interstitial_type); |
| } |
| |
| // Test to see if the dynamic interstitial is matched if no issuer |
| // organization name regex is set. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListNoOrganizationRegex) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| // Add a dynamic interstitial that will mismatch. |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type(chrome_browser_ssl::DynamicInterstitial:: |
| INTERSTITIAL_PAGE_CAPTIVE_PORTAL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| filter->add_sha256_hash("sha256/nightjar"); |
| filter->add_sha256_hash("sha256/frogmouth"); |
| filter->add_sha256_hash("sha256/poorwill"); |
| |
| // Add a matching dynamic interstitial with an empty issuer organization |
| // name regex. |
| filter = config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::ERR_CERT_COMMON_NAME_INVALID); |
| filter->add_sha256_hash("sha256/nuthatch"); |
| filter->add_sha256_hash(ssl_info().public_key_hashes[0].ToString()); |
| filter->add_sha256_hash("sha256/treecreeper"); |
| |
| filter->set_issuer_common_name_regex(issuer_common_name()); |
| filter->set_issuer_organization_regex(std::string()); |
| filter->set_mitm_software_name("UwS"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| base::Optional<DynamicInterstitialInfo> dynamic_interstitial = |
| error_assistant()->MatchDynamicInterstitial(ssl_info()); |
| ASSERT_TRUE(dynamic_interstitial); |
| EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL, |
| dynamic_interstitial->interstitial_type); |
| } |
| |
| // Test to see if the dynamic interstitial is matched if no certificate hash is |
| // provided. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListNoCertHashes) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| // Add a dynamic interstitial that will mismatch. |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type(chrome_browser_ssl::DynamicInterstitial:: |
| INTERSTITIAL_PAGE_CAPTIVE_PORTAL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| filter->add_sha256_hash("sha256/nightjar"); |
| filter->add_sha256_hash("sha256/frogmouth"); |
| filter->add_sha256_hash("sha256/poorwill"); |
| |
| // Add a dynamic interstitial that will match. |
| filter = config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::ERR_CERT_COMMON_NAME_INVALID); |
| |
| filter->set_issuer_common_name_regex(issuer_common_name()); |
| filter->set_issuer_organization_regex(issuer_organization_name()); |
| filter->set_mitm_software_name("UwS"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| base::Optional<DynamicInterstitialInfo> dynamic_interstitial = |
| error_assistant()->MatchDynamicInterstitial(ssl_info()); |
| ASSERT_TRUE(dynamic_interstitial); |
| EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL, |
| dynamic_interstitial->interstitial_type); |
| } |
| |
| // Test to see if the dynamic interstitial is matched if no certificate hash, |
| // cert error or regexes is provided. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListMatchBlank) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| // Add a dynamic interstitial that will mismatch. |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| |
| base::Optional<DynamicInterstitialInfo> dynamic_interstitial = |
| error_assistant()->MatchDynamicInterstitial(ssl_info()); |
| ASSERT_TRUE(dynamic_interstitial); |
| EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL, |
| dynamic_interstitial->interstitial_type); |
| } |
| |
| // Test for a dynamic interstitial mismatch in the cert error. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListCertErrorMismatch) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::ERR_CERT_DATE_INVALID); |
| filter->add_sha256_hash("sha256/nuthatch"); |
| filter->add_sha256_hash(ssl_info().public_key_hashes[0].ToString()); |
| filter->add_sha256_hash("sha256/treecreeper"); |
| |
| filter->set_issuer_common_name_regex(issuer_common_name()); |
| filter->set_issuer_organization_regex(issuer_organization_name()); |
| filter->set_mitm_software_name("UwS"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| EXPECT_FALSE(error_assistant()->MatchDynamicInterstitial(ssl_info())); |
| } |
| |
| // Test for a dynamic interstitial mismatch in the certificate hashes. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListHashesMismatch) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| |
| filter->add_sha256_hash("sha256/yellowlegs"); |
| filter->add_sha256_hash("sha256/killdeer"); |
| |
| filter->set_issuer_common_name_regex(issuer_common_name()); |
| filter->set_issuer_organization_regex(issuer_organization_name()); |
| filter->set_mitm_software_name("UwS"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| EXPECT_FALSE(error_assistant()->MatchDynamicInterstitial(ssl_info())); |
| } |
| |
| // Test for a dynamic interstitial with an issuer common name regex mismatch. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListCommonNameMismatch) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| |
| filter->add_sha256_hash("sha256/nuthatch"); |
| filter->add_sha256_hash(ssl_info().public_key_hashes[0].ToString()); |
| filter->add_sha256_hash("sha256/treecreeper"); |
| |
| filter->set_issuer_common_name_regex("beeeater"); |
| filter->set_issuer_organization_regex(issuer_organization_name()); |
| filter->set_mitm_software_name("UwS"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| EXPECT_FALSE(error_assistant()->MatchDynamicInterstitial(ssl_info())); |
| } |
| |
| // Test for a dynamic interstitial with an issuer organization regex mismatch. |
| TEST_F(SSLErrorAssistantTest, DynamicInterstitialListOrganizationMismatch) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); |
| |
| auto config_proto = |
| std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); |
| config_proto->set_version_id(kLargeVersionId); |
| |
| chrome_browser_ssl::DynamicInterstitial* filter = |
| config_proto->add_dynamic_interstitial(); |
| filter->set_interstitial_type( |
| chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL); |
| filter->set_cert_error( |
| chrome_browser_ssl::DynamicInterstitial::UNKNOWN_CERT_ERROR); |
| |
| filter->add_sha256_hash("sha256/nuthatch"); |
| filter->add_sha256_hash(ssl_info().public_key_hashes[0].ToString()); |
| filter->add_sha256_hash("sha256/treecreeper"); |
| |
| filter->set_issuer_common_name_regex(issuer_common_name()); |
| filter->set_issuer_organization_regex("beeeater"); |
| filter->set_mitm_software_name("UwS"); |
| |
| error_assistant()->SetErrorAssistantProto(std::move(config_proto)); |
| EXPECT_FALSE(error_assistant()->MatchDynamicInterstitial(ssl_info())); |
| } |