Commit f589d992 authored by Takashi Toyoshima's avatar Takashi Toyoshima Committed by Commit Bot

OOR-CORS: OriginAccessList cleanups

This patch changes the data structure to have the allow/block lists.
Also, modifies the interfaces not to have list specific clear methods,
but just have them to clear both lists together.

Still |Patterns| isn't the best structure to have multiple patterns
for the same origin with priorities, but since matching rule is not
simple, and will be changed to count port number, it is not updated
in this patch.

Bug: 908756
Change-Id: Ie148b5f35c66968fb2a1c8a9332a1442b6091586
TBR: tsepez@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1614380
Commit-Queue: Takashi Toyoshima <toyoshim@chromium.org>
Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#660779}
parent 67536d57
...@@ -16,7 +16,7 @@ OriginAccessList::~OriginAccessList() = default; ...@@ -16,7 +16,7 @@ OriginAccessList::~OriginAccessList() = default;
void OriginAccessList::SetAllowListForOrigin( void OriginAccessList::SetAllowListForOrigin(
const url::Origin& source_origin, const url::Origin& source_origin,
const std::vector<CorsOriginPatternPtr>& patterns) { const std::vector<CorsOriginPatternPtr>& patterns) {
SetForOrigin(source_origin, patterns, &allow_list_); SetForOrigin(source_origin, patterns, &map_, MapType::kAllowPatterns);
} }
void OriginAccessList::AddAllowListEntryForOrigin( void OriginAccessList::AddAllowListEntryForOrigin(
...@@ -27,23 +27,13 @@ void OriginAccessList::AddAllowListEntryForOrigin( ...@@ -27,23 +27,13 @@ void OriginAccessList::AddAllowListEntryForOrigin(
const mojom::CorsOriginAccessMatchPriority priority) { const mojom::CorsOriginAccessMatchPriority priority) {
AddForOrigin(source_origin, AddForOrigin(source_origin,
mojom::CorsOriginPattern::New(protocol, domain, mode, priority), mojom::CorsOriginPattern::New(protocol, domain, mode, priority),
&allow_list_); &map_, MapType::kAllowPatterns);
}
void OriginAccessList::ClearAllowListForOrigin(
const url::Origin& source_origin) {
SetForOrigin(source_origin, std::vector<mojom::CorsOriginPatternPtr>(),
&allow_list_);
}
void OriginAccessList::ClearAllowList() {
allow_list_.clear();
} }
void OriginAccessList::SetBlockListForOrigin( void OriginAccessList::SetBlockListForOrigin(
const url::Origin& source_origin, const url::Origin& source_origin,
const std::vector<CorsOriginPatternPtr>& patterns) { const std::vector<CorsOriginPatternPtr>& patterns) {
SetForOrigin(source_origin, patterns, &block_list_); SetForOrigin(source_origin, patterns, &map_, MapType::kBlockPatterns);
} }
void OriginAccessList::AddBlockListEntryForOrigin( void OriginAccessList::AddBlockListEntryForOrigin(
...@@ -54,17 +44,16 @@ void OriginAccessList::AddBlockListEntryForOrigin( ...@@ -54,17 +44,16 @@ void OriginAccessList::AddBlockListEntryForOrigin(
const mojom::CorsOriginAccessMatchPriority priority) { const mojom::CorsOriginAccessMatchPriority priority) {
AddForOrigin(source_origin, AddForOrigin(source_origin,
mojom::CorsOriginPattern::New(protocol, domain, mode, priority), mojom::CorsOriginPattern::New(protocol, domain, mode, priority),
&block_list_); &map_, MapType::kBlockPatterns);
} }
void OriginAccessList::ClearBlockListForOrigin( void OriginAccessList::ClearForOrigin(const url::Origin& source_origin) {
const url::Origin& source_origin) { DCHECK(!source_origin.opaque());
SetForOrigin(source_origin, std::vector<mojom::CorsOriginPatternPtr>(), map_.erase(source_origin.Serialize());
&block_list_);
} }
void OriginAccessList::ClearBlockList() { void OriginAccessList::Clear() {
block_list_.clear(); map_.clear();
} }
OriginAccessList::AccessState OriginAccessList::CheckAccessState( OriginAccessList::AccessState OriginAccessList::CheckAccessState(
...@@ -73,56 +62,48 @@ OriginAccessList::AccessState OriginAccessList::CheckAccessState( ...@@ -73,56 +62,48 @@ OriginAccessList::AccessState OriginAccessList::CheckAccessState(
if (source_origin.opaque()) if (source_origin.opaque())
return AccessState::kBlocked; return AccessState::kBlocked;
std::string source = source_origin.Serialize(); const std::string source = source_origin.Serialize();
url::Origin destination_origin = url::Origin::Create(destination); const url::Origin destination_origin = url::Origin::Create(destination);
network::mojom::CorsOriginAccessMatchPriority allow_list_priority = const auto patterns_map_it = map_.find(source);
GetHighestPriorityOfRuleForOrigin(source, destination_origin, if (patterns_map_it == map_.end())
allow_list_); return AccessState::kNotListed;
network::mojom::CorsOriginAccessMatchPriority block_list_priority =
GetHighestPriorityOfRuleForOrigin(source, destination_origin, const network::mojom::CorsOriginAccessMatchPriority allow_list_priority =
block_list_); GetHighestPriorityOfRuleForOrigin(
destination_origin, patterns_map_it->second, MapType::kAllowPatterns);
if (allow_list_priority == const network::mojom::CorsOriginAccessMatchPriority block_list_priority =
GetHighestPriorityOfRuleForOrigin(
destination_origin, patterns_map_it->second, MapType::kBlockPatterns);
if (block_list_priority ==
network::mojom::CorsOriginAccessMatchPriority::kNoMatchingOrigin) { network::mojom::CorsOriginAccessMatchPriority::kNoMatchingOrigin) {
return block_list_priority == return (allow_list_priority ==
network::mojom::CorsOriginAccessMatchPriority:: network::mojom::CorsOriginAccessMatchPriority::kNoMatchingOrigin)
kNoMatchingOrigin
? AccessState::kNotListed ? AccessState::kNotListed
: AccessState::kBlocked; : AccessState::kAllowed;
} }
if (block_list_priority ==
network::mojom::CorsOriginAccessMatchPriority::kNoMatchingOrigin)
return AccessState::kAllowed;
return (allow_list_priority > block_list_priority) ? AccessState::kAllowed return (allow_list_priority > block_list_priority) ? AccessState::kAllowed
: AccessState::kBlocked; : AccessState::kBlocked;
} }
std::vector<mojo::StructPtr<mojom::CorsOriginAccessPatterns>> std::vector<mojo::StructPtr<mojom::CorsOriginAccessPatterns>>
OriginAccessList::CreateCorsOriginAccessPatternsList() const { OriginAccessList::CreateCorsOriginAccessPatternsList() const {
std::set<std::string> origins;
for (const auto& allow_map : allow_list_)
origins.insert(allow_map.first);
for (const auto& block_map : block_list_)
origins.insert(block_map.first);
std::vector<mojom::CorsOriginAccessPatternsPtr> access_patterns; std::vector<mojom::CorsOriginAccessPatternsPtr> access_patterns;
for (const auto& origin : origins) { for (const auto& it : map_) {
std::vector<mojom::CorsOriginPatternPtr> allow_patterns; std::vector<mojom::CorsOriginPatternPtr> allow_patterns;
const auto& allow_entries = allow_list_.find(origin); const auto& allow_entries = it.second.find(MapType::kAllowPatterns);
if (allow_entries != allow_list_.end()) { if (allow_entries != it.second.end()) {
for (const auto& pattern : allow_entries->second) for (const auto& pattern : allow_entries->second)
allow_patterns.push_back(pattern.CreateCorsOriginPattern()); allow_patterns.push_back(pattern.CreateCorsOriginPattern());
} }
std::vector<mojom::CorsOriginPatternPtr> block_patterns; std::vector<mojom::CorsOriginPatternPtr> block_patterns;
const auto& block_entries = block_list_.find(origin); const auto& block_entries = it.second.find(MapType::kBlockPatterns);
if (block_entries != block_list_.end()) { if (block_entries != it.second.end()) {
for (const auto& pattern : block_entries->second) for (const auto& pattern : block_entries->second)
block_patterns.push_back(pattern.CreateCorsOriginPattern()); block_patterns.push_back(pattern.CreateCorsOriginPattern());
} }
access_patterns.push_back(mojom::CorsOriginAccessPatterns::New( access_patterns.push_back(mojom::CorsOriginAccessPatterns::New(
origin, std::move(allow_patterns), std::move(block_patterns))); it.first, std::move(allow_patterns), std::move(block_patterns)));
} }
return access_patterns; return access_patterns;
} }
...@@ -131,32 +112,36 @@ OriginAccessList::CreateCorsOriginAccessPatternsList() const { ...@@ -131,32 +112,36 @@ OriginAccessList::CreateCorsOriginAccessPatternsList() const {
void OriginAccessList::SetForOrigin( void OriginAccessList::SetForOrigin(
const url::Origin& source_origin, const url::Origin& source_origin,
const std::vector<CorsOriginPatternPtr>& patterns, const std::vector<CorsOriginPatternPtr>& patterns,
PatternMap* map) { OriginPatternsMap* map,
MapType type) {
DCHECK(map); DCHECK(map);
DCHECK(!source_origin.opaque()); DCHECK(!source_origin.opaque());
std::string source = source_origin.Serialize(); const std::string source = source_origin.Serialize();
map->erase(source); PatternsMap& patterns_map = (*map)[source];
if (patterns.empty()) Patterns& patterns_for_type = patterns_map[type];
return; patterns_for_type.clear();
Patterns& native_patterns = (*map)[source];
for (const auto& pattern : patterns) { for (const auto& pattern : patterns) {
native_patterns.push_back(OriginAccessEntry( patterns_for_type.push_back(OriginAccessEntry(
pattern->protocol, pattern->domain, pattern->mode, pattern->priority)); pattern->protocol, pattern->domain, pattern->mode, pattern->priority));
} }
if (patterns_map[MapType::kAllowPatterns].empty() &&
patterns_map[MapType::kBlockPatterns].empty()) {
(*map).erase(source);
}
} }
// static // static
void OriginAccessList::AddForOrigin(const url::Origin& source_origin, void OriginAccessList::AddForOrigin(const url::Origin& source_origin,
const CorsOriginPatternPtr& pattern, const CorsOriginPatternPtr& pattern,
PatternMap* map) { OriginPatternsMap* map,
MapType type) {
DCHECK(map); DCHECK(map);
DCHECK(!source_origin.opaque()); DCHECK(!source_origin.opaque());
std::string source = source_origin.Serialize(); const std::string source = source_origin.Serialize();
(*map)[source].push_back(OriginAccessEntry(pattern->protocol, pattern->domain, (*map)[source][type].push_back(OriginAccessEntry(
pattern->mode, pattern->priority)); pattern->protocol, pattern->domain, pattern->mode, pattern->priority));
} }
// static // static
...@@ -164,15 +149,16 @@ void OriginAccessList::AddForOrigin(const url::Origin& source_origin, ...@@ -164,15 +149,16 @@ void OriginAccessList::AddForOrigin(const url::Origin& source_origin,
// first match which will be the top priority. // first match which will be the top priority.
network::mojom::CorsOriginAccessMatchPriority network::mojom::CorsOriginAccessMatchPriority
OriginAccessList::GetHighestPriorityOfRuleForOrigin( OriginAccessList::GetHighestPriorityOfRuleForOrigin(
const std::string& source,
const url::Origin& destination_origin, const url::Origin& destination_origin,
const PatternMap& map) { const PatternsMap& patterns_map,
MapType type) {
const auto patterns_it = patterns_map.find(type);
if (patterns_it == patterns_map.end())
return network::mojom::CorsOriginAccessMatchPriority::kNoMatchingOrigin;
network::mojom::CorsOriginAccessMatchPriority highest_priority = network::mojom::CorsOriginAccessMatchPriority highest_priority =
network::mojom::CorsOriginAccessMatchPriority::kNoMatchingOrigin; network::mojom::CorsOriginAccessMatchPriority::kNoMatchingOrigin;
auto patterns_for_origin_it = map.find(source); for (const auto& entry : patterns_it->second) {
if (patterns_for_origin_it == map.end())
return highest_priority;
for (const auto& entry : patterns_for_origin_it->second) {
if (entry.MatchesOrigin(destination_origin) != if (entry.MatchesOrigin(destination_origin) !=
OriginAccessEntry::kDoesNotMatchOrigin) { OriginAccessEntry::kDoesNotMatchOrigin) {
highest_priority = std::max(highest_priority, entry.priority()); highest_priority = std::max(highest_priority, entry.priority());
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include "base/component_export.h" #include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/macros.h" #include "base/macros.h"
#include "services/network/public/cpp/cors/origin_access_entry.h" #include "services/network/public/cpp/cors/origin_access_entry.h"
#include "services/network/public/mojom/cors_origin_pattern.mojom-shared.h" #include "services/network/public/mojom/cors_origin_pattern.mojom-shared.h"
...@@ -56,12 +57,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessList { ...@@ -56,12 +57,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessList {
const mojom::CorsOriginAccessMatchMode mode, const mojom::CorsOriginAccessMatchMode mode,
const mojom::CorsOriginAccessMatchPriority priority); const mojom::CorsOriginAccessMatchPriority priority);
// Clears the old allow list for |source_origin|.
void ClearAllowListForOrigin(const url::Origin& source_origin);
// Clears the old allow list.
void ClearAllowList();
// Clears the old block list for |source_origin| and set |patterns| to the // Clears the old block list for |source_origin| and set |patterns| to the
// block list. When two or more patterns in a list match, the entry with the // block list. When two or more patterns in a list match, the entry with the
// higher |priority| takes precedence. // higher |priority| takes precedence.
...@@ -77,11 +72,11 @@ class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessList { ...@@ -77,11 +72,11 @@ class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessList {
const mojom::CorsOriginAccessMatchMode mode, const mojom::CorsOriginAccessMatchMode mode,
const mojom::CorsOriginAccessMatchPriority priority); const mojom::CorsOriginAccessMatchPriority priority);
// Clears the old block list for |source_origin|. // Clears the old allow/block lists for |source_origin|.
void ClearBlockListForOrigin(const url::Origin& source_origin); void ClearForOrigin(const url::Origin& source_origin);
// Clears the old block list. // Clears the old allow/block lists.
void ClearBlockList(); void Clear();
// Returns |destination|'s AccessState in the list for |source_origin|. // Returns |destination|'s AccessState in the list for |source_origin|.
AccessState CheckAccessState(const url::Origin& source_origin, AccessState CheckAccessState(const url::Origin& source_origin,
...@@ -93,24 +88,29 @@ class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessList { ...@@ -93,24 +88,29 @@ class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessList {
CreateCorsOriginAccessPatternsList() const; CreateCorsOriginAccessPatternsList() const;
private: private:
enum class MapType {
kAllowPatterns,
kBlockPatterns,
};
using Patterns = std::vector<OriginAccessEntry>; using Patterns = std::vector<OriginAccessEntry>;
using PatternMap = std::map<std::string, Patterns>; using PatternsMap = base::flat_map<MapType, Patterns>;
using OriginPatternsMap =
std::map<std::string /* source_origin */, PatternsMap>;
static void SetForOrigin(const url::Origin& source_origin, static void SetForOrigin(const url::Origin& source_origin,
const std::vector<CorsOriginPatternPtr>& patterns, const std::vector<CorsOriginPatternPtr>& patterns,
PatternMap* map); OriginPatternsMap* map,
MapType type);
static void AddForOrigin(const url::Origin& source_origin, static void AddForOrigin(const url::Origin& source_origin,
const CorsOriginPatternPtr& pattern, const CorsOriginPatternPtr& pattern,
PatternMap* map); OriginPatternsMap* map,
MapType type);
static mojom::CorsOriginAccessMatchPriority GetHighestPriorityOfRuleForOrigin( static mojom::CorsOriginAccessMatchPriority GetHighestPriorityOfRuleForOrigin(
const std::string& source,
const url::Origin& destination_origin, const url::Origin& destination_origin,
const PatternMap& map); const PatternsMap& patterns_map,
MapType type);
// TODO(toyoshim): Redesign to have an unified map to be consistent with OriginPatternsMap map_;
// mojom::CorsOriginAccessPatterns. See https://crbug.com/908756.
PatternMap allow_list_;
PatternMap block_list_;
DISALLOW_COPY_AND_ASSIGN(OriginAccessList); DISALLOW_COPY_AND_ASSIGN(OriginAccessList);
}; };
......
...@@ -278,15 +278,12 @@ void SecurityPolicy::AddOriginAccessBlockListEntry( ...@@ -278,15 +278,12 @@ void SecurityPolicy::AddOriginAccessBlockListEntry(
void SecurityPolicy::ClearOriginAccessListForOrigin( void SecurityPolicy::ClearOriginAccessListForOrigin(
const SecurityOrigin& source_origin) { const SecurityOrigin& source_origin) {
MutexLocker lock(GetMutex()); MutexLocker lock(GetMutex());
const url::Origin origin = source_origin.ToUrlOrigin(); GetOriginAccessList().ClearForOrigin(source_origin.ToUrlOrigin());
GetOriginAccessList().ClearAllowListForOrigin(origin);
GetOriginAccessList().ClearBlockListForOrigin(origin);
} }
void SecurityPolicy::ClearOriginAccessList() { void SecurityPolicy::ClearOriginAccessList() {
MutexLocker lock(GetMutex()); MutexLocker lock(GetMutex());
GetOriginAccessList().ClearAllowList(); GetOriginAccessList().Clear();
GetOriginAccessList().ClearBlockList();
} }
bool SecurityPolicy::ReferrerPolicyFromString( bool SecurityPolicy::ReferrerPolicyFromString(
......
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