diff options
-rw-r--r-- | chrome/browser/net/chrome_fraudulent_certificate_reporter.cc | 22 | ||||
-rw-r--r-- | net/http/transport_security_persister_unittest.cc | 9 | ||||
-rw-r--r-- | net/http/transport_security_state.cc | 37 | ||||
-rw-r--r-- | net/http/transport_security_state.h | 15 | ||||
-rw-r--r-- | net/http/transport_security_state_unittest.cc | 8 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 5 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.h | 5 | ||||
-rw-r--r-- | net/ssl/ssl_info.cc | 2 | ||||
-rw-r--r-- | net/ssl/ssl_info.h | 5 |
9 files changed, 40 insertions, 68 deletions
diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc index 30fd547..f666c87 100644 --- a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc +++ b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc @@ -51,27 +51,7 @@ static std::string BuildReport(const std::string& hostname, for (size_t i = 0; i < pem_encoded_chain.size(); ++i) *cert_chain += pem_encoded_chain[i]; - for (net::HashValueVector::const_iterator i = - ssl_info.public_key_hashes.begin(); i != - ssl_info.public_key_hashes.end(); ++i) { - request.add_public_key_hash(i->ToString()); - } - - const char* const* required_pins; - const char* const* excluded_pins; - if (net::TransportSecurityState::GetPinsForDebugging( - hostname, &required_pins, &excluded_pins)) { - for (size_t i = 0; required_pins[i]; i++) { - net::HashValue hash_value(net::HASH_VALUE_SHA1); - memcpy(hash_value.data(), required_pins[i], hash_value.size()); - request.add_pin(hash_value.ToString()); - } - for (size_t i = 0; excluded_pins[i]; i++) { - net::HashValue hash_value(net::HASH_VALUE_SHA1); - memcpy(hash_value.data(), excluded_pins[i], hash_value.size()); - request.add_pin("!" + hash_value.ToString()); - } - } + request.add_pin(ssl_info.pinning_failure_log); std::string out; request.SerializeToString(&out); diff --git a/net/http/transport_security_persister_unittest.cc b/net/http/transport_security_persister_unittest.cc index 114e933..c7a8dc5 100644 --- a/net/http/transport_security_persister_unittest.cc +++ b/net/http/transport_security_persister_unittest.cc @@ -168,19 +168,20 @@ TEST_F(TransportSecurityPersisterTest, PublicKeyHashes) { static const char kTestDomain[] = "example.com"; EXPECT_FALSE(state_.GetDomainState(kTestDomain, false, &domain_state)); net::HashValueVector hashes; - EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes)); + std::string failure_log; + EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log)); net::HashValue sha1(net::HASH_VALUE_SHA1); memset(sha1.data(), '1', sha1.size()); domain_state.dynamic_spki_hashes.push_back(sha1); - EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes)); + EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log)); hashes.push_back(sha1); - EXPECT_TRUE(domain_state.CheckPublicKeyPins(hashes)); + EXPECT_TRUE(domain_state.CheckPublicKeyPins(hashes, &failure_log)); hashes[0].data()[0] = '2'; - EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes)); + EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log)); const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc index 8142e09..1bd55c6 100644 --- a/net/http/transport_security_state.cc +++ b/net/http/transport_security_state.cc @@ -718,21 +718,6 @@ bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, } // static -bool TransportSecurityState::GetPinsForDebugging( - const std::string& host, - const char* const** out_required_pins, - const char* const** out_excluded_pins) { - const std::string canonicalized_host = CanonicalizeHost(host); - const struct HSTSPreload* entry = - GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); - if (!entry) - return false; - *out_required_pins = entry->pins.required_hashes; - *out_excluded_pins = entry->pins.excluded_hashes; - return true; -} - -// static void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { std::string canonicalized_host = CanonicalizeHost(host); @@ -860,21 +845,21 @@ TransportSecurityState::DomainState::~DomainState() { } bool TransportSecurityState::DomainState::CheckPublicKeyPins( - const HashValueVector& hashes) const { + const HashValueVector& hashes, std::string* failure_log) const { // Validate that hashes is not empty. By the time this code is called (in // production), that should never happen, but it's good to be defensive. // And, hashes *can* be empty in some test scenarios. if (hashes.empty()) { - LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned " - "domain " << domain; + *failure_log = "Rejecting empty public key chain for public-key-pinned " + "domains: " + domain; return false; } if (HashesIntersect(bad_static_spki_hashes, hashes)) { - LOG(ERROR) << "Rejecting public key chain for domain " << domain - << ". Validated chain: " << HashesToBase64String(hashes) - << ", matches one or more bad hashes: " - << HashesToBase64String(bad_static_spki_hashes); + *failure_log = "Rejecting public key chain for domain " + domain + + ". Validated chain: " + HashesToBase64String(hashes) + + ", matches one or more bad hashes: " + + HashesToBase64String(bad_static_spki_hashes); return false; } @@ -887,10 +872,10 @@ bool TransportSecurityState::DomainState::CheckPublicKeyPins( return true; } - LOG(ERROR) << "Rejecting public key chain for domain " << domain - << ". Validated chain: " << HashesToBase64String(hashes) - << ", expected: " << HashesToBase64String(dynamic_spki_hashes) - << " or: " << HashesToBase64String(static_spki_hashes); + *failure_log = "Rejecting public key chain for domain " + domain + + ". Validated chain: " + HashesToBase64String(hashes) + + ", expected: " + HashesToBase64String(dynamic_spki_hashes) + + " or: " + HashesToBase64String(static_spki_hashes); return false; } diff --git a/net/http/transport_security_state.h b/net/http/transport_security_state.h index 8aaecb69..82a3c45 100644 --- a/net/http/transport_security_state.h +++ b/net/http/transport_security_state.h @@ -77,7 +77,8 @@ class NET_EXPORT TransportSecurityState // // |bad_static_spki_hashes| contains public keys that we don't want to // trust. - bool CheckPublicKeyPins(const HashValueVector& hashes) const; + bool CheckPublicKeyPins(const HashValueVector& hashes, + std::string* failure_log) const; // Returns true if any of the HashValueVectors |static_spki_hashes|, // |bad_static_spki_hashes|, or |dynamic_spki_hashes| contains any @@ -248,18 +249,6 @@ class NET_EXPORT TransportSecurityState static bool IsGooglePinnedProperty(const std::string& host, bool sni_enabled); - // GetPinsForDebugging finds the preloaded entry for the given host. If none - // exists, it returns false. Otherwise it returns true and sets |out_pins| - // and |out_bad_pins| to point to arrays of SHA-1 hashes, each 20 bytes long - // with a NULL pointer signalling the end of the array, for the required and - // excluded pins, respectively. - // This is a temporary debugging measure to check for binary alteration / - // corruption. - static bool GetPinsForDebugging( - const std::string& host, - const char* const** out_pins, - const char* const** out_bad_pins); - // The maximum number of seconds for which we'll cache an HSTS request. static const long int kMaxHSTSAgeSecs; diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc index c3d15da..dfcd50f 100644 --- a/net/http/transport_security_state_unittest.cc +++ b/net/http/transport_security_state_unittest.cc @@ -493,8 +493,9 @@ TEST_F(TransportSecurityStateTest, BuiltinCertPins) { EXPECT_TRUE(HasPublicKeyPins("chrome.google.com")); HashValueVector hashes; + std::string failure_log; // Checks that a built-in list does exist. - EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes)); + EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log)); EXPECT_FALSE(HasPublicKeyPins("www.paypal.com")); EXPECT_TRUE(HasPublicKeyPins("docs.google.com")); @@ -579,8 +580,9 @@ TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { EXPECT_TRUE(state.GetDomainState("blog.torproject.org", true, &domain_state)); EXPECT_TRUE(domain_state.HasPublicKeyPins()); - EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes)); - EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes)); + std::string failure_log; + EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes, &failure_log)); + EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes, &failure_log)); } TEST_F(TransportSecurityStateTest, OptionalHSTSCertPins) { diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index b3c8e0e..fd7e86c 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -2859,6 +2859,7 @@ bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { ssl_info->client_cert_sent = ssl_config_.send_client_cert && ssl_config_.client_cert.get(); ssl_info->channel_id_sent = WasChannelIDSent(); + ssl_info->pinning_failure_log = pinning_failure_log_; PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite( core_->state().ssl_connection_status); @@ -3501,7 +3502,9 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { &domain_state) && domain_state.HasPublicKeyPins()) { if (!domain_state.CheckPublicKeyPins( - server_cert_verify_result_.public_key_hashes)) { + server_cert_verify_result_.public_key_hashes, + &pinning_failure_log_)) { + LOG(ERROR) << pinning_failure_log_; result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN; UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", false); TransportSecurityState::ReportUMAOnPinFailure(host); diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h index acd5d37..853daa4 100644 --- a/net/socket/ssl_client_socket_nss.h +++ b/net/socket/ssl_client_socket_nss.h @@ -201,6 +201,11 @@ class SSLClientSocketNSS : public SSLClientSocket { TransportSecurityState* transport_security_state_; + // pinning_failure_log contains a message produced by + // TransportSecurityState::DomainState::CheckPublicKeyPins in the event of a + // pinning failure. It is a (somewhat) human-readable string. + std::string pinning_failure_log_; + // The following two variables are added for debugging bug 65948. Will // remove this code after fixing bug 65948. // Added the following code Debugging in release mode. diff --git a/net/ssl/ssl_info.cc b/net/ssl/ssl_info.cc index 77ddb62..d2973d2 100644 --- a/net/ssl/ssl_info.cc +++ b/net/ssl/ssl_info.cc @@ -33,6 +33,7 @@ SSLInfo& SSLInfo::operator=(const SSLInfo& info) { handshake_type = info.handshake_type; public_key_hashes = info.public_key_hashes; signed_certificate_timestamps = info.signed_certificate_timestamps; + pinning_failure_log = info.pinning_failure_log; return *this; } @@ -48,6 +49,7 @@ void SSLInfo::Reset() { handshake_type = HANDSHAKE_UNKNOWN; public_key_hashes.clear(); signed_certificate_timestamps.clear(); + pinning_failure_log.clear(); } void SSLInfo::SetCertError(int error) { diff --git a/net/ssl/ssl_info.h b/net/ssl/ssl_info.h index 00a8815..154c4a0 100644 --- a/net/ssl/ssl_info.h +++ b/net/ssl/ssl_info.h @@ -80,6 +80,11 @@ class NET_EXPORT SSLInfo { // each certificate in the chain. HashValueVector public_key_hashes; + // pinning_failure_log contains a message produced by + // TransportSecurityState::DomainState::CheckPublicKeyPins in the event of a + // pinning failure. It is a (somewhat) human-readable string. + std::string pinning_failure_log; + // List of SignedCertificateTimestamps and their corresponding validation // status. SignedCertificateTimestampAndStatusList signed_certificate_timestamps; |