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 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 |
OLD | NEW |