Commit ee9c3db3 authored by Antonio Sartori's avatar Antonio Sartori Committed by Commit Bot

Add 'block-all-mixed-content' directive to network CSP code

The Content Security Policies code under services/network and the
relative mojo types still misses support for a few CSP directives. We
need to support all CSP directives in order to use it as a replacement
to the Blink types, and also if we want to add Content Security
Policies to the Policy Container (see attached bugs).

This CL implements support for the directive 'block-all-mixed-content'.

Bug: 1021462,1149272
Change-Id: Id90438e8c3f335041a1351aea174df5b671ee253
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2539914
Commit-Queue: Antonio Sartori <antoniosartori@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarArthur Sonzogni <arthursonzogni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#829623}
parent 5d507426
...@@ -45,6 +45,7 @@ network::mojom::ContentSecurityPolicyPtr BuildContentSecurityPolicy( ...@@ -45,6 +45,7 @@ network::mojom::ContentSecurityPolicyPtr BuildContentSecurityPolicy(
policy->directives[name] = BuildCSPSourceList(directive.source_list); policy->directives[name] = BuildCSPSourceList(directive.source_list);
} }
policy->upgrade_insecure_requests = policy_in.upgrade_insecure_requests; policy->upgrade_insecure_requests = policy_in.upgrade_insecure_requests;
policy->block_all_mixed_content = policy_in.block_all_mixed_content;
for (const blink::WebString& endpoint : policy_in.report_endpoints) for (const blink::WebString& endpoint : policy_in.report_endpoints)
policy->report_endpoints.push_back(endpoint.Utf8()); policy->report_endpoints.push_back(endpoint.Utf8());
......
...@@ -827,6 +827,19 @@ void ParseReportDirective(const GURL& request_url, ...@@ -827,6 +827,19 @@ void ParseReportDirective(const GURL& request_url,
} }
} }
void WarnIfDirectiveValueNotEmpty(
const std::pair<base::StringPiece, base::StringPiece>& directive,
std::vector<std::string>& parsing_errors) {
if (!directive.second.empty()) {
parsing_errors.emplace_back(base::StringPrintf(
"The Content Security Policy directive '%s' should be empty, but was "
"delivered with a value of '%s'. The directive has been applied, and "
"the value ignored.",
directive.first.as_string().c_str(),
directive.second.as_string().c_str()));
}
}
void AddContentSecurityPolicyFromHeader(base::StringPiece header, void AddContentSecurityPolicyFromHeader(base::StringPiece header,
mojom::ContentSecurityPolicyType type, mojom::ContentSecurityPolicyType type,
const GURL& base_url, const GURL& base_url,
...@@ -914,24 +927,11 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header, ...@@ -914,24 +927,11 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header,
break; break;
case CSPDirectiveName::UpgradeInsecureRequests: case CSPDirectiveName::UpgradeInsecureRequests:
out->upgrade_insecure_requests = true; out->upgrade_insecure_requests = true;
if (!directive.second.empty()) { WarnIfDirectiveValueNotEmpty(directive, out->parsing_errors);
out->parsing_errors.emplace_back(base::StringPrintf(
"The Content Security Policy directive "
"'upgrade-insecure-requests' should be empty, but was delivered "
"with a value of '%s'. The directive has been applied, and the "
"value ignored.",
directive.second.as_string().c_str()));
}
break; break;
case CSPDirectiveName::TreatAsPublicAddress: case CSPDirectiveName::TreatAsPublicAddress:
out->treat_as_public_address = true; out->treat_as_public_address = true;
if (!directive.second.empty()) { WarnIfDirectiveValueNotEmpty(directive, out->parsing_errors);
out->parsing_errors.emplace_back(base::StringPrintf(
"The Content Security Policy directive 'treat-as-public-address' "
"should be empty, but was delivered with a value of '%s'. The "
"directive has been applied, and the value ignored.",
directive.second.as_string().c_str()));
}
break; break;
case CSPDirectiveName::PluginTypes: case CSPDirectiveName::PluginTypes:
// If the plugin-types directive is present, then always initialize // If the plugin-types directive is present, then always initialize
...@@ -951,11 +951,9 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header, ...@@ -951,11 +951,9 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header,
ParseTrustedTypes(directive.second, out->parsing_errors); ParseTrustedTypes(directive.second, out->parsing_errors);
break; break;
// We check the following directive so that we do not trigger a warning
// because of an unrecognized directive. However, we skip parsing it for
// now since we do not need it here (it is parsed and enforced in the
// blink CSP parser).
case CSPDirectiveName::BlockAllMixedContent: case CSPDirectiveName::BlockAllMixedContent:
out->block_all_mixed_content = true;
WarnIfDirectiveValueNotEmpty(directive, out->parsing_errors);
break; break;
case CSPDirectiveName::ReportTo: case CSPDirectiveName::ReportTo:
......
...@@ -715,6 +715,36 @@ TEST(ContentSecurityPolicy, ParseTrustedTypes) { ...@@ -715,6 +715,36 @@ TEST(ContentSecurityPolicy, ParseTrustedTypes) {
} }
} }
TEST(ContentSecurityPolicy, ParseBlockAllMixedContent) {
{
std::vector<mojom::ContentSecurityPolicyPtr> policies =
ParseCSP("script-src 'none'");
EXPECT_EQ(policies[0]->directives.size(), 1u);
EXPECT_FALSE(policies[0]->block_all_mixed_content);
}
{
std::vector<mojom::ContentSecurityPolicyPtr> policies =
ParseCSP("block-all-mixed-content");
EXPECT_EQ(policies[0]->directives.size(), 0u);
EXPECT_TRUE(policies[0]->block_all_mixed_content);
EXPECT_EQ(policies[0]->parsing_errors.size(), 0u);
}
{
std::vector<mojom::ContentSecurityPolicyPtr> policies =
ParseCSP("block-all-mixed-content true");
EXPECT_EQ(policies[0]->directives.size(), 0u);
EXPECT_TRUE(policies[0]->block_all_mixed_content);
EXPECT_EQ(policies[0]->parsing_errors.size(), 1u);
EXPECT_EQ(policies[0]->parsing_errors[0],
"The Content Security Policy directive "
"'block-all-mixed-content' should be empty, but was delivered "
"with a value of 'true'. The directive has been applied, and the "
"value ignored.");
}
}
TEST(ContentSecurityPolicy, ParseReportEndpoint) { TEST(ContentSecurityPolicy, ParseReportEndpoint) {
// report-uri directive. // report-uri directive.
{ {
......
...@@ -161,6 +161,9 @@ struct ContentSecurityPolicy { ...@@ -161,6 +161,9 @@ struct ContentSecurityPolicy {
// https://wicg.github.io/cors-rfc1918/#csp // https://wicg.github.io/cors-rfc1918/#csp
bool treat_as_public_address = false; bool treat_as_public_address = false;
// https://www.w3.org/TR/mixed-content/#strict-opt-in
bool block_all_mixed_content = false;
// https://www.w3.org/TR/CSP3/#directive-sandbox // https://www.w3.org/TR/CSP3/#directive-sandbox
// This uses the convention: kNone means "nothing is disallowed". // This uses the convention: kNone means "nothing is disallowed".
WebSandboxFlags sandbox = WebSandboxFlags.kNone; WebSandboxFlags sandbox = WebSandboxFlags.kNone;
......
...@@ -86,6 +86,7 @@ struct WebContentSecurityPolicy { ...@@ -86,6 +86,7 @@ struct WebContentSecurityPolicy {
network::mojom::ContentSecurityPolicySource source; network::mojom::ContentSecurityPolicySource source;
WebVector<WebContentSecurityPolicyDirective> directives; WebVector<WebContentSecurityPolicyDirective> directives;
bool upgrade_insecure_requests; bool upgrade_insecure_requests;
bool block_all_mixed_content;
WebVector<WebString> report_endpoints; WebVector<WebString> report_endpoints;
WebString header; WebString header;
bool use_reporting_api; bool use_reporting_api;
......
...@@ -281,6 +281,7 @@ WebContentSecurityPolicy ConvertToPublic( ...@@ -281,6 +281,7 @@ WebContentSecurityPolicy ConvertToPublic(
policy->header->source, policy->header->source,
std::move(directives), std::move(directives),
policy->upgrade_insecure_requests, policy->upgrade_insecure_requests,
policy->block_all_mixed_content,
std::move(policy->report_endpoints), std::move(policy->report_endpoints),
policy->header->header_value, policy->header->header_value,
policy->use_reporting_api, policy->use_reporting_api,
......
...@@ -134,7 +134,8 @@ blink::ContentSecurityPolicyPtr ConvertToBlink( ...@@ -134,7 +134,8 @@ blink::ContentSecurityPolicyPtr ConvertToBlink(
return blink::ContentSecurityPolicy::New( return blink::ContentSecurityPolicy::New(
ConvertToBlink(std::move(policy_in->directives)), ConvertToBlink(std::move(policy_in->directives)),
policy_in->upgrade_insecure_requests, policy_in->treat_as_public_address, policy_in->upgrade_insecure_requests, policy_in->treat_as_public_address,
policy_in->sandbox, ConvertToBlink(std::move(policy_in->header)), policy_in->block_all_mixed_content, policy_in->sandbox,
ConvertToBlink(std::move(policy_in->header)),
policy_in->use_reporting_api, policy_in->use_reporting_api,
ConvertToBlink(std::move(policy_in->report_endpoints)), ConvertToBlink(std::move(policy_in->report_endpoints)),
policy_in->plugin_types.has_value() policy_in->plugin_types.has_value()
......
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