blob: 343c4c1bb07bdb585a72688c548d8ea776dcc7b4 [file] [log] [blame]
// 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 "content/common/content_security_policy/csp_context.h"
namespace content {
namespace {
bool AllowFromSources(const GURL& url,
const std::vector<CSPSource>& sources,
CSPContext* context,
bool has_followed_redirect) {
for (const CSPSource& source : sources) {
if (CSPSource::Allow(source, url, context, has_followed_redirect))
return true;
}
return false;
}
}; // namespace
CSPSourceList::CSPSourceList()
: allow_self(false),
allow_star(false),
allow_response_redirects(false),
sources() {}
CSPSourceList::CSPSourceList(bool allow_self,
bool allow_star,
bool allow_response_redirects,
std::vector<CSPSource> sources)
: allow_self(allow_self),
allow_star(allow_star),
allow_response_redirects(allow_response_redirects),
sources(sources) {}
CSPSourceList::CSPSourceList(const CSPSourceList&) = default;
CSPSourceList::~CSPSourceList() = default;
// static
bool CSPSourceList::Allow(const CSPSourceList& source_list,
const GURL& url,
CSPContext* context,
bool has_followed_redirect,
bool is_response_check) {
// If the source list allows all redirects, the decision can't be made until
// the response is received.
if (source_list.allow_response_redirects && !is_response_check)
return true;
// If the source list does not allow all redirects, the decision has already
// been made when checking the request.
if (!source_list.allow_response_redirects && is_response_check)
return true;
// 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 (source_list.allow_star) {
if (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS() ||
url.SchemeIs("ftp")) {
return true;
}
if (context->self_source() && url.SchemeIs(context->self_source()->scheme))
return true;
}
if (source_list.allow_self && context->self_source() &&
CSPSource::Allow(context->self_source().value(), url, context,
has_followed_redirect)) {
return true;
}
return AllowFromSources(url, source_list.sources, context,
has_followed_redirect);
}
std::string CSPSourceList::ToString() const {
if (IsNone())
return "'none'";
if (allow_star)
return "*";
bool is_empty = true;
std::stringstream text;
if (allow_self) {
text << "'self'";
is_empty = false;
}
for (const auto& source : sources) {
if (!is_empty)
text << " ";
text << source.ToString();
is_empty = false;
}
return text.str();
}
bool CSPSourceList::IsNone() const {
return !allow_self && !allow_star && sources.empty();
}
} // namespace content