blob: 3338c81cd0914618ab67ccf43baab62fcc2adf94 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ssl/sct_reporting_service.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/common/chrome_features.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.h"
#include "google_apis/google_api_keys.h"
#include "net/base/escape.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
constexpr net::NetworkTrafficAnnotationTag kSCTAuditReportTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("sct_auditing", R"(
semantics {
sender: "Safe Browsing"
description:
"When a user connects to a site, opted-in clients may upload "
"a report about the Signed Certificate Timestamps used for meeting "
"Chrome's Certificate Transparency Policy to Safe Browsing to "
"detect misbehaving Certificate Transparency logs. This helps "
"improve the security and trustworthiness of the HTTPS ecosystem."
trigger:
"The browser will upload a report to Google when a connection to a "
"website includes Signed Certificate Timestamps, and the user is "
"opted in to extended reporting."
data:
"The time of the request, the hostname and port being requested, "
"the certificate chain, and the Signed Certificate Timestamps "
"observed on the connection."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: NO
setting:
"Users can enable or disable this feature by enabling or disabling "
"'Enhanced Protection' in Chrome's settings under Security, "
"Safe Browsing, or by enabling or disabling 'Help improve security "
"on the web for everyone' under 'Standard Protection' in Chrome's "
"settings under Security, Safe Browsing. The feature is disabled "
"by default."
chrome_policy {
SafeBrowsingExtendedReportingEnabled {
policy_options {mode: MANDATORY}
SafeBrowsingExtendedReportingEnabled: false
}
}
})");
constexpr net::NetworkTrafficAnnotationTag kSCTHashdanceTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("sct_auditing_hashdance", R"(
semantics {
sender: "Safe Browsing"
description:
"When a user connects to a site, clients with Safe Browsing "
"enabled may query Google about similar Signed Certificate "
"Timestamps. If the SCT has not been seen before, this indicates a "
"security incident and the client will upload a full report. This "
"helps improve the security and trustworthiness of the HTTPS "
"ecosystem."
trigger:
"The browser will query Google when a connection to a website "
"includes Signed Certificate Timestamps, and the user is opted in "
"to Safe Browsing."
data:
"A short prefix of the SCT leaf hash, the length of the prefix, "
"and a short user agent string."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: NO
setting:
"Users can enable or disable this feature by enabling or disabling "
"'Safe Browsing' in Chrome's settings under Security, "
"Safe Browsing. This feature is enabled by default."
chrome_policy {
SafeBrowsingProtectionLevel {
policy_options {mode: MANDATORY}
SafeBrowsingProtectionLevel: 0
}
}
})");
constexpr char kSBSCTAuditingReportURL[] =
"https://safebrowsing.google.com/safebrowsing/clientreport/"
"chrome-sct-auditing";
constexpr char kHashdanceLookupQueryURL[] =
"https://sctauditing-pa.googleapis.com/v1/knownscts/"
"length/$1/prefix/$2?key=";
// static
GURL& SCTReportingService::GetReportURLInstance() {
static base::NoDestructor<GURL> instance(kSBSCTAuditingReportURL);
return *instance;
}
// static
GURL& SCTReportingService::GetHashdanceLookupQueryURLInstance() {
static base::NoDestructor<GURL> instance(
std::string(kHashdanceLookupQueryURL) +
net::EscapeQueryParamValue(google_apis::GetAPIKey(), /*use_plus=*/true));
return *instance;
}
// static
void SCTReportingService::ReconfigureAfterNetworkRestart() {
content::GetNetworkService()->ConfigureSCTAuditing(
features::kSCTAuditingSamplingRate.Get(),
features::kSCTLogExpectedIngestionDelay.Get(),
features::kSCTLogMaxIngestionRandomDelay.Get(),
SCTReportingService::GetReportURLInstance(),
SCTReportingService::GetHashdanceLookupQueryURLInstance(),
net::MutableNetworkTrafficAnnotationTag(kSCTAuditReportTrafficAnnotation),
net::MutableNetworkTrafficAnnotationTag(kSCTHashdanceTrafficAnnotation));
}
SCTReportingService::SCTReportingService(
safe_browsing::SafeBrowsingService* safe_browsing_service,
Profile* profile)
: safe_browsing_service_(safe_browsing_service),
pref_service_(*profile->GetPrefs()),
profile_(profile) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// SCT auditing should stay disabled for Incognito/OTR profiles, so we don't
// need to subscribe to the prefs.
if (profile_->IsOffTheRecord())
return;
// Subscribe to SafeBrowsing preference change notifications. The initial Safe
// Browsing state gets emitted to subscribers during Profile creation.
safe_browsing_state_subscription_ =
safe_browsing_service_->RegisterStateCallback(base::BindRepeating(
&SCTReportingService::OnPreferenceChanged, base::Unretained(this)));
}
SCTReportingService::~SCTReportingService() = default;
namespace {
void SetSCTAuditingEnabledForStoragePartition(
network::mojom::SCTAuditingMode mode,
content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()->SetSCTAuditingMode(mode);
}
} // namespace
network::mojom::SCTAuditingMode SCTReportingService::GetReportingMode() {
if (profile_->IsOffTheRecord() ||
!base::FeatureList::IsEnabled(features::kSCTAuditing)) {
return network::mojom::SCTAuditingMode::kDisabled;
}
if (safe_browsing::IsSafeBrowsingEnabled(pref_service_)) {
if (safe_browsing::IsExtendedReportingEnabled(pref_service_)) {
return network::mojom::SCTAuditingMode::kEnhancedSafeBrowsingReporting;
}
if (base::FeatureList::IsEnabled(features::kSCTAuditingHashdance)) {
return network::mojom::SCTAuditingMode::kHashdance;
}
}
return network::mojom::SCTAuditingMode::kDisabled;
}
void SCTReportingService::OnPreferenceChanged() {
network::mojom::SCTAuditingMode mode = GetReportingMode();
// Iterate over StoragePartitions for this Profile, and for each get the
// NetworkContext and set the SCT auditing mode.
profile_->ForEachStoragePartition(
base::BindRepeating(&SetSCTAuditingEnabledForStoragePartition, mode));
if (mode == network::mojom::SCTAuditingMode::kDisabled)
content::GetNetworkService()->ClearSCTAuditingCache();
}