Commit 3c616886 authored by Takashi Toyoshima's avatar Takashi Toyoshima Committed by Commit Bot

OOR-CORS: Chrome Extension's manifest supports port limit

With this change, specifying port in the manifest URLPattern
works even for CORS bypassing rules.

Bug: 936900
Change-Id: I3744b65307c923c9c593efef7a41a651ab67d494
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1619530
Commit-Queue: Takashi Toyoshima <toyoshim@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#662973}
parent 300013be
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
...@@ -427,6 +428,39 @@ IN_PROC_BROWSER_TEST_P(BackgroundXhrWebstoreTest, PolicyUpdateIndividualXHR) { ...@@ -427,6 +428,39 @@ IN_PROC_BROWSER_TEST_P(BackgroundXhrWebstoreTest, PolicyUpdateIndividualXHR) {
EXPECT_FALSE(CanFetch(extension, public_example_url)); EXPECT_FALSE(CanFetch(extension, public_example_url));
} }
IN_PROC_BROWSER_TEST_P(BackgroundXhrWebstoreTest, XHRAnyPortPermission) {
const Extension* extension = LoadXhrExtension("http://example.com:*/*");
GURL permitted_url_to_fetch =
embedded_test_server()->GetURL("example.com", "/simple.html");
EXPECT_TRUE(CanFetch(extension, permitted_url_to_fetch));
}
IN_PROC_BROWSER_TEST_P(BackgroundXhrWebstoreTest,
XHRPortSpecificPermissionAllow) {
const Extension* extension = LoadXhrExtension(
"http://example.com:" +
base::NumberToString(embedded_test_server()->port()) + "/*");
GURL permitted_url_to_fetch =
embedded_test_server()->GetURL("example.com", "/simple.html");
EXPECT_TRUE(CanFetch(extension, permitted_url_to_fetch));
}
IN_PROC_BROWSER_TEST_P(BackgroundXhrWebstoreTest,
XHRPortSpecificPermissionBlock) {
const Extension* extension = LoadXhrExtension(
"http://example.com:" +
base::NumberToString(embedded_test_server()->port() + 1) + "/*");
GURL not_permitted_url_to_fetch =
embedded_test_server()->GetURL("example.com", "/simple.html");
EXPECT_FALSE(CanFetch(extension, not_permitted_url_to_fetch));
}
INSTANTIATE_TEST_SUITE_P(WithoutAny, INSTANTIATE_TEST_SUITE_P(WithoutAny,
BackgroundXhrWebstoreTest, BackgroundXhrWebstoreTest,
testing::Values(TestMode::kWithoutAny)); testing::Values(TestMode::kWithoutAny));
......
...@@ -231,7 +231,6 @@ void ChromeExtensionsClient::AddOriginAccessPermissions( ...@@ -231,7 +231,6 @@ void ChromeExtensionsClient::AddOriginAccessPermissions(
// conservative. Components shouldn't be subject to enterprise policy controls // conservative. Components shouldn't be subject to enterprise policy controls
// or blocking access to the webstore so they get the highest priority // or blocking access to the webstore so they get the highest priority
// allowlist entry. // allowlist entry.
// TODO(crbug.com/936900): Specify the port argument.
if (extensions::Manifest::IsComponentLocation(extension.location()) && if (extensions::Manifest::IsComponentLocation(extension.location()) &&
is_extension_active) { is_extension_active) {
origin_patterns->push_back(network::mojom::CorsOriginPattern::New( origin_patterns->push_back(network::mojom::CorsOriginPattern::New(
...@@ -244,7 +243,6 @@ void ChromeExtensionsClient::AddOriginAccessPermissions( ...@@ -244,7 +243,6 @@ void ChromeExtensionsClient::AddOriginAccessPermissions(
// TODO(jstritar): We should try to remove this special case. Also, these // TODO(jstritar): We should try to remove this special case. Also, these
// whitelist entries need to be updated when the kManagement permission // whitelist entries need to be updated when the kManagement permission
// changes. // changes.
// TODO(crbug.com/936900): Specify the port argument.
if (is_extension_active && extension.permissions_data()->HasAPIPermission( if (is_extension_active && extension.permissions_data()->HasAPIPermission(
extensions::APIPermission::kManagement)) { extensions::APIPermission::kManagement)) {
origin_patterns->push_back(network::mojom::CorsOriginPattern::New( origin_patterns->push_back(network::mojom::CorsOriginPattern::New(
......
...@@ -2056,8 +2056,11 @@ void TestRunner::AddOriginAccessAllowListEntry( ...@@ -2056,8 +2056,11 @@ void TestRunner::AddOriginAccessAllowListEntry(
blink::WebSecurityPolicy::AddOriginAccessAllowListEntry( blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(
url, blink::WebString::FromUTF8(destination_protocol), url, blink::WebString::FromUTF8(destination_protocol),
blink::WebString::FromUTF8(destination_host), blink::WebString::FromUTF8(destination_host), /*destination_port=*/0,
allow_destination_subdomains, allow_destination_subdomains
? network::mojom::CorsDomainMatchMode::kAllowSubdomains
: network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <utility> #include <utility>
#include "base/strings/string_number_conversions.h"
#include "content/public/common/url_constants.h" #include "content/public/common/url_constants.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
...@@ -17,6 +18,15 @@ namespace extensions { ...@@ -17,6 +18,15 @@ namespace extensions {
namespace { namespace {
uint16_t GetEffectivePort(const std::string& port_string) {
int port_int = 0;
bool success = base::StringToInt(port_string, &port_int);
// The URLPattern should verify that |port| is a number or "*", so conversion
// should never fail.
DCHECK(success) << port_string;
return port_int;
}
void AddURLPatternSetToList( void AddURLPatternSetToList(
const URLPatternSet& pattern_set, const URLPatternSet& pattern_set,
std::vector<network::mojom::CorsOriginPatternPtr>* list, std::vector<network::mojom::CorsOriginPatternPtr>* list,
...@@ -36,13 +46,22 @@ void AddURLPatternSetToList( ...@@ -36,13 +46,22 @@ void AddURLPatternSetToList(
for (const char* const scheme : kSchemes) { for (const char* const scheme : kSchemes) {
if (!pattern.MatchesScheme(scheme)) if (!pattern.MatchesScheme(scheme))
continue; continue;
// TODO(crbug.com/936900): Specify the port argument. network::mojom::CorsDomainMatchMode domain_match_mode =
list->push_back(network::mojom::CorsOriginPattern::New(
scheme, pattern.host(), /*port=*/0,
pattern.match_subdomains() pattern.match_subdomains()
? network::mojom::CorsDomainMatchMode::kAllowSubdomains ? network::mojom::CorsDomainMatchMode::kAllowSubdomains
: network::mojom::CorsDomainMatchMode::kDisallowSubdomains, : network::mojom::CorsDomainMatchMode::kDisallowSubdomains;
network::mojom::CorsPortMatchMode::kAllowAnyPort, priority)); network::mojom::CorsPortMatchMode port_match_mode =
(pattern.port() == "*")
? network::mojom::CorsPortMatchMode::kAllowAnyPort
: network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort;
uint16_t port =
(port_match_mode ==
network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort)
? GetEffectivePort(pattern.port())
: 0u;
list->push_back(network::mojom::CorsOriginPattern::New(
scheme, pattern.host(), port, domain_match_mode, port_match_mode,
priority));
} }
} }
} }
...@@ -86,7 +105,6 @@ CreateCorsOriginAccessBlockList(const Extension& extension) { ...@@ -86,7 +105,6 @@ CreateCorsOriginAccessBlockList(const Extension& extension) {
network::mojom::CorsOriginAccessMatchPriority::kLowPriority); network::mojom::CorsOriginAccessMatchPriority::kLowPriority);
GURL webstore_launch_url = extension_urls::GetWebstoreLaunchURL(); GURL webstore_launch_url = extension_urls::GetWebstoreLaunchURL();
// TODO(crbug.com/936900): Specify the port argument.
block_list.push_back(network::mojom::CorsOriginPattern::New( block_list.push_back(network::mojom::CorsOriginPattern::New(
webstore_launch_url.scheme(), webstore_launch_url.host(), /*port=*/0, webstore_launch_url.scheme(), webstore_launch_url.host(), /*port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains, network::mojom::CorsDomainMatchMode::kAllowSubdomains,
......
...@@ -1227,23 +1227,17 @@ void Dispatcher::UpdateOriginPermissions(const Extension& extension) { ...@@ -1227,23 +1227,17 @@ void Dispatcher::UpdateOriginPermissions(const Extension& extension) {
ExtensionsClient::Get()->AddOriginAccessPermissions( ExtensionsClient::Get()->AddOriginAccessPermissions(
extension, IsExtensionActive(extension.id()), &allow_list); extension, IsExtensionActive(extension.id()), &allow_list);
for (const auto& entry : allow_list) { for (const auto& entry : allow_list) {
// TODO(crbug.com/936900): Use port information.
WebSecurityPolicy::AddOriginAccessAllowListEntry( WebSecurityPolicy::AddOriginAccessAllowListEntry(
extension.url(), WebString::FromUTF8(entry->protocol), extension.url(), WebString::FromUTF8(entry->protocol),
WebString::FromUTF8(entry->domain), WebString::FromUTF8(entry->domain), entry->port,
entry->domain_match_mode == entry->domain_match_mode, entry->port_match_mode, entry->priority);
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
entry->priority);
} }
for (const auto& entry : CreateCorsOriginAccessBlockList(extension)) { for (const auto& entry : CreateCorsOriginAccessBlockList(extension)) {
// TODO(crbug.com/936900): Use port information.
WebSecurityPolicy::AddOriginAccessBlockListEntry( WebSecurityPolicy::AddOriginAccessBlockListEntry(
extension.url(), WebString::FromUTF8(entry->protocol), extension.url(), WebString::FromUTF8(entry->protocol),
WebString::FromUTF8(entry->domain), WebString::FromUTF8(entry->domain), entry->port,
entry->domain_match_mode == entry->domain_match_mode, entry->port_match_mode, entry->priority);
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
entry->priority);
} }
} }
......
...@@ -87,7 +87,7 @@ class OriginAccessListTest : public testing::Test { ...@@ -87,7 +87,7 @@ class OriginAccessListTest : public testing::Test {
} }
void SetBlockListEntry(const std::string& protocol, void SetBlockListEntry(const std::string& protocol,
const std::string& host, const std::string& host,
const uint16_t port, const int16_t port,
const mojom::CorsDomainMatchMode domain_match_mode, const mojom::CorsDomainMatchMode domain_match_mode,
const mojom::CorsPortMatchMode port_match_mode) { const mojom::CorsPortMatchMode port_match_mode) {
std::vector<mojom::CorsOriginPatternPtr> patterns; std::vector<mojom::CorsOriginPatternPtr> patterns;
......
...@@ -78,13 +78,17 @@ class WebSecurityPolicy { ...@@ -78,13 +78,17 @@ class WebSecurityPolicy {
const WebURL& source_origin, const WebURL& source_origin,
const WebString& destination_protocol, const WebString& destination_protocol,
const WebString& destination_host, const WebString& destination_host,
bool allow_destination_subdomains, const uint16_t destination_port,
network::mojom::CorsDomainMatchMode domain_match_mode,
network::mojom::CorsPortMatchMode port_match_mode,
const network::mojom::CorsOriginAccessMatchPriority priority); const network::mojom::CorsOriginAccessMatchPriority priority);
BLINK_EXPORT static void AddOriginAccessBlockListEntry( BLINK_EXPORT static void AddOriginAccessBlockListEntry(
const WebURL& source_origin, const WebURL& source_origin,
const WebString& destination_protocol, const WebString& destination_protocol,
const WebString& destination_host, const WebString& destination_host,
bool disallow_destination_subdomains, const uint16_t destination_port,
network::mojom::CorsDomainMatchMode domain_match_mode,
network::mojom::CorsPortMatchMode port_match_mode,
const network::mojom::CorsOriginAccessMatchPriority priority); const network::mojom::CorsOriginAccessMatchPriority priority);
BLINK_EXPORT static void ClearOriginAccessListForOrigin( BLINK_EXPORT static void ClearOriginAccessListForOrigin(
const WebURL& source_origin); const WebURL& source_origin);
......
...@@ -70,22 +70,28 @@ void WebSecurityPolicy::AddOriginAccessAllowListEntry( ...@@ -70,22 +70,28 @@ void WebSecurityPolicy::AddOriginAccessAllowListEntry(
const WebURL& source_origin, const WebURL& source_origin,
const WebString& destination_protocol, const WebString& destination_protocol,
const WebString& destination_host, const WebString& destination_host,
bool allow_destination_subdomains, const uint16_t destination_port,
const network::mojom::CorsDomainMatchMode domain_match_mode,
const network::mojom::CorsPortMatchMode port_match_mode,
const network::mojom::CorsOriginAccessMatchPriority priority) { const network::mojom::CorsOriginAccessMatchPriority priority) {
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*SecurityOrigin::Create(source_origin), destination_protocol, *SecurityOrigin::Create(source_origin), destination_protocol,
destination_host, allow_destination_subdomains, priority); destination_host, destination_port, domain_match_mode, port_match_mode,
priority);
} }
void WebSecurityPolicy::AddOriginAccessBlockListEntry( void WebSecurityPolicy::AddOriginAccessBlockListEntry(
const WebURL& source_origin, const WebURL& source_origin,
const WebString& destination_protocol, const WebString& destination_protocol,
const WebString& destination_host, const WebString& destination_host,
bool allow_destination_subdomains, const uint16_t destination_port,
const network::mojom::CorsDomainMatchMode domain_match_mode,
const network::mojom::CorsPortMatchMode port_match_mode,
const network::mojom::CorsOriginAccessMatchPriority priority) { const network::mojom::CorsOriginAccessMatchPriority priority) {
SecurityPolicy::AddOriginAccessBlockListEntry( SecurityPolicy::AddOriginAccessBlockListEntry(
*SecurityOrigin::Create(source_origin), destination_protocol, *SecurityOrigin::Create(source_origin), destination_protocol,
destination_host, allow_destination_subdomains, priority); destination_host, destination_port, domain_match_mode, port_match_mode,
priority);
} }
void WebSecurityPolicy::ClearOriginAccessListForOrigin( void WebSecurityPolicy::ClearOriginAccessListForOrigin(
......
...@@ -362,7 +362,10 @@ TEST_F(SecurityOriginTest, CanRequestWithAllowListedAccess) { ...@@ -362,7 +362,10 @@ TEST_F(SecurityOriginTest, CanRequestWithAllowListedAccess) {
EXPECT_FALSE(origin->CanRequest(url)); EXPECT_FALSE(origin->CanRequest(url));
// Adding the url to the access allowlist should allow the request. // Adding the url to the access allowlist should allow the request.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*origin, "https", "example.com", false, *origin, "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority); network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
EXPECT_TRUE(origin->CanRequest(url)); EXPECT_TRUE(origin->CanRequest(url));
} }
...@@ -375,10 +378,16 @@ TEST_F(SecurityOriginTest, CannotRequestWithBlockListedAccess) { ...@@ -375,10 +378,16 @@ TEST_F(SecurityOriginTest, CannotRequestWithBlockListedAccess) {
// BlockList that is more or same specificity wins. // BlockList that is more or same specificity wins.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*origin, "https", "example.com", true, *origin, "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
SecurityPolicy::AddOriginAccessBlockListEntry( SecurityPolicy::AddOriginAccessBlockListEntry(
*origin, "https", "example.com", false, *origin, "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kLowPriority); network::mojom::CorsOriginAccessMatchPriority::kLowPriority);
// Block since example.com is on the allowlist & blocklist. // Block since example.com is on the allowlist & blocklist.
EXPECT_FALSE(origin->CanRequest(blocked_url)); EXPECT_FALSE(origin->CanRequest(blocked_url));
...@@ -393,10 +402,16 @@ TEST_F(SecurityOriginTest, CanRequestWithMoreSpecificAllowList) { ...@@ -393,10 +402,16 @@ TEST_F(SecurityOriginTest, CanRequestWithMoreSpecificAllowList) {
const blink::KURL blocked_url("https://example.com"); const blink::KURL blocked_url("https://example.com");
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*origin, "https", "test.example.com", true, *origin, "https", "test.example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority); network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
SecurityPolicy::AddOriginAccessBlockListEntry( SecurityPolicy::AddOriginAccessBlockListEntry(
*origin, "https", "example.com", true, *origin, "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kLowPriority); network::mojom::CorsOriginAccessMatchPriority::kLowPriority);
// Allow since test.example.com (allowlist) has a higher priority than // Allow since test.example.com (allowlist) has a higher priority than
// *.example.com (blocklist). // *.example.com (blocklist).
...@@ -405,6 +420,29 @@ TEST_F(SecurityOriginTest, CanRequestWithMoreSpecificAllowList) { ...@@ -405,6 +420,29 @@ TEST_F(SecurityOriginTest, CanRequestWithMoreSpecificAllowList) {
EXPECT_FALSE(origin->CanRequest(blocked_url)); EXPECT_FALSE(origin->CanRequest(blocked_url));
} }
TEST_F(SecurityOriginTest, CanRequestWithPortSpecificAllowList) {
scoped_refptr<const SecurityOrigin> origin =
SecurityOrigin::CreateFromString("https://chromium.org");
SecurityPolicy::AddOriginAccessAllowListEntry(
*origin, "https", "test1.example.com", 443,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
SecurityPolicy::AddOriginAccessAllowListEntry(
*origin, "https", "test2.example.com", 444,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
EXPECT_TRUE(origin->CanRequest(blink::KURL("https://test1.example.com")));
EXPECT_TRUE(origin->CanRequest(blink::KURL("https://test1.example.com:443")));
EXPECT_FALSE(origin->CanRequest(blink::KURL("https://test1.example.com:43")));
EXPECT_FALSE(origin->CanRequest(blink::KURL("https://test2.example.com")));
EXPECT_FALSE(origin->CanRequest(blink::KURL("https://test2.example.com:44")));
EXPECT_TRUE(origin->CanRequest(blink::KURL("https://test2.example.com:444")));
}
TEST_F(SecurityOriginTest, PunycodeNotUnicode) { TEST_F(SecurityOriginTest, PunycodeNotUnicode) {
scoped_refptr<const SecurityOrigin> origin = scoped_refptr<const SecurityOrigin> origin =
SecurityOrigin::CreateFromString("https://chromium.org"); SecurityOrigin::CreateFromString("https://chromium.org");
...@@ -417,14 +455,20 @@ TEST_F(SecurityOriginTest, PunycodeNotUnicode) { ...@@ -417,14 +455,20 @@ TEST_F(SecurityOriginTest, PunycodeNotUnicode) {
// Verify unicode origin can not be allowlisted. // Verify unicode origin can not be allowlisted.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*origin, "https", "☃.net", true, *origin, "https", "☃.net",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority); network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
EXPECT_FALSE(origin->CanRequest(punycode_url)); EXPECT_FALSE(origin->CanRequest(punycode_url));
EXPECT_FALSE(origin->CanRequest(unicode_url)); EXPECT_FALSE(origin->CanRequest(unicode_url));
// Verify punycode allowlist only affects punycode URLs. // Verify punycode allowlist only affects punycode URLs.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*origin, "https", "xn--n3h.net", true, *origin, "https", "xn--n3h.net",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority); network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
EXPECT_TRUE(origin->CanRequest(punycode_url)); EXPECT_TRUE(origin->CanRequest(punycode_url));
EXPECT_FALSE(origin->CanRequest(unicode_url)); EXPECT_FALSE(origin->CanRequest(unicode_url));
...@@ -437,7 +481,10 @@ TEST_F(SecurityOriginTest, PunycodeNotUnicode) { ...@@ -437,7 +481,10 @@ TEST_F(SecurityOriginTest, PunycodeNotUnicode) {
// Simulate <all_urls> being in the extension permissions. // Simulate <all_urls> being in the extension permissions.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*origin, "https", "", true, *origin, "https", "",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
EXPECT_TRUE(origin->CanRequest(punycode_url)); EXPECT_TRUE(origin->CanRequest(punycode_url));
...@@ -445,14 +492,20 @@ TEST_F(SecurityOriginTest, PunycodeNotUnicode) { ...@@ -445,14 +492,20 @@ TEST_F(SecurityOriginTest, PunycodeNotUnicode) {
// Verify unicode origin can not be blocklisted. // Verify unicode origin can not be blocklisted.
SecurityPolicy::AddOriginAccessBlockListEntry( SecurityPolicy::AddOriginAccessBlockListEntry(
*origin, "https", "☃.net", true, *origin, "https", "☃.net",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kLowPriority); network::mojom::CorsOriginAccessMatchPriority::kLowPriority);
EXPECT_TRUE(origin->CanRequest(punycode_url)); EXPECT_TRUE(origin->CanRequest(punycode_url));
EXPECT_FALSE(origin->CanRequest(unicode_url)); EXPECT_FALSE(origin->CanRequest(unicode_url));
// Verify punycode blocklist only affects punycode URLs. // Verify punycode blocklist only affects punycode URLs.
SecurityPolicy::AddOriginAccessBlockListEntry( SecurityPolicy::AddOriginAccessBlockListEntry(
*origin, "https", "xn--n3h.net", true, *origin, "https", "xn--n3h.net",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kLowPriority); network::mojom::CorsOriginAccessMatchPriority::kLowPriority);
EXPECT_FALSE(origin->CanRequest(punycode_url)); EXPECT_FALSE(origin->CanRequest(punycode_url));
EXPECT_FALSE(origin->CanRequest(unicode_url)); EXPECT_FALSE(origin->CanRequest(unicode_url));
......
...@@ -253,32 +253,30 @@ void SecurityPolicy::AddOriginAccessAllowListEntry( ...@@ -253,32 +253,30 @@ void SecurityPolicy::AddOriginAccessAllowListEntry(
const SecurityOrigin& source_origin, const SecurityOrigin& source_origin,
const String& destination_protocol, const String& destination_protocol,
const String& destination_domain, const String& destination_domain,
bool allow_destination_subdomains, const uint16_t port,
const network::mojom::CorsDomainMatchMode domain_match_mode,
const network::mojom::CorsPortMatchMode port_match_mode,
const network::mojom::CorsOriginAccessMatchPriority priority) { const network::mojom::CorsOriginAccessMatchPriority priority) {
MutexLocker lock(GetMutex()); MutexLocker lock(GetMutex());
GetOriginAccessList().AddAllowListEntryForOrigin( GetOriginAccessList().AddAllowListEntryForOrigin(
source_origin.ToUrlOrigin(), WebString(destination_protocol).Utf8(), source_origin.ToUrlOrigin(), WebString(destination_protocol).Utf8(),
WebString(destination_domain).Utf8(), /*port=*/0, WebString(destination_domain).Utf8(), port, domain_match_mode,
allow_destination_subdomains port_match_mode, priority);
? network::mojom::CorsDomainMatchMode::kAllowSubdomains
: network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort, priority);
} }
void SecurityPolicy::AddOriginAccessBlockListEntry( void SecurityPolicy::AddOriginAccessBlockListEntry(
const SecurityOrigin& source_origin, const SecurityOrigin& source_origin,
const String& destination_protocol, const String& destination_protocol,
const String& destination_domain, const String& destination_domain,
bool allow_destination_subdomains, const uint16_t port,
const network::mojom::CorsDomainMatchMode domain_match_mode,
const network::mojom::CorsPortMatchMode port_match_mode,
const network::mojom::CorsOriginAccessMatchPriority priority) { const network::mojom::CorsOriginAccessMatchPriority priority) {
MutexLocker lock(GetMutex()); MutexLocker lock(GetMutex());
GetOriginAccessList().AddBlockListEntryForOrigin( GetOriginAccessList().AddBlockListEntryForOrigin(
source_origin.ToUrlOrigin(), WebString(destination_protocol).Utf8(), source_origin.ToUrlOrigin(), WebString(destination_protocol).Utf8(),
WebString(destination_domain).Utf8(), /*port=*/0, WebString(destination_domain).Utf8(), port, domain_match_mode,
allow_destination_subdomains port_match_mode, priority);
? network::mojom::CorsDomainMatchMode::kAllowSubdomains
: network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort, priority);
} }
void SecurityPolicy::ClearOriginAccessListForOrigin( void SecurityPolicy::ClearOriginAccessListForOrigin(
......
...@@ -74,18 +74,21 @@ class PLATFORM_EXPORT SecurityPolicy { ...@@ -74,18 +74,21 @@ class PLATFORM_EXPORT SecurityPolicy {
const KURL&, const KURL&,
const String& referrer); const String& referrer);
// TODO(crbug.com/936900): Update to take the port.
static void AddOriginAccessAllowListEntry( static void AddOriginAccessAllowListEntry(
const SecurityOrigin& source_origin, const SecurityOrigin& source_origin,
const String& destination_protocol, const String& destination_protocol,
const String& destination_domain, const String& destination_domain,
bool allow_destination_subdomains, const uint16_t port,
const network::mojom::CorsDomainMatchMode domain_match_mode,
const network::mojom::CorsPortMatchMode port_match_mode,
const network::mojom::CorsOriginAccessMatchPriority priority); const network::mojom::CorsOriginAccessMatchPriority priority);
static void AddOriginAccessBlockListEntry( static void AddOriginAccessBlockListEntry(
const SecurityOrigin& source_origin, const SecurityOrigin& source_origin,
const String& destination_protocol, const String& destination_protocol,
const String& destination_domain, const String& destination_domain,
bool allow_destination_subdomains, const uint16_t port,
const network::mojom::CorsDomainMatchMode domain_match_mode,
const network::mojom::CorsPortMatchMode port_match_mode,
const network::mojom::CorsOriginAccessMatchPriority priority); const network::mojom::CorsOriginAccessMatchPriority priority);
static void ClearOriginAccessListForOrigin( static void ClearOriginAccessListForOrigin(
const SecurityOrigin& source_origin); const SecurityOrigin& source_origin);
......
...@@ -395,7 +395,10 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowed) { ...@@ -395,7 +395,10 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowed) {
// Adding access for https://example.com should work, but should not grant // Adding access for https://example.com should work, but should not grant
// access to subdomains or other schemes. // access to subdomains or other schemes.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "example.com", false, *https_chromium_origin(), "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(), EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(),
https_example_origin())); https_example_origin()));
...@@ -416,7 +419,10 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowed) { ...@@ -416,7 +419,10 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowed) {
// Adding an entry that matches subdomains should grant access to any // Adding an entry that matches subdomains should grant access to any
// subdomains. // subdomains.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "example.com", true, *https_chromium_origin(), "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(), EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(),
https_example_origin())); https_example_origin()));
...@@ -429,7 +435,10 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowed) { ...@@ -429,7 +435,10 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowed) {
TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedWildCard) { TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedWildCard) {
// An empty domain that matches subdomains results in matching every domain. // An empty domain that matches subdomains results in matching every domain.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "", true, *https_chromium_origin(), "https", "",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(), EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(),
https_example_origin())); https_example_origin()));
...@@ -442,10 +451,16 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedWildCard) { ...@@ -442,10 +451,16 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedWildCard) {
TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedWithBlockListEntry) { TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedWithBlockListEntry) {
// The block list takes priority over the allow list. // The block list takes priority over the allow list.
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "example.com", true, *https_chromium_origin(), "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
SecurityPolicy::AddOriginAccessBlockListEntry( SecurityPolicy::AddOriginAccessBlockListEntry(
*https_chromium_origin(), "https", "example.com", false, *https_chromium_origin(), "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
EXPECT_FALSE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(), EXPECT_FALSE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(),
...@@ -457,10 +472,16 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedWithBlockListEntry) { ...@@ -457,10 +472,16 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedWithBlockListEntry) {
TEST_F(SecurityPolicyAccessTest, TEST_F(SecurityPolicyAccessTest,
IsOriginAccessAllowedWildcardWithBlockListEntry) { IsOriginAccessAllowedWildcardWithBlockListEntry) {
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "", true, *https_chromium_origin(), "https", "",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
SecurityPolicy::AddOriginAccessBlockListEntry( SecurityPolicy::AddOriginAccessBlockListEntry(
*https_chromium_origin(), "https", "google.com", false, *https_chromium_origin(), "https", "google.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(), EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(https_chromium_origin(),
...@@ -471,13 +492,22 @@ TEST_F(SecurityPolicyAccessTest, ...@@ -471,13 +492,22 @@ TEST_F(SecurityPolicyAccessTest,
TEST_F(SecurityPolicyAccessTest, ClearOriginAccessListForOrigin) { TEST_F(SecurityPolicyAccessTest, ClearOriginAccessListForOrigin) {
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "example.com", true, *https_chromium_origin(), "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "google.com", true, *https_chromium_origin(), "https", "google.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_example_origin(), "https", "google.com", true, *https_example_origin(), "https", "google.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority); network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
SecurityPolicy::ClearOriginAccessListForOrigin(*https_chromium_origin()); SecurityPolicy::ClearOriginAccessListForOrigin(*https_chromium_origin());
...@@ -494,19 +524,27 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedPriority) { ...@@ -494,19 +524,27 @@ TEST_F(SecurityPolicyAccessTest, IsOriginAccessAllowedPriority) {
EXPECT_FALSE(SecurityPolicy::IsOriginAccessAllowed( EXPECT_FALSE(SecurityPolicy::IsOriginAccessAllowed(
https_chromium_origin(), https_sub_example_origin())); https_chromium_origin(), https_sub_example_origin()));
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "sub.example.com", false, *https_chromium_origin(), "https", "sub.example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kLowPriority); network::mojom::CorsOriginAccessMatchPriority::kLowPriority);
EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed( EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(
https_chromium_origin(), https_sub_example_origin())); https_chromium_origin(), https_sub_example_origin()));
SecurityPolicy::AddOriginAccessBlockListEntry( SecurityPolicy::AddOriginAccessBlockListEntry(
*https_chromium_origin(), "https", "example.com", true, *https_chromium_origin(), "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority); network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
EXPECT_FALSE(SecurityPolicy::IsOriginAccessAllowed( EXPECT_FALSE(SecurityPolicy::IsOriginAccessAllowed(
https_chromium_origin(), https_sub_example_origin())); https_chromium_origin(), https_sub_example_origin()));
SecurityPolicy::AddOriginAccessAllowListEntry( SecurityPolicy::AddOriginAccessAllowListEntry(
*https_chromium_origin(), "https", "example.com", true, *https_chromium_origin(), "https", "example.com",
/*destination_port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kHighPriority); network::mojom::CorsOriginAccessMatchPriority::kHighPriority);
EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed( EXPECT_TRUE(SecurityPolicy::IsOriginAccessAllowed(
https_chromium_origin(), https_sub_example_origin())); https_chromium_origin(), https_sub_example_origin()));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment