OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "components/security_state/core/security_state.h" |
| 6 |
| 7 #include <stdint.h> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" |
| 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/test/histogram_tester.h" |
| 13 #include "components/security_state/core/switches.h" |
| 14 #include "net/cert/x509_certificate.h" |
| 15 #include "net/ssl/ssl_cipher_suite_names.h" |
| 16 #include "net/ssl/ssl_connection_status_flags.h" |
| 17 #include "net/test/cert_test_util.h" |
| 18 #include "net/test/test_certificate_data.h" |
| 19 #include "net/test/test_data_directory.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" |
| 21 |
| 22 namespace security_state { |
| 23 |
| 24 namespace { |
| 25 |
| 26 const char kHttpsUrl[] = "https://foo.test/"; |
| 27 const char kHttpUrl[] = "http://foo.test/"; |
| 28 |
| 29 bool IsOriginSecure(const GURL& url) { |
| 30 return url == kHttpsUrl; |
| 31 } |
| 32 |
| 33 class TestSecurityStateHelper { |
| 34 public: |
| 35 TestSecurityStateHelper() |
| 36 : url_(kHttpsUrl), |
| 37 connection_status_(net::SSL_CONNECTION_VERSION_TLS1_2 |
| 38 << net::SSL_CONNECTION_VERSION_SHIFT), |
| 39 cert_status_(net::CERT_STATUS_SHA1_SIGNATURE_PRESENT), |
| 40 displayed_mixed_content_(false), |
| 41 ran_mixed_content_(false), |
| 42 malicious_content_status_(MALICIOUS_CONTENT_STATUS_NONE), |
| 43 displayed_password_field_on_http_(false), |
| 44 displayed_credit_card_field_on_http_(false) { |
| 45 cert_ = |
| 46 net::ImportCertFromFile(net::GetTestCertsDirectory(), "sha1_2016.pem"); |
| 47 } |
| 48 virtual ~TestSecurityStateHelper() {} |
| 49 |
| 50 void set_connection_status(int connection_status) { |
| 51 connection_status_ = connection_status; |
| 52 } |
| 53 void SetCipherSuite(uint16_t ciphersuite) { |
| 54 net::SSLConnectionStatusSetCipherSuite(ciphersuite, &connection_status_); |
| 55 } |
| 56 void AddCertStatus(net::CertStatus cert_status) { |
| 57 cert_status_ |= cert_status; |
| 58 } |
| 59 void SetDisplayedMixedContent(bool displayed_mixed_content) { |
| 60 displayed_mixed_content_ = displayed_mixed_content; |
| 61 } |
| 62 void SetRanMixedContent(bool ran_mixed_content) { |
| 63 ran_mixed_content_ = ran_mixed_content; |
| 64 } |
| 65 void set_malicious_content_status( |
| 66 MaliciousContentStatus malicious_content_status) { |
| 67 malicious_content_status_ = malicious_content_status; |
| 68 } |
| 69 void set_displayed_password_field_on_http( |
| 70 bool displayed_password_field_on_http) { |
| 71 displayed_password_field_on_http_ = displayed_password_field_on_http; |
| 72 } |
| 73 void set_displayed_credit_card_field_on_http( |
| 74 bool displayed_credit_card_field_on_http) { |
| 75 displayed_credit_card_field_on_http_ = displayed_credit_card_field_on_http; |
| 76 } |
| 77 |
| 78 void UseHttpUrl() { url_ = GURL(kHttpUrl); } |
| 79 |
| 80 std::unique_ptr<VisibleSecurityState> GetVisibleSecurityState() { |
| 81 auto state = base::MakeUnique<VisibleSecurityState>(); |
| 82 state->connection_info_initialized = true; |
| 83 state->url = url_; |
| 84 state->certificate = cert_; |
| 85 state->cert_status = cert_status_; |
| 86 state->connection_status = connection_status_; |
| 87 state->security_bits = 256; |
| 88 state->displayed_mixed_content = displayed_mixed_content_; |
| 89 state->ran_mixed_content = ran_mixed_content_; |
| 90 state->malicious_content_status = malicious_content_status_; |
| 91 state->displayed_password_field_on_http = displayed_password_field_on_http_; |
| 92 state->displayed_credit_card_field_on_http = |
| 93 displayed_credit_card_field_on_http_; |
| 94 return state; |
| 95 } |
| 96 |
| 97 void GetSecurityInfo(SecurityInfo* security_info) { |
| 98 security_state::GetSecurityInfo( |
| 99 GetVisibleSecurityState(), |
| 100 false /* used policy installed certificate */, |
| 101 base::Bind(&IsOriginSecure), security_info); |
| 102 } |
| 103 |
| 104 private: |
| 105 GURL url_; |
| 106 scoped_refptr<net::X509Certificate> cert_; |
| 107 int connection_status_; |
| 108 net::CertStatus cert_status_; |
| 109 bool displayed_mixed_content_; |
| 110 bool ran_mixed_content_; |
| 111 MaliciousContentStatus malicious_content_status_; |
| 112 bool displayed_password_field_on_http_; |
| 113 bool displayed_credit_card_field_on_http_; |
| 114 }; |
| 115 |
| 116 } // namespace |
| 117 |
| 118 // Tests that SHA1-signed certificates expiring in 2016 downgrade the |
| 119 // security state of the page. |
| 120 TEST(SecurityStateTest, SHA1Warning) { |
| 121 TestSecurityStateHelper helper; |
| 122 SecurityInfo security_info; |
| 123 helper.GetSecurityInfo(&security_info); |
| 124 EXPECT_EQ(DEPRECATED_SHA1_MINOR, security_info.sha1_deprecation_status); |
| 125 EXPECT_EQ(NONE, security_info.security_level); |
| 126 } |
| 127 |
| 128 // Tests that SHA1 warnings don't interfere with the handling of mixed |
| 129 // content. |
| 130 TEST(SecurityStateTest, SHA1WarningMixedContent) { |
| 131 TestSecurityStateHelper helper; |
| 132 helper.SetDisplayedMixedContent(true); |
| 133 SecurityInfo security_info1; |
| 134 helper.GetSecurityInfo(&security_info1); |
| 135 EXPECT_EQ(DEPRECATED_SHA1_MINOR, security_info1.sha1_deprecation_status); |
| 136 EXPECT_EQ(CONTENT_STATUS_DISPLAYED, security_info1.mixed_content_status); |
| 137 EXPECT_EQ(NONE, security_info1.security_level); |
| 138 |
| 139 helper.SetDisplayedMixedContent(false); |
| 140 helper.SetRanMixedContent(true); |
| 141 SecurityInfo security_info2; |
| 142 helper.GetSecurityInfo(&security_info2); |
| 143 EXPECT_EQ(DEPRECATED_SHA1_MINOR, security_info2.sha1_deprecation_status); |
| 144 EXPECT_EQ(CONTENT_STATUS_RAN, security_info2.mixed_content_status); |
| 145 EXPECT_EQ(DANGEROUS, security_info2.security_level); |
| 146 } |
| 147 |
| 148 // Tests that SHA1 warnings don't interfere with the handling of major |
| 149 // cert errors. |
| 150 TEST(SecurityStateTest, SHA1WarningBrokenHTTPS) { |
| 151 TestSecurityStateHelper helper; |
| 152 helper.AddCertStatus(net::CERT_STATUS_DATE_INVALID); |
| 153 SecurityInfo security_info; |
| 154 helper.GetSecurityInfo(&security_info); |
| 155 EXPECT_EQ(DEPRECATED_SHA1_MINOR, security_info.sha1_deprecation_status); |
| 156 EXPECT_EQ(DANGEROUS, security_info.security_level); |
| 157 } |
| 158 |
| 159 // Tests that |security_info.is_secure_protocol_and_ciphersuite| is |
| 160 // computed correctly. |
| 161 TEST(SecurityStateTest, SecureProtocolAndCiphersuite) { |
| 162 TestSecurityStateHelper helper; |
| 163 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 from |
| 164 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-param
eters-4 |
| 165 const uint16_t ciphersuite = 0xc02f; |
| 166 helper.set_connection_status(net::SSL_CONNECTION_VERSION_TLS1_2 |
| 167 << net::SSL_CONNECTION_VERSION_SHIFT); |
| 168 helper.SetCipherSuite(ciphersuite); |
| 169 SecurityInfo security_info; |
| 170 helper.GetSecurityInfo(&security_info); |
| 171 EXPECT_EQ(net::OBSOLETE_SSL_NONE, security_info.obsolete_ssl_status); |
| 172 } |
| 173 |
| 174 TEST(SecurityStateTest, NonsecureProtocol) { |
| 175 TestSecurityStateHelper helper; |
| 176 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 from |
| 177 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-param
eters-4 |
| 178 const uint16_t ciphersuite = 0xc02f; |
| 179 helper.set_connection_status(net::SSL_CONNECTION_VERSION_TLS1_1 |
| 180 << net::SSL_CONNECTION_VERSION_SHIFT); |
| 181 helper.SetCipherSuite(ciphersuite); |
| 182 SecurityInfo security_info; |
| 183 helper.GetSecurityInfo(&security_info); |
| 184 EXPECT_EQ(net::OBSOLETE_SSL_MASK_PROTOCOL, security_info.obsolete_ssl_status); |
| 185 } |
| 186 |
| 187 TEST(SecurityStateTest, NonsecureCiphersuite) { |
| 188 TestSecurityStateHelper helper; |
| 189 // TLS_RSA_WITH_AES_128_CCM_8 from |
| 190 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-param
eters-4 |
| 191 const uint16_t ciphersuite = 0xc0a0; |
| 192 helper.set_connection_status(net::SSL_CONNECTION_VERSION_TLS1_2 |
| 193 << net::SSL_CONNECTION_VERSION_SHIFT); |
| 194 helper.SetCipherSuite(ciphersuite); |
| 195 SecurityInfo security_info; |
| 196 helper.GetSecurityInfo(&security_info); |
| 197 EXPECT_EQ(net::OBSOLETE_SSL_MASK_KEY_EXCHANGE | net::OBSOLETE_SSL_MASK_CIPHER, |
| 198 security_info.obsolete_ssl_status); |
| 199 } |
| 200 |
| 201 // Tests that the malware/phishing status is set, and it overrides valid HTTPS. |
| 202 TEST(SecurityStateTest, MalwareOverride) { |
| 203 TestSecurityStateHelper helper; |
| 204 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 from |
| 205 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-param
eters-4 |
| 206 const uint16_t ciphersuite = 0xc02f; |
| 207 helper.set_connection_status(net::SSL_CONNECTION_VERSION_TLS1_2 |
| 208 << net::SSL_CONNECTION_VERSION_SHIFT); |
| 209 helper.SetCipherSuite(ciphersuite); |
| 210 |
| 211 SecurityInfo security_info; |
| 212 helper.GetSecurityInfo(&security_info); |
| 213 EXPECT_EQ(MALICIOUS_CONTENT_STATUS_NONE, |
| 214 security_info.malicious_content_status); |
| 215 |
| 216 helper.set_malicious_content_status(MALICIOUS_CONTENT_STATUS_MALWARE); |
| 217 helper.GetSecurityInfo(&security_info); |
| 218 |
| 219 EXPECT_EQ(MALICIOUS_CONTENT_STATUS_MALWARE, |
| 220 security_info.malicious_content_status); |
| 221 EXPECT_EQ(DANGEROUS, security_info.security_level); |
| 222 } |
| 223 |
| 224 // Tests that the malware/phishing status is set, even if other connection info |
| 225 // is not available. |
| 226 TEST(SecurityStateTest, MalwareWithoutConnectionState) { |
| 227 TestSecurityStateHelper helper; |
| 228 helper.set_malicious_content_status( |
| 229 MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING); |
| 230 SecurityInfo security_info; |
| 231 helper.GetSecurityInfo(&security_info); |
| 232 EXPECT_EQ(MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING, |
| 233 security_info.malicious_content_status); |
| 234 EXPECT_EQ(DANGEROUS, security_info.security_level); |
| 235 } |
| 236 |
| 237 // Tests that password fields cause the security level to be downgraded |
| 238 // to HTTP_SHOW_WARNING when the command-line switch is set. |
| 239 TEST(SecurityStateTest, PasswordFieldWarning) { |
| 240 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| 241 switches::kMarkHttpAs, switches::kMarkHttpWithPasswordsOrCcWithChip); |
| 242 TestSecurityStateHelper helper; |
| 243 helper.UseHttpUrl(); |
| 244 helper.set_displayed_password_field_on_http(true); |
| 245 SecurityInfo security_info; |
| 246 helper.GetSecurityInfo(&security_info); |
| 247 EXPECT_TRUE(security_info.displayed_password_field_on_http); |
| 248 EXPECT_EQ(HTTP_SHOW_WARNING, security_info.security_level); |
| 249 } |
| 250 |
| 251 // Tests that credit card fields cause the security level to be downgraded |
| 252 // to HTTP_SHOW_WARNING when the command-line switch is set. |
| 253 TEST(SecurityStateTest, CreditCardFieldWarning) { |
| 254 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| 255 switches::kMarkHttpAs, switches::kMarkHttpWithPasswordsOrCcWithChip); |
| 256 TestSecurityStateHelper helper; |
| 257 helper.UseHttpUrl(); |
| 258 helper.set_displayed_credit_card_field_on_http(true); |
| 259 SecurityInfo security_info; |
| 260 helper.GetSecurityInfo(&security_info); |
| 261 EXPECT_TRUE(security_info.displayed_credit_card_field_on_http); |
| 262 EXPECT_EQ(HTTP_SHOW_WARNING, security_info.security_level); |
| 263 } |
| 264 |
| 265 // Tests that neither password nor credit fields cause the security |
| 266 // level to be downgraded to HTTP_SHOW_WARNING when the command-line switch |
| 267 // is NOT set. |
| 268 TEST(SecurityStateTest, HttpWarningNotSetWithoutSwitch) { |
| 269 TestSecurityStateHelper helper; |
| 270 helper.UseHttpUrl(); |
| 271 helper.set_displayed_password_field_on_http(true); |
| 272 SecurityInfo security_info; |
| 273 helper.GetSecurityInfo(&security_info); |
| 274 EXPECT_TRUE(security_info.displayed_password_field_on_http); |
| 275 EXPECT_EQ(NONE, security_info.security_level); |
| 276 |
| 277 helper.set_displayed_credit_card_field_on_http(true); |
| 278 helper.GetSecurityInfo(&security_info); |
| 279 EXPECT_TRUE(security_info.displayed_credit_card_field_on_http); |
| 280 EXPECT_EQ(NONE, security_info.security_level); |
| 281 } |
| 282 |
| 283 // Tests that neither |displayed_password_field_on_http| nor |
| 284 // |displayed_credit_card_field_on_http| is set when the corresponding |
| 285 // VisibleSecurityState flags are not set. |
| 286 TEST(SecurityStateTest, PrivateUserDataNotSet) { |
| 287 TestSecurityStateHelper helper; |
| 288 helper.UseHttpUrl(); |
| 289 SecurityInfo security_info; |
| 290 helper.GetSecurityInfo(&security_info); |
| 291 EXPECT_FALSE(security_info.displayed_password_field_on_http); |
| 292 EXPECT_FALSE(security_info.displayed_credit_card_field_on_http); |
| 293 EXPECT_EQ(NONE, security_info.security_level); |
| 294 } |
| 295 |
| 296 // Tests that SSL.MarkHttpAsStatus histogram is updated when security state is |
| 297 // computed for a page. |
| 298 TEST(SecurityStateTest, MarkHttpAsStatusHistogram) { |
| 299 const char* kHistogramName = "SSL.MarkHttpAsStatus"; |
| 300 base::HistogramTester histograms; |
| 301 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| 302 switches::kMarkHttpAs, switches::kMarkHttpWithPasswordsOrCcWithChip); |
| 303 TestSecurityStateHelper helper; |
| 304 helper.UseHttpUrl(); |
| 305 |
| 306 // Ensure histogram recorded correctly when a non-secure password input is |
| 307 // found on the page. |
| 308 helper.set_displayed_password_field_on_http(true); |
| 309 SecurityInfo security_info; |
| 310 histograms.ExpectTotalCount(kHistogramName, 0); |
| 311 helper.GetSecurityInfo(&security_info); |
| 312 histograms.ExpectUniqueSample(kHistogramName, 2 /* HTTP_SHOW_WARNING */, 1); |
| 313 |
| 314 // Ensure histogram recorded correctly even without a password input. |
| 315 helper.set_displayed_password_field_on_http(false); |
| 316 helper.GetSecurityInfo(&security_info); |
| 317 histograms.ExpectUniqueSample(kHistogramName, 2 /* HTTP_SHOW_WARNING */, 2); |
| 318 } |
| 319 |
| 320 } // namespace security_state |
OLD | NEW |