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

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

Issue 103803012: Make HSTS headers not clobber preloaded pins. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove spurious debugging junk. Sigh. Created 7 years 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 | Annotate | Revision Log
« no previous file with comments | « net/http/http_security_headers_unittest.cc ('k') | no next file » | 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 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 return NULL; 607 return NULL;
608 } 608 }
609 609
610 bool TransportSecurityState::AddHSTSHeader(const std::string& host, 610 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
611 const std::string& value) { 611 const std::string& value) {
612 DCHECK(CalledOnValidThread()); 612 DCHECK(CalledOnValidThread());
613 613
614 base::Time now = base::Time::Now(); 614 base::Time now = base::Time::Now();
615 base::TimeDelta max_age; 615 base::TimeDelta max_age;
616 TransportSecurityState::DomainState domain_state; 616 TransportSecurityState::DomainState domain_state;
617 //GetDomainState(host, true /* SNI enabled */, &domain_state);
Ryan Sleevi 2013/12/27 00:21:06 Remove
palmer 2014/01/03 22:43:44 Done.
617 GetDynamicDomainState(host, &domain_state); 618 GetDynamicDomainState(host, &domain_state);
618 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { 619 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) {
619 // Handle max-age == 0 620 // Handle max-age == 0
620 if (max_age.InSeconds() == 0) 621 if (max_age.InSeconds() == 0)
621 domain_state.upgrade_mode = DomainState::MODE_DEFAULT; 622 domain_state.upgrade_mode = DomainState::MODE_DEFAULT;
622 else 623 else
623 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 624 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
624 domain_state.sts_observed = now; 625 domain_state.sts_observed = now;
625 domain_state.upgrade_expiry = now + max_age; 626 domain_state.upgrade_expiry = now + max_age;
626 EnableHost(host, domain_state); 627 EnableHost(host, domain_state);
627 return true; 628 return true;
628 } 629 }
629 return false; 630 return false;
630 } 631 }
631 632
632 bool TransportSecurityState::AddHPKPHeader(const std::string& host, 633 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
633 const std::string& value, 634 const std::string& value,
634 const SSLInfo& ssl_info) { 635 const SSLInfo& ssl_info) {
635 DCHECK(CalledOnValidThread()); 636 DCHECK(CalledOnValidThread());
636 637
637 base::Time now = base::Time::Now(); 638 base::Time now = base::Time::Now();
638 base::TimeDelta max_age; 639 base::TimeDelta max_age;
639 TransportSecurityState::DomainState domain_state; 640 TransportSecurityState::DomainState domain_state;
641 //GetDomainState(host, true /* SNI enabled */, &domain_state);
Ryan Sleevi 2013/12/27 00:21:06 Remove
palmer 2014/01/03 22:43:44 Done.
640 GetDynamicDomainState(host, &domain_state); 642 GetDynamicDomainState(host, &domain_state);
641 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, 643 if (ParseHPKPHeader(value, ssl_info.public_key_hashes,
642 &max_age, &domain_state.pkp_include_subdomains, 644 &max_age, &domain_state.pkp_include_subdomains,
643 &domain_state.dynamic_spki_hashes)) { 645 &domain_state.dynamic_spki_hashes)) {
644 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. 646 // TODO(palmer): http://crbug.com/243865 handle max-age == 0.
645 domain_state.pkp_observed = now; 647 domain_state.pkp_observed = now;
646 domain_state.dynamic_spki_hashes_expiry = now + max_age; 648 domain_state.dynamic_spki_hashes_expiry = now + max_age;
647 EnableHost(host, domain_state); 649 EnableHost(host, domain_state);
648 return true; 650 return true;
649 } 651 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 const HashValueVector& hashes) const { 848 const HashValueVector& hashes) const {
847 // Validate that hashes is not empty. By the time this code is called (in 849 // 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. 850 // production), that should never happen, but it's good to be defensive.
849 // And, hashes *can* be empty in some test scenarios. 851 // And, hashes *can* be empty in some test scenarios.
850 if (hashes.empty()) { 852 if (hashes.empty()) {
851 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned " 853 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned "
852 "domain " << domain; 854 "domain " << domain;
853 return false; 855 return false;
854 } 856 }
855 857
856 if (HashesIntersect(bad_static_spki_hashes, hashes)) { 858 // If there is a static entry, check its pins (if any). |this| may have
859 // been loaded via GetDynamicDomainState (only), and hence we would
860 // erroneously ignore static key pins if we did not do this check.
861 // See crbug.com/29386.
Ryan Sleevi 2013/12/27 00:21:06 Avoid pronouns in comments. // TODO(palmer): Stat
palmer 2014/01/03 22:43:44 Done.
862 //
863 // This is a terrible hack and should be resolved with a proper refactor
864 // in the very near future (as of Dec 2013). TODO(palmer).
Ryan Sleevi 2013/12/27 00:21:06 note: remove this bit.
palmer 2014/01/03 22:43:44 Done.
865 HashValueVector restored_static_hashes;
866 HashValueVector restored_bad_static_hashes;
867 DomainState restored_static_state;
868 bool did_restore_static_state = false;
Ryan Sleevi 2013/12/27 00:21:06 The naming here is a bit confusing, because you're
869 if (IsBuildTimely()) {
Ryan Sleevi 2013/12/27 00:21:06 if (TransportSecurityState::IsBuildTimely()) - you
palmer 2014/01/03 22:43:44 <spiderman>...and I'm just sitting here, compiling
870 std::string canonicalized_host = CanonicalizeHost(domain);
871
872 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
873 std::string host_sub_chunk(&canonicalized_host[i],
Ryan Sleevi 2013/12/27 00:21:06 This duplicates significant portions of GetStaticD
palmer 2014/01/03 22:43:44 Done.
874 canonicalized_host.size() - i);
875 restored_static_state.domain = DNSDomainToString(host_sub_chunk);
876 if (HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i,
877 &restored_static_state, &did_restore_static_state)) {
878 break;
879 }
880 if (HasPreload(kPreloadedSNISTS, kNumPreloadedSNISTS, canonicalized_host,
881 i, &restored_static_state, &did_restore_static_state)) {
Ryan Sleevi 2013/12/27 00:21:06 You're unconditionally checking against SNI hosts.
palmer 2014/01/03 22:43:44 Handled this by getting rid of that code.
882 break;
883 }
884 }
885 }
886 if (did_restore_static_state) {
887 restored_bad_static_hashes = restored_static_state.bad_static_spki_hashes;
888 restored_static_hashes = restored_static_state.static_spki_hashes;
889 }
890
891 if (HashesIntersect(restored_bad_static_hashes, hashes) ||
892 HashesIntersect(bad_static_spki_hashes, hashes)) {
857 LOG(ERROR) << "Rejecting public key chain for domain " << domain 893 LOG(ERROR) << "Rejecting public key chain for domain " << domain
858 << ". Validated chain: " << HashesToBase64String(hashes) 894 << ". Validated chain: " << HashesToBase64String(hashes)
859 << ", matches one or more bad hashes: " 895 << ", matches one or more bad hashes: "
860 << HashesToBase64String(bad_static_spki_hashes); 896 << HashesToBase64String(bad_static_spki_hashes) <<
897 ", " << HashesToBase64String(restored_bad_static_hashes);
861 return false; 898 return false;
862 } 899 }
863 900
864 // If there are no pins, then any valid chain is acceptable. 901 // If there are no pins, then any valid chain is acceptable.
865 if (dynamic_spki_hashes.empty() && static_spki_hashes.empty()) 902 if (dynamic_spki_hashes.empty() && static_spki_hashes.empty() &&
903 restored_static_hashes.empty()) {
866 return true; 904 return true;
905 }
867 906
868 if (HashesIntersect(dynamic_spki_hashes, hashes) || 907 if (HashesIntersect(dynamic_spki_hashes, hashes) ||
869 HashesIntersect(static_spki_hashes, hashes)) { 908 HashesIntersect(static_spki_hashes, hashes) ||
909 HashesIntersect(restored_static_hashes, hashes)) {
870 return true; 910 return true;
871 } 911 }
872 912
873 LOG(ERROR) << "Rejecting public key chain for domain " << domain 913 LOG(ERROR) << "Rejecting public key chain for domain " << domain
874 << ". Validated chain: " << HashesToBase64String(hashes) 914 << ". Validated chain: " << HashesToBase64String(hashes)
875 << ", expected: " << HashesToBase64String(dynamic_spki_hashes) 915 << ", expected: " << HashesToBase64String(dynamic_spki_hashes)
876 << " or: " << HashesToBase64String(static_spki_hashes); 916 << " or: " << HashesToBase64String(static_spki_hashes)
917 << " or: " << HashesToBase64String(restored_static_hashes);
877 return false; 918 return false;
878 } 919 }
879 920
880 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { 921 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
881 return upgrade_mode == MODE_FORCE_HTTPS; 922 return upgrade_mode == MODE_FORCE_HTTPS;
882 } 923 }
883 924
884 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { 925 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
885 return true; 926 return true;
886 } 927 }
887 928
888 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { 929 bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
889 return static_spki_hashes.size() > 0 || 930 return static_spki_hashes.size() > 0 ||
890 bad_static_spki_hashes.size() > 0 || 931 bad_static_spki_hashes.size() > 0 ||
891 dynamic_spki_hashes.size() > 0; 932 dynamic_spki_hashes.size() > 0;
892 } 933 }
893 934
894 } // namespace 935 } // namespace
OLDNEW
« no previous file with comments | « net/http/http_security_headers_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698