OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <algorithm> |
| 6 |
| 7 #include "base/strings/string_split.h" |
| 8 #include "content/common/content_security_policy/csp_context.h" |
| 9 |
| 10 namespace content { |
| 11 |
| 12 namespace { |
| 13 |
| 14 void ReportInvalidSourceExpression(CSPContext* context, |
| 15 const base::StringPiece& directive_name, |
| 16 const base::StringPiece& source_expression) { |
| 17 std::string message = |
| 18 "The source list for Content Security Policy directive '" + |
| 19 directive_name.as_string() + "' contains an invalid source: '" + |
| 20 source_expression.as_string() + "'. It will be ignored."; |
| 21 |
| 22 if (source_expression == "'none'") |
| 23 message += |
| 24 " Note that 'none' has no effect unless it is the only expression in " |
| 25 "the source list."; |
| 26 |
| 27 context->LogToConsole(message); |
| 28 } |
| 29 |
| 30 } // namespace; |
| 31 |
| 32 CSPSourceList::CSPSourceList() |
| 33 : allow_self(false), allow_star(false), source_list() {} |
| 34 |
| 35 CSPSourceList::CSPSourceList(bool allow_self, |
| 36 bool allow_star, |
| 37 std::vector<CSPSource> source_list) |
| 38 : allow_self(allow_self), allow_star(allow_star), source_list(source_list) { |
| 39 DCHECK(!allow_star || (allow_self || source_list.empty())); |
| 40 } |
| 41 |
| 42 CSPSourceList::CSPSourceList(const CSPSourceList&) = default; |
| 43 CSPSourceList::~CSPSourceList() = default; |
| 44 |
| 45 // static |
| 46 CSPSourceList CSPSourceList::Parse(CSPContext* context, |
| 47 const base::StringPiece& directive_name, |
| 48 const base::StringPiece& directive_value) { |
| 49 CSPSourceList source_list; |
| 50 // serialized-source-list = ( source-expression *( RWS source-expression ) ) |
| 51 // / "'none'" |
| 52 std::vector<base::StringPiece> source_expressions = base::SplitStringPiece( |
| 53 directive_value, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 54 |
| 55 if (source_expressions.size() == 1 && source_expressions[0] == "'none'") |
| 56 return source_list; |
| 57 |
| 58 for (const base::StringPiece& source_expression : source_expressions) { |
| 59 if (source_expression == "'none'") { |
| 60 ReportInvalidSourceExpression(context, directive_name, source_expression); |
| 61 } else if (source_expression == "'self'") { |
| 62 source_list.allow_self = true; |
| 63 } else if (source_expression == "*") { |
| 64 source_list.allow_star = true; |
| 65 } else { |
| 66 if (auto source = CSPSource::Parse(source_expression.as_string())) { |
| 67 source_list.source_list.push_back(*source); |
| 68 } else { |
| 69 ReportInvalidSourceExpression(context, directive_name, |
| 70 source_expression); |
| 71 } |
| 72 } |
| 73 } |
| 74 return source_list; |
| 75 } |
| 76 |
| 77 bool CSPSourceList::Allow(CSPContext* context, |
| 78 const GURL& url, |
| 79 bool is_redirect) const { |
| 80 // Wildcards match network schemes ('http', 'https', 'ftp', 'ws', 'wss'), and |
| 81 // the scheme of the protected resource: |
| 82 // https://w3c.github.io/webappsec-csp/#match-url-to-source-expression. Other |
| 83 // schemes, including custom schemes, must be explicitly listed in a source |
| 84 // list. |
| 85 if (allow_star) { |
| 86 if (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsSuborigin() || |
| 87 url.SchemeIsWSOrWSS() || url.SchemeIs("ftp") || |
| 88 context->ProtocolMatchesSelf(url)) |
| 89 return true; |
| 90 |
| 91 return AllowFromSources(context, url, is_redirect); |
| 92 } |
| 93 |
| 94 // TODO(arthursonzogni): compute the effectiveURL in the same way it is done |
| 95 // in SourceListDirective.cpp |
| 96 |
| 97 if (allow_self && context->AllowSelf(url)) |
| 98 return true; |
| 99 |
| 100 return AllowFromSources(context, url, is_redirect); |
| 101 } |
| 102 |
| 103 bool CSPSourceList::AllowFromSources(CSPContext* context, |
| 104 const GURL& url, |
| 105 bool is_redirect) const { |
| 106 for (const CSPSource& source : source_list) { |
| 107 if (source.Allow(context, url, is_redirect)) |
| 108 return true; |
| 109 } |
| 110 return false; |
| 111 } |
| 112 |
| 113 std::string CSPSourceList::ToString() const { |
| 114 if (allow_star) |
| 115 return "*"; |
| 116 |
| 117 bool is_empty = true; |
| 118 std::stringstream text; |
| 119 if (allow_self) { |
| 120 text << "'self'"; |
| 121 is_empty = false; |
| 122 } |
| 123 |
| 124 for (const auto& source : source_list) { |
| 125 if (!is_empty) |
| 126 text << " "; |
| 127 text << source.ToString(); |
| 128 is_empty = false; |
| 129 } |
| 130 |
| 131 return text.str(); |
| 132 } |
| 133 |
| 134 } // namespace content |
OLD | NEW |