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 #if defined(USE_OPENSSL) 8 #include <openssl/ecdsa.h> 9 #include <openssl/ssl.h> 10 #else // !defined(USE_OPENSSL) 11 #include <cryptohi.h> 12 #include <hasht.h> 13 #include <keyhi.h> 14 #include <nspr.h> 15 #include <pk11pub.h> 16 #endif 17 18 #include <algorithm> 19 20 #include "base/base64.h" 21 #include "base/build_time.h" 22 #include "base/logging.h" 23 #include "base/memory/scoped_ptr.h" 24 #include "base/metrics/histogram.h" 25 #include "base/sha1.h" 26 #include "base/strings/string_number_conversions.h" 27 #include "base/strings/string_util.h" 28 #include "base/strings/utf_string_conversions.h" 29 #include "base/time/time.h" 30 #include "base/values.h" 31 #include "crypto/sha2.h" 32 #include "net/base/dns_util.h" 33 #include "net/cert/x509_cert_types.h" 34 #include "net/cert/x509_certificate.h" 35 #include "net/http/http_security_headers.h" 36 #include "net/ssl/ssl_info.h" 37 #include "url/gurl.h" 38 39 #if defined(USE_OPENSSL) 40 #include "crypto/openssl_util.h" 41 #endif 42 43 namespace net { 44 45 namespace { 46 47 std::string HashesToBase64String(const HashValueVector& hashes) { 48 std::string str; 49 for (size_t i = 0; i != hashes.size(); ++i) { 50 if (i != 0) 51 str += ","; 52 str += hashes[i].ToString(); 53 } 54 return str; 55 } 56 57 std::string HashHost(const std::string& canonicalized_host) { 58 char hashed[crypto::kSHA256Length]; 59 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed)); 60 return std::string(hashed, sizeof(hashed)); 61 } 62 63 // Returns true if the intersection of |a| and |b| is not empty. If either 64 // |a| or |b| is empty, returns false. 65 bool HashesIntersect(const HashValueVector& a, 66 const HashValueVector& b) { 67 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) { 68 HashValueVector::const_iterator j = 69 std::find_if(b.begin(), b.end(), HashValuesEqual(*i)); 70 if (j != b.end()) 71 return true; 72 } 73 return false; 74 } 75 76 bool AddHash(const char* sha1_hash, 77 HashValueVector* out) { 78 HashValue hash(HASH_VALUE_SHA1); 79 memcpy(hash.data(), sha1_hash, hash.size()); 80 out->push_back(hash); 81 return true; 82 } 83 84 } // namespace 85 86 TransportSecurityState::TransportSecurityState() 87 : delegate_(NULL) { 88 DCHECK(CalledOnValidThread()); 89 } 90 91 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) 92 : iterator_(state.enabled_hosts_.begin()), 93 end_(state.enabled_hosts_.end()) { 94 } 95 96 TransportSecurityState::Iterator::~Iterator() {} 97 98 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host, 99 bool sni_enabled) { 100 DomainState state; 101 if (GetStaticDomainState(host, sni_enabled, &state)) 102 return true; 103 return GetDynamicDomainState(host, &state); 104 } 105 106 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host, 107 bool sni_enabled) { 108 DomainState dynamic_state; 109 if (GetDynamicDomainState(host, &dynamic_state)) 110 return dynamic_state.ShouldUpgradeToSSL(); 111 112 DomainState static_state; 113 if (GetStaticDomainState(host, sni_enabled, &static_state) && 114 static_state.ShouldUpgradeToSSL()) { 115 return true; 116 } 117 118 return false; 119 } 120 121 bool TransportSecurityState::CheckPublicKeyPins(const std::string& host, 122 bool sni_enabled, 123 const HashValueVector& hashes, 124 std::string* failure_log) { 125 DomainState dynamic_state; 126 if (GetDynamicDomainState(host, &dynamic_state)) 127 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); 128 129 DomainState static_state; 130 if (GetStaticDomainState(host, sni_enabled, &static_state) && 131 static_state.CheckPublicKeyPins(hashes, failure_log)) { 132 return true; 133 } 134 135 return false; 136 } 137 138 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, 139 bool sni_enabled) { 140 DomainState dynamic_state; 141 if (GetDynamicDomainState(host, &dynamic_state)) 142 return dynamic_state.HasPublicKeyPins(); 143 144 DomainState static_state; 145 if (GetStaticDomainState(host, sni_enabled, &static_state)) { 146 if (static_state.HasPublicKeyPins()) 147 return true; 148 } 149 150 return false; 151 } 152 153 void TransportSecurityState::SetDelegate( 154 TransportSecurityState::Delegate* delegate) { 155 DCHECK(CalledOnValidThread()); 156 delegate_ = delegate; 157 } 158 159 void TransportSecurityState::EnableHost(const std::string& host, 160 const DomainState& state) { 161 DCHECK(CalledOnValidThread()); 162 163 const std::string canonicalized_host = CanonicalizeHost(host); 164 if (canonicalized_host.empty()) 165 return; 166 167 DomainState state_copy(state); 168 // No need to store this value since it is redundant. (|canonicalized_host| 169 // is the map key.) 170 state_copy.domain.clear(); 171 172 enabled_hosts_[HashHost(canonicalized_host)] = state_copy; 173 DirtyNotify(); 174 } 175 176 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) { 177 DCHECK(CalledOnValidThread()); 178 179 const std::string canonicalized_host = CanonicalizeHost(host); 180 if (canonicalized_host.empty()) 181 return false; 182 183 DomainStateMap::iterator i = enabled_hosts_.find( 184 HashHost(canonicalized_host)); 185 if (i != enabled_hosts_.end()) { 186 enabled_hosts_.erase(i); 187 DirtyNotify(); 188 return true; 189 } 190 return false; 191 } 192 193 void TransportSecurityState::ClearDynamicData() { 194 DCHECK(CalledOnValidThread()); 195 enabled_hosts_.clear(); 196 } 197 198 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { 199 DCHECK(CalledOnValidThread()); 200 201 bool dirtied = false; 202 DomainStateMap::iterator i = enabled_hosts_.begin(); 203 while (i != enabled_hosts_.end()) { 204 if (i->second.sts.last_observed >= time && 205 i->second.pkp.last_observed >= time) { 206 dirtied = true; 207 enabled_hosts_.erase(i++); 208 continue; 209 } 210 211 if (i->second.sts.last_observed >= time) { 212 dirtied = true; 213 i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT; 214 } else if (i->second.pkp.last_observed >= time) { 215 dirtied = true; 216 i->second.pkp.spki_hashes.clear(); 217 i->second.pkp.expiry = base::Time(); 218 } 219 ++i; 220 } 221 222 if (dirtied) 223 DirtyNotify(); 224 } 225 226 TransportSecurityState::~TransportSecurityState() { 227 DCHECK(CalledOnValidThread()); 228 } 229 230 void TransportSecurityState::DirtyNotify() { 231 DCHECK(CalledOnValidThread()); 232 233 if (delegate_) 234 delegate_->StateIsDirty(this); 235 } 236 237 // static 238 std::string TransportSecurityState::CanonicalizeHost(const std::string& host) { 239 // We cannot perform the operations as detailed in the spec here as |host| 240 // has already undergone IDN processing before it reached us. Thus, we check 241 // that there are no invalid characters in the host and lowercase the result. 242 243 std::string new_host; 244 if (!DNSDomainFromDot(host, &new_host)) { 245 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole 246 // name is >255 bytes. However, search terms can have those properties. 247 return std::string(); 248 } 249 250 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) { 251 const unsigned label_length = static_cast<unsigned>(new_host[i]); 252 if (!label_length) 253 break; 254 255 for (size_t j = 0; j < label_length; ++j) { 256 new_host[i + 1 + j] = tolower(new_host[i + 1 + j]); 257 } 258 } 259 260 return new_host; 261 } 262 263 // |ReportUMAOnPinFailure| uses these to report which domain was associated 264 // with the public key pinning failure. 265 // 266 // DO NOT CHANGE THE ORDERING OF THESE NAMES OR REMOVE ANY OF THEM. Add new 267 // domains at the END of the listing (but before DOMAIN_NUM_EVENTS). 268 enum SecondLevelDomainName { 269 DOMAIN_NOT_PINNED, 270 271 DOMAIN_GOOGLE_COM, 272 DOMAIN_ANDROID_COM, 273 DOMAIN_GOOGLE_ANALYTICS_COM, 274 DOMAIN_GOOGLEPLEX_COM, 275 DOMAIN_YTIMG_COM, 276 DOMAIN_GOOGLEUSERCONTENT_COM, 277 DOMAIN_YOUTUBE_COM, 278 DOMAIN_GOOGLEAPIS_COM, 279 DOMAIN_GOOGLEADSERVICES_COM, 280 DOMAIN_GOOGLECODE_COM, 281 DOMAIN_APPSPOT_COM, 282 DOMAIN_GOOGLESYNDICATION_COM, 283 DOMAIN_DOUBLECLICK_NET, 284 DOMAIN_GSTATIC_COM, 285 DOMAIN_GMAIL_COM, 286 DOMAIN_GOOGLEMAIL_COM, 287 DOMAIN_GOOGLEGROUPS_COM, 288 289 DOMAIN_TORPROJECT_ORG, 290 291 DOMAIN_TWITTER_COM, 292 DOMAIN_TWIMG_COM, 293 294 DOMAIN_AKAMAIHD_NET, 295 296 DOMAIN_TOR2WEB_ORG, 297 298 DOMAIN_YOUTU_BE, 299 DOMAIN_GOOGLECOMMERCE_COM, 300 DOMAIN_URCHIN_COM, 301 DOMAIN_GOO_GL, 302 DOMAIN_G_CO, 303 DOMAIN_GOOGLE_AC, 304 DOMAIN_GOOGLE_AD, 305 DOMAIN_GOOGLE_AE, 306 DOMAIN_GOOGLE_AF, 307 DOMAIN_GOOGLE_AG, 308 DOMAIN_GOOGLE_AM, 309 DOMAIN_GOOGLE_AS, 310 DOMAIN_GOOGLE_AT, 311 DOMAIN_GOOGLE_AZ, 312 DOMAIN_GOOGLE_BA, 313 DOMAIN_GOOGLE_BE, 314 DOMAIN_GOOGLE_BF, 315 DOMAIN_GOOGLE_BG, 316 DOMAIN_GOOGLE_BI, 317 DOMAIN_GOOGLE_BJ, 318 DOMAIN_GOOGLE_BS, 319 DOMAIN_GOOGLE_BY, 320 DOMAIN_GOOGLE_CA, 321 DOMAIN_GOOGLE_CAT, 322 DOMAIN_GOOGLE_CC, 323 DOMAIN_GOOGLE_CD, 324 DOMAIN_GOOGLE_CF, 325 DOMAIN_GOOGLE_CG, 326 DOMAIN_GOOGLE_CH, 327 DOMAIN_GOOGLE_CI, 328 DOMAIN_GOOGLE_CL, 329 DOMAIN_GOOGLE_CM, 330 DOMAIN_GOOGLE_CN, 331 DOMAIN_CO_AO, 332 DOMAIN_CO_BW, 333 DOMAIN_CO_CK, 334 DOMAIN_CO_CR, 335 DOMAIN_CO_HU, 336 DOMAIN_CO_ID, 337 DOMAIN_CO_IL, 338 DOMAIN_CO_IM, 339 DOMAIN_CO_IN, 340 DOMAIN_CO_JE, 341 DOMAIN_CO_JP, 342 DOMAIN_CO_KE, 343 DOMAIN_CO_KR, 344 DOMAIN_CO_LS, 345 DOMAIN_CO_MA, 346 DOMAIN_CO_MZ, 347 DOMAIN_CO_NZ, 348 DOMAIN_CO_TH, 349 DOMAIN_CO_TZ, 350 DOMAIN_CO_UG, 351 DOMAIN_CO_UK, 352 DOMAIN_CO_UZ, 353 DOMAIN_CO_VE, 354 DOMAIN_CO_VI, 355 DOMAIN_CO_ZA, 356 DOMAIN_CO_ZM, 357 DOMAIN_CO_ZW, 358 DOMAIN_COM_AF, 359 DOMAIN_COM_AG, 360 DOMAIN_COM_AI, 361 DOMAIN_COM_AR, 362 DOMAIN_COM_AU, 363 DOMAIN_COM_BD, 364 DOMAIN_COM_BH, 365 DOMAIN_COM_BN, 366 DOMAIN_COM_BO, 367 DOMAIN_COM_BR, 368 DOMAIN_COM_BY, 369 DOMAIN_COM_BZ, 370 DOMAIN_COM_CN, 371 DOMAIN_COM_CO, 372 DOMAIN_COM_CU, 373 DOMAIN_COM_CY, 374 DOMAIN_COM_DO, 375 DOMAIN_COM_EC, 376 DOMAIN_COM_EG, 377 DOMAIN_COM_ET, 378 DOMAIN_COM_FJ, 379 DOMAIN_COM_GE, 380 DOMAIN_COM_GH, 381 DOMAIN_COM_GI, 382 DOMAIN_COM_GR, 383 DOMAIN_COM_GT, 384 DOMAIN_COM_HK, 385 DOMAIN_COM_IQ, 386 DOMAIN_COM_JM, 387 DOMAIN_COM_JO, 388 DOMAIN_COM_KH, 389 DOMAIN_COM_KW, 390 DOMAIN_COM_LB, 391 DOMAIN_COM_LY, 392 DOMAIN_COM_MT, 393 DOMAIN_COM_MX, 394 DOMAIN_COM_MY, 395 DOMAIN_COM_NA, 396 DOMAIN_COM_NF, 397 DOMAIN_COM_NG, 398 DOMAIN_COM_NI, 399 DOMAIN_COM_NP, 400 DOMAIN_COM_NR, 401 DOMAIN_COM_OM, 402 DOMAIN_COM_PA, 403 DOMAIN_COM_PE, 404 DOMAIN_COM_PH, 405 DOMAIN_COM_PK, 406 DOMAIN_COM_PL, 407 DOMAIN_COM_PR, 408 DOMAIN_COM_PY, 409 DOMAIN_COM_QA, 410 DOMAIN_COM_RU, 411 DOMAIN_COM_SA, 412 DOMAIN_COM_SB, 413 DOMAIN_COM_SG, 414 DOMAIN_COM_SL, 415 DOMAIN_COM_SV, 416 DOMAIN_COM_TJ, 417 DOMAIN_COM_TN, 418 DOMAIN_COM_TR, 419 DOMAIN_COM_TW, 420 DOMAIN_COM_UA, 421 DOMAIN_COM_UY, 422 DOMAIN_COM_VC, 423 DOMAIN_COM_VE, 424 DOMAIN_COM_VN, 425 DOMAIN_GOOGLE_CV, 426 DOMAIN_GOOGLE_CZ, 427 DOMAIN_GOOGLE_DE, 428 DOMAIN_GOOGLE_DJ, 429 DOMAIN_GOOGLE_DK, 430 DOMAIN_GOOGLE_DM, 431 DOMAIN_GOOGLE_DZ, 432 DOMAIN_GOOGLE_EE, 433 DOMAIN_GOOGLE_ES, 434 DOMAIN_GOOGLE_FI, 435 DOMAIN_GOOGLE_FM, 436 DOMAIN_GOOGLE_FR, 437 DOMAIN_GOOGLE_GA, 438 DOMAIN_GOOGLE_GE, 439 DOMAIN_GOOGLE_GG, 440 DOMAIN_GOOGLE_GL, 441 DOMAIN_GOOGLE_GM, 442 DOMAIN_GOOGLE_GP, 443 DOMAIN_GOOGLE_GR, 444 DOMAIN_GOOGLE_GY, 445 DOMAIN_GOOGLE_HK, 446 DOMAIN_GOOGLE_HN, 447 DOMAIN_GOOGLE_HR, 448 DOMAIN_GOOGLE_HT, 449 DOMAIN_GOOGLE_HU, 450 DOMAIN_GOOGLE_IE, 451 DOMAIN_GOOGLE_IM, 452 DOMAIN_GOOGLE_INFO, 453 DOMAIN_GOOGLE_IQ, 454 DOMAIN_GOOGLE_IS, 455 DOMAIN_GOOGLE_IT, 456 DOMAIN_IT_AO, 457 DOMAIN_GOOGLE_JE, 458 DOMAIN_GOOGLE_JO, 459 DOMAIN_GOOGLE_JOBS, 460 DOMAIN_GOOGLE_JP, 461 DOMAIN_GOOGLE_KG, 462 DOMAIN_GOOGLE_KI, 463 DOMAIN_GOOGLE_KZ, 464 DOMAIN_GOOGLE_LA, 465 DOMAIN_GOOGLE_LI, 466 DOMAIN_GOOGLE_LK, 467 DOMAIN_GOOGLE_LT, 468 DOMAIN_GOOGLE_LU, 469 DOMAIN_GOOGLE_LV, 470 DOMAIN_GOOGLE_MD, 471 DOMAIN_GOOGLE_ME, 472 DOMAIN_GOOGLE_MG, 473 DOMAIN_GOOGLE_MK, 474 DOMAIN_GOOGLE_ML, 475 DOMAIN_GOOGLE_MN, 476 DOMAIN_GOOGLE_MS, 477 DOMAIN_GOOGLE_MU, 478 DOMAIN_GOOGLE_MV, 479 DOMAIN_GOOGLE_MW, 480 DOMAIN_GOOGLE_NE, 481 DOMAIN_NE_JP, 482 DOMAIN_GOOGLE_NET, 483 DOMAIN_GOOGLE_NL, 484 DOMAIN_GOOGLE_NO, 485 DOMAIN_GOOGLE_NR, 486 DOMAIN_GOOGLE_NU, 487 DOMAIN_OFF_AI, 488 DOMAIN_GOOGLE_PK, 489 DOMAIN_GOOGLE_PL, 490 DOMAIN_GOOGLE_PN, 491 DOMAIN_GOOGLE_PS, 492 DOMAIN_GOOGLE_PT, 493 DOMAIN_GOOGLE_RO, 494 DOMAIN_GOOGLE_RS, 495 DOMAIN_GOOGLE_RU, 496 DOMAIN_GOOGLE_RW, 497 DOMAIN_GOOGLE_SC, 498 DOMAIN_GOOGLE_SE, 499 DOMAIN_GOOGLE_SH, 500 DOMAIN_GOOGLE_SI, 501 DOMAIN_GOOGLE_SK, 502 DOMAIN_GOOGLE_SM, 503 DOMAIN_GOOGLE_SN, 504 DOMAIN_GOOGLE_SO, 505 DOMAIN_GOOGLE_ST, 506 DOMAIN_GOOGLE_TD, 507 DOMAIN_GOOGLE_TG, 508 DOMAIN_GOOGLE_TK, 509 DOMAIN_GOOGLE_TL, 510 DOMAIN_GOOGLE_TM, 511 DOMAIN_GOOGLE_TN, 512 DOMAIN_GOOGLE_TO, 513 DOMAIN_GOOGLE_TP, 514 DOMAIN_GOOGLE_TT, 515 DOMAIN_GOOGLE_US, 516 DOMAIN_GOOGLE_UZ, 517 DOMAIN_GOOGLE_VG, 518 DOMAIN_GOOGLE_VU, 519 DOMAIN_GOOGLE_WS, 520 521 DOMAIN_CHROMIUM_ORG, 522 523 DOMAIN_CRYPTO_CAT, 524 DOMAIN_LAVABIT_COM, 525 526 DOMAIN_GOOGLETAGMANAGER_COM, 527 DOMAIN_GOOGLETAGSERVICES_COM, 528 529 // Boundary value for UMA_HISTOGRAM_ENUMERATION: 530 DOMAIN_NUM_EVENTS 531 }; 532 533 // PublicKeyPins contains a number of SubjectPublicKeyInfo hashes for a site. 534 // The validated certificate chain for the site must not include any of 535 // |excluded_hashes| and must include one or more of |required_hashes|. 536 struct PublicKeyPins { 537 const char* const* required_hashes; 538 const char* const* excluded_hashes; 539 }; 540 541 struct HSTSPreload { 542 uint8 length; 543 bool include_subdomains; 544 char dns_name[38]; 545 bool https_required; 546 PublicKeyPins pins; 547 SecondLevelDomainName second_level_domain_name; 548 }; 549 550 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, 551 const std::string& canonicalized_host, size_t i, 552 TransportSecurityState::DomainState* out, bool* ret) { 553 for (size_t j = 0; j < num_entries; j++) { 554 if (entries[j].length == canonicalized_host.size() - i && 555 memcmp(entries[j].dns_name, &canonicalized_host[i], 556 entries[j].length) == 0) { 557 if (!entries[j].include_subdomains && i != 0) { 558 *ret = false; 559 } else { 560 out->sts.include_subdomains = entries[j].include_subdomains; 561 out->sts.last_observed = base::GetBuildTime(); 562 out->pkp.include_subdomains = entries[j].include_subdomains; 563 out->pkp.last_observed = base::GetBuildTime(); 564 *ret = true; 565 out->sts.upgrade_mode = 566 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; 567 if (!entries[j].https_required) 568 out->sts.upgrade_mode = 569 TransportSecurityState::DomainState::MODE_DEFAULT; 570 if (entries[j].pins.required_hashes) { 571 const char* const* sha1_hash = entries[j].pins.required_hashes; 572 while (*sha1_hash) { 573 AddHash(*sha1_hash, &out->pkp.spki_hashes); 574 sha1_hash++; 575 } 576 } 577 if (entries[j].pins.excluded_hashes) { 578 const char* const* sha1_hash = entries[j].pins.excluded_hashes; 579 while (*sha1_hash) { 580 AddHash(*sha1_hash, &out->pkp.bad_spki_hashes); 581 sha1_hash++; 582 } 583 } 584 } 585 return true; 586 } 587 } 588 return false; 589 } 590 591 #include "net/http/transport_security_state_static.h" 592 593 // Returns the HSTSPreload entry for the |canonicalized_host| in |entries|, 594 // or NULL if there is none. Prefers exact hostname matches to those that 595 // match only because HSTSPreload.include_subdomains is true. 596 // 597 // |canonicalized_host| should be the hostname as canonicalized by 598 // CanonicalizeHost. 599 static const struct HSTSPreload* GetHSTSPreload( 600 const std::string& canonicalized_host, 601 const struct HSTSPreload* entries, 602 size_t num_entries) { 603 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 604 for (size_t j = 0; j < num_entries; j++) { 605 const struct HSTSPreload* entry = entries + j; 606 607 if (i != 0 && !entry->include_subdomains) 608 continue; 609 610 if (entry->length == canonicalized_host.size() - i && 611 memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) { 612 return entry; 613 } 614 } 615 } 616 617 return NULL; 618 } 619 620 bool TransportSecurityState::AddHSTSHeader(const std::string& host, 621 const std::string& value) { 622 DCHECK(CalledOnValidThread()); 623 624 base::Time now = base::Time::Now(); 625 base::TimeDelta max_age; 626 TransportSecurityState::DomainState domain_state; 627 GetDynamicDomainState(host, &domain_state); 628 if (ParseHSTSHeader(value, &max_age, &domain_state.sts.include_subdomains)) { 629 // Handle max-age == 0. 630 if (max_age.InSeconds() == 0) 631 domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT; 632 else 633 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 634 domain_state.sts.last_observed = now; 635 domain_state.sts.expiry = now + max_age; 636 EnableHost(host, domain_state); 637 return true; 638 } 639 return false; 640 } 641 642 bool TransportSecurityState::AddHPKPHeader(const std::string& host, 643 const std::string& value, 644 const SSLInfo& ssl_info) { 645 DCHECK(CalledOnValidThread()); 646 647 base::Time now = base::Time::Now(); 648 base::TimeDelta max_age; 649 TransportSecurityState::DomainState domain_state; 650 GetDynamicDomainState(host, &domain_state); 651 if (ParseHPKPHeader(value, 652 ssl_info.public_key_hashes, 653 &max_age, 654 &domain_state.pkp.include_subdomains, 655 &domain_state.pkp.spki_hashes)) { 656 // Handle max-age == 0. 657 if (max_age.InSeconds() == 0) 658 domain_state.pkp.spki_hashes.clear(); 659 domain_state.pkp.last_observed = now; 660 domain_state.pkp.expiry = now + max_age; 661 EnableHost(host, domain_state); 662 return true; 663 } 664 return false; 665 } 666 667 bool TransportSecurityState::AddHSTS(const std::string& host, 668 const base::Time& expiry, 669 bool include_subdomains) { 670 DCHECK(CalledOnValidThread()); 671 672 // Copy-and-modify the existing DomainState for this host (if any). 673 TransportSecurityState::DomainState domain_state; 674 const std::string canonicalized_host = CanonicalizeHost(host); 675 const std::string hashed_host = HashHost(canonicalized_host); 676 DomainStateMap::const_iterator i = enabled_hosts_.find( 677 hashed_host); 678 if (i != enabled_hosts_.end()) 679 domain_state = i->second; 680 681 domain_state.sts.last_observed = base::Time::Now(); 682 domain_state.sts.include_subdomains = include_subdomains; 683 domain_state.sts.expiry = expiry; 684 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 685 EnableHost(host, domain_state); 686 return true; 687 } 688 689 bool TransportSecurityState::AddHPKP(const std::string& host, 690 const base::Time& expiry, 691 bool include_subdomains, 692 const HashValueVector& hashes) { 693 DCHECK(CalledOnValidThread()); 694 695 // Copy-and-modify the existing DomainState for this host (if any). 696 TransportSecurityState::DomainState domain_state; 697 const std::string canonicalized_host = CanonicalizeHost(host); 698 const std::string hashed_host = HashHost(canonicalized_host); 699 DomainStateMap::const_iterator i = enabled_hosts_.find( 700 hashed_host); 701 if (i != enabled_hosts_.end()) 702 domain_state = i->second; 703 704 domain_state.pkp.last_observed = base::Time::Now(); 705 domain_state.pkp.include_subdomains = include_subdomains; 706 domain_state.pkp.expiry = expiry; 707 domain_state.pkp.spki_hashes = hashes; 708 EnableHost(host, domain_state); 709 return true; 710 } 711 712 // static 713 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, 714 bool sni_enabled) { 715 std::string canonicalized_host = CanonicalizeHost(host); 716 const struct HSTSPreload* entry = 717 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); 718 719 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) 720 return true; 721 722 if (sni_enabled) { 723 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, 724 kNumPreloadedSNISTS); 725 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) 726 return true; 727 } 728 729 return false; 730 } 731 732 // static 733 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { 734 std::string canonicalized_host = CanonicalizeHost(host); 735 736 const struct HSTSPreload* entry = 737 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); 738 739 if (!entry) { 740 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, 741 kNumPreloadedSNISTS); 742 } 743 744 if (!entry) { 745 // We don't care to report pin failures for dynamic pins. 746 return; 747 } 748 749 DCHECK(entry); 750 DCHECK(entry->pins.required_hashes); 751 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); 752 753 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", 754 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); 755 } 756 757 // static 758 bool TransportSecurityState::IsBuildTimely() { 759 const base::Time build_time = base::GetBuildTime(); 760 // We consider built-in information to be timely for 10 weeks. 761 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; 762 } 763 764 bool TransportSecurityState::GetStaticDomainState(const std::string& host, 765 bool sni_enabled, 766 DomainState* out) const { 767 DCHECK(CalledOnValidThread()); 768 769 const std::string canonicalized_host = CanonicalizeHost(host); 770 771 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 772 out->sts.include_subdomains = false; 773 out->pkp.include_subdomains = false; 774 775 const bool is_build_timely = IsBuildTimely(); 776 777 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 778 std::string host_sub_chunk(&canonicalized_host[i], 779 canonicalized_host.size() - i); 780 out->domain = DNSDomainToString(host_sub_chunk); 781 bool ret; 782 if (is_build_timely && 783 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, 784 &ret)) { 785 return ret; 786 } 787 if (sni_enabled && 788 is_build_timely && 789 HasPreload(kPreloadedSNISTS, kNumPreloadedSNISTS, canonicalized_host, i, 790 out, &ret)) { 791 return ret; 792 } 793 } 794 795 return false; 796 } 797 798 bool TransportSecurityState::GetDynamicDomainState(const std::string& host, 799 DomainState* result) { 800 DCHECK(CalledOnValidThread()); 801 802 DomainState state; 803 const std::string canonicalized_host = CanonicalizeHost(host); 804 if (canonicalized_host.empty()) 805 return false; 806 807 base::Time current_time(base::Time::Now()); 808 809 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 810 std::string host_sub_chunk(&canonicalized_host[i], 811 canonicalized_host.size() - i); 812 DomainStateMap::iterator j = 813 enabled_hosts_.find(HashHost(host_sub_chunk)); 814 if (j == enabled_hosts_.end()) 815 continue; 816 817 if (current_time > j->second.sts.expiry && 818 current_time > j->second.pkp.expiry) { 819 enabled_hosts_.erase(j); 820 DirtyNotify(); 821 continue; 822 } 823 824 state = j->second; 825 state.domain = DNSDomainToString(host_sub_chunk); 826 827 // Succeed if we matched the domain exactly or if subdomain matches are 828 // allowed. 829 if (i == 0 || j->second.sts.include_subdomains || 830 j->second.pkp.include_subdomains) { 831 *result = state; 832 return true; 833 } 834 835 return false; 836 } 837 838 return false; 839 } 840 841 void TransportSecurityState::AddOrUpdateEnabledHosts( 842 const std::string& hashed_host, const DomainState& state) { 843 DCHECK(CalledOnValidThread()); 844 enabled_hosts_[hashed_host] = state; 845 } 846 847 TransportSecurityState::DomainState::DomainState() { 848 sts.upgrade_mode = MODE_DEFAULT; 849 sts.include_subdomains = false; 850 pkp.include_subdomains = false; 851 } 852 853 TransportSecurityState::DomainState::~DomainState() { 854 } 855 856 bool TransportSecurityState::DomainState::CheckPublicKeyPins( 857 const HashValueVector& hashes, std::string* failure_log) const { 858 // Validate that hashes is not empty. By the time this code is called (in 859 // production), that should never happen, but it's good to be defensive. 860 // And, hashes *can* be empty in some test scenarios. 861 if (hashes.empty()) { 862 failure_log->append( 863 "Rejecting empty public key chain for public-key-pinned domains: " + 864 domain); 865 return false; 866 } 867 868 if (HashesIntersect(pkp.bad_spki_hashes, hashes)) { 869 failure_log->append("Rejecting public key chain for domain " + domain + 870 ". Validated chain: " + HashesToBase64String(hashes) + 871 ", matches one or more bad hashes: " + 872 HashesToBase64String(pkp.bad_spki_hashes)); 873 return false; 874 } 875 876 // If there are no pins, then any valid chain is acceptable. 877 if (pkp.spki_hashes.empty()) 878 return true; 879 880 if (HashesIntersect(pkp.spki_hashes, hashes)) { 881 return true; 882 } 883 884 failure_log->append("Rejecting public key chain for domain " + domain + 885 ". Validated chain: " + HashesToBase64String(hashes) + 886 ", expected: " + HashesToBase64String(pkp.spki_hashes)); 887 return false; 888 } 889 890 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { 891 return sts.upgrade_mode == MODE_FORCE_HTTPS; 892 } 893 894 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { 895 return true; 896 } 897 898 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { 899 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; 900 } 901 902 TransportSecurityState::DomainState::PKPState::PKPState() { 903 } 904 905 TransportSecurityState::DomainState::PKPState::~PKPState() { 906 } 907 908 } // namespace 909