| Index: content/common/content_security_policy/csp_source.cc
|
| diff --git a/content/common/content_security_policy/csp_source.cc b/content/common/content_security_policy/csp_source.cc
|
| index 59657d16d2bfbddb3922549c059497409d957f8f..94064d5683704ae986c4b98ea9f63d0fd2ade523 100644
|
| --- a/content/common/content_security_policy/csp_source.cc
|
| +++ b/content/common/content_security_policy/csp_source.cc
|
| @@ -20,20 +20,21 @@ bool DecodePath(const base::StringPiece& path, std::string* output) {
|
| return base::UTF16ToUTF8(unescaped.data(), unescaped.length(), output);
|
| }
|
|
|
| -int DefaultPortForScheme(const std::string& scheme) {
|
| +int DefaultPortForScheme(const base::StringPiece& scheme) {
|
| return url::DefaultPortForScheme(scheme.data(), scheme.size());
|
| }
|
|
|
| bool SourceAllowScheme(const CSPSource& source,
|
| - const GURL& url,
|
| + const base::StringPiece& scheme,
|
| CSPContext* context) {
|
| - if (source.scheme.empty())
|
| - return context->ProtocolMatchesSelf(url);
|
| - if (source.scheme == url::kHttpScheme)
|
| - return url.SchemeIsHTTPOrHTTPS();
|
| - if (source.scheme == url::kWsScheme)
|
| - return url.SchemeIsWSOrWSS();
|
| - return url.SchemeIs(source.scheme);
|
| + const std::string& source_scheme =
|
| + source.scheme.empty() ? context->GetSelfScheme() : source.scheme;
|
| +
|
| + return (scheme == source_scheme) ||
|
| + (source_scheme == url::kHttpScheme &&
|
| + scheme == url::kHttpSuboriginScheme) ||
|
| + (source_scheme == url::kHttpsScheme &&
|
| + scheme == url::kHttpsSuboriginScheme);
|
| }
|
|
|
| bool SourceAllowHost(const CSPSource& source, const GURL& url) {
|
| @@ -50,19 +51,16 @@ bool SourceAllowHost(const CSPSource& source, const GURL& url) {
|
| return url.host() == source.host;
|
| }
|
|
|
| -bool SourceAllowPort(const CSPSource& source, const GURL& url) {
|
| - int url_port = url.EffectiveIntPort();
|
| -
|
| +bool SourceAllowPort(const CSPSource& source,
|
| + const base::StringPiece& scheme,
|
| + int port) {
|
| if (source.is_port_wildcard)
|
| return true;
|
|
|
| if (source.port == url::PORT_UNSPECIFIED)
|
| - return DefaultPortForScheme(url.scheme()) == url_port;
|
| -
|
| - if (source.port == url_port)
|
| - return true;
|
| + return DefaultPortForScheme(scheme) == port;
|
|
|
| - if (source.port == 80 && url_port == 443)
|
| + if (source.port == port)
|
| return true;
|
|
|
| return false;
|
| @@ -93,6 +91,21 @@ bool SourceAllowPath(const CSPSource& source,
|
| return source.path == url_path;
|
| }
|
|
|
| +bool AllowInternal(const CSPSource& source,
|
| + const GURL& url,
|
| + const base::StringPiece& scheme,
|
| + int port,
|
| + CSPContext* context,
|
| + bool is_redirect) {
|
| + if (source.IsSchemeOnly())
|
| + return SourceAllowScheme(source, scheme, context);
|
| +
|
| + return SourceAllowScheme(source, scheme, context) &&
|
| + SourceAllowHost(source, url) &&
|
| + SourceAllowPort(source, scheme, port) &&
|
| + SourceAllowPath(source, url, is_redirect);
|
| +}
|
| +
|
| } // namespace
|
|
|
| CSPSource::CSPSource()
|
| @@ -128,12 +141,31 @@ bool CSPSource::Allow(const CSPSource& source,
|
| const GURL& url,
|
| CSPContext* context,
|
| bool is_redirect) {
|
| - if (source.IsSchemeOnly())
|
| - return SourceAllowScheme(source, url, context);
|
| + base::StringPiece scheme = url.scheme_piece();
|
| + int port = url.EffectiveIntPort();
|
|
|
| - return SourceAllowScheme(source, url, context) &&
|
| - SourceAllowHost(source, url) && SourceAllowPort(source, url) &&
|
| - SourceAllowPath(source, url, is_redirect);
|
| + if (AllowInternal(source, url, scheme, port, context, is_redirect))
|
| + return true;
|
| +
|
| + // A secure upgrade from an explicitly insecure expression is always allowed.
|
| + const struct {
|
| + std::string insecure_scheme;
|
| + std::string secure_scheme;
|
| + int insecure_port;
|
| + int secure_port;
|
| + } kUpgrade[] = {
|
| + {url::kHttpScheme, url::kHttpsScheme, 80, 443},
|
| + {url::kHttpSuboriginScheme, url::kHttpsSuboriginScheme, 80, 443},
|
| + {url::kWsScheme, url::kWssScheme, 80, 443},
|
| + };
|
| + for (const auto& upgrade : kUpgrade) {
|
| + if (scheme == upgrade.secure_scheme && port == upgrade.secure_port) {
|
| + return AllowInternal(source, url, upgrade.insecure_scheme,
|
| + upgrade.insecure_port, context, is_redirect);
|
| + }
|
| + }
|
| +
|
| + return false;
|
| }
|
|
|
| std::string CSPSource::ToString() const {
|
|
|