summaryrefslogtreecommitdiffstats
path: root/dom/security/nsCSPUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/security/nsCSPUtils.h')
-rw-r--r--dom/security/nsCSPUtils.h699
1 files changed, 699 insertions, 0 deletions
diff --git a/dom/security/nsCSPUtils.h b/dom/security/nsCSPUtils.h
new file mode 100644
index 0000000000..dd3ea9a1c4
--- /dev/null
+++ b/dom/security/nsCSPUtils.h
@@ -0,0 +1,699 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsCSPUtils_h___
+#define nsCSPUtils_h___
+
+#include "nsCOMPtr.h"
+#include "nsIContentSecurityPolicy.h"
+#include "nsIURI.h"
+#include "nsLiteralString.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsUnicharUtils.h"
+#include "mozilla/Logging.h"
+
+class nsIChannel;
+
+namespace mozilla::dom {
+struct CSP;
+class Document;
+} // namespace mozilla::dom
+
+/* =============== Logging =================== */
+
+void CSP_LogLocalizedStr(const char* aName, const nsTArray<nsString>& aParams,
+ const nsAString& aSourceName,
+ const nsAString& aSourceLine, uint32_t aLineNumber,
+ uint32_t aColumnNumber, uint32_t aFlags,
+ const nsACString& aCategory, uint64_t aInnerWindowID,
+ bool aFromPrivateWindow);
+
+void CSP_GetLocalizedStr(const char* aName, const nsTArray<nsString>& aParams,
+ nsAString& outResult);
+
+void CSP_LogStrMessage(const nsAString& aMsg);
+
+void CSP_LogMessage(const nsAString& aMessage, const nsAString& aSourceName,
+ const nsAString& aSourceLine, uint32_t aLineNumber,
+ uint32_t aColumnNumber, uint32_t aFlags,
+ const nsACString& aCategory, uint64_t aInnerWindowID,
+ bool aFromPrivateWindow);
+
+/* =============== Constant and Type Definitions ================== */
+
+#define INLINE_STYLE_VIOLATION_OBSERVER_TOPIC \
+ "violated base restriction: Inline Stylesheets will not apply"
+#define INLINE_SCRIPT_VIOLATION_OBSERVER_TOPIC \
+ "violated base restriction: Inline Scripts will not execute"
+#define EVAL_VIOLATION_OBSERVER_TOPIC \
+ "violated base restriction: Code will not be created from strings"
+#define WASM_EVAL_VIOLATION_OBSERVER_TOPIC \
+ "violated base restriction: WebAssembly code will not be created from " \
+ "dynamically"
+#define SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC "Inline Script had invalid nonce"
+#define STYLE_NONCE_VIOLATION_OBSERVER_TOPIC "Inline Style had invalid nonce"
+#define SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC "Inline Script had invalid hash"
+#define STYLE_HASH_VIOLATION_OBSERVER_TOPIC "Inline Style had invalid hash"
+
+// these strings map to the CSPDirectives in nsIContentSecurityPolicy
+// NOTE: When implementing a new directive, you will need to add it here but
+// also add a corresponding entry to the constants in
+// nsIContentSecurityPolicy.idl and also create an entry for the new directive
+// in nsCSPDirective::toDomCSPStruct() and add it to CSPDictionaries.webidl.
+// Order of elements below important! Make sure it matches the order as in
+// nsIContentSecurityPolicy.idl
+static const char* CSPStrDirectives[] = {
+ "-error-", // NO_DIRECTIVE
+ "default-src", // DEFAULT_SRC_DIRECTIVE
+ "script-src", // SCRIPT_SRC_DIRECTIVE
+ "object-src", // OBJECT_SRC_DIRECTIVE
+ "style-src", // STYLE_SRC_DIRECTIVE
+ "img-src", // IMG_SRC_DIRECTIVE
+ "media-src", // MEDIA_SRC_DIRECTIVE
+ "frame-src", // FRAME_SRC_DIRECTIVE
+ "font-src", // FONT_SRC_DIRECTIVE
+ "connect-src", // CONNECT_SRC_DIRECTIVE
+ "report-uri", // REPORT_URI_DIRECTIVE
+ "frame-ancestors", // FRAME_ANCESTORS_DIRECTIVE
+ "reflected-xss", // REFLECTED_XSS_DIRECTIVE
+ "base-uri", // BASE_URI_DIRECTIVE
+ "form-action", // FORM_ACTION_DIRECTIVE
+ "manifest-src", // MANIFEST_SRC_DIRECTIVE
+ "upgrade-insecure-requests", // UPGRADE_IF_INSECURE_DIRECTIVE
+ "child-src", // CHILD_SRC_DIRECTIVE
+ "block-all-mixed-content", // BLOCK_ALL_MIXED_CONTENT
+ "sandbox", // SANDBOX_DIRECTIVE
+ "worker-src", // WORKER_SRC_DIRECTIVE
+ "navigate-to", // NAVIGATE_TO_DIRECTIVE
+ "script-src-elem", // SCRIPT_SRC_ELEM_DIRECTIVE
+ "script-src-attr", // SCRIPT_SRC_ATTR_DIRECTIVE
+ "style-src-elem", // STYLE_SRC_ELEM_DIRECTIVE
+ "style-src-attr", // STYLE_SRC_ATTR_DIRECTIVE
+};
+
+inline const char* CSP_CSPDirectiveToString(CSPDirective aDir) {
+ return CSPStrDirectives[static_cast<uint32_t>(aDir)];
+}
+
+inline CSPDirective CSP_StringToCSPDirective(const nsAString& aDir) {
+ nsString lowerDir = PromiseFlatString(aDir);
+ ToLowerCase(lowerDir);
+
+ uint32_t numDirs = (sizeof(CSPStrDirectives) / sizeof(CSPStrDirectives[0]));
+ for (uint32_t i = 1; i < numDirs; i++) {
+ if (lowerDir.EqualsASCII(CSPStrDirectives[i])) {
+ return static_cast<CSPDirective>(i);
+ }
+ }
+ return nsIContentSecurityPolicy::NO_DIRECTIVE;
+}
+
+#define FOR_EACH_CSP_KEYWORD(MACRO) \
+ MACRO(CSP_SELF, "'self'") \
+ MACRO(CSP_UNSAFE_INLINE, "'unsafe-inline'") \
+ MACRO(CSP_UNSAFE_EVAL, "'unsafe-eval'") \
+ MACRO(CSP_UNSAFE_HASHES, "'unsafe-hashes'") \
+ MACRO(CSP_NONE, "'none'") \
+ MACRO(CSP_NONCE, "'nonce-") \
+ MACRO(CSP_REPORT_SAMPLE, "'report-sample'") \
+ MACRO(CSP_STRICT_DYNAMIC, "'strict-dynamic'") \
+ MACRO(CSP_UNSAFE_ALLOW_REDIRECTS, "'unsafe-allow-redirects'") \
+ MACRO(CSP_WASM_UNSAFE_EVAL, "'wasm-unsafe-eval'")
+
+enum CSPKeyword {
+#define KEYWORD_ENUM(id_, string_) id_,
+ FOR_EACH_CSP_KEYWORD(KEYWORD_ENUM)
+#undef KEYWORD_ENUM
+
+ // CSP_LAST_KEYWORD_VALUE always needs to be the last element in the enum
+ // because we use it to calculate the size for the char* array.
+ CSP_LAST_KEYWORD_VALUE,
+
+ // Putting CSP_HASH after the delimitor, because CSP_HASH is not a valid
+ // keyword (hash uses e.g. sha256, sha512) but we use CSP_HASH internally
+ // to identify allowed hashes in ::allows.
+ CSP_HASH
+};
+
+// The keywords, in UTF-8 form.
+static const char* gCSPUTF8Keywords[] = {
+#define KEYWORD_UTF8_LITERAL(id_, string_) string_,
+ FOR_EACH_CSP_KEYWORD(KEYWORD_UTF8_LITERAL)
+#undef KEYWORD_UTF8_LITERAL
+};
+
+// The keywords, in UTF-16 form.
+static const char16_t* gCSPUTF16Keywords[] = {
+#define KEYWORD_UTF16_LITERAL(id_, string_) u"" string_,
+ FOR_EACH_CSP_KEYWORD(KEYWORD_UTF16_LITERAL)
+#undef KEYWORD_UTF16_LITERAL
+};
+
+#undef FOR_EACH_CSP_KEYWORD
+
+inline const char* CSP_EnumToUTF8Keyword(enum CSPKeyword aKey) {
+ // Make sure all elements in enum CSPKeyword got added to gCSPUTF8Keywords.
+ static_assert((sizeof(gCSPUTF8Keywords) / sizeof(gCSPUTF8Keywords[0]) ==
+ CSP_LAST_KEYWORD_VALUE),
+ "CSP_LAST_KEYWORD_VALUE != length(gCSPUTF8Keywords)");
+
+ if (static_cast<uint32_t>(aKey) <
+ static_cast<uint32_t>(CSP_LAST_KEYWORD_VALUE)) {
+ return gCSPUTF8Keywords[static_cast<uint32_t>(aKey)];
+ }
+ return "error: invalid keyword in CSP_EnumToUTF8Keyword";
+}
+
+inline const char16_t* CSP_EnumToUTF16Keyword(enum CSPKeyword aKey) {
+ // Make sure all elements in enum CSPKeyword got added to gCSPUTF16Keywords.
+ static_assert((sizeof(gCSPUTF16Keywords) / sizeof(gCSPUTF16Keywords[0]) ==
+ CSP_LAST_KEYWORD_VALUE),
+ "CSP_LAST_KEYWORD_VALUE != length(gCSPUTF16Keywords)");
+
+ if (static_cast<uint32_t>(aKey) <
+ static_cast<uint32_t>(CSP_LAST_KEYWORD_VALUE)) {
+ return gCSPUTF16Keywords[static_cast<uint32_t>(aKey)];
+ }
+ return u"error: invalid keyword in CSP_EnumToUTF16Keyword";
+}
+
+inline CSPKeyword CSP_UTF16KeywordToEnum(const nsAString& aKey) {
+ nsString lowerKey = PromiseFlatString(aKey);
+ ToLowerCase(lowerKey);
+
+ for (uint32_t i = 0; i < CSP_LAST_KEYWORD_VALUE; i++) {
+ if (lowerKey.Equals(gCSPUTF16Keywords[i])) {
+ return static_cast<CSPKeyword>(i);
+ }
+ }
+ NS_ASSERTION(false, "Can not convert unknown Keyword to Enum");
+ return CSP_LAST_KEYWORD_VALUE;
+}
+
+nsresult CSP_AppendCSPFromHeader(nsIContentSecurityPolicy* aCsp,
+ const nsAString& aHeaderValue,
+ bool aReportOnly);
+
+/* =============== Helpers ================== */
+
+class nsCSPHostSrc;
+
+nsCSPHostSrc* CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI);
+bool CSP_IsEmptyDirective(const nsAString& aValue, const nsAString& aDir);
+bool CSP_IsDirective(const nsAString& aValue, CSPDirective aDir);
+bool CSP_IsKeyword(const nsAString& aValue, enum CSPKeyword aKey);
+bool CSP_IsQuotelessKeyword(const nsAString& aKey);
+CSPDirective CSP_ContentTypeToDirective(nsContentPolicyType aType);
+
+class nsCSPSrcVisitor;
+
+void CSP_PercentDecodeStr(const nsAString& aEncStr, nsAString& outDecStr);
+bool CSP_ShouldResponseInheritCSP(nsIChannel* aChannel);
+
+void CSP_ApplyMetaCSPToDoc(mozilla::dom::Document& aDoc,
+ const nsAString& aPolicyStr);
+
+/* =============== nsCSPSrc ================== */
+
+class nsCSPBaseSrc {
+ public:
+ nsCSPBaseSrc();
+ virtual ~nsCSPBaseSrc();
+
+ virtual bool permits(nsIURI* aUri, const nsAString& aNonce,
+ bool aWasRedirected, bool aReportOnly,
+ bool aUpgradeInsecure, bool aParserCreated) const;
+ virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
+ bool aParserCreated) const;
+ virtual bool visit(nsCSPSrcVisitor* aVisitor) const = 0;
+ virtual void toString(nsAString& outStr) const = 0;
+
+ virtual void invalidate() const { mInvalidated = true; }
+
+ virtual bool isReportSample() const { return false; }
+
+ protected:
+ // invalidate srcs if 'script-dynamic' is present or also invalidate
+ // unsafe-inline' if nonce- or hash-source specified
+ mutable bool mInvalidated;
+};
+
+/* =============== nsCSPSchemeSrc ============ */
+
+class nsCSPSchemeSrc : public nsCSPBaseSrc {
+ public:
+ explicit nsCSPSchemeSrc(const nsAString& aScheme);
+ virtual ~nsCSPSchemeSrc();
+
+ bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
+ bool aReportOnly, bool aUpgradeInsecure,
+ bool aParserCreated) const override;
+ bool visit(nsCSPSrcVisitor* aVisitor) const override;
+ void toString(nsAString& outStr) const override;
+
+ inline void getScheme(nsAString& outStr) const { outStr.Assign(mScheme); };
+
+ private:
+ nsString mScheme;
+};
+
+/* =============== nsCSPHostSrc ============== */
+
+class nsCSPHostSrc : public nsCSPBaseSrc {
+ public:
+ explicit nsCSPHostSrc(const nsAString& aHost);
+ virtual ~nsCSPHostSrc();
+
+ bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
+ bool aReportOnly, bool aUpgradeInsecure,
+ bool aParserCreated) const override;
+ bool visit(nsCSPSrcVisitor* aVisitor) const override;
+ void toString(nsAString& outStr) const override;
+
+ void setScheme(const nsAString& aScheme);
+ void setPort(const nsAString& aPort);
+ void appendPath(const nsAString& aPath);
+
+ inline void setGeneratedFromSelfKeyword() const {
+ mGeneratedFromSelfKeyword = true;
+ }
+
+ inline void setIsUniqueOrigin() const { mIsUniqueOrigin = true; }
+
+ inline void setWithinFrameAncestorsDir(bool aValue) const {
+ mWithinFrameAncstorsDir = aValue;
+ }
+
+ inline void getScheme(nsAString& outStr) const { outStr.Assign(mScheme); };
+
+ inline void getHost(nsAString& outStr) const { outStr.Assign(mHost); };
+
+ inline void getPort(nsAString& outStr) const { outStr.Assign(mPort); };
+
+ inline void getPath(nsAString& outStr) const { outStr.Assign(mPath); };
+
+ private:
+ nsString mScheme;
+ nsString mHost;
+ nsString mPort;
+ nsString mPath;
+ mutable bool mGeneratedFromSelfKeyword;
+ mutable bool mIsUniqueOrigin;
+ mutable bool mWithinFrameAncstorsDir;
+};
+
+/* =============== nsCSPKeywordSrc ============ */
+
+class nsCSPKeywordSrc : public nsCSPBaseSrc {
+ public:
+ explicit nsCSPKeywordSrc(CSPKeyword aKeyword);
+ virtual ~nsCSPKeywordSrc();
+
+ bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
+ bool aParserCreated) const override;
+ bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
+ bool aReportOnly, bool aUpgradeInsecure,
+ bool aParserCreated) const override;
+ bool visit(nsCSPSrcVisitor* aVisitor) const override;
+ void toString(nsAString& outStr) const override;
+
+ inline CSPKeyword getKeyword() const { return mKeyword; };
+
+ inline void invalidate() const override {
+ // keywords that need to invalidated
+ if (mKeyword == CSP_SELF || mKeyword == CSP_UNSAFE_INLINE ||
+ mKeyword == CSP_REPORT_SAMPLE) {
+ mInvalidated = true;
+ }
+ }
+
+ bool isReportSample() const override { return mKeyword == CSP_REPORT_SAMPLE; }
+
+ private:
+ CSPKeyword mKeyword;
+};
+
+/* =============== nsCSPNonceSource =========== */
+
+class nsCSPNonceSrc : public nsCSPBaseSrc {
+ public:
+ explicit nsCSPNonceSrc(const nsAString& aNonce);
+ virtual ~nsCSPNonceSrc();
+
+ bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
+ bool aReportOnly, bool aUpgradeInsecure,
+ bool aParserCreated) const override;
+ bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
+ bool aParserCreated) const override;
+ bool visit(nsCSPSrcVisitor* aVisitor) const override;
+ void toString(nsAString& outStr) const override;
+
+ inline void getNonce(nsAString& outStr) const { outStr.Assign(mNonce); };
+
+ inline void invalidate() const override {
+ // overwrite nsCSPBaseSRC::invalidate() and explicitily
+ // do *not* invalidate, because 'strict-dynamic' should
+ // not invalidate nonces.
+ }
+
+ private:
+ nsString mNonce;
+};
+
+/* =============== nsCSPHashSource ============ */
+
+class nsCSPHashSrc : public nsCSPBaseSrc {
+ public:
+ nsCSPHashSrc(const nsAString& algo, const nsAString& hash);
+ virtual ~nsCSPHashSrc();
+
+ bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
+ bool aParserCreated) const override;
+ void toString(nsAString& outStr) const override;
+ bool visit(nsCSPSrcVisitor* aVisitor) const override;
+
+ inline void getAlgorithm(nsAString& outStr) const {
+ outStr.Assign(mAlgorithm);
+ };
+
+ inline void getHash(nsAString& outStr) const { outStr.Assign(mHash); };
+
+ inline void invalidate() const override {
+ // overwrite nsCSPBaseSRC::invalidate() and explicitily
+ // do *not* invalidate, because 'strict-dynamic' should
+ // not invalidate hashes.
+ }
+
+ private:
+ nsString mAlgorithm;
+ nsString mHash;
+};
+
+/* =============== nsCSPReportURI ============ */
+
+class nsCSPReportURI : public nsCSPBaseSrc {
+ public:
+ explicit nsCSPReportURI(nsIURI* aURI);
+ virtual ~nsCSPReportURI();
+
+ bool visit(nsCSPSrcVisitor* aVisitor) const override;
+ void toString(nsAString& outStr) const override;
+
+ private:
+ nsCOMPtr<nsIURI> mReportURI;
+};
+
+/* =============== nsCSPSandboxFlags ================== */
+
+class nsCSPSandboxFlags : public nsCSPBaseSrc {
+ public:
+ explicit nsCSPSandboxFlags(const nsAString& aFlags);
+ virtual ~nsCSPSandboxFlags();
+
+ bool visit(nsCSPSrcVisitor* aVisitor) const override;
+ void toString(nsAString& outStr) const override;
+
+ private:
+ nsString mFlags;
+};
+
+/* =============== nsCSPSrcVisitor ================== */
+
+class nsCSPSrcVisitor {
+ public:
+ virtual bool visitSchemeSrc(const nsCSPSchemeSrc& src) = 0;
+
+ virtual bool visitHostSrc(const nsCSPHostSrc& src) = 0;
+
+ virtual bool visitKeywordSrc(const nsCSPKeywordSrc& src) = 0;
+
+ virtual bool visitNonceSrc(const nsCSPNonceSrc& src) = 0;
+
+ virtual bool visitHashSrc(const nsCSPHashSrc& src) = 0;
+
+ protected:
+ explicit nsCSPSrcVisitor() = default;
+ virtual ~nsCSPSrcVisitor() = default;
+};
+
+/* =============== nsCSPDirective ============= */
+
+class nsCSPDirective {
+ public:
+ explicit nsCSPDirective(CSPDirective aDirective);
+ virtual ~nsCSPDirective();
+
+ virtual bool permits(nsIURI* aUri, const nsAString& aNonce,
+ bool aWasRedirected, bool aReportOnly,
+ bool aUpgradeInsecure, bool aParserCreated) const;
+ virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
+ bool aParserCreated) const;
+ virtual void toString(nsAString& outStr) const;
+ void toDomCSPStruct(mozilla::dom::CSP& outCSP) const;
+
+ virtual void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs) {
+ mSrcs = aSrcs.Clone();
+ }
+
+ inline bool isDefaultDirective() const {
+ return mDirective == nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE;
+ }
+
+ virtual bool equals(CSPDirective aDirective) const;
+
+ void getReportURIs(nsTArray<nsString>& outReportURIs) const;
+
+ bool visitSrcs(nsCSPSrcVisitor* aVisitor) const;
+
+ virtual void getDirName(nsAString& outStr) const;
+
+ bool hasReportSampleKeyword() const;
+
+ protected:
+ CSPDirective mDirective;
+ nsTArray<nsCSPBaseSrc*> mSrcs;
+};
+
+/* =============== nsCSPChildSrcDirective ============= */
+
+/*
+ * In CSP 3 child-src is deprecated. For backwards compatibility
+ * child-src needs to restrict:
+ * (*) frames, in case frame-src is not expicitly specified
+ * (*) workers, in case worker-src is not expicitly specified
+ */
+class nsCSPChildSrcDirective : public nsCSPDirective {
+ public:
+ explicit nsCSPChildSrcDirective(CSPDirective aDirective);
+ virtual ~nsCSPChildSrcDirective();
+
+ void setRestrictFrames() { mRestrictFrames = true; }
+
+ void setRestrictWorkers() { mRestrictWorkers = true; }
+
+ virtual bool equals(CSPDirective aDirective) const override;
+
+ private:
+ bool mRestrictFrames;
+ bool mRestrictWorkers;
+};
+
+/* =============== nsCSPScriptSrcDirective ============= */
+
+/*
+ * In CSP 3 worker-src restricts workers, for backwards compatibily
+ * script-src has to restrict workers as the ultimate fallback if
+ * neither worker-src nor child-src is present in a CSP.
+ */
+class nsCSPScriptSrcDirective : public nsCSPDirective {
+ public:
+ explicit nsCSPScriptSrcDirective(CSPDirective aDirective);
+ virtual ~nsCSPScriptSrcDirective();
+
+ void setRestrictWorkers() { mRestrictWorkers = true; }
+ void setRestrictScriptElem() { mRestrictScriptElem = true; }
+ void setRestrictScriptAttr() { mRestrictScriptAttr = true; }
+
+ bool equals(CSPDirective aDirective) const override;
+
+ private:
+ bool mRestrictWorkers = false;
+ bool mRestrictScriptElem = false;
+ bool mRestrictScriptAttr = false;
+};
+
+/* =============== nsCSPStyleSrcDirective ============= */
+
+/*
+ * In CSP 3 style-src is use as a fallback for style-src-elem and
+ * style-src-attr.
+ */
+class nsCSPStyleSrcDirective : public nsCSPDirective {
+ public:
+ explicit nsCSPStyleSrcDirective(CSPDirective aDirective);
+ virtual ~nsCSPStyleSrcDirective();
+
+ void setRestrictStyleElem() { mRestrictStyleElem = true; }
+ void setRestrictStyleAttr() { mRestrictStyleAttr = true; }
+
+ bool equals(CSPDirective aDirective) const override;
+
+ private:
+ bool mRestrictStyleElem = false;
+ bool mRestrictStyleAttr = false;
+};
+
+/* =============== nsBlockAllMixedContentDirective === */
+
+class nsBlockAllMixedContentDirective : public nsCSPDirective {
+ public:
+ explicit nsBlockAllMixedContentDirective(CSPDirective aDirective);
+ ~nsBlockAllMixedContentDirective();
+
+ bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
+ bool aReportOnly, bool aUpgradeInsecure,
+ bool aParserCreated) const override {
+ return false;
+ }
+
+ bool permits(nsIURI* aUri) const { return false; }
+
+ bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
+ bool aParserCreated) const override {
+ return false;
+ }
+
+ void toString(nsAString& outStr) const override;
+
+ void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs) override {
+ MOZ_ASSERT(false, "block-all-mixed-content does not hold any srcs");
+ }
+
+ void getDirName(nsAString& outStr) const override;
+};
+
+/* =============== nsUpgradeInsecureDirective === */
+
+/*
+ * Upgrading insecure requests includes the following actors:
+ * (1) CSP:
+ * The CSP implementation allowlists the http-request
+ * in case the policy is executed in enforcement mode.
+ * The CSP implementation however does not allow http
+ * requests to succeed if executed in report-only mode.
+ * In such a case the CSP implementation reports the
+ * error back to the page.
+ *
+ * (2) MixedContent:
+ * The evalution of MixedContent allowlists all http
+ * requests with the promise that the http requests
+ * gets upgraded to https before any data is fetched
+ * from the network.
+ *
+ * (3) CORS:
+ * Does not consider the http request to be of a
+ * different origin in case the scheme is the only
+ * difference in otherwise matching URIs.
+ *
+ * (4) nsHttpChannel:
+ * Before connecting, the channel gets redirected
+ * to use https.
+ *
+ * (5) WebSocketChannel:
+ * Similar to the httpChannel, the websocketchannel
+ * gets upgraded from ws to wss.
+ */
+class nsUpgradeInsecureDirective : public nsCSPDirective {
+ public:
+ explicit nsUpgradeInsecureDirective(CSPDirective aDirective);
+ ~nsUpgradeInsecureDirective();
+
+ bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
+ bool aReportOnly, bool aUpgradeInsecure,
+ bool aParserCreated) const override {
+ return false;
+ }
+
+ bool permits(nsIURI* aUri) const { return false; }
+
+ bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
+ bool aParserCreated) const override {
+ return false;
+ }
+
+ void toString(nsAString& outStr) const override;
+
+ void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs) override {
+ MOZ_ASSERT(false, "upgrade-insecure-requests does not hold any srcs");
+ }
+
+ void getDirName(nsAString& outStr) const override;
+};
+
+/* =============== nsCSPPolicy ================== */
+
+class nsCSPPolicy {
+ public:
+ nsCSPPolicy();
+ virtual ~nsCSPPolicy();
+
+ bool permits(CSPDirective aDirective, nsIURI* aUri, const nsAString& aNonce,
+ bool aWasRedirected, bool aSpecific, bool aParserCreated,
+ nsAString& outViolatedDirective) const;
+ bool allows(CSPDirective aDirective, enum CSPKeyword aKeyword,
+ const nsAString& aHashOrNonce, bool aParserCreated) const;
+ void toString(nsAString& outStr) const;
+ void toDomCSPStruct(mozilla::dom::CSP& outCSP) const;
+
+ inline void addDirective(nsCSPDirective* aDir) {
+ mDirectives.AppendElement(aDir);
+ }
+
+ inline void addUpgradeInsecDir(nsUpgradeInsecureDirective* aDir) {
+ mUpgradeInsecDir = aDir;
+ addDirective(aDir);
+ }
+
+ bool hasDirective(CSPDirective aDir) const;
+
+ inline void setDeliveredViaMetaTagFlag(bool aFlag) {
+ mDeliveredViaMetaTag = aFlag;
+ }
+
+ inline bool getDeliveredViaMetaTagFlag() const {
+ return mDeliveredViaMetaTag;
+ }
+
+ inline void setReportOnlyFlag(bool aFlag) { mReportOnly = aFlag; }
+
+ inline bool getReportOnlyFlag() const { return mReportOnly; }
+
+ void getReportURIs(nsTArray<nsString>& outReportURIs) const;
+
+ void getDirectiveStringAndReportSampleForContentType(
+ CSPDirective aDirective, nsAString& outDirective,
+ bool* aReportSample) const;
+
+ void getDirectiveAsString(CSPDirective aDir, nsAString& outDirective) const;
+
+ uint32_t getSandboxFlags() const;
+
+ inline uint32_t getNumDirectives() const { return mDirectives.Length(); }
+
+ bool visitDirectiveSrcs(CSPDirective aDir, nsCSPSrcVisitor* aVisitor) const;
+
+ bool allowsNavigateTo(nsIURI* aURI, bool aWasRedirected,
+ bool aEnforceAllowlist) const;
+
+ private:
+ nsUpgradeInsecureDirective* mUpgradeInsecDir;
+ nsTArray<nsCSPDirective*> mDirectives;
+ bool mReportOnly;
+ bool mDeliveredViaMetaTag;
+};
+
+#endif /* nsCSPUtils_h___ */