Bug 1346774: move subjectToCSP into static helper function r?ckerschb
MozReview-Commit-ID: 7paR4pLnJXD
--- a/dom/security/nsCSPService.cpp
+++ b/dom/security/nsCSPService.cpp
@@ -7,16 +7,17 @@
#include "mozilla/Logging.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIURI.h"
#include "nsIPrincipal.h"
#include "nsIObserver.h"
#include "nsIContent.h"
#include "nsCSPService.h"
+#include "nsCSPUtils.h"
#include "nsIContentSecurityPolicy.h"
#include "nsError.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsAsyncRedirectVerifyHelper.h"
#include "mozilla/Preferences.h"
#include "nsIScriptError.h"
#include "nsContentUtils.h"
#include "nsContentPolicyUtils.h"
@@ -35,75 +36,16 @@ CSPService::CSPService()
CSPService::~CSPService()
{
mAppStatusCache.Clear();
}
NS_IMPL_ISUPPORTS(CSPService, nsIContentPolicy, nsIChannelEventSink)
-// Helper function to identify protocols and content types not subject to CSP.
-bool
-subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
- // These content types are not subject to CSP content policy checks:
- // TYPE_CSP_REPORT -- csp can't block csp reports
- // TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl)
- // TYPE_DOCUMENT -- used for frame-ancestors
- if (aContentType == nsIContentPolicy::TYPE_CSP_REPORT ||
- aContentType == nsIContentPolicy::TYPE_REFRESH ||
- aContentType == nsIContentPolicy::TYPE_DOCUMENT) {
- return false;
- }
-
- // The three protocols: data:, blob: and filesystem: share the same
- // protocol flag (URI_IS_LOCAL_RESOURCE) with other protocols, like
- // chrome:, resource:, moz-icon:, but those three protocols get
- // special attention in CSP and are subject to CSP, hence we have
- // to make sure those protocols are subject to CSP, see:
- // http://www.w3.org/TR/CSP2/#source-list-guid-matching
- bool match = false;
- nsresult rv = aURI->SchemeIs("data", &match);
- if (NS_SUCCEEDED(rv) && match) {
- return true;
- }
- rv = aURI->SchemeIs("blob", &match);
- if (NS_SUCCEEDED(rv) && match) {
- return true;
- }
- rv = aURI->SchemeIs("filesystem", &match);
- if (NS_SUCCEEDED(rv) && match) {
- return true;
- }
-
- // Finally we have to whitelist "about:" which does not fall into
- // the category underneath and also "javascript:" which is not
- // subject to CSP content loading rules.
- rv = aURI->SchemeIs("about", &match);
- if (NS_SUCCEEDED(rv) && match) {
- return false;
- }
- rv = aURI->SchemeIs("javascript", &match);
- if (NS_SUCCEEDED(rv) && match) {
- return false;
- }
-
- // Other protocols are not subject to CSP and can be whitelisted:
- // * URI_IS_LOCAL_RESOURCE
- // e.g. chrome:, data:, blob:, resource:, moz-icon:
- // Please note that it should be possible for websites to
- // whitelist their own protocol handlers with respect to CSP,
- // hence we use protocol flags to accomplish that.
- rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &match);
- if (NS_SUCCEEDED(rv) && match) {
- return false;
- }
- // all other protocols are subject To CSP.
- return true;
-}
-
/* nsIContentPolicy implementation */
NS_IMETHODIMP
CSPService::ShouldLoad(uint32_t aContentType,
nsIURI *aContentLocation,
nsIURI *aRequestOrigin,
nsISupports *aRequestContext,
const nsACString &aMimeTypeGuess,
nsISupports *aExtra,
@@ -122,18 +64,18 @@ CSPService::ShouldLoad(uint32_t aContent
// default decision, CSP can revise it if there's a policy to enforce
*aDecision = nsIContentPolicy::ACCEPT;
// No need to continue processing if CSP is disabled or if the protocol
// or type is *not* subject to CSP.
// Please note, the correct way to opt-out of CSP using a custom
// protocolHandler is to set one of the nsIProtocolHandler flags
- // that are whitelistet in subjectToCSP()
- if (!sCSPEnabled || !subjectToCSP(aContentLocation, aContentType)) {
+ // that are whitelistet in CSP_IsRequestSubjectToCSP()
+ if (!sCSPEnabled || !CSP_IsRequestSubjectToCSP(aContentLocation, aContentType)) {
return NS_OK;
}
// query the principal of the document; if no document is passed, then
// fall back to using the requestPrincipal (e.g. service workers do not
// pass a document).
nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
nsCOMPtr<nsIPrincipal> principal = node ? node->NodePrincipal()
@@ -254,19 +196,19 @@ CSPService::AsyncOnChannelRedirect(nsICh
if (!loadInfo) {
return NS_OK;
}
// No need to continue processing if CSP is disabled or if the protocol
// is *not* subject to CSP.
// Please note, the correct way to opt-out of CSP using a custom
// protocolHandler is to set one of the nsIProtocolHandler flags
- // that are whitelistet in subjectToCSP()
+ // that are whitelistet in CSP_IsRequestSubjectToCSP()
nsContentPolicyType policyType = loadInfo->InternalContentPolicyType();
- if (!sCSPEnabled || !subjectToCSP(newUri, policyType)) {
+ if (!sCSPEnabled || !CSP_IsRequestSubjectToCSP(newUri, policyType)) {
return NS_OK;
}
/* Since redirecting channels don't call into nsIContentPolicy, we call our
* Content Policy implementation directly when redirects occur using the
* information set in the LoadInfo when channels are created.
*
* We check if the CSP permits this host for this type of load, if not,
--- a/dom/security/nsCSPService.h
+++ b/dom/security/nsCSPService.h
@@ -6,16 +6,18 @@
#ifndef nsCSPService_h___
#define nsCSPService_h___
#include "nsXPCOM.h"
#include "nsIContentPolicy.h"
#include "nsIChannel.h"
#include "nsIChannelEventSink.h"
+#include "nsNetUtil.h"
+#include "nsIProtocolHandler.h"
#include "nsDataHashtable.h"
#define CSPSERVICE_CONTRACTID "@mozilla.org/cspservice;1"
#define CSPSERVICE_CID \
{ 0x8d2f40b2, 0x4875, 0x4c95, \
{ 0x97, 0xd9, 0x3f, 0x7d, 0xca, 0x2c, 0xb4, 0x60 } }
class CSPService : public nsIContentPolicy,
public nsIChannelEventSink
@@ -30,9 +32,10 @@ public:
protected:
virtual ~CSPService();
private:
// Maps origins to app status.
nsDataHashtable<nsCStringHashKey, uint16_t> mAppStatusCache;
};
+
#endif /* nsCSPService_h___ */
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -25,16 +25,75 @@ GetCspUtilsLog()
{
static mozilla::LazyLogModule gCspUtilsPRLog("CSPUtils");
return gCspUtilsPRLog;
}
#define CSPUTILSLOG(args) MOZ_LOG(GetCspUtilsLog(), mozilla::LogLevel::Debug, args)
#define CSPUTILSLOGENABLED() MOZ_LOG_TEST(GetCspUtilsLog(), mozilla::LogLevel::Debug)
+// Helper function to identify protocols and content types not subject to CSP.
+bool
+CSP_IsRequestSubjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
+ // These content types are not subject to CSP content policy checks:
+ // TYPE_CSP_REPORT -- csp can't block csp reports
+ // TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl)
+ // TYPE_DOCUMENT -- used for frame-ancestors
+ if (aContentType == nsIContentPolicy::TYPE_CSP_REPORT ||
+ aContentType == nsIContentPolicy::TYPE_REFRESH ||
+ aContentType == nsIContentPolicy::TYPE_DOCUMENT) {
+ return false;
+ }
+
+ // The three protocols: data:, blob: and filesystem: share the same
+ // protocol flag (URI_IS_LOCAL_RESOURCE) with other protocols, like
+ // chrome:, resource:, moz-icon:, but those three protocols get
+ // special attention in CSP and are subject to CSP, hence we have
+ // to make sure those protocols are subject to CSP, see:
+ // http://www.w3.org/TR/CSP2/#source-list-guid-matching
+ bool match = false;
+ nsresult rv = aURI->SchemeIs("data", &match);
+ if (NS_SUCCEEDED(rv) && match) {
+ return true;
+ }
+ rv = aURI->SchemeIs("blob", &match);
+ if (NS_SUCCEEDED(rv) && match) {
+ return true;
+ }
+ rv = aURI->SchemeIs("filesystem", &match);
+ if (NS_SUCCEEDED(rv) && match) {
+ return true;
+ }
+
+ // Finally we have to whitelist "about:" which does not fall into
+ // the category underneath and also "javascript:" which is not
+ // subject to CSP content loading rules.
+ rv = aURI->SchemeIs("about", &match);
+ if (NS_SUCCEEDED(rv) && match) {
+ return false;
+ }
+ rv = aURI->SchemeIs("javascript", &match);
+ if (NS_SUCCEEDED(rv) && match) {
+ return false;
+ }
+
+ // Other protocols are not subject to CSP and can be whitelisted:
+ // * URI_IS_LOCAL_RESOURCE
+ // e.g. chrome:, data:, blob:, resource:, moz-icon:
+ // Please note that it should be possible for websites to
+ // whitelist their own protocol handlers with respect to CSP,
+ // hence we use protocol flags to accomplish that.
+ rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &match);
+ if (NS_SUCCEEDED(rv) && match) {
+ return false;
+ }
+ // all other protocols are subject To CSP.
+ return true;
+}
+
void
CSP_PercentDecodeStr(const nsAString& aEncStr, nsAString& outDecStr)
{
outDecStr.Truncate();
// helper function that should not be visible outside this methods scope
struct local {
static inline char16_t convertHexDig(char16_t aHexDig) {
--- a/dom/security/nsCSPUtils.h
+++ b/dom/security/nsCSPUtils.h
@@ -6,16 +6,18 @@
#ifndef nsCSPUtils_h___
#define nsCSPUtils_h___
#include "nsCOMPtr.h"
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIURI.h"
+#include "nsNetUtil.h"
+#include "nsIProtocolHandler.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsUnicharUtils.h"
#include "mozilla/Logging.h"
namespace mozilla {
namespace dom {
struct CSP;
@@ -111,16 +113,21 @@ inline CSPDirective CSP_StringToCSPDirec
if (lowerDir.EqualsASCII(CSPStrDirectives[i])) {
return static_cast<CSPDirective>(i);
}
}
NS_ASSERTION(false, "Can not convert unknown Directive to Integer");
return nsIContentSecurityPolicy::NO_DIRECTIVE;
}
+// Helper function to identify protocols and content types not subject to CSP.
+bool
+CSP_IsRequestSubjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType);
+
+
// Please add any new enum items not only to CSPKeyword, but also add
// a string version for every enum >> using the same index << to
// CSPStrKeywords underneath.
enum CSPKeyword {
CSP_SELF = 0,
CSP_UNSAFE_INLINE,
CSP_UNSAFE_EVAL,
CSP_NONE,