Bug 951457 - Create C++ CSP Parser and policy classes, part 1 - backend stubs r=sstamm, r=grobinson

This commit is contained in:
Christoph Kerschbaumer 2014-04-01 09:35:22 -07:00
parent 0b7bf8cdea
commit 20d36d770e
9 changed files with 292 additions and 11 deletions

View File

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISerializable.idl"
#include "nsIContentPolicy.idl"
interface nsIURI;
interface nsIChannel;
@ -16,7 +17,7 @@ interface nsIPrincipal;
* one of these per document/principal.
*/
[scriptable, uuid(8b91f829-b1bf-4327-8ece-4000aa823394)]
[scriptable, uuid(1ae83090-e1e1-4272-b0c4-0fbd751c1e27)]
interface nsIContentSecurityPolicy : nsISerializable
{
@ -25,7 +26,7 @@ interface nsIContentSecurityPolicy : nsISerializable
* enforce. This is a barrier for the nsDocument so it doesn't load any
* sub-content until either it knows that a CSP is ready or will not be used.
*/
attribute boolean isInitialized;
readonly attribute boolean isInitialized;
/**
* Accessor method for a read-only string version of the policy at a given
@ -37,7 +38,7 @@ interface nsIContentSecurityPolicy : nsISerializable
* Returns the number of policies attached to this CSP instance. Useful with
* getPolicy().
*/
attribute long policyCount;
readonly attribute unsigned long policyCount;
/**
* Remove a policy associated with this CSP context.
@ -217,7 +218,7 @@ interface nsIContentSecurityPolicy : nsISerializable
* Calls to this may trigger violation reports when queried, so
* this value should not be cached.
*/
short shouldLoad(in unsigned long aContentType,
short shouldLoad(in nsContentPolicyType aContentType,
in nsIURI aContentLocation,
in nsIURI aRequestOrigin,
in nsISupports aContext,
@ -229,11 +230,16 @@ interface nsIContentSecurityPolicy : nsISerializable
* document are being processed. Given a bit of information about the request,
* decides whether or not the policy is satisfied.
*/
short shouldProcess(in unsigned long aContentType,
short shouldProcess(in nsContentPolicyType aContentType,
in nsIURI aContentLocation,
in nsIURI aRequestOrigin,
in nsISupports aContext,
in ACString aMimeType,
in nsISupports aExtra);
%{ C++
// nsIObserver topic to fire when the policy encounters a violation.
#define CSP_VIOLATION_TOPIC "csp-on-violate-policy"
%}
};

View File

@ -110,6 +110,7 @@ UNIFIED_SOURCES += [
'nsContentSink.cpp',
'nsCopySupport.cpp',
'nsCrossSiteListenerProxy.cpp',
'nsCSPContext.cpp',
'nsCSPParser.cpp',
'nsCSPService.cpp',
'nsCSPUtils.cpp',

View File

@ -0,0 +1,204 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "mozilla/Preferences.h"
#include "nsAsyncRedirectVerifyHelper.h"
#include "nsChannelProperties.h"
#include "nsCOMPtr.h"
#include "nsContentPolicyUtils.h"
#include "nsContentUtils.h"
#include "nsCSPContext.h"
#include "nsCSPParser.h"
#include "nsCSPService.h"
#include "nsError.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIChannelEventSink.h"
#include "nsIChannelPolicy.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIHttpChannel.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIPrincipal.h"
#include "nsIPropertyBag2.h"
#include "nsIScriptError.h"
#include "nsIWritablePropertyBag2.h"
#include "nsString.h"
#include "prlog.h"
using namespace mozilla;
/* ===== nsIContentSecurityPolicy impl ====== */
NS_IMETHODIMP
nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
nsIURI* aContentLocation,
nsIURI* aRequestOrigin,
nsISupports* aRequestContext,
const nsACString& aMimeTypeGuess,
nsISupports* aExtra,
int16_t* outDecision)
{
*outDecision = nsIContentPolicy::ACCEPT;
return NS_OK;
}
NS_IMETHODIMP
nsCSPContext::ShouldProcess(nsContentPolicyType aContentType,
nsIURI* aContentLocation,
nsIURI* aRequestOrigin,
nsISupports* aRequestContext,
const nsACString& aMimeType,
nsISupports* aExtra,
int16_t* outDecision)
{
*outDecision = nsIContentPolicy::ACCEPT;
return NS_OK;
}
/* ===== nsISupports implementation ========== */
NS_IMPL_ISUPPORTS(nsCSPContext,
nsIContentSecurityPolicy,
nsISerializable)
nsCSPContext::nsCSPContext()
{
}
nsCSPContext::~nsCSPContext()
{
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
delete mPolicies[i];
}
}
NS_IMETHODIMP
nsCSPContext::GetIsInitialized(bool *outIsInitialized)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::GetPolicy(uint32_t aIndex, nsAString& outStr)
{
if (aIndex >= mPolicies.Length()) {
return NS_ERROR_FAILURE;
}
mPolicies[aIndex]->toString(outStr);
return NS_OK;
}
NS_IMETHODIMP
nsCSPContext::GetPolicyCount(uint32_t *outPolicyCount)
{
*outPolicyCount = mPolicies.Length();
return NS_OK;
}
NS_IMETHODIMP
nsCSPContext::RemovePolicy(uint32_t aIndex)
{
if (aIndex >= mPolicies.Length()) {
return NS_ERROR_ILLEGAL_VALUE;
}
mPolicies.RemoveElementAt(aIndex);
return NS_OK;
}
NS_IMETHODIMP
nsCSPContext::AppendPolicy(const nsAString& aPolicyString,
nsIURI* aSelfURI,
bool aReportOnly,
bool aSpecCompliant)
{
NS_ASSERTION(aSelfURI, "aSelfURI required for AppendPolicy");
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(aPolicyString, aSelfURI, aReportOnly, 0);
if (policy) {
mPolicies.AppendElement(policy);
}
return NS_OK;
}
NS_IMETHODIMP
nsCSPContext::GetAllowsInlineScript(bool* outShouldReportViolations,
bool* outAllowsInlineScript)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::GetAllowsEval(bool* outShouldReportViolations,
bool* outAllowsEval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::GetAllowsInlineStyle(bool* outShouldReportViolations,
bool* outAllowsInlineStyle)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::GetAllowsNonce(const nsAString& aNonce,
uint32_t aContentType,
bool* outShouldReportViolation,
bool* outAllowsNonce)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::GetAllowsHash(const nsAString& aContent,
uint16_t aContentType,
bool* outShouldReportViolation,
bool* outAllowsHash)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::LogViolationDetails(uint16_t aViolationType,
const nsAString& aSourceFile,
const nsAString& aScriptSample,
int32_t aLineNum,
const nsAString& aNonce,
const nsAString& aContent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::SetRequestContext(nsIURI* aSelfURI,
nsIURI* aReferrer,
nsIPrincipal* aDocumentPrincipal,
nsIChannel* aChannel)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::PermitsAncestry(nsIDocShell* aDocShell, bool* outPermitsAncestry)
{
// For now, we allows permitsAncestry, this will be fixed in Bug 994320
*outPermitsAncestry = true;
return NS_OK;
}
/* ===== nsISerializable implementation ====== */
NS_IMETHODIMP
nsCSPContext::Read(nsIObjectInputStream* aStream)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::Write(nsIObjectOutputStream* aStream)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 nsCSPContext_h___
#define nsCSPContext_h___
#include "nsCSPUtils.h"
#include "nsIChannel.h"
#include "nsIContentSecurityPolicy.h"
#include "nsISerializable.h"
#include "nsXPCOM.h"
class nsIObjectInputStream;
class nsIObjectOutputStream;
#define NS_CSPCONTEXT_CONTRACTID "@mozilla.org/cspcontext;1"
// 09d9ed1a-e5d4-4004-bfe0-27ceb923d9ac
#define NS_CSPCONTEXT_CID \
{ 0x09d9ed1a, 0xe5d4, 0x4004, \
{ 0xbf, 0xe0, 0x27, 0xce, 0xb9, 0x23, 0xd9, 0xac } }
class nsCSPContext : public nsIContentSecurityPolicy
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTSECURITYPOLICY
NS_DECL_NSISERIALIZABLE
nsCSPContext();
virtual ~nsCSPContext();
private:
nsTArray<nsCSPPolicy*> mPolicies;
nsCOMPtr<nsIURI> mSelfURI;
};
#endif /* nsCSPContext_h___ */

View File

@ -28,6 +28,7 @@ using namespace mozilla;
/* Keeps track of whether or not CSP is enabled */
bool CSPService::sCSPEnabled = true;
bool CSPService::sNewBackendEnabled = true;
#ifdef PR_LOGGING
static PRLogModuleInfo* gCspPRLog;
@ -36,6 +37,7 @@ static PRLogModuleInfo* gCspPRLog;
CSPService::CSPService()
{
Preferences::AddBoolVarCache(&sCSPEnabled, "security.csp.enable");
Preferences::AddBoolVarCache(&sNewBackendEnabled, "security.csp.newbackend.enable");
#ifdef PR_LOGGING
if (!gCspPRLog)
@ -167,10 +169,10 @@ CSPService::ShouldLoad(uint32_t aContentType,
if (csp) {
#ifdef PR_LOGGING
{
int numPolicies = 0;
uint32_t numPolicies = 0;
nsresult rv = csp->GetPolicyCount(&numPolicies);
if (NS_SUCCEEDED(rv)) {
for (int i=0; i<numPolicies; i++) {
for (uint32_t i=0; i<numPolicies; i++) {
nsAutoString policy;
csp->GetPolicy(i, policy);
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
@ -235,10 +237,10 @@ CSPService::ShouldProcess(uint32_t aContentType,
if (csp) {
#ifdef PR_LOGGING
{
int numPolicies = 0;
uint32_t numPolicies = 0;
nsresult rv = csp->GetPolicyCount(&numPolicies);
if (NS_SUCCEEDED(rv)) {
for (int i=0; i<numPolicies; i++) {
for (uint32_t i=0; i<numPolicies; i++) {
nsAutoString policy;
csp->GetPolicy(i, policy);
PR_LOG(gCspPRLog, PR_LOG_DEBUG,

View File

@ -3,6 +3,9 @@
* 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 nsCSPService_h___
#define nsCSPService_h___
#include "nsXPCOM.h"
#include "nsIContentPolicy.h"
#include "nsIChannel.h"
@ -23,7 +26,9 @@ public:
CSPService();
virtual ~CSPService();
static bool sCSPEnabled;
static bool sNewBackendEnabled;
private:
// Maps origins to app status.
nsDataHashtable<nsCStringHashKey, uint16_t> mAppStatusCache;
};
#endif /* nsCSPService_h___ */

View File

@ -2802,8 +2802,26 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
}
// create new CSP object
csp = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv);
// Create new CSP object - if we're using the new CSP implementation and backend,
// use the new contract ID (same interface, but use C++ implementation).
if (CSPService::sNewBackendEnabled) {
if (oldHeaderIsPresent && !newHeaderIsPresent) {
// New CSP implementation doesn't support old header! ABORT CSP INIT!
// (Not a problem if newHeaderIsPresent because the old header will be
// ignored). This check will get removed when x- header support is
// removed (see bug 949533)
#ifdef PR_LOGGING
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("%s %s %s",
"This document has an old, x-content-security-policy",
"header and the new CSP implementation doesn't support the non-standard",
"CSP. Skipping CSP initialization."));
#endif
return NS_OK;
}
csp = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
} else {
csp = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv);
}
if (NS_FAILED(rv)) {
#ifdef PR_LOGGING

View File

@ -215,6 +215,7 @@ static void Shutdown();
#include "mozilla/dom/GamepadService.h"
#endif
#include "nsCSPService.h"
#include "nsCSPContext.h"
#include "nsISmsService.h"
#include "nsIMmsService.h"
#include "nsIMobileMessageService.h"
@ -588,6 +589,7 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AudioChannelService, AudioChannelServic
NS_GENERIC_FACTORY_CONSTRUCTOR(FakeSpeechRecognitionService)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCSPContext)
NS_GENERIC_FACTORY_CONSTRUCTOR(CSPService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMixedContentBlocker)
@ -732,6 +734,7 @@ NS_DEFINE_NAMED_CID(NS_GEOLOCATION_CID);
NS_DEFINE_NAMED_CID(NS_AUDIOCHANNEL_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_FOCUSMANAGER_CID);
NS_DEFINE_NAMED_CID(CSPSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_CSPCONTEXT_CID);
NS_DEFINE_NAMED_CID(NS_MIXEDCONTENTBLOCKER_CID);
NS_DEFINE_NAMED_CID(NS_EVENTLISTENERSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_GLOBALMESSAGEMANAGER_CID);
@ -1021,6 +1024,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_SYNTHVOICEREGISTRY_CID, true, nullptr, nsSynthVoiceRegistryConstructor },
#endif
{ &kCSPSERVICE_CID, false, nullptr, CSPServiceConstructor },
{ &kNS_CSPCONTEXT_CID, false, nullptr, nsCSPContextConstructor },
{ &kNS_MIXEDCONTENTBLOCKER_CID, false, nullptr, nsMixedContentBlockerConstructor },
{ &kNS_EVENTLISTENERSERVICE_CID, false, nullptr, CreateEventListenerService },
{ &kNS_GLOBALMESSAGEMANAGER_CID, false, nullptr, CreateGlobalMessageManager },
@ -1174,6 +1178,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ NS_SYNTHVOICEREGISTRY_CONTRACTID, &kNS_SYNTHVOICEREGISTRY_CID },
#endif
{ CSPSERVICE_CONTRACTID, &kCSPSERVICE_CID },
{ NS_CSPCONTEXT_CONTRACTID, &kNS_CSPCONTEXT_CID },
{ NS_MIXEDCONTENTBLOCKER_CONTRACTID, &kNS_MIXEDCONTENTBLOCKER_CID },
{ NS_EVENTLISTENERSERVICE_CONTRACTID, &kNS_EVENTLISTENERSERVICE_CID },
{ NS_GLOBALMESSAGEMANAGER_CONTRACTID, &kNS_GLOBALMESSAGEMANAGER_CID },

View File

@ -1555,6 +1555,7 @@ pref("security.notification_enable_delay", 500);
pref("security.csp.enable", true);
pref("security.csp.debug", false);
pref("security.csp.experimentalEnabled", false);
pref("security.csp.newbackend.enable", false);
// Mixed content blocking
pref("security.mixed_content.block_active_content", false);