blob: 0181289aab3702bdbfdb965e15a743b9639bd882 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/frame/csp/trusted_types_directive.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
#include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
namespace {
bool IsNotPolicyNameChar(UChar c) {
// This implements the negation of one char of tt-policy-name from
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#trusted-types-csp-directive/
bool is_name_char = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') || c == '-' || c == '#' ||
c == '=' || c == '_' || c == '/' || c == '@' ||
c == '.' || c == '%';
return !is_name_char;
}
bool IsPolicyName(const String& name) {
// This implements tt-policy-name from
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#trusted-types-csp-directive/
return name.Find(&IsNotPolicyNameChar) == kNotFound;
}
} // namespace
network::mojom::blink::CSPTrustedTypesPtr CSPTrustedTypesParse(
const String& value,
ContentSecurityPolicy* policy) {
auto result = network::mojom::blink::CSPTrustedTypes::New();
// Turn whitespace-y characters into ' ' and then split on ' ' into list_.
value.SimplifyWhiteSpace().Split(' ', false, result->list);
auto drop_fn = [policy, &result](const String& src) -> bool {
DCHECK_EQ(src, src.StripWhiteSpace());
// Handle keywords and special tokens first:
if (src == "'allow-duplicates'") {
result->allow_duplicates = true;
return true;
}
if (src == "*") {
result->allow_any = true;
return true;
}
if (src == "'none'") {
if (result->list.size() > 1) {
policy->ReportInvalidSourceExpression("trusted-types", src);
}
return true;
}
return !IsPolicyName(src);
};
// There appears to be no wtf::Vector equivalent to STLs erase(from, to)
// method, so we can't do the canonical .erase(remove_if(..), end) and have
// to emulate this:
result->list.Shrink(
std::remove_if(result->list.begin(), result->list.end(), drop_fn) -
result->list.begin());
return result;
}
bool CSPTrustedTypesAllows(
const network::mojom::blink::CSPTrustedTypes& trusted_types,
const String& value,
bool is_duplicate,
ContentSecurityPolicy::AllowTrustedTypePolicyDetails& violation_details) {
if (is_duplicate && !trusted_types.allow_duplicates) {
violation_details = ContentSecurityPolicy::AllowTrustedTypePolicyDetails::
kDisallowedDuplicateName;
} else if (is_duplicate && value == "default") {
violation_details = ContentSecurityPolicy::AllowTrustedTypePolicyDetails::
kDisallowedDuplicateName;
} else if (!IsPolicyName(value)) {
violation_details =
ContentSecurityPolicy::AllowTrustedTypePolicyDetails::kDisallowedName;
} else if (!(trusted_types.allow_any || trusted_types.list.Contains(value))) {
violation_details =
ContentSecurityPolicy::AllowTrustedTypePolicyDetails::kDisallowedName;
} else {
violation_details =
ContentSecurityPolicy::AllowTrustedTypePolicyDetails::kAllowed;
}
return violation_details ==
ContentSecurityPolicy::AllowTrustedTypePolicyDetails::kAllowed;
}
} // namespace blink