Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Side by Side Diff: net/http/transport_security_state.cc

Issue 1149753002: Normalize hostnames before searching for HSTS/HPKP preloads (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | net/http/transport_security_state_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | net/http/transport_security_state_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698