summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos IL <carlosil@chromium.org>2023-01-26 20:32:33 +0000
committerMichael BrĂ¼ning <michael.bruning@qt.io>2023-02-17 12:54:36 +0000
commit19ddfb039984262e389e8e4de3852c44d0d4be05 (patch)
tree8e0c70c7fc630b172ba28531e026f827893829e0
parent4468b016ee2d512246051b5b196350a65c203d11 (diff)
downloadqtwebengine-chromium-19ddfb039984262e389e8e4de3852c44d0d4be05.tar.gz
[Backport] Security bug 1404811
Cherry-pick of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/4171564: Fix include_subdomains handling with PKI Metadata pins list M102 merge issues: net/http/transport_security_state_unittest.cc: - Conflicting names for network_anonymization_key (network_isolation_key in 102). - The kStaticKeyPinningEnforcement feature flag isn't present in 102, but removing its init/activation from the test didn't affect test results Previously include_subdomains was ignored once the pinning list was loaded from a component (due to the find() call for the map using the full domain). This fixes this by calling it again with the url substring starting at the next . if the full domain is not found. (cherry picked from commit ca9cbe0aad4e4070b1e3c1ca530ede8a8a52cc4f) Bug: 1404811 Change-Id: I2d487401711a8a44e9cedb4b91c84ae5553c6932 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4137286 Commit-Queue: Carlos IL <carlosil@chromium.org> Cr-Original-Commit-Position: refs/heads/main@{#1091464} Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4171564 Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com> Owners-Override: Achuith Bhandarkar <achuith@chromium.org> Reviewed-by: Achuith Bhandarkar <achuith@chromium.org> Cr-Commit-Position: refs/branch-heads/5005@{#1427} Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738} Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/460489 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--chromium/net/http/transport_security_state.cc78
-rw-r--r--chromium/net/http/transport_security_state.h3
2 files changed, 55 insertions, 26 deletions
diff --git a/chromium/net/http/transport_security_state.cc b/chromium/net/http/transport_security_state.cc
index ecaeaba37f8..de3084675bb 100644
--- a/chromium/net/http/transport_security_state.cc
+++ b/chromium/net/http/transport_security_state.cc
@@ -643,8 +643,7 @@ void TransportSecurityState::UpdatePinList(
base::Time update_time) {
pinsets_ = pinsets;
key_pins_list_last_update_time_ = update_time;
- host_pins_ = absl::make_optional(
- std::map<std::string, std::pair<PinSet const*, bool>>());
+ host_pins_.emplace();
std::map<std::string, PinSet const*> pinset_names_map;
for (const auto& pinset : pinsets_) {
pinset_names_map[pinset.name()] = &pinset;
@@ -1186,32 +1185,61 @@ bool TransportSecurityState::GetStaticPKPState(const std::string& host,
PreloadResult result;
if (host_pins_.has_value()) {
- auto iter = host_pins_->find(host);
- if (iter != host_pins_->end()) {
- pkp_result->domain = host;
- pkp_result->last_observed = key_pins_list_last_update_time_;
- pkp_result->include_subdomains = iter->second.second;
- const PinSet* pinset = iter->second.first;
- if (!pinset->report_uri().empty()) {
- pkp_result->report_uri = GURL(pinset->report_uri());
- }
- for (auto hash : pinset->static_spki_hashes()) {
- // If the update is malformed, it's preferable to skip the hash than
- // crash.
- if (hash.size() == 32) {
- AddHash(reinterpret_cast<const char*>(hash.data()),
- &pkp_result->spki_hashes);
+ // Ensure that |host| is a valid hostname before processing.
+ if (CanonicalizeHost(host).empty()) {
+ return false;
+ }
+ // Normalize any trailing '.' used for DNS suffix searches.
+ std::string normalized_host = host;
+ size_t trailing_dot_found = normalized_host.find_last_not_of('.');
+ if (trailing_dot_found == std::string::npos) {
+ // Hostname is either empty or all dots
+ return false;
+ }
+ normalized_host.erase(trailing_dot_found + 1);
+ normalized_host = base::ToLowerASCII(normalized_host);
+
+ base::StringPiece search_hostname = normalized_host;
+ while (true) {
+ auto iter = host_pins_->find(search_hostname);
+ // Only consider this a match if either include_subdomains is set, or
+ // this is an exact match of the full hostname.
+ if (iter != host_pins_->end() &&
+ (iter->second.second || search_hostname == normalized_host)) {
+ pkp_result->domain = std::string(search_hostname);
+ pkp_result->last_observed = key_pins_list_last_update_time_;
+ pkp_result->include_subdomains = iter->second.second;
+ const PinSet* pinset = iter->second.first;
+ if (!pinset->report_uri().empty()) {
+ pkp_result->report_uri = GURL(pinset->report_uri());
}
- }
- for (auto hash : pinset->bad_static_spki_hashes()) {
- // If the update is malformed, it's preferable to skip the hash than
- // crash.
- if (hash.size() == 32) {
- AddHash(reinterpret_cast<const char*>(hash.data()),
- &pkp_result->bad_spki_hashes);
+ for (auto hash : pinset->static_spki_hashes()) {
+ // If the update is malformed, it's preferable to skip the hash than
+ // crash.
+ if (hash.size() == 32) {
+ AddHash(reinterpret_cast<const char*>(hash.data()),
+ &pkp_result->spki_hashes);
+ }
}
+ for (auto hash : pinset->bad_static_spki_hashes()) {
+ // If the update is malformed, it's preferable to skip the hash than
+ // crash.
+ if (hash.size() == 32) {
+ AddHash(reinterpret_cast<const char*>(hash.data()),
+ &pkp_result->bad_spki_hashes);
+ }
+ }
+ return true;
}
- return true;
+ auto dot_pos = search_hostname.find(".");
+ if (dot_pos == std::string::npos) {
+ // If this was not a match, and there are no more dots in the string,
+ // there are no more domains to try.
+ return false;
+ }
+ // Try again in case this is a subdomain of a pinned domain that includes
+ // subdomains.
+ search_hostname = search_hostname.substr(dot_pos + 1);
}
} else if (DecodeHSTSPreload(host, &result) && result.has_pins) {
if (result.pinset_id >= g_hsts_source->pinsets_count)
diff --git a/chromium/net/http/transport_security_state.h b/chromium/net/http/transport_security_state.h
index e8d50dbf23a..45c1765ed65 100644
--- a/chromium/net/http/transport_security_state.h
+++ b/chromium/net/http/transport_security_state.h
@@ -808,7 +808,8 @@ class NET_EXPORT TransportSecurityState {
// The values in host_pins_ maps are references to PinSet objects in the
// pinsets_ vector.
- absl::optional<std::map<std::string, std::pair<const PinSet*, bool>>>
+ absl::optional<
+ std::map<std::string, std::pair<const PinSet*, bool>, std::less<>>>
host_pins_;
base::Time key_pins_list_last_update_time_;
std::vector<PinSet> pinsets_;