| Index: content/common/content_security_policy/csp_source_list.cc
|
| diff --git a/content/common/content_security_policy/csp_source_list.cc b/content/common/content_security_policy/csp_source_list.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..19f2b23c2a5c4c3afd1c44f15619bdc3468ec693
|
| --- /dev/null
|
| +++ b/content/common/content_security_policy/csp_source_list.cc
|
| @@ -0,0 +1,134 @@
|
| +// Copyright 2017 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 <algorithm>
|
| +
|
| +#include "base/strings/string_split.h"
|
| +#include "content/common/content_security_policy/csp_context.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +void ReportInvalidSourceExpression(CSPContext* context,
|
| + const base::StringPiece& directive_name,
|
| + const base::StringPiece& source_expression) {
|
| + std::string message =
|
| + "The source list for Content Security Policy directive '" +
|
| + directive_name.as_string() + "' contains an invalid source: '" +
|
| + source_expression.as_string() + "'. It will be ignored.";
|
| +
|
| + if (source_expression == "'none'")
|
| + message +=
|
| + " Note that 'none' has no effect unless it is the only expression in "
|
| + "the source list.";
|
| +
|
| + context->LogToConsole(message);
|
| +}
|
| +
|
| +} // namespace;
|
| +
|
| +CSPSourceList::CSPSourceList()
|
| + : allow_self(false), allow_star(false), source_list() {}
|
| +
|
| +CSPSourceList::CSPSourceList(bool allow_self,
|
| + bool allow_star,
|
| + std::vector<CSPSource> source_list)
|
| + : allow_self(allow_self), allow_star(allow_star), source_list(source_list) {
|
| + DCHECK(!allow_star || (allow_self || source_list.empty()));
|
| +}
|
| +
|
| +CSPSourceList::CSPSourceList(const CSPSourceList&) = default;
|
| +CSPSourceList::~CSPSourceList() = default;
|
| +
|
| +// static
|
| +CSPSourceList CSPSourceList::Parse(CSPContext* context,
|
| + const base::StringPiece& directive_name,
|
| + const base::StringPiece& directive_value) {
|
| + CSPSourceList source_list;
|
| + // serialized-source-list = ( source-expression *( RWS source-expression ) )
|
| + // / "'none'"
|
| + std::vector<base::StringPiece> source_expressions = base::SplitStringPiece(
|
| + directive_value, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
| +
|
| + if (source_expressions.size() == 1 && source_expressions[0] == "'none'")
|
| + return source_list;
|
| +
|
| + for (const base::StringPiece& source_expression : source_expressions) {
|
| + if (source_expression == "'none'") {
|
| + ReportInvalidSourceExpression(context, directive_name, source_expression);
|
| + } else if (source_expression == "'self'") {
|
| + source_list.allow_self = true;
|
| + } else if (source_expression == "*") {
|
| + source_list.allow_star = true;
|
| + } else {
|
| + if (auto source = CSPSource::Parse(source_expression.as_string())) {
|
| + source_list.source_list.push_back(*source);
|
| + } else {
|
| + ReportInvalidSourceExpression(context, directive_name,
|
| + source_expression);
|
| + }
|
| + }
|
| + }
|
| + return source_list;
|
| +}
|
| +
|
| +bool CSPSourceList::Allow(CSPContext* context,
|
| + const GURL& url,
|
| + bool is_redirect) const {
|
| + // Wildcards match network schemes ('http', 'https', 'ftp', 'ws', 'wss'), and
|
| + // the scheme of the protected resource:
|
| + // https://w3c.github.io/webappsec-csp/#match-url-to-source-expression. Other
|
| + // schemes, including custom schemes, must be explicitly listed in a source
|
| + // list.
|
| + if (allow_star) {
|
| + if (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsSuborigin() ||
|
| + url.SchemeIsWSOrWSS() || url.SchemeIs("ftp") ||
|
| + context->ProtocolMatchesSelf(url))
|
| + return true;
|
| +
|
| + return AllowFromSources(context, url, is_redirect);
|
| + }
|
| +
|
| + // TODO(arthursonzogni): compute the effectiveURL in the same way it is done
|
| + // in SourceListDirective.cpp
|
| +
|
| + if (allow_self && context->AllowSelf(url))
|
| + return true;
|
| +
|
| + return AllowFromSources(context, url, is_redirect);
|
| +}
|
| +
|
| +bool CSPSourceList::AllowFromSources(CSPContext* context,
|
| + const GURL& url,
|
| + bool is_redirect) const {
|
| + for (const CSPSource& source : source_list) {
|
| + if (source.Allow(context, url, is_redirect))
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +std::string CSPSourceList::ToString() const {
|
| + if (allow_star)
|
| + return "*";
|
| +
|
| + bool is_empty = true;
|
| + std::stringstream text;
|
| + if (allow_self) {
|
| + text << "'self'";
|
| + is_empty = false;
|
| + }
|
| +
|
| + for (const auto& source : source_list) {
|
| + if (!is_empty)
|
| + text << " ";
|
| + text << source.ToString();
|
| + is_empty = false;
|
| + }
|
| +
|
| + return text.str();
|
| +}
|
| +
|
| +} // namespace content
|
|
|