Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/transport_security_state.h" | 5 #include "net/http/transport_security_state.h" |
| 6 | 6 |
| 7 #if defined(USE_OPENSSL) | 7 #if defined(USE_OPENSSL) |
| 8 #include <openssl/ecdsa.h> | 8 #include <openssl/ecdsa.h> |
| 9 #include <openssl/ssl.h> | 9 #include <openssl/ssl.h> |
| 10 #else // !defined(USE_OPENSSL) | 10 #else // !defined(USE_OPENSSL) |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 | 291 |
| 292 if (delegate_) | 292 if (delegate_) |
| 293 delegate_->StateIsDirty(this); | 293 delegate_->StateIsDirty(this); |
| 294 } | 294 } |
| 295 | 295 |
| 296 // static | 296 // static |
| 297 std::string TransportSecurityState::CanonicalizeHost(const std::string& host) { | 297 std::string TransportSecurityState::CanonicalizeHost(const std::string& host) { |
| 298 // We cannot perform the operations as detailed in the spec here as |host| | 298 // We cannot perform the operations as detailed in the spec here as |host| |
| 299 // has already undergone IDN processing before it reached us. Thus, we check | 299 // has already undergone IDN processing before it reached us. Thus, we check |
| 300 // that there are no invalid characters in the host and lowercase the result. | 300 // that there are no invalid characters in the host and lowercase the result. |
| 301 | |
|
davidben
2015/05/20 19:21:09
Stray change?
Ryan Sleevi
2015/05/20 19:26:39
Readability ;)
| |
| 302 std::string new_host; | 301 std::string new_host; |
| 303 if (!DNSDomainFromDot(host, &new_host)) { | 302 if (!DNSDomainFromDot(host, &new_host)) { |
| 304 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole | 303 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole |
| 305 // name is >255 bytes. However, search terms can have those properties. | 304 // name is >255 bytes. However, search terms can have those properties. |
| 306 return std::string(); | 305 return std::string(); |
| 307 } | 306 } |
| 308 | 307 |
| 309 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) { | 308 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) { |
| 310 const unsigned label_length = static_cast<unsigned>(new_host[i]); | 309 const unsigned label_length = static_cast<unsigned>(new_host[i]); |
| 311 if (!label_length) | 310 if (!label_length) |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 488 // In the dispatch table, the zero character represents the "end of string" | 487 // In the dispatch table, the zero character represents the "end of string" |
| 489 // (which is the *beginning* of a hostname since we process it backwards). The | 488 // (which is the *beginning* of a hostname since we process it backwards). The |
| 490 // value in that case is special -- rather than an offset to another trie node, | 489 // value in that case is special -- rather than an offset to another trie node, |
| 491 // it contains the HSTS information: whether subdomains are included, pinsets | 490 // it contains the HSTS information: whether subdomains are included, pinsets |
| 492 // etc. If an "end of string" matches a period in the hostname then the | 491 // etc. If an "end of string" matches a period in the hostname then the |
| 493 // information is remembered because, if no more specific node is found, then | 492 // information is remembered because, if no more specific node is found, then |
| 494 // that information applies to the hostname. | 493 // that information applies to the hostname. |
| 495 // | 494 // |
| 496 // Dispatch tables are always given in order, but the "end of string" (zero) | 495 // Dispatch tables are always given in order, but the "end of string" (zero) |
| 497 // value always comes before an entry for '.'. | 496 // value always comes before an entry for '.'. |
| 498 bool DecodeHSTSPreloadRaw(const std::string& hostname, | 497 bool DecodeHSTSPreloadRaw(const std::string& search_hostname, |
| 499 bool* out_found, | 498 bool* out_found, |
| 500 PreloadResult* out) { | 499 PreloadResult* out) { |
| 501 HuffmanDecoder huffman(kHSTSHuffmanTree, sizeof(kHSTSHuffmanTree)); | 500 HuffmanDecoder huffman(kHSTSHuffmanTree, sizeof(kHSTSHuffmanTree)); |
| 502 BitReader reader(kPreloadedHSTSData, kPreloadedHSTSBits); | 501 BitReader reader(kPreloadedHSTSData, kPreloadedHSTSBits); |
| 503 size_t bit_offset = kHSTSRootPosition; | 502 size_t bit_offset = kHSTSRootPosition; |
| 504 static const char kEndOfString = 0; | 503 static const char kEndOfString = 0; |
| 505 static const char kEndOfTable = 127; | 504 static const char kEndOfTable = 127; |
| 506 | 505 |
| 507 *out_found = false; | 506 *out_found = false; |
| 508 | 507 |
| 508 // Normalize any trailing '.' used for DNS suffix searches | |
|
davidben
2015/05/20 19:21:08
Nit: period
| |
| 509 std::string hostname = search_hostname; | |
| 510 size_t found = hostname.find_last_not_of('.'); | |
| 511 if (found != std::string::npos) { | |
| 512 hostname.erase(found + 1); | |
| 513 } else { | |
| 514 hostname.clear(); | |
| 515 } | |
| 516 | |
| 517 // |hostname| has already undergone IDN conversion, so should be | |
| 518 // entirely A-Labels. The preload data is entirely normalized to | |
| 519 // lower case | |
|
davidben
2015/05/20 19:21:09
Nit: period
| |
| 520 base::StringToLowerASCII(&hostname); | |
| 521 | |
| 509 if (hostname.empty()) { | 522 if (hostname.empty()) { |
| 510 return true; | 523 return true; |
| 511 } | 524 } |
| 525 | |
| 512 // hostname_offset contains one more than the index of the current character | 526 // hostname_offset contains one more than the index of the current character |
| 513 // in the hostname that is being considered. It's one greater so that we can | 527 // in the hostname that is being considered. It's one greater so that we can |
| 514 // represent the position just before the beginning (with zero). | 528 // represent the position just before the beginning (with zero). |
| 515 size_t hostname_offset = hostname.size(); | 529 size_t hostname_offset = hostname.size(); |
| 516 | 530 |
| 517 for (;;) { | 531 for (;;) { |
| 518 // Seek to the desired location. | 532 // Seek to the desired location. |
| 519 if (!reader.Seek(bit_offset)) { | 533 if (!reader.Seek(bit_offset)) { |
| 520 return false; | 534 return false; |
| 521 } | 535 } |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 718 const base::Time& expiry, | 732 const base::Time& expiry, |
| 719 bool include_subdomains, | 733 bool include_subdomains, |
| 720 const HashValueVector& hashes) { | 734 const HashValueVector& hashes) { |
| 721 DCHECK(CalledOnValidThread()); | 735 DCHECK(CalledOnValidThread()); |
| 722 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes); | 736 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes); |
| 723 } | 737 } |
| 724 | 738 |
| 725 // static | 739 // static |
| 726 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) { | 740 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) { |
| 727 PreloadResult result; | 741 PreloadResult result; |
| 728 return DecodeHSTSPreload(host, &result) && result.has_pins && | 742 return !CanonicalizeHost(host).empty() && DecodeHSTSPreload(host, &result) && |
|
davidben
2015/05/20 19:21:09
Would it be better to move the CanonicalizeHost ch
| |
| 743 result.has_pins && | |
| 729 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts; | 744 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts; |
| 730 } | 745 } |
| 731 | 746 |
| 732 // static | 747 // static |
| 733 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { | 748 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { |
| 734 PreloadResult result; | 749 PreloadResult result; |
| 735 if (!DecodeHSTSPreload(host, &result) || | 750 if (CanonicalizeHost(host).empty() || !DecodeHSTSPreload(host, &result) || |
| 736 !result.has_pins) { | 751 !result.has_pins) { |
| 737 return; | 752 return; |
| 738 } | 753 } |
| 739 | 754 |
| 740 DCHECK(result.domain_id != DOMAIN_NOT_PINNED); | 755 DCHECK(result.domain_id != DOMAIN_NOT_PINNED); |
| 741 | 756 |
| 742 UMA_HISTOGRAM_SPARSE_SLOWLY( | 757 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 743 "Net.PublicKeyPinFailureDomain", result.domain_id); | 758 "Net.PublicKeyPinFailureDomain", result.domain_id); |
| 744 } | 759 } |
| 745 | 760 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 781 DCHECK(CalledOnValidThread()); | 796 DCHECK(CalledOnValidThread()); |
| 782 | 797 |
| 783 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 798 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
| 784 out->sts.include_subdomains = false; | 799 out->sts.include_subdomains = false; |
| 785 out->pkp.include_subdomains = false; | 800 out->pkp.include_subdomains = false; |
| 786 | 801 |
| 787 if (!IsBuildTimely()) | 802 if (!IsBuildTimely()) |
| 788 return false; | 803 return false; |
| 789 | 804 |
| 790 PreloadResult result; | 805 PreloadResult result; |
| 791 if (!DecodeHSTSPreload(host, &result)) | 806 if (CanonicalizeHost(host).empty() || !DecodeHSTSPreload(host, &result)) |
| 792 return false; | 807 return false; |
| 793 | 808 |
| 794 out->sts.domain = host.substr(result.hostname_offset); | 809 out->sts.domain = host.substr(result.hostname_offset); |
| 795 out->pkp.domain = out->sts.domain; | 810 out->pkp.domain = out->sts.domain; |
| 796 out->sts.include_subdomains = result.sts_include_subdomains; | 811 out->sts.include_subdomains = result.sts_include_subdomains; |
| 797 out->sts.last_observed = base::GetBuildTime(); | 812 out->sts.last_observed = base::GetBuildTime(); |
| 798 out->sts.upgrade_mode = | 813 out->sts.upgrade_mode = |
| 799 TransportSecurityState::DomainState::MODE_DEFAULT; | 814 TransportSecurityState::DomainState::MODE_DEFAULT; |
| 800 if (result.force_https) { | 815 if (result.force_https) { |
| 801 out->sts.upgrade_mode = | 816 out->sts.upgrade_mode = |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 970 TransportSecurityState::DomainState::STSState::~STSState() { | 985 TransportSecurityState::DomainState::STSState::~STSState() { |
| 971 } | 986 } |
| 972 | 987 |
| 973 TransportSecurityState::DomainState::PKPState::PKPState() { | 988 TransportSecurityState::DomainState::PKPState::PKPState() { |
| 974 } | 989 } |
| 975 | 990 |
| 976 TransportSecurityState::DomainState::PKPState::~PKPState() { | 991 TransportSecurityState::DomainState::PKPState::~PKPState() { |
| 977 } | 992 } |
| 978 | 993 |
| 979 } // namespace | 994 } // namespace |
| OLD | NEW |