1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ssl/ssl_error_classification.h" 6 7#include "base/files/file_path.h" 8#include "base/strings/string_split.h" 9#include "base/time/time.h" 10#include "chrome/test/base/chrome_render_view_host_test_harness.h" 11#include "content/public/browser/web_contents.h" 12#include "net/base/net_errors.h" 13#include "net/base/test_data_directory.h" 14#include "net/cert/x509_cert_types.h" 15#include "net/cert/x509_certificate.h" 16#include "net/test/cert_test_util.h" 17#include "net/test/test_certificate_data.h" 18#include "testing/gtest/include/gtest/gtest.h" 19#include "url/gurl.h" 20 21using base::Time; 22using content::WebContents; 23 24class SSLErrorClassificationTest : public ChromeRenderViewHostTestHarness { 25 public: 26 SSLErrorClassificationTest() { 27 SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD); 28 } 29}; 30 31TEST_F(SSLErrorClassificationTest, TestDateInvalidScore) { 32 base::FilePath certs_dir = net::GetTestCertsDirectory(); 33 scoped_refptr<net::X509Certificate> expired_cert = 34 net::ImportCertFromFile(certs_dir, "expired_cert.pem"); 35 base::Time time; 36 GURL origin("https://example.com"); 37 int cert_error = net::ERR_CERT_DATE_INVALID; 38 WebContents* contents = web_contents(); 39 40 { 41 EXPECT_TRUE(base::Time::FromString("Wed, 03 Jan 2007 12:00:00 GMT", &time)); 42 SSLErrorClassification ssl_error(contents, 43 time, 44 origin, 45 cert_error, 46 *expired_cert); 47 EXPECT_FLOAT_EQ(0.2f, ssl_error.CalculateScoreTimePassedSinceExpiry()); 48 } 49 50 { 51 EXPECT_TRUE(base::Time::FromString("Sat, 06 Jan 2007 12:00:00 GMT", &time)); 52 SSLErrorClassification ssl_error(contents, 53 time, 54 origin, 55 cert_error, 56 *expired_cert); 57 EXPECT_FLOAT_EQ(0.3f, ssl_error.CalculateScoreTimePassedSinceExpiry()); 58 } 59 60 { 61 EXPECT_TRUE(base::Time::FromString("Mon, 08 Jan 2007 12:00:00 GMT", &time)); 62 SSLErrorClassification ssl_error(contents, 63 time, 64 origin, 65 cert_error, 66 *expired_cert); 67 EXPECT_FLOAT_EQ(0.4f, ssl_error.CalculateScoreTimePassedSinceExpiry()); 68 } 69} 70 71TEST_F(SSLErrorClassificationTest, TestNameMismatch) { 72 scoped_refptr<net::X509Certificate> google_cert( 73 net::X509Certificate::CreateFromBytes( 74 reinterpret_cast<const char*>(google_der), sizeof(google_der))); 75 ASSERT_NE(static_cast<net::X509Certificate*>(NULL), google_cert.get()); 76 base::Time time = base::Time::NowFromSystemTime(); 77 std::vector<std::string> dns_names_google; 78 dns_names_google.push_back("www"); 79 dns_names_google.push_back("google"); 80 dns_names_google.push_back("com"); 81 std::vector<std::vector<std::string>> dns_name_tokens_google; 82 dns_name_tokens_google.push_back(dns_names_google); 83 int cert_error = net::ERR_CERT_COMMON_NAME_INVALID; 84 WebContents* contents = web_contents(); 85 { 86 GURL origin("https://google.com"); 87 std::string host_name = origin.host(); 88 std::vector<std::string> host_name_tokens; 89 base::SplitStringDontTrim(host_name, '.', &host_name_tokens); 90 SSLErrorClassification ssl_error(contents, 91 time, 92 origin, 93 cert_error, 94 *google_cert); 95 EXPECT_TRUE(ssl_error.IsWWWSubDomainMatch()); 96 EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, 97 dns_name_tokens_google)); 98 EXPECT_FALSE(ssl_error.AnyNamesUnderName(dns_name_tokens_google, 99 host_name_tokens)); 100 EXPECT_FALSE(ssl_error.IsSubDomainOutsideWildcard(host_name_tokens)); 101 EXPECT_FALSE(ssl_error.IsCertLikelyFromMultiTenantHosting()); 102 } 103 104 { 105 GURL origin("https://foo.blah.google.com"); 106 std::string host_name = origin.host(); 107 std::vector<std::string> host_name_tokens; 108 base::SplitStringDontTrim(host_name, '.', &host_name_tokens); 109 SSLErrorClassification ssl_error(contents, 110 time, 111 origin, 112 cert_error, 113 *google_cert); 114 EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); 115 EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, 116 dns_name_tokens_google)); 117 EXPECT_FALSE(ssl_error.AnyNamesUnderName(dns_name_tokens_google, 118 host_name_tokens)); 119 } 120 121 { 122 GURL origin("https://foo.www.google.com"); 123 std::string host_name = origin.host(); 124 std::vector<std::string> host_name_tokens; 125 base::SplitStringDontTrim(host_name, '.', &host_name_tokens); 126 SSLErrorClassification ssl_error(contents, 127 time, 128 origin, 129 cert_error, 130 *google_cert); 131 EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); 132 EXPECT_TRUE(ssl_error.NameUnderAnyNames(host_name_tokens, 133 dns_name_tokens_google)); 134 EXPECT_FALSE(ssl_error.AnyNamesUnderName(dns_name_tokens_google, 135 host_name_tokens)); 136 } 137 138 { 139 GURL origin("https://www.google.com.foo"); 140 std::string host_name = origin.host(); 141 std::vector<std::string> host_name_tokens; 142 base::SplitStringDontTrim(host_name, '.', &host_name_tokens); 143 SSLErrorClassification ssl_error(contents, 144 time, 145 origin, 146 cert_error, 147 *google_cert); 148 EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); 149 EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, 150 dns_name_tokens_google)); 151 EXPECT_FALSE(ssl_error.AnyNamesUnderName(dns_name_tokens_google, 152 host_name_tokens)); 153 } 154 155 { 156 GURL origin("https://www.foogoogle.com."); 157 std::string host_name = origin.host(); 158 std::vector<std::string> host_name_tokens; 159 base::SplitStringDontTrim(host_name, '.', &host_name_tokens); 160 SSLErrorClassification ssl_error(contents, 161 time, 162 origin, 163 cert_error, 164 *google_cert); 165 EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); 166 EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, 167 dns_name_tokens_google)); 168 EXPECT_FALSE(ssl_error.AnyNamesUnderName(dns_name_tokens_google, 169 host_name_tokens)); 170 } 171 172 scoped_refptr<net::X509Certificate> webkit_cert( 173 net::X509Certificate::CreateFromBytes( 174 reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der))); 175 ASSERT_NE(static_cast<net::X509Certificate*>(NULL), webkit_cert.get()); 176 std::vector<std::string> dns_names_webkit; 177 dns_names_webkit.push_back("webkit"); 178 dns_names_webkit.push_back("org"); 179 std::vector<std::vector<std::string>> dns_name_tokens_webkit; 180 dns_name_tokens_webkit.push_back(dns_names_webkit); 181 { 182 GURL origin("https://a.b.webkit.org"); 183 std::string host_name = origin.host(); 184 std::vector<std::string> host_name_tokens; 185 base::SplitStringDontTrim(host_name, '.', &host_name_tokens); 186 SSLErrorClassification ssl_error(contents, 187 time, 188 origin, 189 cert_error, 190 *webkit_cert); 191 EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); 192 EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, 193 dns_name_tokens_webkit)); 194 EXPECT_FALSE(ssl_error.AnyNamesUnderName(dns_name_tokens_webkit, 195 host_name_tokens)); 196 EXPECT_TRUE(ssl_error.IsSubDomainOutsideWildcard(host_name_tokens)); 197 EXPECT_FALSE(ssl_error.IsCertLikelyFromMultiTenantHosting()); 198 } 199} 200 201TEST_F(SSLErrorClassificationTest, TestHostNameHasKnownTLD) { 202 std::string url1 = "www.google.com"; 203 std::string url2 = "b.appspot.com"; 204 std::string url3 = "a.private"; 205 EXPECT_TRUE(SSLErrorClassification::IsHostNameKnownTLD(url1)); 206 EXPECT_TRUE(SSLErrorClassification::IsHostNameKnownTLD(url2)); 207 EXPECT_FALSE(SSLErrorClassification::IsHostNameKnownTLD(url3)); 208} 209