From d0ad345508ef81ed9369dd7fb5e228b5f394bf36 Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Wed, 17 Apr 2024 21:04:02 +0200 Subject: [PATCH] #344 Add UI for INSECURE_PRIVATE_NETWORK site setting --- ...vate-network-access-content-settings.patch | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 build/patches/Private-network-access-content-settings.patch diff --git a/build/patches/Private-network-access-content-settings.patch b/build/patches/Private-network-access-content-settings.patch new file mode 100644 index 000000000..65d46d607 --- /dev/null +++ b/build/patches/Private-network-access-content-settings.patch @@ -0,0 +1,246 @@ +From: uazo +Date: Wed, 17 Apr 2024 18:45:54 +0000 +Subject: Private network access content settings + +Block access to the local network by default in android while allowing +user choice in desktop platforms. + +License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html + +--- + .../browser/chrome_content_browser_client.cc | 3 +- + ...eInsecurePrivateNetworkContentSetting.java | 93 +++++++++++++++++++ + .../insecure_private_network.grdp | 18 ++++ + .../insecure_private_network.inc | 16 ++++ + services/network/cors/cors_url_loader.cc | 8 +- + .../network/private_network_access_checker.cc | 16 +++- + 6 files changed, 144 insertions(+), 10 deletions(-) + create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteInsecurePrivateNetworkContentSetting.java + create mode 100644 components/browser_ui/strings/bromite_content_settings/insecure_private_network.grdp + create mode 100644 components/content_settings/core/browser/bromite_content_settings/insecure_private_network.inc + +diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc +--- a/chrome/browser/chrome_content_browser_client.cc ++++ b/chrome/browser/chrome_content_browser_client.cc +@@ -7514,8 +7514,7 @@ ChromeContentBrowserClient::ShouldOverridePrivateNetworkRequestPolicy( + + #if BUILDFLAG(IS_ANDROID) + if (base::FeatureList::IsEnabled( +- kPrivateNetworkAccessRestrictionsForAutomotive) && +- base::android::BuildInfo::GetInstance()->is_automotive()) { ++ kPrivateNetworkAccessRestrictionsForAutomotive)) { + return content::ContentBrowserClient::PrivateNetworkRequestPolicyOverride:: + kBlockInsteadOfWarn; + } +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteInsecurePrivateNetworkContentSetting.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteInsecurePrivateNetworkContentSetting.java +new file mode 100644 +--- /dev/null ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteInsecurePrivateNetworkContentSetting.java +@@ -0,0 +1,93 @@ ++/* ++ This file is part of Bromite. ++ ++ Bromite is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ Bromite is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with Bromite. If not, see . ++*/ ++ ++package org.chromium.components.browser_ui.site_settings.impl; ++ ++import org.chromium.components.browser_ui.site_settings.R; ++ ++import org.chromium.components.browser_ui.site_settings.BromiteCustomContentSetting; ++import org.chromium.components.browser_ui.site_settings.ContentSettingsResources; ++import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; ++import org.chromium.components.content_settings.ContentSettingValues; ++import org.chromium.components.content_settings.ContentSettingsType; ++import org.chromium.content_public.browser.BrowserContextHandle; ++ ++import androidx.annotation.Nullable; ++import androidx.preference.Preference; ++import androidx.preference.PreferenceScreen; ++ ++import java.util.ArrayList; ++ ++public class BromiteInsecurePrivateNetworkContentSetting extends BromiteCustomContentSetting { ++ public BromiteInsecurePrivateNetworkContentSetting() { ++ super(/*contentSettingsType*/ ContentSettingsType.INSECURE_PRIVATE_NETWORK, ++ /*defaultEnabledValue*/ ContentSettingValues.ALLOW, ++ /*defaultDisabledValue*/ ContentSettingValues.BLOCK, ++ /*allowException*/ true, ++ /*preferenceKey*/ "insecure_private_network", ++ /*profilePrefKey*/ "insecure_private_network"); ++ } ++ ++ @Override ++ public ContentSettingsResources.ResourceItem getResourceItem() { ++ return new ContentSettingsResources.ResourceItem( ++ /*icon*/ R.drawable.web_asset, ++ /*title*/ R.string.insecure_private_network_permission_title, ++ /*defaultEnabledValue*/ getDefaultEnabledValue(), ++ /*defaultDisabledValue*/ getDefaultDisabledValue(), ++ /*enabledSummary*/ R.string.website_settings_category_insecure_private_network_allowed, ++ /*disabledSummary*/ R.string.website_settings_category_insecure_private_network_blocked, ++ /*summaryOverrideForScreenReader*/ 0); ++ } ++ ++ @Override ++ public int getCategorySummary(@Nullable @ContentSettingValues int value) { ++ switch (value) { ++ case ContentSettingValues.ALLOW: ++ return R.string.website_settings_category_insecure_private_network_allowed; ++ case ContentSettingValues.BLOCK: ++ return R.string.website_settings_category_insecure_private_network_blocked; ++ default: ++ return 0; ++ } ++ } ++ ++ @Override ++ public int getCategoryDescription() { ++ return R.string.settings_site_settings_insecure_private_network_description; ++ } ++ ++ @Override ++ public boolean requiresTriStateContentSetting() { ++ return false; ++ } ++ ++ @Override ++ public boolean showOnlyDescriptions() { ++ return true; ++ } ++ ++ @Override ++ public int getAddExceptionDialogMessage() { ++ return R.string.website_settings_category_insecure_private_network_allowed; ++ } ++ ++ @Override ++ public @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSettingValues int value) { ++ return value != ContentSettingValues.BLOCK; ++ } ++} +diff --git a/components/browser_ui/strings/bromite_content_settings/insecure_private_network.grdp b/components/browser_ui/strings/bromite_content_settings/insecure_private_network.grdp +new file mode 100644 +--- /dev/null ++++ b/components/browser_ui/strings/bromite_content_settings/insecure_private_network.grdp +@@ -0,0 +1,18 @@ ++ ++ ++ ++ Access to Private Network ++ ++ ++ Enable access to private network ++ ++ ++ Allow access to private network ++ ++ ++ Block access to private network ++ ++ ++ Ask access to private network ++ ++ +diff --git a/components/content_settings/core/browser/bromite_content_settings/insecure_private_network.inc b/components/content_settings/core/browser/bromite_content_settings/insecure_private_network.inc +new file mode 100644 +--- /dev/null ++++ b/components/content_settings/core/browser/bromite_content_settings/insecure_private_network.inc +@@ -0,0 +1,16 @@ ++ content_settings::WebsiteSettingsRegistry::GetInstance() ++ ->GetMutable(ContentSettingsType::INSECURE_PRIVATE_NETWORK) ++ ->set_show_into_info_page() ++ .set_desktop_ui() ++ .set_title_ui(IDS_INSECURE_PRIVATE_NETWORK_PERMISSION_TITLE) ++ .set_description_ui(IDS_SETTINGS_SITE_SETTINGS_INSECURE_PRIVATE_NETWORK_DESCRIPTION) ++ .set_allowed_ui(IDS_WEBSITE_SETTINGS_CATEGORY_INSECURE_PRIVATE_NETWORK_ALLOWED) ++ .set_allowed_exceptions_ui(IDS_WEBSITE_SETTINGS_CATEGORY_INSECURE_PRIVATE_NETWORK_ALLOWED) ++#if BUILDFLAG(IS_ANDROID) ++ .set_blocked_ui(IDS_WEBSITE_SETTINGS_CATEGORY_INSECURE_PRIVATE_NETWORK_BLOCKED) ++ .set_blocked_exceptions_ui(IDS_WEBSITE_SETTINGS_CATEGORY_INSECURE_PRIVATE_NETWORK_BLOCKED) ++#else ++ .set_blocked_ui(IDS_WEBSITE_SETTINGS_CATEGORY_INSECURE_PRIVATE_NETWORK_ASK) ++ .set_blocked_exceptions_ui(IDS_WEBSITE_SETTINGS_CATEGORY_INSECURE_PRIVATE_NETWORK_ASK) ++#endif ++ .set_mid_sentence_ui(IDS_INSECURE_PRIVATE_NETWORK_PERMISSION_TITLE); +diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc +--- a/services/network/cors/cors_url_loader.cc ++++ b/services/network/cors/cors_url_loader.cc +@@ -984,7 +984,7 @@ std::optional CorsURLLoader::ConvertPreflightResult( + } + + // Private Network Access warning: ignore net and CORS errors. +- if (net_error == net::OK || sending_pna_only_warning_preflight_) { ++ if (net_error == net::OK) { + CHECK(ShouldIgnorePrivateNetworkAccessErrors( + request_.required_ip_address_space)); + CHECK_EQ(*reason, PreflightRequiredReason::kPrivateNetworkAccess); +@@ -1330,12 +1330,6 @@ bool CorsURLLoader::ShouldIgnorePrivateNetworkAccessErrors( + if (!state) { + return false; + } +- // When the PNA permission prompt shown, we should always respect the +- // preflight results, otherwise it would be a bypass of mixed content checker. +- if (PrivateNetworkAccessChecker::NeedPermission( +- request_.url, state->is_web_secure_context, target_address_space)) { +- return false; +- } + return state->private_network_request_policy == + mojom::PrivateNetworkRequestPolicy::kPreflightWarn; + } +diff --git a/services/network/private_network_access_checker.cc b/services/network/private_network_access_checker.cc +--- a/services/network/private_network_access_checker.cc ++++ b/services/network/private_network_access_checker.cc +@@ -7,6 +7,7 @@ + #include "base/feature_list.h" + #include "base/metrics/histogram_functions.h" + #include "net/base/transport_info.h" ++#include "net/base/url_util.h" + #include "services/network/public/cpp/features.h" + #include "services/network/public/cpp/ip_address_space_util.h" + #include "services/network/public/cpp/is_potentially_trustworthy.h" +@@ -20,6 +21,13 @@ + namespace network { + namespace { + ++bool IsReservedIPAddress(const std::string host) { ++ net::IPAddress address; ++ if (!net::ParseURLHostnameToAddress(host, &address)) ++ return false; ++ return !address.IsPubliclyRoutable(); ++} ++ + using Result = PrivateNetworkAccessCheckResult; + using Policy = mojom::PrivateNetworkRequestPolicy; + +@@ -280,11 +288,17 @@ bool PrivateNetworkAccessChecker::NeedPermission( + const GURL& url, + bool is_web_secure_context, + mojom::IPAddressSpace target_address_space) { +- return base::FeatureList::IsEnabled( ++ bool need_permission = base::FeatureList::IsEnabled( + network::features::kPrivateNetworkAccessPermissionPrompt) && + is_web_secure_context && !network::IsUrlPotentiallyTrustworthy(url) && + (target_address_space == mojom::IPAddressSpace::kLocal || + target_address_space == mojom::IPAddressSpace::kPrivate); ++ std::string host = url.host(); ++ if (IsReservedIPAddress(host) || ++ host == "[::1]" || net::HostStringIsLocalhost(host)) { ++ need_permission = true; ++ } ++ return need_permission; + } + + } // namespace network +--