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