Commit 240c8a0c authored by Antonio Sartori's avatar Antonio Sartori Committed by Chromium LUCI CQ

CSP: Replace blink::CSPSource with mojo type

In the Blink Content Security Policy code, we switch from using the
internal blink type blink::CSPSource to using the mojo type
network::mojom::blink::CSPSource for handling CSP source expressions.

This is part of a project to harmonize the CSP code in Blink and in
services/network, and will make it easier to synchronize Content
Security Policies between the two.

Change-Id: If7769b321934ee73cf1aa0faa6d8b371360684a7
Bug: 1021462,1149272
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412339Reviewed-by: default avatarMike West <mkwst@chromium.org>
Reviewed-by: default avatarArthur Sonzogni <arthursonzogni@chromium.org>
Commit-Queue: Antonio Sartori <antoniosartori@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834599}
parent a66dbdcf
......@@ -178,19 +178,18 @@ void ContentSecurityPolicy::BindToDelegate(
void ContentSecurityPolicy::SetupSelf(const SecurityOrigin& security_origin) {
// Ensure that 'self' processes correctly.
self_protocol_ = security_origin.Protocol();
self_source_ = MakeGarbageCollected<CSPSource>(
this, self_protocol_, security_origin.Host(),
self_source_ = network::mojom::blink::CSPSource::New(
self_protocol_, security_origin.Host(),
security_origin.Port() == DefaultPortForProtocol(self_protocol_)
? CSPSource::kPortUnspecified
? url::PORT_UNSPECIFIED
: security_origin.Port(),
String(), CSPSource::kNoWildcard, CSPSource::kNoWildcard);
"", /*is_host_wildcard=*/false, /*is_port_wildcard=*/false);
}
void ContentSecurityPolicy::SetupSelf(const ContentSecurityPolicy& other) {
self_protocol_ = other.self_protocol_;
if (other.self_source_) {
self_source_ =
MakeGarbageCollected<CSPSource>(this, *(other.self_source_.Get()));
self_source_ = other.self_source_.Clone();
}
}
......@@ -294,15 +293,14 @@ void ContentSecurityPolicy::Trace(Visitor* visitor) const {
visitor->Trace(delegate_);
visitor->Trace(policies_);
visitor->Trace(console_messages_);
visitor->Trace(self_source_);
}
void ContentSecurityPolicy::CopyStateFrom(const ContentSecurityPolicy* other) {
DCHECK(policies_.IsEmpty());
SetupSelf(*other);
for (const auto& policy : other->policies_)
AddAndReportPolicyFromHeaderValue(policy->Header(), policy->HeaderType(),
policy->HeaderSource());
SetupSelf(*other);
}
void ContentSecurityPolicy::CopyPluginTypesFrom(
......@@ -435,9 +433,9 @@ void ContentSecurityPolicy::SetOverrideURLForSelf(const KURL& url) {
// to an execution context.
scoped_refptr<const SecurityOrigin> origin = SecurityOrigin::Create(url);
self_protocol_ = origin->Protocol();
self_source_ = MakeGarbageCollected<CSPSource>(
this, self_protocol_, origin->Host(), origin->Port(), String(),
CSPSource::kNoWildcard, CSPSource::kNoWildcard);
self_source_ = network::mojom::blink::CSPSource::New(
self_protocol_, origin->Host(), origin->Port(), "",
/*is_host_wildcard=*/false, /*is_port_wildcard=*/false);
}
Vector<CSPHeaderAndType> ContentSecurityPolicy::Headers() const {
......@@ -1478,7 +1476,8 @@ bool ContentSecurityPolicy::ShouldSendCSPHeader(ResourceType type) const {
}
bool ContentSecurityPolicy::UrlMatchesSelf(const KURL& url) const {
return self_source_->MatchesAsSelf(url);
DCHECK(self_source_);
return CSPSourceMatchesAsSelf(*self_source_, self_protocol_, url);
}
bool ContentSecurityPolicy::ProtocolEqualsSelf(const String& protocol) const {
......
......@@ -64,7 +64,6 @@ namespace blink {
class ContentSecurityPolicyResponseHeaders;
class ConsoleMessage;
class CSPDirectiveList;
class CSPSource;
class DOMWrapperWorld;
class Element;
class ExecutionContext;
......@@ -443,7 +442,9 @@ class CORE_EXPORT ContentSecurityPolicy final
bool ShouldSendCSPHeader(ResourceType) const;
CSPSource* GetSelfSource() const { return self_source_; }
network::mojom::blink::CSPSource* GetSelfSource() const {
return self_source_.get();
}
// Whether the main world's CSP should be bypassed based on the current
// javascript world we are in.
......@@ -595,7 +596,7 @@ class CORE_EXPORT ContentSecurityPolicy final
String disable_eval_error_message_;
mojom::blink::InsecureRequestPolicy insecure_request_policy_;
Member<CSPSource> self_source_;
network::mojom::blink::CSPSourcePtr self_source_;
String self_protocol_;
bool supports_wasm_eval_ = false;
......
......@@ -980,7 +980,7 @@ void CSPDirectiveList::ParseReportURI(const String& name, const String& value) {
return false;
}
if (MixedContentChecker::IsMixedContent(
policy_->GetSelfSource()->GetScheme(),
policy_->GetSelfSource()->scheme,
parsed_endpoint)) {
policy_->ReportMixedContentReportURI(endpoint);
return true;
......@@ -1431,9 +1431,7 @@ CSPDirectiveList::ExposeForNavigationalChecks() const {
auto policy = network::mojom::blink::ContentSecurityPolicy::New();
policy->self_origin =
policy_->GetSelfSource()
? policy_->GetSelfSource()->ExposeForNavigationalChecks()
: nullptr;
policy_->GetSelfSource() ? policy_->GetSelfSource()->Clone() : nullptr;
policy->use_reporting_api = use_reporting_api_;
policy->report_endpoints = report_endpoints_;
policy->header = network::mojom::blink::ContentSecurityPolicyHeader::New(
......
......@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_CSP_CSP_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_CSP_CSP_SOURCE_H_
#include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_content_security_policy_struct.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
......@@ -15,86 +16,22 @@
namespace blink {
class ContentSecurityPolicy;
class KURL;
class CORE_EXPORT CSPSource final : public GarbageCollected<CSPSource> {
public:
// Represents the absence of a port.
const static int kPortUnspecified;
CORE_EXPORT
bool CSPSourceIsSchemeOnly(const network::mojom::blink::CSPSource& source);
enum WildcardDisposition { kNoWildcard, kHasWildcard };
CORE_EXPORT
bool CSPSourceMatches(const network::mojom::blink::CSPSource& source,
const String& self_protocol,
const KURL& url,
ResourceRequest::RedirectStatus =
ResourceRequest::RedirectStatus::kNoRedirect);
// NotMatching is the only negative member, the rest are different types of
// matches. NotMatching should always be 0 to let if statements work nicely
enum class PortMatchingResult {
kNotMatching,
kMatchingWildcard,
kMatchingUpgrade,
kMatchingExact
};
enum class SchemeMatchingResult {
kNotMatching,
kMatchingUpgrade,
kMatchingExact
};
CSPSource(ContentSecurityPolicy*,
const String& scheme,
const String& host,
int port,
const String& path,
WildcardDisposition host_wildcard,
WildcardDisposition port_wildcard);
CSPSource(ContentSecurityPolicy* policy, const CSPSource& other);
bool IsSchemeOnly() const;
const String& GetScheme() { return scheme_; }
bool Matches(const KURL&,
ResourceRequest::RedirectStatus =
ResourceRequest::RedirectStatus::kNoRedirect) const;
bool MatchesAsSelf(const KURL&);
network::mojom::blink::CSPSourcePtr ExposeForNavigationalChecks() const;
void Trace(Visitor*) const;
private:
FRIEND_TEST_ALL_PREFIXES(CSPDirectiveListTest, OperativeDirectiveGivenType);
SchemeMatchingResult SchemeMatches(const String&) const;
bool HostMatches(const String&) const;
bool PathMatches(const String&) const;
// Protocol is necessary to determine default port if it is zero.
PortMatchingResult PortMatches(int port, const String& protocol) const;
// Helper inline functions for Port and Scheme MatchingResult enums
bool inline RequiresUpgrade(const PortMatchingResult result) const {
return result == PortMatchingResult::kMatchingUpgrade;
}
bool inline RequiresUpgrade(const SchemeMatchingResult result) const {
return result == SchemeMatchingResult::kMatchingUpgrade;
}
bool inline CanUpgrade(const PortMatchingResult result) const {
return result == PortMatchingResult::kMatchingUpgrade ||
result == PortMatchingResult::kMatchingWildcard;
}
bool inline CanUpgrade(const SchemeMatchingResult result) const {
return result == SchemeMatchingResult::kMatchingUpgrade;
}
Member<ContentSecurityPolicy> policy_;
String scheme_;
String host_;
int port_;
String path_;
WildcardDisposition host_wildcard_;
WildcardDisposition port_wildcard_;
};
CORE_EXPORT
bool CSPSourceMatchesAsSelf(const network::mojom::blink::CSPSource& source,
const String& self_protocol,
const KURL& url);
} // namespace blink
......
......@@ -160,10 +160,14 @@ void SourceListDirective::Parse(const UChar* begin, const UChar* end) {
const UChar* begin_source = position;
SkipWhile<UChar, IsSourceCharacter>(position, end);
String scheme, host, path;
int port = CSPSource::kPortUnspecified;
CSPSource::WildcardDisposition host_wildcard = CSPSource::kNoWildcard;
CSPSource::WildcardDisposition port_wildcard = CSPSource::kNoWildcard;
// We need to initialize all strings, since they can't be null in the mojo
// struct.
String scheme = "";
String host = "";
String path = "";
int port = url::PORT_UNSPECIFIED;
bool host_wildcard = false;
bool port_wildcard = false;
if (ParseSource(begin_source, position, &scheme, &host, &port, &path,
&host_wildcard, &port_wildcard)) {
......@@ -175,8 +179,8 @@ void SourceListDirective::Parse(const UChar* begin, const UChar* end) {
if (ContentSecurityPolicy::GetDirectiveType(host) !=
ContentSecurityPolicy::DirectiveType::kUndefined)
policy_->ReportDirectiveAsSourceExpression(directive_name_, host);
list_.push_back(MakeGarbageCollected<CSPSource>(
policy_, scheme, host, port, path, host_wildcard, port_wildcard));
list_.push_back(network::mojom::blink::CSPSource::New(
scheme, host, port, path, host_wildcard, port_wildcard));
} else {
policy_->ReportInvalidSourceExpression(
directive_name_, String(begin_source, static_cast<wtf_size_t>(
......@@ -190,15 +194,14 @@ void SourceListDirective::Parse(const UChar* begin, const UChar* end) {
// source = scheme ":"
// / ( [ scheme "://" ] host [ port ] [ path ] )
// / "'self'"
bool SourceListDirective::ParseSource(
const UChar* begin,
const UChar* end,
String* scheme,
String* host,
int* port,
String* path,
CSPSource::WildcardDisposition* host_wildcard,
CSPSource::WildcardDisposition* port_wildcard) {
bool SourceListDirective::ParseSource(const UChar* begin,
const UChar* end,
String* scheme,
String* host,
int* port,
String* path,
bool* host_wildcard,
bool* port_wildcard) {
if (begin == end)
return false;
......@@ -339,7 +342,7 @@ bool SourceListDirective::ParseSource(
if (!ParsePort(begin_port, begin_path, port, port_wildcard))
return false;
} else {
*port = CSPSource::kPortUnspecified;
*port = url::PORT_UNSPECIFIED;
}
if (begin_path != end) {
......@@ -480,14 +483,13 @@ bool SourceListDirective::ParseScheme(const UChar* begin,
// host-char = ALPHA / DIGIT / "-"
//
// static
bool SourceListDirective::ParseHost(
const UChar* begin,
const UChar* end,
String* host,
CSPSource::WildcardDisposition* host_wildcard) {
bool SourceListDirective::ParseHost(const UChar* begin,
const UChar* end,
String* host,
bool* host_wildcard) {
DCHECK(begin <= end);
DCHECK(host->IsEmpty());
DCHECK(*host_wildcard == CSPSource::kNoWildcard);
DCHECK(!*host_wildcard);
if (begin == end)
return false;
......@@ -496,7 +498,7 @@ bool SourceListDirective::ParseHost(
// Parse "*" or [ "*." ].
if (SkipExactly<UChar>(position, end, '*')) {
*host_wildcard = CSPSource::kHasWildcard;
*host_wildcard = true;
if (position == end) {
// "*"
......@@ -553,14 +555,13 @@ bool SourceListDirective::ParsePath(const UChar* begin,
// port = ":" ( 1*DIGIT / "*" )
//
bool SourceListDirective::ParsePort(
const UChar* begin,
const UChar* end,
int* port,
CSPSource::WildcardDisposition* port_wildcard) {
bool SourceListDirective::ParsePort(const UChar* begin,
const UChar* end,
int* port,
bool* port_wildcard) {
DCHECK(begin <= end);
DCHECK_EQ(*port, CSPSource::kPortUnspecified);
DCHECK(*port_wildcard == CSPSource::kNoWildcard);
DCHECK_EQ(*port, url::PORT_UNSPECIFIED);
DCHECK(!*port_wildcard);
if (!SkipExactly<UChar>(begin, end, ':'))
NOTREACHED();
......@@ -569,8 +570,8 @@ bool SourceListDirective::ParsePort(
return false;
if (end - begin == 1 && *begin == '*') {
*port = CSPSource::kPortUnspecified;
*port_wildcard = CSPSource::kHasWildcard;
*port = url::PORT_UNSPECIFIED;
*port_wildcard = true;
return true;
}
......@@ -636,9 +637,11 @@ void SourceListDirective::AddSourceHash(
bool SourceListDirective::HasSourceMatchInList(
const KURL& url,
ResourceRequest::RedirectStatus redirect_status) const {
for (wtf_size_t i = 0; i < list_.size(); ++i) {
if (list_[i]->Matches(url, redirect_status))
for (const auto& source : list_) {
if (CSPSourceMatches(*source, policy_->GetSelfProtocol(), url,
redirect_status)) {
return true;
}
}
return false;
......@@ -661,7 +664,7 @@ network::mojom::blink::CSPSourceListPtr
SourceListDirective::ExposeForNavigationalChecks() const {
WTF::Vector<network::mojom::blink::CSPSourcePtr> sources;
for (const auto& source : list_)
sources.push_back(source->ExposeForNavigationalChecks());
sources.push_back(source.Clone());
// We do not need nonces and hashes for navigational checks
WTF::Vector<WTF::String> nonces;
......@@ -675,7 +678,6 @@ SourceListDirective::ExposeForNavigationalChecks() const {
void SourceListDirective::Trace(Visitor* visitor) const {
visitor->Trace(policy_);
visitor->Trace(list_);
CSPDirective::Trace(visitor);
}
......
......@@ -71,17 +71,17 @@ class CORE_EXPORT SourceListDirective final : public CSPDirective {
String* host,
int* port,
String* path,
CSPSource::WildcardDisposition*,
CSPSource::WildcardDisposition*);
bool* is_host_wildcard,
bool* is_port_wildcard);
bool ParseScheme(const UChar* begin, const UChar* end, String* scheme);
static bool ParseHost(const UChar* begin,
const UChar* end,
String* host,
CSPSource::WildcardDisposition*);
bool* is_host_wildcard);
bool ParsePort(const UChar* begin,
const UChar* end,
int* port,
CSPSource::WildcardDisposition*);
bool* is_port_wildcard);
bool ParsePath(const UChar* begin, const UChar* end, String* path);
bool ParseNonce(const UChar* begin, const UChar* end, String* nonce);
bool ParseHash(const UChar* begin,
......@@ -105,7 +105,7 @@ class CORE_EXPORT SourceListDirective final : public CSPDirective {
bool HasSourceMatchInList(const KURL&, ResourceRequest::RedirectStatus) const;
Member<ContentSecurityPolicy> policy_;
HeapVector<Member<CSPSource>> list_;
WTF::Vector<network::mojom::blink::CSPSourcePtr> list_;
String directive_name_;
bool allow_self_;
bool allow_star_;
......
......@@ -26,8 +26,8 @@ class SourceListDirectiveTest : public testing::Test {
String host;
const int port;
String path;
CSPSource::WildcardDisposition host_wildcard;
CSPSource::WildcardDisposition port_wildcard;
bool host_wildcard;
bool port_wildcard;
};
void SetUp() override {
......@@ -430,7 +430,7 @@ TEST_F(SourceListDirectiveTest, ParseHost) {
for (const auto& test : cases) {
String host;
CSPSource::WildcardDisposition disposition = CSPSource::kNoWildcard;
bool disposition = false;
Vector<UChar> characters;
test.sources.AppendTo(characters);
const UChar* start = characters.data();
......
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