/work/obj-fuzz/dist/include/mozilla/dom/nsCSPUtils.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef nsCSPUtils_h___ |
8 | | #define nsCSPUtils_h___ |
9 | | |
10 | | #include "nsCOMPtr.h" |
11 | | #include "nsIContentPolicy.h" |
12 | | #include "nsIContentSecurityPolicy.h" |
13 | | #include "nsIURI.h" |
14 | | #include "nsLiteralString.h" |
15 | | #include "nsString.h" |
16 | | #include "nsTArray.h" |
17 | | #include "nsUnicharUtils.h" |
18 | | #include "mozilla/Logging.h" |
19 | | |
20 | | namespace mozilla { |
21 | | namespace dom { |
22 | | struct CSP; |
23 | | } // namespace dom |
24 | | } // namespace mozilla |
25 | | |
26 | | /* =============== Logging =================== */ |
27 | | |
28 | | void CSP_LogLocalizedStr(const char* aName, |
29 | | const char16_t** aParams, |
30 | | uint32_t aLength, |
31 | | const nsAString& aSourceName, |
32 | | const nsAString& aSourceLine, |
33 | | uint32_t aLineNumber, |
34 | | uint32_t aColumnNumber, |
35 | | uint32_t aFlags, |
36 | | const nsACString& aCategory, |
37 | | uint64_t aInnerWindowID, |
38 | | bool aFromPrivateWindow); |
39 | | |
40 | | void CSP_GetLocalizedStr(const char* aName, |
41 | | const char16_t** aParams, |
42 | | uint32_t aLength, |
43 | | nsAString& outResult); |
44 | | |
45 | | void CSP_LogStrMessage(const nsAString& aMsg); |
46 | | |
47 | | void CSP_LogMessage(const nsAString& aMessage, |
48 | | const nsAString& aSourceName, |
49 | | const nsAString& aSourceLine, |
50 | | uint32_t aLineNumber, |
51 | | uint32_t aColumnNumber, |
52 | | uint32_t aFlags, |
53 | | const nsACString& aCategory, |
54 | | uint64_t aInnerWindowID, |
55 | | bool aFromPrivateWindow); |
56 | | |
57 | | |
58 | | /* =============== Constant and Type Definitions ================== */ |
59 | | |
60 | | #define INLINE_STYLE_VIOLATION_OBSERVER_TOPIC "violated base restriction: Inline Stylesheets will not apply" |
61 | | #define INLINE_SCRIPT_VIOLATION_OBSERVER_TOPIC "violated base restriction: Inline Scripts will not execute" |
62 | | #define EVAL_VIOLATION_OBSERVER_TOPIC "violated base restriction: Code will not be created from strings" |
63 | | #define SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC "Inline Script had invalid nonce" |
64 | | #define STYLE_NONCE_VIOLATION_OBSERVER_TOPIC "Inline Style had invalid nonce" |
65 | | #define SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC "Inline Script had invalid hash" |
66 | | #define STYLE_HASH_VIOLATION_OBSERVER_TOPIC "Inline Style had invalid hash" |
67 | | #define REQUIRE_SRI_SCRIPT_VIOLATION_OBSERVER_TOPIC "Missing required Subresource Integrity for Script" |
68 | | #define REQUIRE_SRI_STYLE_VIOLATION_OBSERVER_TOPIC "Missing required Subresource Integrity for Style" |
69 | | |
70 | | // these strings map to the CSPDirectives in nsIContentSecurityPolicy |
71 | | // NOTE: When implementing a new directive, you will need to add it here but also |
72 | | // add a corresponding entry to the constants in nsIContentSecurityPolicy.idl |
73 | | // and also create an entry for the new directive in |
74 | | // nsCSPDirective::toDomCSPStruct() and add it to CSPDictionaries.webidl. |
75 | | // Order of elements below important! Make sure it matches the order as in |
76 | | // nsIContentSecurityPolicy.idl |
77 | | static const char* CSPStrDirectives[] = { |
78 | | "-error-", // NO_DIRECTIVE |
79 | | "default-src", // DEFAULT_SRC_DIRECTIVE |
80 | | "script-src", // SCRIPT_SRC_DIRECTIVE |
81 | | "object-src", // OBJECT_SRC_DIRECTIVE |
82 | | "style-src", // STYLE_SRC_DIRECTIVE |
83 | | "img-src", // IMG_SRC_DIRECTIVE |
84 | | "media-src", // MEDIA_SRC_DIRECTIVE |
85 | | "frame-src", // FRAME_SRC_DIRECTIVE |
86 | | "font-src", // FONT_SRC_DIRECTIVE |
87 | | "connect-src", // CONNECT_SRC_DIRECTIVE |
88 | | "report-uri", // REPORT_URI_DIRECTIVE |
89 | | "frame-ancestors", // FRAME_ANCESTORS_DIRECTIVE |
90 | | "reflected-xss", // REFLECTED_XSS_DIRECTIVE |
91 | | "base-uri", // BASE_URI_DIRECTIVE |
92 | | "form-action", // FORM_ACTION_DIRECTIVE |
93 | | "manifest-src", // MANIFEST_SRC_DIRECTIVE |
94 | | "upgrade-insecure-requests", // UPGRADE_IF_INSECURE_DIRECTIVE |
95 | | "child-src", // CHILD_SRC_DIRECTIVE |
96 | | "block-all-mixed-content", // BLOCK_ALL_MIXED_CONTENT |
97 | | "require-sri-for", // REQUIRE_SRI_FOR |
98 | | "sandbox", // SANDBOX_DIRECTIVE |
99 | | "worker-src" // WORKER_SRC_DIRECTIVE |
100 | | }; |
101 | | |
102 | | inline const char* CSP_CSPDirectiveToString(CSPDirective aDir) |
103 | 96.3k | { |
104 | 96.3k | return CSPStrDirectives[static_cast<uint32_t>(aDir)]; |
105 | 96.3k | } |
106 | | |
107 | | inline CSPDirective CSP_StringToCSPDirective(const nsAString& aDir) |
108 | 21.0k | { |
109 | 21.0k | nsString lowerDir = PromiseFlatString(aDir); |
110 | 21.0k | ToLowerCase(lowerDir); |
111 | 21.0k | |
112 | 21.0k | uint32_t numDirs = (sizeof(CSPStrDirectives) / sizeof(CSPStrDirectives[0])); |
113 | 224k | for (uint32_t i = 1; i < numDirs; i++) { |
114 | 224k | if (lowerDir.EqualsASCII(CSPStrDirectives[i])) { |
115 | 21.0k | return static_cast<CSPDirective>(i); |
116 | 21.0k | } |
117 | 224k | } |
118 | 21.0k | NS_ASSERTION(false, "Can not convert unknown Directive to Integer"); |
119 | 0 | return nsIContentSecurityPolicy::NO_DIRECTIVE; |
120 | 21.0k | } |
121 | | |
122 | | #define FOR_EACH_CSP_KEYWORD(macro) \ |
123 | | macro(CSP_SELF, "'self'") \ |
124 | | macro(CSP_UNSAFE_INLINE, "'unsafe-inline'") \ |
125 | | macro(CSP_UNSAFE_EVAL, "'unsafe-eval'") \ |
126 | | macro(CSP_NONE, "'none'") \ |
127 | | macro(CSP_NONCE, "'nonce-") \ |
128 | | macro(CSP_REQUIRE_SRI_FOR, "require-sri-for") \ |
129 | | macro(CSP_REPORT_SAMPLE, "'report-sample'") \ |
130 | | macro(CSP_STRICT_DYNAMIC, "'strict-dynamic'") |
131 | | |
132 | | enum CSPKeyword { |
133 | | #define KEYWORD_ENUM(id_, string_) id_, |
134 | | FOR_EACH_CSP_KEYWORD(KEYWORD_ENUM) |
135 | | #undef KEYWORD_ENUM |
136 | | |
137 | | // CSP_LAST_KEYWORD_VALUE always needs to be the last element in the enum |
138 | | // because we use it to calculate the size for the char* array. |
139 | | CSP_LAST_KEYWORD_VALUE, |
140 | | |
141 | | // Putting CSP_HASH after the delimitor, because CSP_HASH is not a valid |
142 | | // keyword (hash uses e.g. sha256, sha512) but we use CSP_HASH internally |
143 | | // to identify allowed hashes in ::allows. |
144 | | CSP_HASH |
145 | | }; |
146 | | |
147 | | // The keywords, in UTF-8 form. |
148 | | static const char* gCSPUTF8Keywords[] = { |
149 | | #define KEYWORD_UTF8_LITERAL(id_, string_) string_, |
150 | | FOR_EACH_CSP_KEYWORD(KEYWORD_UTF8_LITERAL) |
151 | | #undef KEYWORD_UTF8_LITERAL |
152 | | }; |
153 | | |
154 | | // The keywords, in UTF-16 form. |
155 | | static const char16_t* gCSPUTF16Keywords[] = { |
156 | | #define KEYWORD_UTF16_LITERAL(id_, string_) u"" string_, |
157 | | FOR_EACH_CSP_KEYWORD(KEYWORD_UTF16_LITERAL) |
158 | | #undef KEYWORD_UTF16_LITERAL |
159 | | }; |
160 | | |
161 | | #undef FOR_EACH_CSP_KEYWORD |
162 | | |
163 | | inline const char* CSP_EnumToUTF8Keyword(enum CSPKeyword aKey) |
164 | 1.23M | { |
165 | 1.23M | // Make sure all elements in enum CSPKeyword got added to gCSPUTF8Keywords. |
166 | 1.23M | static_assert((sizeof(gCSPUTF8Keywords) / sizeof(gCSPUTF8Keywords[0]) == |
167 | 1.23M | CSP_LAST_KEYWORD_VALUE), |
168 | 1.23M | "CSP_LAST_KEYWORD_VALUE != length(gCSPUTF8Keywords)"); |
169 | 1.23M | |
170 | 1.23M | if (static_cast<uint32_t>(aKey) < |
171 | 1.23M | static_cast<uint32_t>(CSP_LAST_KEYWORD_VALUE)) { |
172 | 1.23M | return gCSPUTF8Keywords[static_cast<uint32_t>(aKey)]; |
173 | 1.23M | } |
174 | 0 | return "error: invalid keyword in CSP_EnumToUTF8Keyword"; |
175 | 0 | } |
176 | | |
177 | | inline const char16_t* CSP_EnumToUTF16Keyword(enum CSPKeyword aKey) |
178 | 206k | { |
179 | 206k | // Make sure all elements in enum CSPKeyword got added to gCSPUTF16Keywords. |
180 | 206k | static_assert((sizeof(gCSPUTF16Keywords) / sizeof(gCSPUTF16Keywords[0]) == |
181 | 206k | CSP_LAST_KEYWORD_VALUE), |
182 | 206k | "CSP_LAST_KEYWORD_VALUE != length(gCSPUTF16Keywords)"); |
183 | 206k | |
184 | 206k | if (static_cast<uint32_t>(aKey) < |
185 | 206k | static_cast<uint32_t>(CSP_LAST_KEYWORD_VALUE)) { |
186 | 206k | return gCSPUTF16Keywords[static_cast<uint32_t>(aKey)]; |
187 | 206k | } |
188 | 0 | return u"error: invalid keyword in CSP_EnumToUTF16Keyword"; |
189 | 0 | } |
190 | | |
191 | | inline CSPKeyword CSP_UTF16KeywordToEnum(const nsAString& aKey) |
192 | 484 | { |
193 | 484 | nsString lowerKey = PromiseFlatString(aKey); |
194 | 484 | ToLowerCase(lowerKey); |
195 | 484 | |
196 | 2.46k | for (uint32_t i = 0; i < CSP_LAST_KEYWORD_VALUE; i++) { |
197 | 2.46k | if (lowerKey.Equals(gCSPUTF16Keywords[i])) { |
198 | 484 | return static_cast<CSPKeyword>(i); |
199 | 484 | } |
200 | 2.46k | } |
201 | 484 | NS_ASSERTION(false, "Can not convert unknown Keyword to Enum"); |
202 | 0 | return CSP_LAST_KEYWORD_VALUE; |
203 | 484 | } |
204 | | |
205 | | nsresult CSP_AppendCSPFromHeader(nsIContentSecurityPolicy* aCsp, |
206 | | const nsAString& aHeaderValue, |
207 | | bool aReportOnly); |
208 | | |
209 | | /* =============== Helpers ================== */ |
210 | | |
211 | | class nsCSPHostSrc; |
212 | | |
213 | | nsCSPHostSrc* CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI); |
214 | | bool CSP_IsEmptyDirective(const nsAString& aValue, const nsAString& aDir); |
215 | | bool CSP_IsValidDirective(const nsAString& aDir); |
216 | | bool CSP_IsDirective(const nsAString& aValue, CSPDirective aDir); |
217 | | bool CSP_IsKeyword(const nsAString& aValue, enum CSPKeyword aKey); |
218 | | bool CSP_IsQuotelessKeyword(const nsAString& aKey); |
219 | | CSPDirective CSP_ContentTypeToDirective(nsContentPolicyType aType); |
220 | | |
221 | | class nsCSPSrcVisitor; |
222 | | |
223 | | void CSP_PercentDecodeStr(const nsAString& aEncStr, nsAString& outDecStr); |
224 | | |
225 | | /* =============== nsCSPSrc ================== */ |
226 | | |
227 | | class nsCSPBaseSrc { |
228 | | public: |
229 | | nsCSPBaseSrc(); |
230 | | virtual ~nsCSPBaseSrc(); |
231 | | |
232 | | virtual bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, |
233 | | bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const; |
234 | | virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, |
235 | | bool aParserCreated) const; |
236 | | virtual bool visit(nsCSPSrcVisitor* aVisitor) const = 0; |
237 | | virtual void toString(nsAString& outStr) const = 0; |
238 | | |
239 | | virtual void invalidate() const |
240 | 1.48k | { mInvalidated = true; } |
241 | | |
242 | | virtual bool isReportSample() const |
243 | 225 | { return false; } |
244 | | |
245 | | protected: |
246 | | // invalidate srcs if 'script-dynamic' is present or also invalidate |
247 | | // unsafe-inline' if nonce- or hash-source specified |
248 | | mutable bool mInvalidated; |
249 | | |
250 | | }; |
251 | | |
252 | | /* =============== nsCSPSchemeSrc ============ */ |
253 | | |
254 | | class nsCSPSchemeSrc : public nsCSPBaseSrc { |
255 | | public: |
256 | | explicit nsCSPSchemeSrc(const nsAString& aScheme); |
257 | | virtual ~nsCSPSchemeSrc(); |
258 | | |
259 | | bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, |
260 | | bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const override; |
261 | | bool visit(nsCSPSrcVisitor* aVisitor) const override; |
262 | | void toString(nsAString& outStr) const override; |
263 | | |
264 | | inline void getScheme(nsAString& outStr) const |
265 | 0 | { outStr.Assign(mScheme); }; |
266 | | |
267 | | private: |
268 | | nsString mScheme; |
269 | | }; |
270 | | |
271 | | /* =============== nsCSPHostSrc ============== */ |
272 | | |
273 | | class nsCSPHostSrc : public nsCSPBaseSrc { |
274 | | public: |
275 | | explicit nsCSPHostSrc(const nsAString& aHost); |
276 | | virtual ~nsCSPHostSrc(); |
277 | | |
278 | | bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, |
279 | | bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const override; |
280 | | bool visit(nsCSPSrcVisitor* aVisitor) const override; |
281 | | void toString(nsAString& outStr) const override; |
282 | | |
283 | | void setScheme(const nsAString& aScheme); |
284 | | void setPort(const nsAString& aPort); |
285 | | void appendPath(const nsAString &aPath); |
286 | | |
287 | | inline void setGeneratedFromSelfKeyword() const |
288 | 289 | { mGeneratedFromSelfKeyword = true; } |
289 | | |
290 | | inline void setIsUniqueOrigin() const |
291 | 0 | { mIsUniqueOrigin = true; } |
292 | | |
293 | | inline void setWithinFrameAncestorsDir(bool aValue) const |
294 | 21.0k | { mWithinFrameAncstorsDir = aValue; } |
295 | | |
296 | | inline void getScheme(nsAString& outStr) const |
297 | 0 | { outStr.Assign(mScheme); }; |
298 | | |
299 | | inline void getHost(nsAString& outStr) const |
300 | 0 | { outStr.Assign(mHost); }; |
301 | | |
302 | | inline void getPort(nsAString& outStr) const |
303 | 0 | { outStr.Assign(mPort); }; |
304 | | |
305 | | inline void getPath(nsAString& outStr) const |
306 | 0 | { outStr.Assign(mPath); }; |
307 | | |
308 | | private: |
309 | | nsString mScheme; |
310 | | nsString mHost; |
311 | | nsString mPort; |
312 | | nsString mPath; |
313 | | mutable bool mGeneratedFromSelfKeyword; |
314 | | mutable bool mIsUniqueOrigin; |
315 | | mutable bool mWithinFrameAncstorsDir; |
316 | | }; |
317 | | |
318 | | /* =============== nsCSPKeywordSrc ============ */ |
319 | | |
320 | | class nsCSPKeywordSrc : public nsCSPBaseSrc { |
321 | | public: |
322 | | explicit nsCSPKeywordSrc(CSPKeyword aKeyword); |
323 | | virtual ~nsCSPKeywordSrc(); |
324 | | |
325 | | bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, |
326 | | bool aParserCreated) const override; |
327 | | bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, |
328 | | bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const override; |
329 | | bool visit(nsCSPSrcVisitor* aVisitor) const override; |
330 | | void toString(nsAString& outStr) const override; |
331 | | |
332 | | inline CSPKeyword getKeyword() const |
333 | 0 | { return mKeyword; }; |
334 | | |
335 | | inline void invalidate() const override |
336 | 280 | { |
337 | 280 | // keywords that need to invalidated |
338 | 280 | if (mKeyword == CSP_SELF || mKeyword == CSP_UNSAFE_INLINE) { |
339 | 1 | mInvalidated = true; |
340 | 1 | } |
341 | 280 | } |
342 | | |
343 | | bool isReportSample() const override |
344 | 17 | { return mKeyword == CSP_REPORT_SAMPLE; } |
345 | | private: |
346 | | CSPKeyword mKeyword; |
347 | | }; |
348 | | |
349 | | /* =============== nsCSPNonceSource =========== */ |
350 | | |
351 | | class nsCSPNonceSrc : public nsCSPBaseSrc { |
352 | | public: |
353 | | explicit nsCSPNonceSrc(const nsAString& aNonce); |
354 | | virtual ~nsCSPNonceSrc(); |
355 | | |
356 | | bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, |
357 | | bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const override; |
358 | | bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, |
359 | | bool aParserCreated) const override; |
360 | | bool visit(nsCSPSrcVisitor* aVisitor) const override; |
361 | | void toString(nsAString& outStr) const override; |
362 | | |
363 | | inline void getNonce(nsAString& outStr) const |
364 | 0 | { outStr.Assign(mNonce); }; |
365 | | |
366 | | inline void invalidate() const override |
367 | 6 | { |
368 | 6 | // overwrite nsCSPBaseSRC::invalidate() and explicitily |
369 | 6 | // do *not* invalidate, because 'strict-dynamic' should |
370 | 6 | // not invalidate nonces. |
371 | 6 | } |
372 | | |
373 | | private: |
374 | | nsString mNonce; |
375 | | }; |
376 | | |
377 | | /* =============== nsCSPHashSource ============ */ |
378 | | |
379 | | class nsCSPHashSrc : public nsCSPBaseSrc { |
380 | | public: |
381 | | nsCSPHashSrc(const nsAString& algo, const nsAString& hash); |
382 | | virtual ~nsCSPHashSrc(); |
383 | | |
384 | | bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, |
385 | | bool aParserCreated) const override; |
386 | | void toString(nsAString& outStr) const override; |
387 | | bool visit(nsCSPSrcVisitor* aVisitor) const override; |
388 | | |
389 | | inline void getAlgorithm(nsAString& outStr) const |
390 | 0 | { outStr.Assign(mAlgorithm); }; |
391 | | |
392 | | inline void getHash(nsAString& outStr) const |
393 | 0 | { outStr.Assign(mHash); }; |
394 | | |
395 | | inline void invalidate() const override |
396 | 156 | { |
397 | 156 | // overwrite nsCSPBaseSRC::invalidate() and explicitily |
398 | 156 | // do *not* invalidate, because 'strict-dynamic' should |
399 | 156 | // not invalidate hashes. |
400 | 156 | } |
401 | | |
402 | | private: |
403 | | nsString mAlgorithm; |
404 | | nsString mHash; |
405 | | }; |
406 | | |
407 | | /* =============== nsCSPReportURI ============ */ |
408 | | |
409 | | class nsCSPReportURI : public nsCSPBaseSrc { |
410 | | public: |
411 | | explicit nsCSPReportURI(nsIURI* aURI); |
412 | | virtual ~nsCSPReportURI(); |
413 | | |
414 | | bool visit(nsCSPSrcVisitor* aVisitor) const override; |
415 | | void toString(nsAString& outStr) const override; |
416 | | |
417 | | private: |
418 | | nsCOMPtr<nsIURI> mReportURI; |
419 | | }; |
420 | | |
421 | | /* =============== nsCSPSandboxFlags ================== */ |
422 | | |
423 | | class nsCSPSandboxFlags : public nsCSPBaseSrc { |
424 | | public: |
425 | | explicit nsCSPSandboxFlags(const nsAString& aFlags); |
426 | | virtual ~nsCSPSandboxFlags(); |
427 | | |
428 | | bool visit(nsCSPSrcVisitor* aVisitor) const override; |
429 | | void toString(nsAString& outStr) const override; |
430 | | |
431 | | private: |
432 | | nsString mFlags; |
433 | | }; |
434 | | |
435 | | /* =============== nsCSPSrcVisitor ================== */ |
436 | | |
437 | | class nsCSPSrcVisitor { |
438 | | public: |
439 | | virtual bool visitSchemeSrc(const nsCSPSchemeSrc& src) = 0; |
440 | | |
441 | | virtual bool visitHostSrc(const nsCSPHostSrc& src) = 0; |
442 | | |
443 | | virtual bool visitKeywordSrc(const nsCSPKeywordSrc& src) = 0; |
444 | | |
445 | | virtual bool visitNonceSrc(const nsCSPNonceSrc& src) = 0; |
446 | | |
447 | | virtual bool visitHashSrc(const nsCSPHashSrc& src) = 0; |
448 | | |
449 | | protected: |
450 | 0 | explicit nsCSPSrcVisitor() {}; |
451 | 0 | virtual ~nsCSPSrcVisitor() {}; |
452 | | }; |
453 | | |
454 | | /* =============== nsCSPDirective ============= */ |
455 | | |
456 | | class nsCSPDirective { |
457 | | public: |
458 | | explicit nsCSPDirective(CSPDirective aDirective); |
459 | | virtual ~nsCSPDirective(); |
460 | | |
461 | | virtual bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, |
462 | | bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const; |
463 | | virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, |
464 | | bool aParserCreated) const; |
465 | | virtual void toString(nsAString& outStr) const; |
466 | | void toDomCSPStruct(mozilla::dom::CSP& outCSP) const; |
467 | | |
468 | | virtual void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs) |
469 | 5.26k | { mSrcs = aSrcs; } |
470 | | |
471 | | virtual bool restrictsContentType(nsContentPolicyType aContentType) const; |
472 | | |
473 | | inline bool isDefaultDirective() const |
474 | 0 | { return mDirective == nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE; } |
475 | | |
476 | | virtual bool equals(CSPDirective aDirective) const; |
477 | | |
478 | | void getReportURIs(nsTArray<nsString> &outReportURIs) const; |
479 | | |
480 | | bool visitSrcs(nsCSPSrcVisitor* aVisitor) const; |
481 | | |
482 | | virtual void getDirName(nsAString& outStr) const; |
483 | | |
484 | | bool hasReportSampleKeyword() const; |
485 | | |
486 | | protected: |
487 | | CSPDirective mDirective; |
488 | | nsTArray<nsCSPBaseSrc*> mSrcs; |
489 | | }; |
490 | | |
491 | | /* =============== nsCSPChildSrcDirective ============= */ |
492 | | |
493 | | /* |
494 | | * In CSP 3 child-src is deprecated. For backwards compatibility |
495 | | * child-src needs to restrict: |
496 | | * (*) frames, in case frame-src is not expicitly specified |
497 | | * (*) workers, in case worker-src is not expicitly specified |
498 | | */ |
499 | | class nsCSPChildSrcDirective : public nsCSPDirective { |
500 | | public: |
501 | | explicit nsCSPChildSrcDirective(CSPDirective aDirective); |
502 | | virtual ~nsCSPChildSrcDirective(); |
503 | | |
504 | | void setRestrictFrames() |
505 | 19 | { mRestrictFrames = true; } |
506 | | |
507 | | void setRestrictWorkers() |
508 | 27 | { mRestrictWorkers = true; } |
509 | | |
510 | | virtual bool restrictsContentType(nsContentPolicyType aContentType) const override; |
511 | | |
512 | | virtual bool equals(CSPDirective aDirective) const override; |
513 | | |
514 | | private: |
515 | | bool mRestrictFrames; |
516 | | bool mRestrictWorkers; |
517 | | }; |
518 | | |
519 | | /* =============== nsCSPScriptSrcDirective ============= */ |
520 | | |
521 | | /* |
522 | | * In CSP 3 worker-src restricts workers, for backwards compatibily |
523 | | * script-src has to restrict workers as the ultimate fallback if |
524 | | * neither worker-src nor child-src is present in a CSP. |
525 | | */ |
526 | | class nsCSPScriptSrcDirective : public nsCSPDirective { |
527 | | public: |
528 | | explicit nsCSPScriptSrcDirective(CSPDirective aDirective); |
529 | | virtual ~nsCSPScriptSrcDirective(); |
530 | | |
531 | | void setRestrictWorkers() |
532 | 68 | { mRestrictWorkers = true; } |
533 | | |
534 | | virtual bool restrictsContentType(nsContentPolicyType aContentType) const override; |
535 | | |
536 | | virtual bool equals(CSPDirective aDirective) const override; |
537 | | |
538 | | private: |
539 | | bool mRestrictWorkers; |
540 | | }; |
541 | | |
542 | | /* =============== nsBlockAllMixedContentDirective === */ |
543 | | |
544 | | class nsBlockAllMixedContentDirective : public nsCSPDirective { |
545 | | public: |
546 | | explicit nsBlockAllMixedContentDirective(CSPDirective aDirective); |
547 | | ~nsBlockAllMixedContentDirective(); |
548 | | |
549 | | bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, |
550 | | bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const override |
551 | 0 | { return false; } |
552 | | |
553 | | bool permits(nsIURI* aUri) const |
554 | 0 | { return false; } |
555 | | |
556 | | bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, |
557 | | bool aParserCreated) const override |
558 | 0 | { return false; } |
559 | | |
560 | | void toString(nsAString& outStr) const override; |
561 | | |
562 | | void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs) override |
563 | 0 | { MOZ_ASSERT(false, "block-all-mixed-content does not hold any srcs"); } |
564 | | |
565 | | void getDirName(nsAString& outStr) const override; |
566 | | }; |
567 | | |
568 | | /* =============== nsUpgradeInsecureDirective === */ |
569 | | |
570 | | /* |
571 | | * Upgrading insecure requests includes the following actors: |
572 | | * (1) CSP: |
573 | | * The CSP implementation whitelists the http-request |
574 | | * in case the policy is executed in enforcement mode. |
575 | | * The CSP implementation however does not allow http |
576 | | * requests to succeed if executed in report-only mode. |
577 | | * In such a case the CSP implementation reports the |
578 | | * error back to the page. |
579 | | * |
580 | | * (2) MixedContent: |
581 | | * The evalution of MixedContent whitelists all http |
582 | | * requests with the promise that the http requests |
583 | | * gets upgraded to https before any data is fetched |
584 | | * from the network. |
585 | | * |
586 | | * (3) CORS: |
587 | | * Does not consider the http request to be of a |
588 | | * different origin in case the scheme is the only |
589 | | * difference in otherwise matching URIs. |
590 | | * |
591 | | * (4) nsHttpChannel: |
592 | | * Before connecting, the channel gets redirected |
593 | | * to use https. |
594 | | * |
595 | | * (5) WebSocketChannel: |
596 | | * Similar to the httpChannel, the websocketchannel |
597 | | * gets upgraded from ws to wss. |
598 | | */ |
599 | | class nsUpgradeInsecureDirective : public nsCSPDirective { |
600 | | public: |
601 | | explicit nsUpgradeInsecureDirective(CSPDirective aDirective); |
602 | | ~nsUpgradeInsecureDirective(); |
603 | | |
604 | | bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, |
605 | | bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const override |
606 | 0 | { return false; } |
607 | | |
608 | | bool permits(nsIURI* aUri) const |
609 | 0 | { return false; } |
610 | | |
611 | | bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, |
612 | | bool aParserCreated) const override |
613 | 0 | { return false; } |
614 | | |
615 | | void toString(nsAString& outStr) const override; |
616 | | |
617 | | void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs) override |
618 | 0 | { MOZ_ASSERT(false, "upgrade-insecure-requests does not hold any srcs"); } |
619 | | |
620 | | void getDirName(nsAString& outStr) const override; |
621 | | }; |
622 | | |
623 | | /* ===== nsRequireSRIForDirective ========================= */ |
624 | | |
625 | | class nsRequireSRIForDirective : public nsCSPDirective { |
626 | | public: |
627 | | explicit nsRequireSRIForDirective(CSPDirective aDirective); |
628 | | ~nsRequireSRIForDirective(); |
629 | | |
630 | | void toString(nsAString& outStr) const override; |
631 | | |
632 | | void addType(nsContentPolicyType aType) |
633 | 0 | { mTypes.AppendElement(aType); } |
634 | | bool hasType(nsContentPolicyType aType) const; |
635 | | bool restrictsContentType(nsContentPolicyType aType) const override; |
636 | | bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, |
637 | | bool aParserCreated) const override; |
638 | | void getDirName(nsAString& outStr) const override; |
639 | | |
640 | | private: |
641 | | nsTArray<nsContentPolicyType> mTypes; |
642 | | }; |
643 | | |
644 | | /* =============== nsCSPPolicy ================== */ |
645 | | |
646 | | class nsCSPPolicy { |
647 | | public: |
648 | | nsCSPPolicy(); |
649 | | virtual ~nsCSPPolicy(); |
650 | | |
651 | | bool permits(CSPDirective aDirective, |
652 | | nsIURI* aUri, |
653 | | const nsAString& aNonce, |
654 | | bool aWasRedirected, |
655 | | bool aSpecific, |
656 | | bool aParserCreated, |
657 | | nsAString& outViolatedDirective) const; |
658 | | bool permits(CSPDirective aDir, |
659 | | nsIURI* aUri, |
660 | | bool aSpecific) const; |
661 | | bool allows(nsContentPolicyType aContentType, |
662 | | enum CSPKeyword aKeyword, |
663 | | const nsAString& aHashOrNonce, |
664 | | bool aParserCreated) const; |
665 | | bool allows(nsContentPolicyType aContentType, |
666 | | enum CSPKeyword aKeyword) const; |
667 | | void toString(nsAString& outStr) const; |
668 | | void toDomCSPStruct(mozilla::dom::CSP& outCSP) const; |
669 | | |
670 | | inline void addDirective(nsCSPDirective* aDir) |
671 | 5.27k | { mDirectives.AppendElement(aDir); } |
672 | | |
673 | | inline void addUpgradeInsecDir(nsUpgradeInsecureDirective* aDir) |
674 | 5 | { |
675 | 5 | mUpgradeInsecDir = aDir; |
676 | 5 | addDirective(aDir); |
677 | 5 | } |
678 | | |
679 | | bool hasDirective(CSPDirective aDir) const; |
680 | | |
681 | | inline void setReportOnlyFlag(bool aFlag) |
682 | 0 | { mReportOnly = aFlag; } |
683 | | |
684 | | inline bool getReportOnlyFlag() const |
685 | 0 | { return mReportOnly; } |
686 | | |
687 | | void getReportURIs(nsTArray<nsString> &outReportURIs) const; |
688 | | |
689 | | void getDirectiveStringAndReportSampleForContentType(nsContentPolicyType aContentType, |
690 | | nsAString& outDirective, |
691 | | bool* aReportSample) const; |
692 | | |
693 | | void getDirectiveAsString(CSPDirective aDir, nsAString& outDirective) const; |
694 | | |
695 | | uint32_t getSandboxFlags() const; |
696 | | |
697 | | bool requireSRIForType(nsContentPolicyType aContentType); |
698 | | |
699 | | inline uint32_t getNumDirectives() const |
700 | 5.77k | { return mDirectives.Length(); } |
701 | | |
702 | | bool visitDirectiveSrcs(CSPDirective aDir, nsCSPSrcVisitor* aVisitor) const; |
703 | | |
704 | | private: |
705 | | nsUpgradeInsecureDirective* mUpgradeInsecDir; |
706 | | nsTArray<nsCSPDirective*> mDirectives; |
707 | | bool mReportOnly; |
708 | | }; |
709 | | |
710 | | #endif /* nsCSPUtils_h___ */ |