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 @@ -7834,8 +7834,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 @@ -1032,7 +1032,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); @@ -1356,12 +1356,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; @@ -292,11 +300,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 == "0.0.0.0" || + host == "[::1]" || net::HostStringIsLocalhost(host)) { + need_permission = true; + } + return need_permission; } } // namespace network --