1 // Copyright (c) 2012 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 "net/http/transport_security_state.h" 6 7 #include <algorithm> 8 #include <string> 9 #include <vector> 10 11 #include "base/base64.h" 12 #include "base/files/file_path.h" 13 #include "base/sha1.h" 14 #include "base/strings/string_piece.h" 15 #include "crypto/sha2.h" 16 #include "net/base/net_errors.h" 17 #include "net/base/net_log.h" 18 #include "net/base/test_completion_callback.h" 19 #include "net/base/test_data_directory.h" 20 #include "net/cert/asn1_util.h" 21 #include "net/cert/cert_verifier.h" 22 #include "net/cert/cert_verify_result.h" 23 #include "net/cert/test_root_certs.h" 24 #include "net/cert/x509_cert_types.h" 25 #include "net/cert/x509_certificate.h" 26 #include "net/http/http_util.h" 27 #include "net/ssl/ssl_info.h" 28 #include "net/test/cert_test_util.h" 29 #include "testing/gtest/include/gtest/gtest.h" 30 31 #if defined(USE_OPENSSL) 32 #include "crypto/openssl_util.h" 33 #else 34 #include "crypto/nss_util.h" 35 #endif 36 37 namespace net { 38 39 class TransportSecurityStateTest : public testing::Test { 40 virtual void SetUp() { 41 #if defined(USE_OPENSSL) 42 crypto::EnsureOpenSSLInit(); 43 #else 44 crypto::EnsureNSSInit(); 45 #endif 46 } 47 48 protected: 49 std::string CanonicalizeHost(const std::string& host) { 50 return TransportSecurityState::CanonicalizeHost(host); 51 } 52 53 bool GetStaticDomainState(TransportSecurityState* state, 54 const std::string& host, 55 bool sni_enabled, 56 TransportSecurityState::DomainState* result) { 57 return state->GetStaticDomainState(host, sni_enabled, result); 58 } 59 60 void EnableHost(TransportSecurityState* state, 61 const std::string& host, 62 const TransportSecurityState::DomainState& domain_state) { 63 return state->EnableHost(host, domain_state); 64 } 65 }; 66 67 TEST_F(TransportSecurityStateTest, SimpleMatches) { 68 TransportSecurityState state; 69 TransportSecurityState::DomainState domain_state; 70 const base::Time current_time(base::Time::Now()); 71 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); 72 73 EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); 74 bool include_subdomains = false; 75 state.AddHSTS("yahoo.com", expiry, include_subdomains); 76 EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state)); 77 } 78 79 TEST_F(TransportSecurityStateTest, MatchesCase1) { 80 TransportSecurityState state; 81 TransportSecurityState::DomainState domain_state; 82 const base::Time current_time(base::Time::Now()); 83 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); 84 85 EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); 86 bool include_subdomains = false; 87 state.AddHSTS("YAhoo.coM", expiry, include_subdomains); 88 EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state)); 89 } 90 91 TEST_F(TransportSecurityStateTest, MatchesCase2) { 92 TransportSecurityState state; 93 TransportSecurityState::DomainState domain_state; 94 const base::Time current_time(base::Time::Now()); 95 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); 96 97 EXPECT_FALSE(state.GetDomainState("YAhoo.coM", true, &domain_state)); 98 bool include_subdomains = false; 99 state.AddHSTS("yahoo.com", expiry, include_subdomains); 100 EXPECT_TRUE(state.GetDomainState("YAhoo.coM", true, &domain_state)); 101 } 102 103 TEST_F(TransportSecurityStateTest, SubdomainMatches) { 104 TransportSecurityState state; 105 TransportSecurityState::DomainState domain_state; 106 const base::Time current_time(base::Time::Now()); 107 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); 108 109 EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); 110 bool include_subdomains = true; 111 state.AddHSTS("yahoo.com", expiry, include_subdomains); 112 EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state)); 113 EXPECT_TRUE(state.GetDomainState("foo.yahoo.com", true, &domain_state)); 114 EXPECT_TRUE(state.GetDomainState("foo.bar.yahoo.com", true, &domain_state)); 115 EXPECT_TRUE(state.GetDomainState("foo.bar.baz.yahoo.com", true, 116 &domain_state)); 117 EXPECT_FALSE(state.GetDomainState("com", true, &domain_state)); 118 } 119 120 TEST_F(TransportSecurityStateTest, DeleteAllDynamicDataSince) { 121 TransportSecurityState state; 122 TransportSecurityState::DomainState domain_state; 123 const base::Time current_time(base::Time::Now()); 124 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); 125 const base::Time older = current_time - base::TimeDelta::FromSeconds(1000); 126 127 EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); 128 bool include_subdomains = false; 129 state.AddHSTS("yahoo.com", expiry, include_subdomains); 130 131 state.DeleteAllDynamicDataSince(expiry); 132 EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state)); 133 state.DeleteAllDynamicDataSince(older); 134 EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); 135 } 136 137 TEST_F(TransportSecurityStateTest, DeleteDynamicDataForHost) { 138 TransportSecurityState state; 139 TransportSecurityState::DomainState domain_state; 140 const base::Time current_time(base::Time::Now()); 141 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); 142 bool include_subdomains = false; 143 state.AddHSTS("yahoo.com", expiry, include_subdomains); 144 145 EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state)); 146 EXPECT_FALSE(state.GetDomainState("example.com", true, &domain_state)); 147 EXPECT_TRUE(state.DeleteDynamicDataForHost("yahoo.com")); 148 EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); 149 } 150 151 TEST_F(TransportSecurityStateTest, IsPreloaded) { 152 const std::string paypal = CanonicalizeHost("paypal.com"); 153 const std::string www_paypal = CanonicalizeHost("www.paypal.com"); 154 const std::string foo_paypal = CanonicalizeHost("foo.paypal.com"); 155 const std::string a_www_paypal = CanonicalizeHost("a.www.paypal.com"); 156 const std::string abc_paypal = CanonicalizeHost("a.b.c.paypal.com"); 157 const std::string example = CanonicalizeHost("example.com"); 158 const std::string aypal = CanonicalizeHost("aypal.com"); 159 160 TransportSecurityState state; 161 TransportSecurityState::DomainState domain_state; 162 163 EXPECT_TRUE(GetStaticDomainState(&state, paypal, true, &domain_state)); 164 EXPECT_TRUE(GetStaticDomainState(&state, www_paypal, true, &domain_state)); 165 EXPECT_FALSE(domain_state.sts_include_subdomains); 166 EXPECT_FALSE(domain_state.pkp_include_subdomains); 167 EXPECT_FALSE(GetStaticDomainState(&state, a_www_paypal, true, &domain_state)); 168 EXPECT_FALSE(GetStaticDomainState(&state, abc_paypal, true, &domain_state)); 169 EXPECT_FALSE(GetStaticDomainState(&state, example, true, &domain_state)); 170 EXPECT_FALSE(GetStaticDomainState(&state, aypal, true, &domain_state)); 171 } 172 173 TEST_F(TransportSecurityStateTest, PreloadedDomainSet) { 174 TransportSecurityState state; 175 TransportSecurityState::DomainState domain_state; 176 177 // The domain wasn't being set, leading to a blank string in the 178 // chrome://net-internals/#hsts UI. So test that. 179 EXPECT_TRUE(state.GetDomainState("market.android.com", true, &domain_state)); 180 EXPECT_EQ(domain_state.domain, "market.android.com"); 181 EXPECT_TRUE(state.GetDomainState("sub.market.android.com", true, 182 &domain_state)); 183 EXPECT_EQ(domain_state.domain, "market.android.com"); 184 } 185 186 static bool ShouldRedirect(const char* hostname) { 187 TransportSecurityState state; 188 TransportSecurityState::DomainState domain_state; 189 return state.GetDomainState(hostname, true /* SNI ok */, &domain_state) && 190 domain_state.ShouldUpgradeToSSL(); 191 } 192 193 static bool HasState(const char* hostname) { 194 TransportSecurityState state; 195 TransportSecurityState::DomainState domain_state; 196 return state.GetDomainState(hostname, true /* SNI ok */, &domain_state); 197 } 198 199 static bool HasPublicKeyPins(const char* hostname, bool sni_enabled) { 200 TransportSecurityState state; 201 TransportSecurityState::DomainState domain_state; 202 if (!state.GetDomainState(hostname, sni_enabled, &domain_state)) 203 return false; 204 205 return domain_state.HasPublicKeyPins(); 206 } 207 208 static bool HasPublicKeyPins(const char* hostname) { 209 return HasPublicKeyPins(hostname, true); 210 } 211 212 static bool OnlyPinning(const char *hostname) { 213 TransportSecurityState state; 214 TransportSecurityState::DomainState domain_state; 215 if (!state.GetDomainState(hostname, true /* SNI ok */, &domain_state)) 216 return false; 217 218 return (domain_state.static_spki_hashes.size() > 0 || 219 domain_state.bad_static_spki_hashes.size() > 0 || 220 domain_state.dynamic_spki_hashes.size() > 0) && 221 !domain_state.ShouldUpgradeToSSL(); 222 } 223 224 TEST_F(TransportSecurityStateTest, Preloaded) { 225 TransportSecurityState state; 226 TransportSecurityState::DomainState domain_state; 227 228 // We do more extensive checks for the first domain. 229 EXPECT_TRUE(state.GetDomainState("www.paypal.com", true, &domain_state)); 230 EXPECT_EQ(domain_state.upgrade_mode, 231 TransportSecurityState::DomainState::MODE_FORCE_HTTPS); 232 EXPECT_FALSE(domain_state.sts_include_subdomains); 233 EXPECT_FALSE(domain_state.pkp_include_subdomains); 234 235 EXPECT_TRUE(HasState("paypal.com")); 236 EXPECT_FALSE(HasState("www2.paypal.com")); 237 EXPECT_FALSE(HasState("www2.paypal.com")); 238 239 // Google hosts: 240 241 EXPECT_TRUE(ShouldRedirect("chrome.google.com")); 242 EXPECT_TRUE(ShouldRedirect("checkout.google.com")); 243 EXPECT_TRUE(ShouldRedirect("health.google.com")); 244 EXPECT_TRUE(ShouldRedirect("docs.google.com")); 245 EXPECT_TRUE(ShouldRedirect("sites.google.com")); 246 EXPECT_TRUE(ShouldRedirect("drive.google.com")); 247 EXPECT_TRUE(ShouldRedirect("spreadsheets.google.com")); 248 EXPECT_TRUE(ShouldRedirect("appengine.google.com")); 249 EXPECT_TRUE(ShouldRedirect("market.android.com")); 250 EXPECT_TRUE(ShouldRedirect("encrypted.google.com")); 251 EXPECT_TRUE(ShouldRedirect("accounts.google.com")); 252 EXPECT_TRUE(ShouldRedirect("profiles.google.com")); 253 EXPECT_TRUE(ShouldRedirect("mail.google.com")); 254 EXPECT_TRUE(ShouldRedirect("chatenabled.mail.google.com")); 255 EXPECT_TRUE(ShouldRedirect("talkgadget.google.com")); 256 EXPECT_TRUE(ShouldRedirect("hostedtalkgadget.google.com")); 257 EXPECT_TRUE(ShouldRedirect("talk.google.com")); 258 EXPECT_TRUE(ShouldRedirect("plus.google.com")); 259 EXPECT_TRUE(ShouldRedirect("groups.google.com")); 260 EXPECT_TRUE(ShouldRedirect("apis.google.com")); 261 EXPECT_FALSE(ShouldRedirect("chart.apis.google.com")); 262 EXPECT_TRUE(ShouldRedirect("ssl.google-analytics.com")); 263 EXPECT_TRUE(ShouldRedirect("gmail.com")); 264 EXPECT_TRUE(ShouldRedirect("www.gmail.com")); 265 EXPECT_TRUE(ShouldRedirect("googlemail.com")); 266 EXPECT_TRUE(ShouldRedirect("www.googlemail.com")); 267 EXPECT_TRUE(ShouldRedirect("googleplex.com")); 268 EXPECT_TRUE(ShouldRedirect("www.googleplex.com")); 269 EXPECT_FALSE(HasState("m.gmail.com")); 270 EXPECT_FALSE(HasState("m.googlemail.com")); 271 272 EXPECT_TRUE(OnlyPinning("www.google.com")); 273 EXPECT_TRUE(OnlyPinning("foo.google.com")); 274 EXPECT_TRUE(OnlyPinning("google.com")); 275 EXPECT_TRUE(OnlyPinning("www.youtube.com")); 276 EXPECT_TRUE(OnlyPinning("youtube.com")); 277 EXPECT_TRUE(OnlyPinning("i.ytimg.com")); 278 EXPECT_TRUE(OnlyPinning("ytimg.com")); 279 EXPECT_TRUE(OnlyPinning("googleusercontent.com")); 280 EXPECT_TRUE(OnlyPinning("www.googleusercontent.com")); 281 EXPECT_TRUE(OnlyPinning("www.google-analytics.com")); 282 EXPECT_TRUE(OnlyPinning("googleapis.com")); 283 EXPECT_TRUE(OnlyPinning("googleadservices.com")); 284 EXPECT_TRUE(OnlyPinning("googlecode.com")); 285 EXPECT_TRUE(OnlyPinning("appspot.com")); 286 EXPECT_TRUE(OnlyPinning("googlesyndication.com")); 287 EXPECT_TRUE(OnlyPinning("doubleclick.net")); 288 EXPECT_TRUE(OnlyPinning("googlegroups.com")); 289 290 // Tests for domains that don't work without SNI. 291 EXPECT_FALSE(state.GetDomainState("gmail.com", false, &domain_state)); 292 EXPECT_FALSE(state.GetDomainState("www.gmail.com", false, &domain_state)); 293 EXPECT_FALSE(state.GetDomainState("m.gmail.com", false, &domain_state)); 294 EXPECT_FALSE(state.GetDomainState("googlemail.com", false, &domain_state)); 295 EXPECT_FALSE(state.GetDomainState("www.googlemail.com", false, 296 &domain_state)); 297 EXPECT_FALSE(state.GetDomainState("m.googlemail.com", false, &domain_state)); 298 299 // Other hosts: 300 301 EXPECT_TRUE(ShouldRedirect("aladdinschools.appspot.com")); 302 303 EXPECT_TRUE(ShouldRedirect("ottospora.nl")); 304 EXPECT_TRUE(ShouldRedirect("www.ottospora.nl")); 305 306 EXPECT_TRUE(ShouldRedirect("www.paycheckrecords.com")); 307 308 EXPECT_TRUE(ShouldRedirect("lastpass.com")); 309 EXPECT_TRUE(ShouldRedirect("www.lastpass.com")); 310 EXPECT_FALSE(HasState("blog.lastpass.com")); 311 312 EXPECT_TRUE(ShouldRedirect("keyerror.com")); 313 EXPECT_TRUE(ShouldRedirect("www.keyerror.com")); 314 315 EXPECT_TRUE(ShouldRedirect("entropia.de")); 316 EXPECT_TRUE(ShouldRedirect("www.entropia.de")); 317 EXPECT_FALSE(HasState("foo.entropia.de")); 318 319 EXPECT_TRUE(ShouldRedirect("www.elanex.biz")); 320 EXPECT_FALSE(HasState("elanex.biz")); 321 EXPECT_FALSE(HasState("foo.elanex.biz")); 322 323 EXPECT_TRUE(ShouldRedirect("sunshinepress.org")); 324 EXPECT_TRUE(ShouldRedirect("www.sunshinepress.org")); 325 EXPECT_TRUE(ShouldRedirect("a.b.sunshinepress.org")); 326 327 EXPECT_TRUE(ShouldRedirect("www.noisebridge.net")); 328 EXPECT_FALSE(HasState("noisebridge.net")); 329 EXPECT_FALSE(HasState("foo.noisebridge.net")); 330 331 EXPECT_TRUE(ShouldRedirect("neg9.org")); 332 EXPECT_FALSE(HasState("www.neg9.org")); 333 334 EXPECT_TRUE(ShouldRedirect("riseup.net")); 335 EXPECT_TRUE(ShouldRedirect("foo.riseup.net")); 336 337 EXPECT_TRUE(ShouldRedirect("factor.cc")); 338 EXPECT_FALSE(HasState("www.factor.cc")); 339 340 EXPECT_TRUE(ShouldRedirect("members.mayfirst.org")); 341 EXPECT_TRUE(ShouldRedirect("support.mayfirst.org")); 342 EXPECT_TRUE(ShouldRedirect("id.mayfirst.org")); 343 EXPECT_TRUE(ShouldRedirect("lists.mayfirst.org")); 344 EXPECT_FALSE(HasState("www.mayfirst.org")); 345 346 EXPECT_TRUE(ShouldRedirect("romab.com")); 347 EXPECT_TRUE(ShouldRedirect("www.romab.com")); 348 EXPECT_TRUE(ShouldRedirect("foo.romab.com")); 349 350 EXPECT_TRUE(ShouldRedirect("logentries.com")); 351 EXPECT_TRUE(ShouldRedirect("www.logentries.com")); 352 EXPECT_FALSE(HasState("foo.logentries.com")); 353 354 EXPECT_TRUE(ShouldRedirect("stripe.com")); 355 EXPECT_TRUE(ShouldRedirect("foo.stripe.com")); 356 357 EXPECT_TRUE(ShouldRedirect("cloudsecurityalliance.org")); 358 EXPECT_TRUE(ShouldRedirect("foo.cloudsecurityalliance.org")); 359 360 EXPECT_TRUE(ShouldRedirect("login.sapo.pt")); 361 EXPECT_TRUE(ShouldRedirect("foo.login.sapo.pt")); 362 363 EXPECT_TRUE(ShouldRedirect("mattmccutchen.net")); 364 EXPECT_TRUE(ShouldRedirect("foo.mattmccutchen.net")); 365 366 EXPECT_TRUE(ShouldRedirect("betnet.fr")); 367 EXPECT_TRUE(ShouldRedirect("foo.betnet.fr")); 368 369 EXPECT_TRUE(ShouldRedirect("uprotect.it")); 370 EXPECT_TRUE(ShouldRedirect("foo.uprotect.it")); 371 372 EXPECT_TRUE(ShouldRedirect("squareup.com")); 373 EXPECT_FALSE(HasState("foo.squareup.com")); 374 375 EXPECT_TRUE(ShouldRedirect("cert.se")); 376 EXPECT_TRUE(ShouldRedirect("foo.cert.se")); 377 378 EXPECT_TRUE(ShouldRedirect("crypto.is")); 379 EXPECT_TRUE(ShouldRedirect("foo.crypto.is")); 380 381 EXPECT_TRUE(ShouldRedirect("simon.butcher.name")); 382 EXPECT_TRUE(ShouldRedirect("foo.simon.butcher.name")); 383 384 EXPECT_TRUE(ShouldRedirect("linx.net")); 385 EXPECT_TRUE(ShouldRedirect("foo.linx.net")); 386 387 EXPECT_TRUE(ShouldRedirect("dropcam.com")); 388 EXPECT_TRUE(ShouldRedirect("www.dropcam.com")); 389 EXPECT_FALSE(HasState("foo.dropcam.com")); 390 391 EXPECT_TRUE(state.GetDomainState("torproject.org", false, &domain_state)); 392 EXPECT_FALSE(domain_state.static_spki_hashes.empty()); 393 EXPECT_TRUE(state.GetDomainState("www.torproject.org", false, 394 &domain_state)); 395 EXPECT_FALSE(domain_state.static_spki_hashes.empty()); 396 EXPECT_TRUE(state.GetDomainState("check.torproject.org", false, 397 &domain_state)); 398 EXPECT_FALSE(domain_state.static_spki_hashes.empty()); 399 EXPECT_TRUE(state.GetDomainState("blog.torproject.org", false, 400 &domain_state)); 401 EXPECT_FALSE(domain_state.static_spki_hashes.empty()); 402 EXPECT_TRUE(ShouldRedirect("ebanking.indovinabank.com.vn")); 403 EXPECT_TRUE(ShouldRedirect("foo.ebanking.indovinabank.com.vn")); 404 405 EXPECT_TRUE(ShouldRedirect("epoxate.com")); 406 EXPECT_FALSE(HasState("foo.epoxate.com")); 407 408 EXPECT_TRUE(HasPublicKeyPins("torproject.org")); 409 EXPECT_TRUE(HasPublicKeyPins("www.torproject.org")); 410 EXPECT_TRUE(HasPublicKeyPins("check.torproject.org")); 411 EXPECT_TRUE(HasPublicKeyPins("blog.torproject.org")); 412 EXPECT_FALSE(HasState("foo.torproject.org")); 413 414 EXPECT_TRUE(ShouldRedirect("www.moneybookers.com")); 415 EXPECT_FALSE(HasState("moneybookers.com")); 416 417 EXPECT_TRUE(ShouldRedirect("ledgerscope.net")); 418 EXPECT_TRUE(ShouldRedirect("www.ledgerscope.net")); 419 EXPECT_FALSE(HasState("status.ledgerscope.net")); 420 421 EXPECT_TRUE(ShouldRedirect("foo.app.recurly.com")); 422 EXPECT_TRUE(ShouldRedirect("foo.api.recurly.com")); 423 424 EXPECT_TRUE(ShouldRedirect("greplin.com")); 425 EXPECT_TRUE(ShouldRedirect("www.greplin.com")); 426 EXPECT_FALSE(HasState("foo.greplin.com")); 427 428 EXPECT_TRUE(ShouldRedirect("luneta.nearbuysystems.com")); 429 EXPECT_TRUE(ShouldRedirect("foo.luneta.nearbuysystems.com")); 430 431 EXPECT_TRUE(ShouldRedirect("ubertt.org")); 432 EXPECT_TRUE(ShouldRedirect("foo.ubertt.org")); 433 434 EXPECT_TRUE(ShouldRedirect("pixi.me")); 435 EXPECT_TRUE(ShouldRedirect("www.pixi.me")); 436 437 EXPECT_TRUE(ShouldRedirect("grepular.com")); 438 EXPECT_TRUE(ShouldRedirect("www.grepular.com")); 439 440 EXPECT_TRUE(ShouldRedirect("mydigipass.com")); 441 EXPECT_FALSE(ShouldRedirect("foo.mydigipass.com")); 442 EXPECT_TRUE(ShouldRedirect("www.mydigipass.com")); 443 EXPECT_FALSE(ShouldRedirect("foo.www.mydigipass.com")); 444 EXPECT_TRUE(ShouldRedirect("developer.mydigipass.com")); 445 EXPECT_FALSE(ShouldRedirect("foo.developer.mydigipass.com")); 446 EXPECT_TRUE(ShouldRedirect("www.developer.mydigipass.com")); 447 EXPECT_FALSE(ShouldRedirect("foo.www.developer.mydigipass.com")); 448 EXPECT_TRUE(ShouldRedirect("sandbox.mydigipass.com")); 449 EXPECT_FALSE(ShouldRedirect("foo.sandbox.mydigipass.com")); 450 EXPECT_TRUE(ShouldRedirect("www.sandbox.mydigipass.com")); 451 EXPECT_FALSE(ShouldRedirect("foo.www.sandbox.mydigipass.com")); 452 453 EXPECT_TRUE(ShouldRedirect("crypto.cat")); 454 EXPECT_FALSE(ShouldRedirect("foo.crypto.cat")); 455 456 EXPECT_TRUE(ShouldRedirect("bigshinylock.minazo.net")); 457 EXPECT_TRUE(ShouldRedirect("foo.bigshinylock.minazo.net")); 458 459 EXPECT_TRUE(ShouldRedirect("crate.io")); 460 EXPECT_TRUE(ShouldRedirect("foo.crate.io")); 461 462 EXPECT_TRUE(HasPublicKeyPins("www.twitter.com")); 463 } 464 465 TEST_F(TransportSecurityStateTest, LongNames) { 466 TransportSecurityState state; 467 const char kLongName[] = 468 "lookupByWaveIdHashAndWaveIdIdAndWaveIdDomainAndWaveletIdIdAnd" 469 "WaveletIdDomainAndBlipBlipid"; 470 TransportSecurityState::DomainState domain_state; 471 // Just checks that we don't hit a NOTREACHED. 472 EXPECT_FALSE(state.GetDomainState(kLongName, true, &domain_state)); 473 } 474 475 TEST_F(TransportSecurityStateTest, BuiltinCertPins) { 476 TransportSecurityState state; 477 TransportSecurityState::DomainState domain_state; 478 479 EXPECT_TRUE(state.GetDomainState("chrome.google.com", true, &domain_state)); 480 EXPECT_TRUE(HasPublicKeyPins("chrome.google.com")); 481 482 HashValueVector hashes; 483 // Checks that a built-in list does exist. 484 EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes)); 485 EXPECT_FALSE(HasPublicKeyPins("www.paypal.com")); 486 487 EXPECT_TRUE(HasPublicKeyPins("docs.google.com")); 488 EXPECT_TRUE(HasPublicKeyPins("1.docs.google.com")); 489 EXPECT_TRUE(HasPublicKeyPins("sites.google.com")); 490 EXPECT_TRUE(HasPublicKeyPins("drive.google.com")); 491 EXPECT_TRUE(HasPublicKeyPins("spreadsheets.google.com")); 492 EXPECT_TRUE(HasPublicKeyPins("health.google.com")); 493 EXPECT_TRUE(HasPublicKeyPins("checkout.google.com")); 494 EXPECT_TRUE(HasPublicKeyPins("appengine.google.com")); 495 EXPECT_TRUE(HasPublicKeyPins("market.android.com")); 496 EXPECT_TRUE(HasPublicKeyPins("encrypted.google.com")); 497 EXPECT_TRUE(HasPublicKeyPins("accounts.google.com")); 498 EXPECT_TRUE(HasPublicKeyPins("profiles.google.com")); 499 EXPECT_TRUE(HasPublicKeyPins("mail.google.com")); 500 EXPECT_TRUE(HasPublicKeyPins("chatenabled.mail.google.com")); 501 EXPECT_TRUE(HasPublicKeyPins("talkgadget.google.com")); 502 EXPECT_TRUE(HasPublicKeyPins("hostedtalkgadget.google.com")); 503 EXPECT_TRUE(HasPublicKeyPins("talk.google.com")); 504 EXPECT_TRUE(HasPublicKeyPins("plus.google.com")); 505 EXPECT_TRUE(HasPublicKeyPins("groups.google.com")); 506 EXPECT_TRUE(HasPublicKeyPins("apis.google.com")); 507 508 EXPECT_TRUE(HasPublicKeyPins("ssl.gstatic.com")); 509 EXPECT_FALSE(HasPublicKeyPins("www.gstatic.com")); 510 EXPECT_TRUE(HasPublicKeyPins("ssl.google-analytics.com")); 511 EXPECT_TRUE(HasPublicKeyPins("www.googleplex.com")); 512 513 // Disabled in order to help track down pinning failures --agl 514 EXPECT_TRUE(HasPublicKeyPins("twitter.com")); 515 EXPECT_FALSE(HasPublicKeyPins("foo.twitter.com")); 516 EXPECT_TRUE(HasPublicKeyPins("www.twitter.com")); 517 EXPECT_TRUE(HasPublicKeyPins("api.twitter.com")); 518 EXPECT_TRUE(HasPublicKeyPins("oauth.twitter.com")); 519 EXPECT_TRUE(HasPublicKeyPins("mobile.twitter.com")); 520 EXPECT_TRUE(HasPublicKeyPins("dev.twitter.com")); 521 EXPECT_TRUE(HasPublicKeyPins("business.twitter.com")); 522 EXPECT_TRUE(HasPublicKeyPins("platform.twitter.com")); 523 EXPECT_TRUE(HasPublicKeyPins("si0.twimg.com")); 524 EXPECT_TRUE(HasPublicKeyPins("twimg0-a.akamaihd.net")); 525 } 526 527 static bool AddHash(const std::string& type_and_base64, 528 HashValueVector* out) { 529 HashValue hash; 530 if (!hash.FromString(type_and_base64)) 531 return false; 532 533 out->push_back(hash); 534 return true; 535 } 536 537 TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) { 538 // kGoodPath is plus.google.com via Google Internet Authority. 539 static const char* kGoodPath[] = { 540 "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", 541 "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0=", 542 "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=", 543 NULL, 544 }; 545 546 // kBadPath is plus.google.com via Trustcenter, which contains a required 547 // certificate (Equifax root), but also an excluded certificate 548 // (Trustcenter). 549 static const char* kBadPath[] = { 550 "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", 551 "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=", 552 "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=", 553 NULL, 554 }; 555 556 HashValueVector good_hashes, bad_hashes; 557 558 for (size_t i = 0; kGoodPath[i]; i++) { 559 EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes)); 560 } 561 for (size_t i = 0; kBadPath[i]; i++) { 562 EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes)); 563 } 564 565 TransportSecurityState state; 566 TransportSecurityState::DomainState domain_state; 567 EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state)); 568 EXPECT_TRUE(domain_state.HasPublicKeyPins()); 569 570 EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes)); 571 EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes)); 572 } 573 574 TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { 575 // kGoodPath is blog.torproject.org. 576 static const char* kGoodPath[] = { 577 "sha1/m9lHYJYke9k0GtVZ+bXSQYE8nDI=", 578 "sha1/o5OZxATDsgmwgcIfIWIneMJ0jkw=", 579 "sha1/wHqYaI2J+6sFZAwRfap9ZbjKzE4=", 580 NULL, 581 }; 582 583 // kBadPath is plus.google.com via Trustcenter, which is utterly wrong for 584 // torproject.org. 585 static const char* kBadPath[] = { 586 "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", 587 "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=", 588 "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=", 589 NULL, 590 }; 591 592 HashValueVector good_hashes, bad_hashes; 593 594 for (size_t i = 0; kGoodPath[i]; i++) { 595 EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes)); 596 } 597 for (size_t i = 0; kBadPath[i]; i++) { 598 EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes)); 599 } 600 601 TransportSecurityState state; 602 TransportSecurityState::DomainState domain_state; 603 EXPECT_TRUE(state.GetDomainState("blog.torproject.org", true, &domain_state)); 604 EXPECT_TRUE(domain_state.HasPublicKeyPins()); 605 606 EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes)); 607 EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes)); 608 } 609 610 TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCertsMixedHashes) { 611 static const char* ee_sha1 = "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU="; 612 static const char* ee_sha256 = 613 "sha256/sRJBQqWhpaKIGcc1NA7/jJ4vgWj+47oYfyU7waOS1+I="; 614 static const char* google_1024_sha1 = "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0="; 615 static const char* google_1024_sha256 = 616 "sha256/trlUMquuV/4CDLK3T0+fkXPIxwivyecyrOIyeQR8bQU="; 617 static const char* equifax_sha1 = "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q="; 618 static const char* equifax_sha256 = 619 "sha256//1aAzXOlcD2gSBegdf1GJQanNQbEuBoVg+9UlHjSZHY="; 620 static const char* trustcenter_sha1 = "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k="; 621 static const char* trustcenter_sha256 = 622 "sha256/Dq58KIA4NMLsboWMLU8/aTREzaAGEFW+EtUule8dd/M="; 623 624 // Good chains for plus.google.com chain up through google_1024_sha{1,256} 625 // to equifax_sha{1,256}. Bad chains chain up to Equifax through 626 // trustcenter_sha{1,256}, which is a blacklisted key. Even though Equifax 627 // and Google1024 are known-good, the blacklistedness of Trustcenter 628 // should override and cause pin validation failure. 629 630 TransportSecurityState state; 631 TransportSecurityState::DomainState domain_state; 632 EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state)); 633 EXPECT_TRUE(domain_state.HasPublicKeyPins()); 634 635 // The statically-defined pins are all SHA-1, so we add some SHA-256 pins 636 // manually: 637 EXPECT_TRUE(AddHash(google_1024_sha256, &domain_state.static_spki_hashes)); 638 EXPECT_TRUE(AddHash(trustcenter_sha256, 639 &domain_state.bad_static_spki_hashes)); 640 641 // Try an all-good SHA1 chain. 642 HashValueVector validated_chain; 643 EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); 644 EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain)); 645 EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); 646 EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain)); 647 648 // Try an all-bad SHA1 chain. 649 validated_chain.clear(); 650 EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); 651 EXPECT_TRUE(AddHash(trustcenter_sha1, &validated_chain)); 652 EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); 653 EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain)); 654 655 // Try an all-good SHA-256 chain. 656 validated_chain.clear(); 657 EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); 658 EXPECT_TRUE(AddHash(google_1024_sha256, &validated_chain)); 659 EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); 660 EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain)); 661 662 // Try an all-bad SHA-256 chain. 663 validated_chain.clear(); 664 EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); 665 EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain)); 666 EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); 667 EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain)); 668 669 // Try a mixed-hash good chain. 670 validated_chain.clear(); 671 EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); 672 EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain)); 673 EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); 674 EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain)); 675 676 // Try a mixed-hash bad chain. 677 validated_chain.clear(); 678 EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); 679 EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain)); 680 EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); 681 EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain)); 682 683 // Try a chain with all good hashes. 684 validated_chain.clear(); 685 EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); 686 EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain)); 687 EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); 688 EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); 689 EXPECT_TRUE(AddHash(google_1024_sha256, &validated_chain)); 690 EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); 691 EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain)); 692 693 // Try a chain with all bad hashes. 694 validated_chain.clear(); 695 EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); 696 EXPECT_TRUE(AddHash(trustcenter_sha1, &validated_chain)); 697 EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); 698 EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); 699 EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain)); 700 EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); 701 EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain)); 702 } 703 704 TEST_F(TransportSecurityStateTest, OptionalHSTSCertPins) { 705 TransportSecurityState state; 706 TransportSecurityState::DomainState domain_state; 707 708 EXPECT_FALSE(ShouldRedirect("www.google-analytics.com")); 709 710 EXPECT_FALSE(HasPublicKeyPins("www.google-analytics.com", false)); 711 EXPECT_TRUE(HasPublicKeyPins("www.google-analytics.com")); 712 EXPECT_TRUE(HasPublicKeyPins("google.com")); 713 EXPECT_TRUE(HasPublicKeyPins("www.google.com")); 714 EXPECT_TRUE(HasPublicKeyPins("mail-attachment.googleusercontent.com")); 715 EXPECT_TRUE(HasPublicKeyPins("www.youtube.com")); 716 EXPECT_TRUE(HasPublicKeyPins("i.ytimg.com")); 717 EXPECT_TRUE(HasPublicKeyPins("googleapis.com")); 718 EXPECT_TRUE(HasPublicKeyPins("ajax.googleapis.com")); 719 EXPECT_TRUE(HasPublicKeyPins("googleadservices.com")); 720 EXPECT_TRUE(HasPublicKeyPins("pagead2.googleadservices.com")); 721 EXPECT_TRUE(HasPublicKeyPins("googlecode.com")); 722 EXPECT_TRUE(HasPublicKeyPins("kibbles.googlecode.com")); 723 EXPECT_TRUE(HasPublicKeyPins("appspot.com")); 724 EXPECT_TRUE(HasPublicKeyPins("googlesyndication.com")); 725 EXPECT_TRUE(HasPublicKeyPins("doubleclick.net")); 726 EXPECT_TRUE(HasPublicKeyPins("ad.doubleclick.net")); 727 EXPECT_FALSE(HasPublicKeyPins("learn.doubleclick.net")); 728 EXPECT_TRUE(HasPublicKeyPins("a.googlegroups.com")); 729 EXPECT_FALSE(HasPublicKeyPins("a.googlegroups.com", false)); 730 } 731 732 TEST_F(TransportSecurityStateTest, OverrideBuiltins) { 733 EXPECT_TRUE(HasPublicKeyPins("google.com")); 734 EXPECT_FALSE(ShouldRedirect("google.com")); 735 EXPECT_FALSE(ShouldRedirect("www.google.com")); 736 737 TransportSecurityState state; 738 TransportSecurityState::DomainState domain_state; 739 const base::Time current_time(base::Time::Now()); 740 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); 741 domain_state.upgrade_expiry = expiry; 742 EnableHost(&state, "www.google.com", domain_state); 743 744 EXPECT_TRUE(state.GetDomainState("www.google.com", true, &domain_state)); 745 } 746 747 static const uint8 kSidePinLeafSPKI[] = { 748 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 749 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xe4, 750 0x1d, 0xcc, 0xf2, 0x92, 0xe7, 0x7a, 0xc6, 0x36, 0xf7, 0x1a, 0x62, 0x31, 0x7d, 751 0x37, 0xea, 0x0d, 0xa2, 0xa8, 0x12, 0x2b, 0xc2, 0x1c, 0x82, 0x3e, 0xa5, 0x70, 752 0x4a, 0x83, 0x5d, 0x9b, 0x84, 0x82, 0x70, 0xa4, 0x88, 0x98, 0x98, 0x41, 0x29, 753 0x31, 0xcb, 0x6e, 0x2a, 0x54, 0x65, 0x14, 0x60, 0xcc, 0x00, 0xe8, 0x10, 0x30, 754 0x0a, 0x4a, 0xd1, 0xa7, 0x52, 0xfe, 0x2d, 0x31, 0x2a, 0x1d, 0x0d, 0x02, 0x03, 755 0x01, 0x00, 0x01, 756 }; 757 758 static const uint8 kSidePinInfo[] = { 759 0x01, 0x00, 0x53, 0x50, 0x49, 0x4e, 0xa0, 0x00, 0x03, 0x00, 0x53, 0x49, 0x47, 760 0x00, 0x50, 0x55, 0x42, 0x4b, 0x41, 0x4c, 0x47, 0x4f, 0x47, 0x00, 0x41, 0x00, 761 0x04, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfb, 0x26, 0xd5, 0xe8, 0x76, 0x35, 762 0x96, 0x6d, 0x91, 0x9b, 0x5b, 0x27, 0xe6, 0x09, 0x1c, 0x7b, 0x6c, 0xcd, 0xc8, 763 0x10, 0x25, 0x95, 0xc0, 0xa5, 0xf6, 0x6c, 0x6f, 0xfb, 0x59, 0x1e, 0x2d, 0xf4, 764 0x02, 0x20, 0x33, 0x0a, 0xf8, 0x8b, 0x3e, 0xc4, 0xca, 0x75, 0x28, 0xdf, 0x5f, 765 0xab, 0xe4, 0x46, 0xa0, 0xdd, 0x2d, 0xe5, 0xad, 0xc3, 0x81, 0x44, 0x70, 0xb2, 766 0x10, 0x87, 0xe8, 0xc3, 0xd6, 0x6e, 0x12, 0x5d, 0x04, 0x67, 0x0b, 0x7d, 0xf2, 767 0x99, 0x75, 0x57, 0x99, 0x3a, 0x98, 0xf8, 0xe4, 0xdf, 0x79, 0xdf, 0x8e, 0x02, 768 0x2c, 0xbe, 0xd8, 0xfd, 0x75, 0x80, 0x18, 0xb1, 0x6f, 0x43, 0xd9, 0x8a, 0x79, 769 0xc3, 0x6e, 0x18, 0xdf, 0x79, 0xc0, 0x59, 0xab, 0xd6, 0x77, 0x37, 0x6a, 0x94, 770 0x5a, 0x7e, 0xfb, 0xa9, 0xc5, 0x54, 0x14, 0x3a, 0x7b, 0x97, 0x17, 0x2a, 0xb6, 771 0x1e, 0x59, 0x4f, 0x2f, 0xb1, 0x15, 0x1a, 0x34, 0x50, 0x32, 0x35, 0x36, 772 }; 773 774 static const uint8 kSidePinExpectedHash[20] = { 775 0xb5, 0x91, 0x66, 0x47, 0x43, 0x16, 0x62, 0x86, 0xd4, 0x1e, 0x5d, 0x36, 0xe1, 776 0xc4, 0x09, 0x3d, 0x2d, 0x1d, 0xea, 0x1e, 777 }; 778 779 TEST_F(TransportSecurityStateTest, GooglePinnedProperties) { 780 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 781 "www.example.com", true)); 782 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 783 "www.paypal.com", true)); 784 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 785 "mail.twitter.com", true)); 786 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 787 "www.google.com.int", true)); 788 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 789 "jottit.com", true)); 790 // learn.doubleclick.net has a more specific match than 791 // *.doubleclick.com, and has 0 or NULL for its required certs. 792 // This test ensures that the exact-match-preferred behavior 793 // works. 794 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 795 "learn.doubleclick.net", true)); 796 797 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 798 "encrypted.google.com", true)); 799 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 800 "mail.google.com", true)); 801 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 802 "accounts.google.com", true)); 803 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 804 "doubleclick.net", true)); 805 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 806 "ad.doubleclick.net", true)); 807 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 808 "youtube.com", true)); 809 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 810 "www.profiles.google.com", true)); 811 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 812 "checkout.google.com", true)); 813 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 814 "googleadservices.com", true)); 815 816 // Test with sni_enabled false: 817 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 818 "www.example.com", false)); 819 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 820 "www.paypal.com", false)); 821 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 822 "checkout.google.com", false)); 823 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 824 "googleadservices.com", false)); 825 826 // Test some SNI hosts: 827 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 828 "gmail.com", true)); 829 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 830 "googlegroups.com", true)); 831 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 832 "www.googlegroups.com", true)); 833 // Expect to fail for SNI hosts when not searching the SNI list: 834 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 835 "gmail.com", false)); 836 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 837 "googlegroups.com", false)); 838 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( 839 "www.googlegroups.com", false)); 840 } 841 842 } // namespace net 843