Coverage Report

Created: 2018-09-25 14:53

/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___ */