Page Speed Optimization Libraries  1.13.35.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
csp.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http:///www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
29 
30 #ifndef NET_INSTAWEB_REWRITER_PUBLIC_CSP_H_
31 #define NET_INSTAWEB_REWRITER_PUBLIC_CSP_H_
32 
33 #include <memory>
34 #include <string>
35 #include <vector>
36 
41 
42 namespace net_instaweb {
43 
45  public:
46  enum Kind {
47  kSelf, kSchemeSource, kHostSource,
48  kUnsafeInline, kUnsafeEval, kStrictDynamic, kUnsafeHashedAttributes,
49  kHashOrNonce, kUnknown
50  };
51 
52  struct UrlData {
53  UrlData() : path_exact_match(false) {}
55  UrlData(StringPiece in_scheme, StringPiece in_host,
56  StringPiece in_port, StringPiece in_path,
57  bool exact_match = false)
58  : scheme_part(in_scheme.as_string()),
59  host_part(in_host.as_string()),
60  port_part(in_port.as_string()),
61  path_exact_match(exact_match) {
62  StringPieceVector portions;
63  SplitStringPieceToVector(in_path, "/", &portions, true);
64  for (StringPiece p : portions) {
65  path_part.push_back(p.as_string());
66  }
67  }
68 
77  GoogleString host_part;
78  GoogleString port_part;
80  std::vector<GoogleString> path_part;
81  bool path_exact_match;
82 
83  GoogleString DebugString() const {
84  return StrCat("scheme:", scheme_part, " host:", host_part,
85  " port:", port_part,
86  " path:", JoinCollection(path_part, "/"),
87  " path_exact_match:", BoolToString(path_exact_match));
88  }
89 
91  bool operator==(const UrlData& other) const {
92  return scheme_part == other.scheme_part &&
93  host_part == other.host_part &&
94  port_part == other.port_part &&
95  path_part == other.path_part &&
96  path_exact_match == other.path_exact_match;
97  }
98  };
99 
100  CspSourceExpression() : kind_(kUnknown) {}
101  explicit CspSourceExpression(Kind kind): kind_(kind) {}
102  CspSourceExpression(Kind kind, const UrlData& url_data) : kind_(kind) {
103  *mutable_url_data() = url_data;
104  }
105 
106  static CspSourceExpression Parse(StringPiece input);
107 
108  bool Matches(const GoogleUrl& origin_url, const GoogleUrl& url) const;
109 
110  GoogleString DebugString() const {
111  return StrCat("kind:", IntegerToString(kind_),
112  " url_data:{", url_data().DebugString(), "}");
113  }
114 
115  bool operator==(const CspSourceExpression& other) const {
116  return (kind_ == other.kind_) && (url_data() == other.url_data());
117  }
118 
119  Kind kind() const { return kind_; }
120 
121  const UrlData& url_data() const {
122  if (url_data_.get() == nullptr) {
123  url_data_.reset(new UrlData());
124  }
125  return *url_data_.get();
126  }
127 
128  private:
130  static CspSourceExpression ParseQuoted(StringPiece input);
131 
133  static bool ParseBase64(StringPiece input);
134 
138  bool TryParseScheme(StringPiece* input);
139 
140  static bool HasDefaultPortForScheme(const GoogleUrl& url);
141 
142  UrlData* mutable_url_data() {
143  if (url_data_.get() == nullptr) {
144  url_data_.reset(new UrlData());
145  }
146  return url_data_.get();
147  }
148 
149  Kind kind_;
150  mutable std::unique_ptr<UrlData> url_data_;
151 };
152 
154  public:
155  CspSourceList()
156  : saw_unsafe_inline_(false), saw_unsafe_eval_(false),
157  saw_strict_dynamic_(false), saw_unsafe_hashed_attributes_(false),
158  saw_hash_or_nonce_(false) {}
159 
160  static std::unique_ptr<CspSourceList> Parse(StringPiece input);
161  const std::vector<CspSourceExpression>& expressions() const {
162  return expressions_;
163  }
164 
165  bool saw_unsafe_inline() const { return saw_unsafe_inline_; }
166  bool saw_unsafe_eval() const { return saw_unsafe_eval_; }
167  bool saw_strict_dynamic() const { return saw_strict_dynamic_; }
168  bool saw_unsafe_hashed_attributes() const {
169  return saw_unsafe_hashed_attributes_;
170  }
171 
172  bool saw_hash_or_nonce() const { return saw_hash_or_nonce_; }
173 
174  bool Matches(const GoogleUrl& origin_url, const GoogleUrl& url) const;
175 
176  private:
177  std::vector<CspSourceExpression> expressions_;
178  bool saw_unsafe_inline_;
179  bool saw_unsafe_eval_;
180  bool saw_strict_dynamic_;
181  bool saw_unsafe_hashed_attributes_;
182  bool saw_hash_or_nonce_;
183 };
184 
187 class CspPolicy {
188  public:
189  CspPolicy();
190 
192  static std::unique_ptr<CspPolicy> Parse(StringPiece input);
193 
195  const CspSourceList* SourceListFor(CspDirective directive) const {
196  return policies_[static_cast<int>(directive)].get();
197  }
198 
199  bool PermitsEval() const;
200  bool PermitsInlineScript() const;
201  bool PermitsInlineScriptAttribute() const;
202  bool PermitsInlineStyle() const;
203  bool PermitsInlineStyleAttribute() const;
204 
207  bool CanLoadUrl(CspDirective role, const GoogleUrl& origin_url,
208  const GoogleUrl& url) const;
209 
210  bool IsBasePermitted(const GoogleUrl& previous_origin,
211  const GoogleUrl& base_candidate) const;
212 
213  private:
215  std::vector<std::unique_ptr<CspSourceList>> policies_;
216 };
217 
221 class CspContext {
222  public:
223  bool PermitsEval() const {
224  return AllPermit(&CspPolicy::PermitsEval);
225  }
226 
227  bool PermitsInlineScript() const {
228  return AllPermit(&CspPolicy::PermitsInlineScript);
229  }
230 
231  bool PermitsInlineScriptAttribute() const {
232  return AllPermit(&CspPolicy::PermitsInlineScriptAttribute);
233  }
234 
235  bool PermitsInlineStyle() const {
236  return AllPermit(&CspPolicy::PermitsInlineStyle);
237  }
238 
239  bool PermitsInlineStyleAttribute() const {
240  return AllPermit(&CspPolicy::PermitsInlineStyleAttribute);
241  }
242 
243  bool CanLoadUrl(CspDirective role, const GoogleUrl& origin_url,
244  const GoogleUrl& url) {
246  for (const auto& policy : policies_) {
247  if (!policy->CanLoadUrl(role, origin_url, url)) {
248  return false;
249  }
250  }
251  return true;
252  }
253 
254  bool IsBasePermitted(const GoogleUrl& previous_origin,
255  const GoogleUrl& base_candidate) const {
256  for (const auto& policy : policies_) {
257  if (!policy->IsBasePermitted(previous_origin, base_candidate)) {
258  return false;
259  }
260  }
261  return true;
262  }
263 
264  bool HasDirective(CspDirective directive) const {
265  for (const auto& policy : policies_) {
266  if (policy->SourceListFor(directive) != nullptr) {
267  return true;
268  }
269  }
270  return false;
271  }
272 
273  bool HasDirectiveOrDefaultSrc(CspDirective directive) const {
274  for (const auto& policy : policies_) {
275  if (policy->SourceListFor(directive) != nullptr ||
276  policy->SourceListFor(CspDirective::kDefaultSrc) != nullptr) {
277  return true;
278  }
279  }
280  return false;
281  }
282 
283  void AddPolicy(std::unique_ptr<CspPolicy> policy);
284  void Clear() { policies_.clear(); }
285  size_t policies_size() const { return policies_.size(); }
286  bool empty() const { return policies_.empty(); }
287 
288  private:
289  typedef bool (CspPolicy::*SimplePredicateFn)() const;
290 
291  bool AllPermit(SimplePredicateFn predicate) const {
295  for (const auto& policy : policies_) {
296  if (!(policy.get()->*predicate)()) {
297  return false;
298  }
299  }
300  return true;
301  }
302 
303  std::vector<std::unique_ptr<CspPolicy>> policies_;
304 };
305 
306 }
307 
308 #endif
class GoogleUrl
Definition: google_url.h:58
const char * BoolToString(bool b)
Converts a boolean to string.
Definition: string_util.h:741
GoogleString scheme_part
doesn't include :
Definition: csp.h:76
bool operator==(const UrlData &other) const
For convenience of unit testing.
Definition: csp.h:91
Definition: csp.h:221
CspDirective
Definition: csp_directive.h:37
std::string GoogleString
PAGESPEED_KERNEL_BASE_STRING_H_.
Definition: string.h:24
bool CanLoadUrl(CspDirective role, const GoogleUrl &origin_url, const GoogleUrl &url)
Definition: csp.h:243
const CspSourceList * SourceListFor(CspDirective directive) const
May return null.
Definition: csp.h:195
static std::unique_ptr< CspPolicy > Parse(StringPiece input)
May return null.
UrlData(StringPiece in_scheme, StringPiece in_host, StringPiece in_port, StringPiece in_path, bool exact_match=false)
Constructor for tests, assumes already normalized.
Definition: csp.h:55
Definition: csp.h:187
std::vector< GoogleString > path_part
separated by /
Definition: csp.h:80
bool CanLoadUrl(CspDirective role, const GoogleUrl &origin_url, const GoogleUrl &url) const
Definition: csp.h:153
void SplitStringPieceToVector(StringPiece sp, StringPiece separators, StringPieceVector *components, bool omit_empty_strings)