--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -321,17 +321,16 @@
@BINPATH@/components/PlacesProtocolHandler.js
@BINPATH@/components/nsDefaultCLH.js
@BINPATH@/components/nsContentPrefService.js
@BINPATH@/components/nsContentDispatchChooser.js
@BINPATH@/components/nsHandlerService.js
@BINPATH@/components/nsWebHandlerApp.js
@BINPATH@/components/nsBadCertHandler.js
@BINPATH@/components/nsFormAutoComplete.js
-@BINPATH@/components/contentSecurityPolicy.js
#ifdef XP_MACOSX
@BINPATH@/components/libalerts_s.dylib
#endif
#ifdef MOZ_ENABLE_DBUS
@BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
#endif
; Modules
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -42,22 +42,21 @@
#include "nsISerializable.idl"
%{C++
struct JSContext;
struct JSPrincipals;
%}
interface nsIURI;
-interface IContentSecurityPolicy;
[ptr] native JSContext(JSContext);
[ptr] native JSPrincipals(JSPrincipals);
-[scriptable, uuid(799ab95c-0038-4e0f-b705-74c21f185bb5)]
+[scriptable, uuid(b8268b9a-2403-44ed-81e3-614075c92034)]
interface nsIPrincipal : nsISerializable
{
/**
* Values of capabilities for each principal. Order is
* significant: if an operation is performed on a set
* of capabilities, the minimum is computed.
*/
const short ENABLE_DENIED = 1;
@@ -237,14 +236,9 @@ interface nsIPrincipal : nsISerializable
*/
readonly attribute AUTF8String subjectName;
/**
* The certificate associated with this principal, if any. If there isn't
* one, this will return null. Getting this attribute never throws.
*/
readonly attribute nsISupports certificate;
-
- /**
- * A Content Security Policy associated with this principal.
- */
- [noscript] attribute IContentSecurityPolicy csp;
};
--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -133,17 +133,16 @@ protected:
// Keep this is a pointer, even though it may slightly increase the
// cost of keeping a certificate, this is a good tradeoff though since
// it is very rare that we actually have a certificate.
nsAutoPtr<Certificate> mCert;
DomainPolicy* mSecurityPolicy;
- nsCOMPtr<IContentSecurityPolicy> mCSP;
nsCOMPtr<nsIURI> mCodebase;
nsCOMPtr<nsIURI> mDomain;
PRPackedBool mTrusted;
PRPackedBool mInitialized;
// If mCodebaseImmutable is true, mCodebase is non-null and immutable
PRPackedBool mCodebaseImmutable;
PRPackedBool mDomainImmutable;
};
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -247,31 +247,16 @@ nsNullPrincipal::DisableCapability(const
NS_IMETHODIMP
nsNullPrincipal::GetURI(nsIURI** aURI)
{
return NS_EnsureSafeToReturn(mURI, aURI);
}
NS_IMETHODIMP
-nsNullPrincipal::GetCsp(IContentSecurityPolicy** aCsp)
-{
- // CSP on a null principal makes no sense
- *aCsp = nsnull;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsNullPrincipal::SetCsp(IContentSecurityPolicy* aCsp)
-{
- // CSP on a null principal makes no sense
- return NS_ERROR_NOT_AVAILABLE;
-}
-
-NS_IMETHODIMP
nsNullPrincipal::GetDomain(nsIURI** aDomain)
{
return NS_EnsureSafeToReturn(mURI, aDomain);
}
NS_IMETHODIMP
nsNullPrincipal::SetDomain(nsIURI* aDomain)
{
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -52,17 +52,16 @@
#include "nsVoidArray.h"
#include "nsHashtable.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsIPrefBranch2.h"
#include "nsIPrefService.h"
#include "nsIClassInfoImpl.h"
#include "nsDOMError.h"
-#include "IContentSecurityPolicy.h"
#include "nsPrincipal.h"
class nsCodeBasePrefObserver : nsIObserver
{
public:
nsCodeBasePrefObserver()
{
@@ -771,35 +770,16 @@ nsPrincipal::GetCertificate(nsISupports*
}
else {
*aCertificate = nsnull;
}
return NS_OK;
}
NS_IMETHODIMP
-nsPrincipal::GetCsp(IContentSecurityPolicy** aCsp)
-{
- NS_IF_ADDREF(*aCsp = mCSP);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPrincipal::SetCsp(IContentSecurityPolicy* aCsp)
-{
- // If CSP was already set, it should not be destroyed! Instead, it should
- // get set anew when a new principal is created.
- if (mCSP)
- return NS_ERROR_ALREADY_INITIALIZED;
-
- mCSP = aCsp;
- return NS_OK;
-}
-
-NS_IMETHODIMP
nsPrincipal::GetHashValue(PRUint32* aValue)
{
NS_PRECONDITION(mCert || mCodebase, "Need a cert or codebase");
// If there is a certificate, it takes precendence over the codebase.
if (mCert) {
*aValue = nsCRT::HashCode(mCert->fingerprint.get());
}
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -219,30 +219,16 @@ nsSystemPrincipal::GetCertificate(nsISup
NS_IMETHODIMP
nsSystemPrincipal::GetHasCertificate(PRBool* aResult)
{
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
-nsSystemPrincipal::GetCsp(IContentSecurityPolicy** aCsp)
-{
- *aCsp = nsnull;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSystemPrincipal::SetCsp(IContentSecurityPolicy* aCsp)
-{
- // CSP on a null principal makes no sense
- return NS_OK;
-}
-
-NS_IMETHODIMP
nsSystemPrincipal::GetDomain(nsIURI** aDomain)
{
*aDomain = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::SetDomain(nsIURI* aDomain)
deleted file mode 100644
--- a/content/base/public/IContentSecurityPolicy.idl
+++ /dev/null
@@ -1,152 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Content Security Policy IDL definition.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation
- *
- * Contributor(s):
- * Sid Stamm <sid@mozilla.com>
- * Brandon Sterne <bsterne@mozilla.com>
- * Daniel Veditz <dveditz@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsISupports.idl"
-
-interface nsIURI;
-interface nsIHttpChannel;
-interface nsIDocShell;
-
-/**
- * IContentSecurityPolicy
- * Describes an XPCOM component used to model an enforce CSPs.
- */
-
-[scriptable, uuid(AB36A2BF-CB32-4AA6-AB41-6B4E4444A221)]
-interface IContentSecurityPolicy : nsISupports
-{
-
- /**
- * Set to true when the CSP has been read in and parsed and is ready to
- * 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;
-
- /**
- * When set to true, content load-blocking and fail-closed are disabled: CSP
- * will ONLY send reports, and not modify behavior.
- */
- attribute boolean reportOnlyMode;
-
- /**
- * A read-only string version of the policy for debugging.
- */
- readonly attribute AString policy;
-
- /**
- * Whether this policy allows in-page script.
- *
- * Calls to this may trigger violation reports when queried, so
- * this value should not be cached.
- */
- readonly attribute boolean allowsInlineScript;
-
- /**
- * whether this policy allows eval and eval-like functions
- * such as setTimeout("code string", time).
- *
- * Calls to this may trigger violation reports when queried, so
- * this value should not be cached.
- */
- readonly attribute boolean allowsEval;
-
- /**
- * Manually triggers violation report sending given a URI and reason.
- * The URI may be null, in which case "self" is sent.
- * @param blockedURI
- * the URI that violated the policy
- * @param violatedDirective
- * the directive that was violated.
- * @return
- * nothing.
- */
- void sendReports(in AString blockedURI, in AString violatedDirective);
-
- /**
- * Called after the CSP object is created to fill in the appropriate request
- * and request header information needed in case a report needs to be sent.
- */
- void scanRequestData(in nsIHttpChannel aChannel);
-
- /**
- * Updates the policy currently stored in the CSP to be "refined" or
- * tightened by the one specified in the string policyString.
- */
- void refinePolicy(in AString policyString, in nsIURI selfURI);
-
- /**
- * Verifies ancestry as permitted by the policy.
- *
- * Calls to this may trigger violation reports when queried, so
- * this value should not be cached.
- *
- * @param docShell
- * containing the protected resource
- * @return
- * true if the frame's ancestors are all permitted by policy
- */
- boolean permitsAncestry(in nsIDocShell docShell);
-
- /**
- * Delegate method called by the service when sub-elements of the protected
- * document are being loaded. Given a bit of information about the request,
- * decides whether or not the policy is satisfied.
- *
- * Calls to this may trigger violation reports when queried, so
- * this value should not be cached.
- */
- short shouldLoad(in unsigned long aContentType,
- in nsIURI aContentLocation,
- in nsIURI aRequestOrigin,
- in nsISupports aContext,
- in ACString aMimeTypeGuess,
- in nsISupports aExtra);
-
- /**
- * Delegate method called by the service when sub-elements of the protected
- * 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,
- in nsIURI aContentLocation,
- in nsIURI aRequestOrigin,
- in nsISupports aContext,
- in ACString aMimeType,
- in nsISupports aExtra);
-
-};
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -108,13 +108,12 @@ XPIDLSRCS = \
nsISyncLoadDOMService.idl \
nsIDragDropHandler.idl \
nsIScriptEventHandler.idl \
nsIScriptEventManager.idl \
nsIImageLoadingContent.idl \
nsIObjectLoadingContent.idl \
nsIFrameLoader.idl \
nsIXMLHttpRequest.idl \
- IContentSecurityPolicy.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/content/base/src/CSPUtils.jsm
+++ /dev/null
@@ -1,1295 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Content Security Policy data structures.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation
- *
- * Contributor(s):
- * Sid Stamm <sid@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/**
- * Content Security Policy Utilities
- *
- * Overview
- * This contains a set of classes and utilities for CSP. It is in this
- * separate file for testing purposes.
- */
-
-// Module stuff
-var EXPORTED_SYMBOLS = ["CSPRep", "CSPSourceList", "CSPSource",
- "CSPHost", "CSPWarning", "CSPError", "CSPdebug"];
-
-
-// these are not exported
-var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
- .getService(Components.interfaces.nsIIOService);
-
-var gETLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
- .getService(Components.interfaces.nsIEffectiveTLDService);
-
-
-function CSPWarning(aMsg) {
- // customize this to redirect output.
- aMsg = 'CSP WARN: ' + aMsg + "\n";
- dump(aMsg);
- Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Components.interfaces.nsIConsoleService)
- .logStringMessage(aMsg);
-}
-function CSPError(aMsg) {
- aMsg = 'CSP ERROR: ' + aMsg + "\n";
- dump(aMsg);
- Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Components.interfaces.nsIConsoleService)
- .logStringMessage(aMsg);
-}
-function CSPdebug(aMsg) {
- aMsg = 'CSP debug: ' + aMsg + "\n";
- dump(aMsg);
- Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Components.interfaces.nsIConsoleService)
- .logStringMessage(aMsg);
-}
-
-//:::::::::::::::::::::::: CLASSES :::::::::::::::::::::::::://
-
-/**
- * Class that represents a parsed policy structure.
- */
-function CSPRep() {
- // this gets set to true when the policy is done parsing, or when a
- // URI-borne policy has finished loading.
- this._isInitialized = false;
-
- this._allowEval = false;
- this._allowInlineScripts = false;
-
- // don't auto-populate _directives, so it is easier to find bugs
- this._directives = {};
-}
-
-CSPRep.SRC_DIRECTIVES = {
- ALLOW: "allow",
- SCRIPT_SRC: "script-src",
- STYLE_SRC: "style-src",
- MEDIA_SRC: "media-src",
- IMG_SRC: "img-src",
- OBJECT_SRC: "object-src",
- FRAME_SRC: "frame-src",
- FRAME_ANCESTORS: "frame-ancestors",
- FONT_SRC: "font-src",
- XHR_SRC: "xhr-src"
-};
-
-CSPRep.URI_DIRECTIVES = {
- REPORT_URI: "report-uri", /* list of URIs */
- POLICY_URI: "policy-uri" /* single URI */
-};
-
-CSPRep.OPTIONS_DIRECTIVE = "options";
-
-/**
- * Factory to create a new CSPRep, parsed from a string.
- *
- * @param aStr
- * string rep of a CSP
- * @param self (optional)
- * string or CSPSource representing the "self" source
- * @returns
- * an instance of CSPRep
- */
-CSPRep.fromString = function(aStr, self) {
- var SD = CSPRep.SRC_DIRECTIVES;
- var UD = CSPRep.URI_DIRECTIVES;
- var aCSPR = new CSPRep();
- aCSPR._originalText = aStr;
-
- var dirs = aStr.split(";");
-
- directive:
- for each(var dir in dirs) {
- dir = dir.trim();
- var dirname = dir.split(/\s+/)[0];
- var dirvalue = dir.substring(dirname.length).trim();
-
- // OPTIONS DIRECTIVE ////////////////////////////////////////////////
- if (dirname === CSPRep.OPTIONS_DIRECTIVE) {
- // grab value tokens and interpret them
- var options = dirvalue.split(/\s+/);
- for each (var opt in options) {
- if (opt === "inline-script")
- aCSPR._allowInlineScripts = true;
- else if (opt === "eval-script")
- aCSPR._allowEval = true;
- else
- CSPWarning("don't understand option '" + opt + "'. Ignoring it.");
- }
- continue directive;
- }
-
- // SOURCE DIRECTIVES ////////////////////////////////////////////////
- for each(var sdi in SD) {
- if (dirname === sdi) {
- // process dirs, and enforce that 'self' is defined.
- var dv = CSPSourceList.fromString(dirvalue, self, true);
- if (dv) {
- aCSPR._directives[sdi] = dv;
- continue directive;
- }
- }
- }
-
- // REPORT URI ///////////////////////////////////////////////////////
- if (dirname === UD.REPORT_URI) {
- // might be space-separated list of URIs
- var uriStrings = dirvalue.split(/\s+/);
- var okUriStrings = [];
- var selfUri = self ? gIoService.newURI(self.toString(),null,null) : null;
-
- // Verify that each report URI is in the same etld + 1
- // if "self" is defined, and just that it's valid otherwise.
- for (let i in uriStrings) {
- try {
- var uri = gIoService.newURI(uriStrings[i],null,null);
- if (self) {
- if (gETLDService.getBaseDomain(uri) ===
- gETLDService.getBaseDomain(selfUri)) {
- okUriStrings.push(uriStrings[i]);
- } else {
- CSPWarning("can't use report URI from non-matching eTLD+1: "
- + gETLDService.getBaseDomain(uri));
- }
- }
- } catch(e) {
- CSPWarning("couldn't parse report URI: " + dirvalue);
- }
- }
- aCSPR._directives[UD.REPORT_URI] = okUriStrings.join(' ');
- continue directive;
- }
-
- // POLICY URI //////////////////////////////////////////////////////////
- if (dirname === UD.POLICY_URI) {
- // POLICY_URI can only be alone
- if (aCSPR._directives.length > 0 || dirs.length > 1) {
- CSPError("policy-uri directive can only appear alone");
- return CSPRep.fromString("allow 'none'");
- }
-
- var uri = '';
- try {
- uri = gIoService.newURI(dirvalue, null, null);
- } catch(e) {
- CSPError("could not parse URI in policy URI: " + dirvalue);
- return CSPRep.fromString("allow 'none'");
- }
-
- // Verify that policy URI comes from the same origin
- if (self) {
- var selfUri = gIoService.newURI(self.toString(), null, null);
- if (selfUri.host !== uri.host){
- CSPError("can't fetch policy uri from non-matching hostname: " + uri.host);
- return CSPRep.fromString("allow 'none'");
- }
- if (selfUri.port !== uri.port){
- CSPError("can't fetch policy uri from non-matching port: " + uri.port);
- return CSPRep.fromString("allow 'none'");
- }
- if (selfUri.scheme !== uri.scheme){
- CSPError("can't fetch policy uri from non-matching scheme: " + uri.scheme);
- return CSPRep.fromString("allow 'none'");
- }
- }
-
- var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
- .createInstance(Components.interfaces.nsIXMLHttpRequest);
-
- // insert error hook
- req.onerror = CSPError;
-
- // synchronous -- otherwise we need to architect a callback into the
- // xpcom component so that whomever creates the policy object gets
- // notified when it's loaded and ready to go.
- req.open("GET", dirvalue, false);
-
- // make request anonymous
- // This prevents sending cookies with the request, in case the policy URI
- // is injected, it can't be abused for CSRF.
- req.channel.loadFlags |= Components.interfaces.nsIChannel.LOAD_ANONYMOUS;
-
- req.send(null);
- if (req.status == 200) {
- aCSPR = CSPRep.fromString(req.responseText, self);
- // remember where we got the policy
- aCSPR._directives[UD.POLICY_URI] = dirvalue;
- return aCSPR;
- }
- CSPError("Error fetching policy URI: server response was " + req.status);
- return CSPRep.fromString("allow 'none'");
- }
-
- // UNIDENTIFIED DIRECTIVE /////////////////////////////////////////////
- CSPWarning("Couldn't process unknown directive '" + dirname + "'");
-
- } // end directive: loop
-
- aCSPR.makeExplicit();
- return aCSPR;
-};
-
-CSPRep.prototype = {
- /**
- * Returns a space-separated list of all report uris defined, or 'none' if there are none.
- */
- getReportURIs:
- function() {
- if (!this._directives[CSPRep.URI_DIRECTIVES.REPORT_URI])
- return "";
- return this._directives[CSPRep.URI_DIRECTIVES.REPORT_URI];
- },
-
- /**
- * Compares this CSPRep instance to another.
- */
- equals:
- function(that) {
- if (this._directives.length != that._directives.length) {
- return false;
- }
- for (var i in this._directives) {
- if (!that._directives[i] || !this._directives[i].equals(that._directives[i])) {
- return false;
- }
- }
- return (this.allowsInlineScripts === that.allowsInlineScripts)
- && (this.allowsEvalInScripts === that.allowsEvalInScripts);
- },
-
- /**
- * Generates string representation of the policy. Should be fairly similar
- * to the original.
- */
- toString:
- function csp_toString() {
- var dirs = [];
-
- if (this._allowEval || this._allowInlineScripts) {
- dirs.push("options " + (this._allowEval ? "eval-script" : "")
- + (this._allowInlineScripts ? "inline-script" : ""));
- }
- for (var i in this._directives) {
- if (this._directives[i]) {
- dirs.push(i + " " + this._directives[i].toString());
- }
- }
- return dirs.join("; ");
- },
-
- /**
- * Determines if this policy accepts a URI.
- * @param aContext
- * one of the SRC_DIRECTIVES defined above
- * @returns
- * true if the policy permits the URI in given context.
- */
- permits:
- function csp_permits(aURI, aContext) {
- if (!aURI) return false;
-
- // GLOBALLY ALLOW "about:" SCHEME
- if (aURI instanceof String && aURI.substring(0,6) === "about:")
- return true;
- if (aURI instanceof Components.interfaces.nsIURI && aURI.scheme === "about")
- return true;
-
- // make sure the context is valid
- for (var i in CSPRep.SRC_DIRECTIVES) {
- if (CSPRep.SRC_DIRECTIVES[i] === aContext) {
- return this._directives[aContext].permits(aURI);
- }
- }
- return false;
- },
-
- /**
- * Intersects with another CSPRep, deciding the subset policy
- * that should be enforced, and returning a new instance.
- * @param aCSPRep
- * a CSPRep instance to use as "other" CSP
- * @returns
- * a new CSPRep instance of the intersection
- */
- intersectWith:
- function cspsd_intersectWith(aCSPRep) {
- var newRep = new CSPRep();
-
- for (var dir in CSPRep.SRC_DIRECTIVES) {
- var dirv = CSPRep.SRC_DIRECTIVES[dir];
- newRep._directives[dirv] = this._directives[dirv]
- .intersectWith(aCSPRep._directives[dirv]);
- }
-
- // REPORT_URI
- var reportURIDir = CSPRep.URI_DIRECTIVES.REPORT_URI;
- if (this._directives[reportURIDir] && aCSPRep._directives[reportURIDir]) {
- newRep._directives[reportURIDir] =
- this._directives[reportURIDir].concat(aCSPRep._directives[reportURIDir]);
- }
- else if (this._directives[reportURIDir]) {
- // blank concat makes a copy of the string.
- newRep._directives[reportURIDir] = this._directives[reportURIDir].concat();
- }
- else if (aCSPRep._directives[reportURIDir]) {
- // blank concat makes a copy of the string.
- newRep._directives[reportURIDir] = aCSPRep._directives[reportURIDir].concat();
- }
-
- for (var dir in CSPRep.SRC_DIRECTIVES) {
- var dirv = CSPRep.SRC_DIRECTIVES[dir];
- newRep._directives[dirv] = this._directives[dirv]
- .intersectWith(aCSPRep._directives[dirv]);
- }
-
- newRep._allowEval = this.allowsEvalInScripts
- && aCSPRep.allowsEvalInScripts;
-
- newRep._allowInlineScripts = this.allowsInlineScripts
- && aCSPRep.allowsInlineScripts;
-
- return newRep;
- },
-
- /**
- * Copies default source list to each unspecified directive.
- * @returns
- * true if the makeExplicit succeeds
- * false if it fails (for some weird reason)
- */
- makeExplicit:
- function cspsd_makeExplicit() {
- var SD = CSPRep.SRC_DIRECTIVES;
- var allowDir = this._directives[SD.ALLOW];
- if (!allowDir) {
- return false;
- }
-
- for (var dir in SD) {
- var dirv = SD[dir];
- if (dirv === SD.ALLOW) continue;
- if (!this._directives[dirv]) {
- // implicit directive, make explicit
- this._directives[dirv] = allowDir.clone();
- this._directives[dirv]._isImplicit = true;
- }
- }
- this._isInitialized = true;
- return true;
- },
-
- /**
- * Returns true if "eval" is enabled through the "eval" keyword.
- */
- get allowsEvalInScripts () {
- return this._allowEval;
- },
-
- /**
- * Returns true if inline scripts are enabled through the "inline"
- * keyword.
- */
- get allowsInlineScripts () {
- return this._allowInlineScripts;
- },
-};
-
-//////////////////////////////////////////////////////////////////////
-/**
- * Class to represent a list of sources
- */
-function CSPSourceList() {
- this._sources = [];
- this._permitAllSources = false;
-
- // Set to true when this list is created using "makeExplicit()"
- // It's useful to know this when reporting the directive that was violated.
- this._isImplicit = false;
-}
-
-/**
- * Factory to create a new CSPSourceList, parsed from a string.
- *
- * @param aStr
- * string rep of a CSP Source List
- * @param self (optional)
- * string or CSPSource representing the "self" source
- * @param enforceSelfChecks (optional)
- * if present, and "true", will check to be sure "self" has the
- * appropriate values to inherit when they are omitted from the source.
- * @returns
- * an instance of CSPSourceList
- */
-CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
- // Source list is:
- // <host-dir-value> ::= <source-list>
- // | "'none'"
- // <source-list> ::= <source>
- // | <source-list>" "<source>
-
- var slObj = new CSPSourceList();
- if (aStr === "'none'")
- return slObj;
-
- if (aStr === "*") {
- slObj._permitAllSources = true;
- return slObj;
- }
-
- var tokens = aStr.split(/\s+/);
- for (var i in tokens) {
- if (tokens[i] === "") continue;
- var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
- if (!src) {
- CSPWarning("Failed to parse unrecoginzied source " + tokens[i]);
- continue;
- }
- slObj._sources.push(src);
- }
-
- return slObj;
-};
-
-CSPSourceList.prototype = {
- /**
- * Compares one CSPSourceList to another.
- *
- * @param that
- * another CSPSourceList
- * @returns
- * true if they have the same data
- */
- equals:
- function(that) {
- if (that._sources.length != this._sources.length) {
- return false;
- }
- // sort both arrays and compare like a zipper
- // XXX (sid): I think we can make this more efficient
- var sortfn = function(a,b) {
- return a.toString() > b.toString();
- };
- var a_sorted = this._sources.sort(sortfn);
- var b_sorted = that._sources.sort(sortfn);
- for (var i in a_sorted) {
- if (!a_sorted[i].equals(b_sorted[i])) {
- return false;
- }
- }
- return true;
- },
-
- /**
- * Generates string representation of the Source List.
- * Should be fairly similar to the original.
- */
- toString:
- function() {
- if (this.isNone()) {
- return "'none'";
- }
- if (this._permitAllSources) {
- return "*";
- }
- return this._sources.map(function(x) { return x.toString(); }).join(" ");
- },
-
- /**
- * Returns whether or not this source list represents the "'none'" special
- * case.
- */
- isNone:
- function() {
- return (!this._permitAllSources) && (this._sources.length < 1);
- },
-
- /**
- * Returns whether or not this source list permits all sources (*).
- */
- isAll:
- function() {
- return this._permitAllSources;
- },
-
- /**
- * Makes a new instance that resembles this object.
- * @returns
- * a new CSPSourceList
- */
- clone:
- function() {
- var aSL = new CSPSourceList();
- aSL._permitAllSources = this._permitAllSources;
- for (var i in this._sources) {
- aSL._sources[i] = this._sources[i].clone();
- }
- return aSL;
- },
-
- /**
- * Determines if this directive accepts a URI.
- * @param aURI
- * the URI in question
- * @returns
- * true if the URI matches a source in this source list.
- */
- permits:
- function cspsd_permits(aURI) {
- if (this.isNone()) return false;
- if (this.isAll()) return true;
-
- for (var i in this._sources) {
- if (this._sources[i].permits(aURI)) {
- return true;
- }
- }
- return false;
- },
-
- /**
- * Intersects with another CSPSourceList, deciding the subset directive
- * that should be enforced, and returning a new instance.
- * @param that
- * the other CSPSourceList to intersect "this" with
- * @returns
- * a new instance of a CSPSourceList representing the intersection
- */
- intersectWith:
- function cspsd_intersectWith(that) {
-
- var newCSPSrcList = null;
-
- if (this.isNone() || that.isNone())
- newCSPSrcList = CSPSourceList.fromString("'none'");
-
- if (this.isAll()) newCSPSrcList = that.clone();
- if (that.isAll()) newCSPSrcList = this.clone();
-
- if (!newCSPSrcList) {
- // the shortcuts didn't apply, must do intersection the hard way.
- // -- find only common sources
-
- // XXX (sid): we should figure out a better algorithm for this.
- // This is horribly inefficient.
- var isrcs = [];
- for (var i in this._sources) {
- for (var j in that._sources) {
- var s = that._sources[j].intersectWith(this._sources[i]);
- if (s) {
- isrcs.push(s);
- }
- }
- }
- // Next, remove duplicates
- dup: for (var i = 0; i < isrcs.length; i++) {
- for (var j = 0; j < i; j++) {
- if (isrcs[i].equals(isrcs[j])) {
- isrcs.splice(i, 1);
- i--;
- continue dup;
- }
- }
- }
- newCSPSrcList = new CSPSourceList();
- newCSPSrcList._sources = isrcs;
- }
-
- // if either was explicit, so is this.
- newCSPSrcList._isImplicit = this._isImplicit && that._isImplicit;
-
- return newCSPSrcList;
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-/**
- * Class to model a source (scheme, host, port)
- */
-function CSPSource() {
- this._scheme = undefined;
- this._port = undefined;
- this._host = undefined;
-
- // when set to true, this source represents 'self'
- this._isSelf = false;
-}
-
-/**
- * General factory method to create a new source from one of the following
- * types:
- * - nsURI
- * - string
- * - CSPSource (clone)
- */
-CSPSource.create = function(aData, self, enforceSelfChecks) {
- if (typeof aData === 'string')
- return CSPSource.fromString(aData, self, enforceSelfChecks);
-
- if (aData instanceof Components.interfaces.nsIURI)
- return CSPSource.fromURI(aData, self, enforceSelfChecks);
-
- if (aData instanceof CSPSource) {
- var ns = aData.clone();
- ns._self = CSPSource.create(self);
- return ns;
- }
-
- return null;
-}
-
-/**
- * Factory to create a new CSPSource, from a nsIURI.
- *
- * Don't use this if you want to wildcard ports!
- *
- * @param aURI
- * nsIURI rep of a URI
- * @param self (optional)
- * string or CSPSource representing the "self" source
- * @param enforceSelfChecks (optional)
- * if present, and "true", will check to be sure "self" has the
- * appropriate values to inherit when they are omitted from aURI.
- * @returns
- * an instance of CSPSource
- */
-CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
- if (!(aURI instanceof Components.interfaces.nsIURI)){
- CSPError("Provided argument is not an nsIURI");
- return null;
- }
-
- if (!self && enforceSelfChecks) {
- CSPError("Can't use 'self' if self data is not provided");
- return null;
- }
-
- if (self && !(self instanceof CSPSource)) {
- self = CSPSource.create(self, undefined, false);
- }
-
- var sObj = new CSPSource();
- sObj._self = self;
-
- // PARSE
- // If 'self' is undefined, then use default port for scheme if there is one.
-
- // grab scheme (if there is one)
- try {
- sObj._scheme = aURI.scheme;
- } catch(e) {
- sObj._scheme = undefined;
- CSPError("can't parse a URI without a scheme: " + aURI.asciiSpec);
- return null;
- }
-
- // grab host (if there is one)
- try {
- // if there's no host, an exception will get thrown
- // (NS_ERROR_FAILURE)
- sObj._host = CSPHost.fromString(aURI.host);
- } catch(e) {
- sObj._host = undefined;
- }
-
- // grab port (if there is one)
- // creating a source from an nsURI is limited in that one cannot specify "*"
- // for port. In fact, there's no way to represent "*" differently than
- // a blank port in an nsURI, since "*" turns into -1, and so does an
- // absence of port declaration.
- try {
- // if there's no port, an exception will get thrown
- // (NS_ERROR_FAILURE)
- if (aURI.port > 0) {
- sObj._port = aURI.port;
- } else {
- // port is never inherited from self -- this gets too confusing.
- // Instead, whatever scheme is used (an explicit one or the inherited
- // one) dictates the port if no port is explicitly stated.
- if (sObj._scheme) {
- sObj._port = gIoService.getProtocolHandler(sObj._scheme).defaultPort;
- if (sObj._port < 1)
- sObj._port = undefined;
- }
- }
- } catch(e) {
- sObj._port = undefined;
- }
-
- return sObj;
-};
-
-/**
- * Factory to create a new CSPSource, parsed from a string.
- *
- * @param aStr
- * string rep of a CSP Source
- * @param self (optional)
- * string or CSPSource representing the "self" source
- * @param enforceSelfChecks (optional)
- * if present, and "true", will check to be sure "self" has the
- * appropriate values to inherit when they are omitted from aURI.
- * @returns
- * an instance of CSPSource
- */
-CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
- if (!aStr)
- return null;
-
- if (!(typeof aStr === 'string')) {
- CSPError("Provided argument is not a string");
- return null;
- }
-
- if (!self && enforceSelfChecks) {
- CSPError("Can't use 'self' if self data is not provided");
- return null;
- }
-
- if (self && !(self instanceof CSPSource)) {
- self = CSPSource.create(self, undefined, false);
- }
-
- var sObj = new CSPSource();
- sObj._self = self;
-
- // take care of 'self' keyword
- if (aStr === "'self'") {
- if (!self) {
- CSPError("self keyword used, but no self data specified");
- return null;
- }
- sObj._isSelf = true;
- sObj._self = self.clone();
- return sObj;
- }
-
- // We could just create a URI and then send this off to fromURI, but
- // there's no way to leave out the scheme or wildcard the port in an nsURI.
- // That has to be supported here.
-
- // split it up
- var chunks = aStr.split(":");
-
- // If there is only one chunk, it's gotta be a host.
- if (chunks.length == 1) {
- sObj._host = CSPHost.fromString(chunks[0]);
- if (!sObj._host) {
- CSPError("Couldn't parse invalid source " + aStr);
- return null;
- }
-
- // enforce 'self' inheritance
- if (enforceSelfChecks) {
- // note: the non _scheme accessor checks sObj._self
- if (!sObj.scheme || !sObj.port) {
- CSPError("Can't create host-only source " + aStr + " without 'self' data");
- return null;
- }
- }
- return sObj;
- }
-
- // If there are two chunks, it's either scheme://host or host:port
- // ... but scheme://host can have an empty host.
- // ... and host:port can have an empty host
- if (chunks.length == 2) {
-
- // is the last bit a port?
- if (chunks[1] === "*" || chunks[1].match(/^\d+$/)) {
- sObj._port = chunks[1];
- // then the previous chunk *must* be a host or empty.
- if (chunks[0] !== "") {
- sObj._host = CSPHost.fromString(chunks[0]);
- if (!sObj._host) {
- CSPError("Couldn't parse invalid source " + aStr);
- return null;
- }
- }
- // enforce 'self' inheritance
- // (scheme:host requires port, host:port does too. Wildcard support is
- // only available if the scheme and host are wildcarded)
- if (enforceSelfChecks) {
- // note: the non _scheme accessor checks sObj._self
- if (!sObj.scheme || !sObj.host || !sObj.port) {
- CSPError("Can't create source " + aStr + " without 'self' data");
- return null;
- }
- }
- }
- // is the first bit a scheme?
- else if (CSPSource.validSchemeName(chunks[0])) {
- sObj._scheme = chunks[0];
- // then the second bit *must* be a host or empty
- if (chunks[1] === "") {
- // Allow scheme-only sources! These default to wildcard host/port,
- // especially since host and port don't always matter.
- // Example: "javascript:" and "data:"
- if (!sObj._host) sObj._host = "*";
- if (!sObj._port) sObj._port = "*";
- } else {
- // some host was defined.
- // ... remove <= 3 leading slashes (from the scheme) and parse
- var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
- // ... and parse
- sObj._host = CSPHost.fromString(cleanHost);
- if (!sObj._host) {
- CSPError("Couldn't parse invalid host " + cleanHost);
- return null;
- }
- }
-
- // enforce 'self' inheritance (scheme-only should be scheme:*:* now, and
- // if there was a host provided it should be scheme:host:selfport
- if (enforceSelfChecks) {
- // note: the non _scheme accessor checks sObj._self
- if (!sObj.scheme || !sObj.host || !sObj.port) {
- CSPError("Can't create source " + aStr + " without 'self' data");
- return null;
- }
- }
- }
- else {
- // AAAH! Don't know what to do! No valid scheme or port!
- CSPError("Couldn't parse invalid source " + aStr);
- return null;
- }
-
- return sObj;
- }
-
- // If there are three chunks, we got 'em all!
- if (!CSPSource.validSchemeName(chunks[0])) {
- CSPError("Couldn't parse scheme in " + aStr);
- return null;
- }
- sObj._scheme = chunks[0];
- if (!(chunks[2] === "*" || chunks[2].match(/^\d+$/))) {
- CSPError("Couldn't parse port in " + aStr);
- return null;
- }
-
- sObj._port = chunks[2];
-
- // ... remove <= 3 leading slashes (from the scheme) and parse
- var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
- sObj._host = CSPHost.fromString(cleanHost);
-
- return sObj._host ? sObj : null;
-};
-
-CSPSource.validSchemeName = function(aStr) {
- // <scheme-name> ::= <alpha><scheme-suffix>
- // <scheme-suffix> ::= <scheme-chr>
- // | <scheme-suffix><scheme-chr>
- // <scheme-chr> ::= <letter> | <digit> | "+" | "." | "-"
-
- return aStr.match(/^[a-zA-Z][a-zA-Z0-9+.-]*$/);
-};
-
-CSPSource.prototype = {
-
- get scheme () {
- if (!this._scheme && this._self)
- return this._self.scheme;
- return this._scheme;
- },
-
- get host () {
- if (!this._host && this._self)
- return this._self.host;
- return this._host;
- },
-
- /**
- * If 'self' has port hard-defined, and this doesn't have a port
- * hard-defined, use the self's port. Otherwise, if both are implicit,
- * resolve default port for this scheme.
- */
- get port () {
- if (this._port) return this._port;
- // if no port, get the default port for the scheme.
- if (this._scheme) {
- try {
- var port = gIoService.getProtocolHandler(this._scheme).defaultPort;
- if (port > 0) return port;
- } catch(e) {
- // if any errors happen, fail gracefully.
- }
- }
- // if there was no scheme (and thus no default scheme), return self.port
- if (this._self && this._self.port) return this._self.port;
-
- return undefined;
- },
-
- /**
- * Generates string representation of the Source.
- * Should be fairly similar to the original.
- */
- toString:
- function() {
- if (this._isSelf)
- return this._self.toString();
-
- var s = "";
- if (this._scheme)
- s = s + this._scheme + "://";
- if (this._host)
- s = s + this._host;
- if (this._port)
- s = s + ":" + this._port;
- return s;
- },
-
- /**
- * Makes a new instance that resembles this object.
- * @returns
- * a new CSPSource
- */
- clone:
- function() {
- var aClone = new CSPSource();
- aClone._self = this._self ? this._self.clone() : undefined;
- aClone._scheme = this._scheme;
- aClone._port = this._port;
- aClone._host = this._host ? this._host.clone() : undefined;
- aClone._isSelf = this._isSelf;
- return aClone;
- },
-
- /**
- * Determines if this Source accepts a URI.
- * @param aSource
- * the URI, or CSPSource in question
- * @returns
- * true if the URI matches a source in this source list.
- */
- permits:
- function(aSource) {
- if (!aSource) return false;
-
- if (!(aSource instanceof CSPSource))
- return this.permits(CSPSource.create(aSource));
-
- // verify scheme
- if (this.scheme != aSource.scheme)
- return false;
-
- // port is defined in 'this' (undefined means it may not be relevant
- // to the scheme) AND this port (implicit or explicit) matches
- // aSource's port
- if (this.port && this.port !== "*" && this.port != aSource.port)
- return false;
-
- // host is defined in 'this' (undefined means it may not be relevant
- // to the scheme) AND this host (implicit or explicit) permits
- // aSource's host.
- if (this.host && !this.host.permits(aSource.host))
- return false;
-
- // all scheme, host and port matched!
- return true;
- },
-
- /**
- * Determines the intersection of two sources.
- * Returns a null object if intersection generates no
- * hosts that satisfy it.
- * @param that
- * the other CSPSource to intersect "this" with
- * @returns
- * a new instance of a CSPSource representing the intersection
- */
- intersectWith:
- function(that) {
- var newSource = new CSPSource();
-
- // 'self' is not part of the intersection. Intersect the raw values from
- // the source, self must be set by someone creating this source.
- // When intersecting, we take the more specific of the two: if one scheme,
- // host or port is undefined, the other is taken. (This is contrary to
- // when "permits" is called -- there, the value of 'self' is looked at
- // when a scheme, host or port is undefined.)
-
- // port
- if (!this._port)
- newSource._port = that._port;
- else if (!that._port)
- newSource._port = this._port;
- else if (this._port === "*")
- newSource._port = that._port;
- else if (that._port === "*")
- newSource._port = this._port;
- else if (that._port === this._port)
- newSource._port = this._port;
- else {
- CSPError("Could not intersect " + this + " with " + that
- + " due to port problems.");
- return null;
- }
-
- // scheme
- if (!this._scheme)
- newSource._scheme = that._scheme;
- else if (!that._scheme)
- newSource._scheme = this._scheme;
- if (this._scheme === "*")
- newSource._scheme = that._scheme;
- else if (that._scheme === "*")
- newSource._scheme = this._scheme;
- else if (that._scheme === this._scheme)
- newSource._scheme = this._scheme;
- else {
- CSPError("Could not intersect " + this + " with " + that
- + " due to scheme problems.");
- return null;
- }
-
- // host
- if (!this._host)
- newSource._host = that._host;
- else if (!that._host)
- newSource._host = this._host;
- else // both this and that have hosts
- newSource._host = this._host.intersectWith(that._host);
-
- return newSource;
- },
-
- /**
- * Compares one CSPSource to another.
- *
- * @param that
- * another CSPSource
- * @param resolveSelf (optional)
- * if present, and 'true', implied values are obtained from 'self'
- * instead of assumed to be "anything"
- * @returns
- * true if they have the same data
- */
- equals:
- function(that, resolveSelf) {
- // 1. schemes match
- // 2. ports match
- // 3. either both hosts are undefined, or one equals the other.
- if (resolveSelf)
- return this.scheme === that.scheme
- && this.port === that.port
- && (!(this.host || that.host) ||
- (this.host && this.host.equals(that.host)));
-
- // otherwise, compare raw (non-self-resolved values)
- return this._scheme === that._scheme
- && this._port === that._port
- && (!(this._host || that._host) ||
- (this._host && this._host.equals(that._host)));
- },
-
-};
-
-//////////////////////////////////////////////////////////////////////
-/**
- * Class to model a host *.x.y.
- */
-function CSPHost() {
- this._segments = [];
-}
-
-/**
- * Factory to create a new CSPHost, parsed from a string.
- *
- * @param aStr
- * string rep of a CSP Host
- * @returns
- * an instance of CSPHost
- */
-CSPHost.fromString = function(aStr) {
- if (!aStr) return null;
-
- // host string must be LDH with dots and stars.
- var invalidChar = aStr.match(/[^a-zA-Z0-9\-\.\*]/);
- if (invalidChar) {
- CSPdebug("Invalid character '" + invalidChar + "' in host " + aStr);
- return null;
- }
-
- var hObj = new CSPHost();
- hObj._segments = aStr.split(/\./);
- if (hObj._segments.length < 1 ||
- hObj._segments.length == 1 && hObj._segments[0] != "*"
- && hObj._segments[0] != "localhost") {
- // only short hosts allowed are "*" and "localhost"
- return null;
- }
-
- // validate data in segments
- for (var i in hObj._segments) {
- var seg = hObj._segments[i];
- if (seg == "*") {
- if (i > 0) {
- // Wildcard must be FIRST
- CSPdebug("Wildcard char located at invalid position in '" + aStr + "'");
- return null;
- }
- }
- else if (seg.match(/[^a-zA-Z0-9\-]/)) {
- // Non-wildcard segment must be LDH string
- CSPdebug("Invalid segment '" + seg + "' in host value");
- return null;
- }
- }
- return hObj;
-};
-
-CSPHost.prototype = {
- /**
- * Generates string representation of the Source.
- * Should be fairly similar to the original.
- */
- toString:
- function() {
- return this._segments.join(".");
- },
-
- /**
- * Makes a new instance that resembles this object.
- * @returns
- * a new CSPHost
- */
- clone:
- function() {
- var aHost = new CSPHost();
- for (var i in this._segments) {
- aHost._segments[i] = this._segments[i];
- }
- return aHost;
- },
-
- /**
- * Returns true if this host accepts the provided host (or the other way
- * around).
- * @param aHost
- * the FQDN in question (CSPHost or String)
- * @returns
- */
- permits:
- function(aHost) {
- if (!aHost) return false;
-
- if (!(aHost instanceof CSPHost)) {
- // -- compare CSPHost to String
- return this.permits(CSPHost.fromString(aHost));
- }
- var thislen = this._segments.length;
- var thatlen = aHost._segments.length;
-
- // don't accept a less specific host:
- // \--> *.b.a doesn't accept b.a.
- if (thatlen < thislen) { return false; }
-
- // check for more specific host (and wildcard):
- // \--> *.b.a accepts d.c.b.a.
- // \--> c.b.a doesn't accept d.c.b.a.
- if ((thatlen > thislen) && this._segments[0] != "*") {
- return false;
- }
-
- // Given the wildcard condition (from above),
- // only necessary to compare elements that are present
- // in this host. Extra tokens in aHost are ok.
- // * Compare from right to left.
- for (var i=1; i <= thislen; i++) {
- if (this._segments[thislen-i] != "*" &&
- (this._segments[thislen-i] != aHost._segments[thatlen-i])) {
- return false;
- }
- }
-
- // at this point, all conditions are met, so the host is allowed
- return true;
- },
-
- /**
- * Determines the intersection of two Hosts.
- * Basically, they must be the same, or one must have a wildcard.
- * @param that
- * the other CSPHost to intersect "this" with
- * @returns
- * a new instance of a CSPHost representing the intersection
- * (or null, if they can't be intersected)
- */
- intersectWith:
- function(that) {
- if (!(this.permits(that) || that.permits(this))) {
- // host definitions cannot co-exist without a more general host
- // ... one must be a subset of the other, or intersection makes no sense.
- return null;
- }
-
- // pick the more specific one, if both are same length.
- if (this._segments.length == that._segments.length) {
- // *.a vs b.a : b.a
- return (this._segments[0] === "*") ? that.clone() : this.clone();
- }
-
- // different lengths...
- // *.b.a vs *.a : *.b.a
- // *.b.a vs d.c.b.a : d.c.b.a
- return (this._segments.length > that._segments.length) ?
- this.clone() : that.clone();
- },
-
- /**
- * Compares one CSPHost to another.
- *
- * @param that
- * another CSPHost
- * @returns
- * true if they have the same data
- */
- equals:
- function(that) {
- if (this._segments.length != that._segments.length)
- return false;
-
- for (var i=0; i<this._segments.length; i++) {
- if (this._segments[i] != that._segments[i])
- return false;
- }
- return true;
- }
-};
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -74,17 +74,16 @@ CPPSRCS = \
nsContentAreaDragDrop.cpp \
nsContentIterator.cpp \
nsContentList.cpp \
nsContentPolicy.cpp \
nsContentSink.cpp \
nsContentUtils.cpp \
nsCopySupport.cpp \
nsCrossSiteListenerProxy.cpp \
- nsCSPService.cpp \
nsDataDocumentContentPolicy.cpp \
nsDOMAttribute.cpp \
nsDOMAttributeMap.cpp \
nsDOMDocumentType.cpp \
nsDOMFile.cpp \
nsDOMFileReader.cpp \
nsDOMLists.cpp \
nsDOMParser.cpp \
@@ -137,24 +136,17 @@ CPPSRCS = \
$(NULL)
GQI_SRCS = contentbase.gqi
# we don't want the shared lib, but we want to force the creation of a
# static lib.
FORCE_STATIC_LIB = 1
-EXTRA_COMPONENTS = \
- $(srcdir)/nsBadCertHandler.js \
- contentSecurityPolicy.js \
- $(NULL)
-
-EXTRA_JS_MODULES = \
- CSPUtils.jsm \
- $(NULL)
+EXTRA_COMPONENTS = $(srcdir)/nsBadCertHandler.js
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../../events/src \
-I$(srcdir)/../../xml/content/src \
-I$(srcdir)/../../../layout/xul/base/src \
-I$(srcdir)/../../xul/content/src \
deleted file mode 100644
--- a/content/base/src/contentSecurityPolicy.js
+++ /dev/null
@@ -1,445 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the ContentSecurityPolicy module.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation
- *
- * Contributor(s):
- * Sid Stamm <sid@mozilla.com>
- * Brandon Sterne <bsterne@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-/**
- * Content Security Policy
- *
- * Overview
- * This is a stub component that will be fleshed out to do all the fancy stuff
- * that ContentSecurityPolicy has to do.
- */
-
-/* :::::::: Constants and Helpers ::::::::::::::: */
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-const CSP_VIOLATION_TOPIC = "csp-on-violate-policy";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/CSPUtils.jsm");
-
-/* ::::: Policy Parsing & Data structures :::::: */
-
-function ContentSecurityPolicy() {
- CSPdebug("CSP CREATED");
- this._isInitialized = false;
- this._reportOnlyMode = false;
- this._policy = CSPRep.fromString("allow *");
-
- // default options "wide open" since this policy will be intersected soon
- this._policy._allowInlineScripts = true;
- this._policy._allowEval = true;
-
- this._requestHeaders = [];
- this._request = "";
- CSPdebug("CSP POLICY INITED TO 'allow *'");
-
- this._observerService = Cc['@mozilla.org/observer-service;1']
- .getService(Ci.nsIObserverService);
-}
-
-/*
- * Set up mappings from nsIContentPolicy content types to CSP directives.
- */
-{
- let cp = Ci.nsIContentPolicy;
- let csp = ContentSecurityPolicy;
- let cspr_sd = CSPRep.SRC_DIRECTIVES;
-
- csp._MAPPINGS=[];
-
- /* default, catch-all case */
- csp._MAPPINGS[cp.TYPE_OTHER] = cspr_sd.ALLOW;
-
- /* self */
- csp._MAPPINGS[cp.TYPE_DOCUMENT] = null;
-
- /* shouldn't see this one */
- csp._MAPPINGS[cp.TYPE_REFRESH] = null;
-
- /* categorized content types */
- csp._MAPPINGS[cp.TYPE_SCRIPT] = cspr_sd.SCRIPT_SRC;
- csp._MAPPINGS[cp.TYPE_IMAGE] = cspr_sd.IMG_SRC;
- csp._MAPPINGS[cp.TYPE_STYLESHEET] = cspr_sd.STYLE_SRC;
- csp._MAPPINGS[cp.TYPE_OBJECT] = cspr_sd.OBJECT_SRC;
- csp._MAPPINGS[cp.TYPE_SUBDOCUMENT] = cspr_sd.FRAME_SRC;
- csp._MAPPINGS[cp.TYPE_MEDIA] = cspr_sd.MEDIA_SRC;
- csp._MAPPINGS[cp.TYPE_FONT] = cspr_sd.FONT_SRC;
- csp._MAPPINGS[cp.TYPE_XMLHTTPREQUEST] = cspr_sd.XHR_SRC;
-
-
- /* These must go through the catch-all */
- csp._MAPPINGS[cp.TYPE_XBL] = cspr_sd.ALLOW;
- csp._MAPPINGS[cp.TYPE_PING] = cspr_sd.ALLOW;
- csp._MAPPINGS[cp.TYPE_OBJECT_SUBREQUEST] = cspr_sd.ALLOW;
- csp._MAPPINGS[cp.TYPE_DTD] = cspr_sd.ALLOW;
-}
-
-ContentSecurityPolicy.prototype = {
- classDescription: "Content Security Policy Component",
- contractID: "@mozilla.org/contentsecuritypolicy;1",
- classID: Components.ID("{AB36A2BF-CB32-4AA6-AB41-6B4E4444A221}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.IContentSecurityPolicy]),
-
- // get this contractID registered for certain categories via XPCOMUtils
- _xpcom_categories: [ ],
-
- get isInitialized() {
- return this._isInitialized;
- },
-
- set isInitialized (foo) {
- this._isInitialized = foo;
- },
-
- get policy () {
- return this._policy.toString();
- },
-
- get allowsInlineScript() {
- // trigger automatic report to go out when inline scripts are disabled.
- if (!this._policy.allowsInlineScripts) {
- var violation = 'violated base restriction: Inline Scripts will not execute';
- // gotta wrap the violation string, since it's sent out to observers as
- // an nsISupports.
- let wrapper = Cc["@mozilla.org/supports-cstring;1"]
- .createInstance(Ci.nsISupportsCString);
- wrapper.data = violation;
- this._observerService.notifyObservers(
- wrapper,
- CSP_VIOLATION_TOPIC,
- 'inline script base restriction');
- this.sendReports('self', violation);
- }
- return this._reportOnlyMode || this._policy.allowsInlineScripts;
- },
-
- get allowsEval() {
- // trigger automatic report to go out when eval and friends are disabled.
- if (!this._policy.allowsEvalInScripts) {
- var violation = 'violated base restriction: Code will not be created from strings';
- // gotta wrap the violation string, since it's sent out to observers as
- // an nsISupports.
- let wrapper = Cc["@mozilla.org/supports-cstring;1"]
- .createInstance(Ci.nsISupportsCString);
- wrapper.data = violation;
- this._observerService.notifyObservers(
- wrapper,
- CSP_VIOLATION_TOPIC,
- 'eval script base restriction');
- this.sendReports('self', violation);
- }
- return this._reportOnlyMode || this._policy.allowsEvalInScripts;
- },
-
- set reportOnlyMode(val) {
- this._reportOnlyMode = val;
- },
-
- get reportOnlyMode () {
- return this._reportOnlyMode;
- },
-
- /*
- // Having a setter is a bad idea... opens up the policy to "loosening"
- // Instead, use "refinePolicy."
- set policy (aStr) {
- this._policy = CSPRep.fromString(aStr);
- },
- */
-
- /**
- * Given an nsIHttpChannel, fill out the appropriate data.
- */
- scanRequestData:
- function(aChannel) {
- // grab the request line
- var internalChannel = aChannel.QueryInterface(Ci.nsIHttpChannelInternal);
- var reqMaj = {};
- var reqMin = {};
- var reqVersion = internalChannel.getRequestVersion(reqMaj, reqMin);
- this._request = aChannel.requestMethod + " "
- + aChannel.URI.asciiSpec
- + " HTTP/" + reqMaj.value + "." + reqMin.value;
-
- // grab the request headers
- var self = this;
- aChannel.visitRequestHeaders({
- visitHeader: function(aHeader, aValue) {
- self._requestHeaders.push(aHeader + ": " + aValue);
- }});
- },
-
-/* ........ Methods .............. */
-
- /**
- * Given a new policy, intersects the currently enforced policy with the new
- * one and stores the result. The effect is a "tightening" or refinement of
- * an old policy. This is called any time a new policy is encountered and
- * the effective policy has to be refined.
- */
- refinePolicy:
- function csp_refinePolicy(aPolicy, selfURI) {
- CSPdebug("REFINE POLICY: " + aPolicy);
- CSPdebug(" SELF: " + selfURI.asciiSpec);
-
- // stay uninitialized until policy merging is done
- this._isInitialized = false;
-
- // If there is a policy-uri, fetch the policy, then re-call this function.
- // (1) parse and create a CSPRep object
- var newpolicy = CSPRep.fromString(aPolicy,
- selfURI.scheme + "://" + selfURI.hostPort);
-
- // (2) Intersect the currently installed CSPRep object with the new one
- var intersect = this._policy.intersectWith(newpolicy);
-
- // (3) Save the result
- this._policy = intersect;
- this._isInitialized = true;
- },
-
- /**
- * Generates and sends a violation report to the specified report URIs.
- */
- sendReports:
- function(blockedUri, violatedDirective) {
- var uriString = this._policy.getReportURIs();
- var uris = uriString.split(/\s+/);
- if (uris.length > 0) {
- // Generate report to send composed of:
- // <csp-report>
- // <request>GET /index.html HTTP/1.1</request>
- // <request-headers>Host: example.com
- // User-Agent: ...
- // ...
- // </request-headers>
- // <blocked-uri>...</blocked-uri>
- // <violated-directive>...</violated-directive>
- // </csp-report>
- //
- var strHeaders = "";
- for (let i in this._requestHeaders) {
- strHeaders += this._requestHeaders[i] + "\n";
- }
-
- var report = "<csp-report>\n" +
- " <request>" + this._request + "</request>\n" +
- " <request-headers><![CDATA[\n" +
- strHeaders +
- " ]]></request-headers>\n" +
- " <blocked-uri>" +
- (typeof blockedUri === "nsIURI" ? blockedUri.asciiSpec : blockedUri) +
- "</blocked-uri>\n" +
- " <violated-directive>" + violatedDirective + "</violated-directive>\n" +
- "</csp-report>\n";
-
- CSPdebug("Constructed violation report:\n" + report);
-
- // For each URI in the report list, send out a report.
- for (let i in uris) {
- if (uris[i] === "")
- continue;
-
- var failure = function(aEvt) {
- if (req.readyState == 4 && req.status != 200) {
- CSPError("Failed to send report to " + reportURI);
- }
- };
- var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
- .createInstance(Ci.nsIXMLHttpRequest);
-
- try {
- req.open("POST", uris[i], true);
- req.setRequestHeader('Content-Type', 'application/xml');
- req.upload.addEventListener("error", failure, false);
- req.upload.addEventListener("abort", failure, false);
- //req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
-
- // make request anonymous
- // This prevents sending cookies with the request,
- // in case the policy URI is injected, it can't be
- // abused for CSRF.
- req.channel.loadFlags |= Ci.nsIChannel.LOAD_ANONYMOUS;
-
- req.send(report);
- CSPdebug("Sent violation report to " + uris[i]);
- } catch(e) {
- // it's possible that the URI was invalid, just log a
- // warning and skip over that.
- CSPWarning("Tried to send report to invalid URI: \"" + uris[i] + "\"");
- }
- }
- }
- },
-
- /**
- * Exposed Method to analyze docShell for approved frame ancestry.
- * Also sends violation reports if necessary.
- * @param docShell
- * the docShell for this policy's resource.
- * @return
- * true if the frame ancestry is allowed by this policy.
- */
- permitsAncestry:
- function(docShell) {
- if (!docShell) { return false; }
- CSPdebug(" in permitsAncestry(), docShell = " + docShell);
-
- // walk up this docShell tree until we hit chrome
- var dst = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDocShellTreeItem);
-
- // collect ancestors and make sure they're allowed.
- var ancestors = [];
- while (dst.parent) {
- dst = dst.parent;
- let it = dst.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation);
- if (it.currentURI) {
- if (it.currentURI.scheme === "chrome") {
- break;
- }
- let ancestor = it.currentURI;
- CSPdebug(" found frame ancestor " + ancestor.asciiSpec);
- ancestors.push(ancestor);
- }
- }
-
- // scan the discovered ancestors
- let cspContext = CSPRep.SRC_DIRECTIVES.FRAME_ANCESTORS;
- for (let i in ancestors) {
- let ancestor = ancestors[i].prePath;
- if (!this._policy.permits(ancestor, cspContext)) {
- // report the frame-ancestor violation
- let directive = this._policy._directives[cspContext];
- let violatedPolicy = (directive._isImplicit
- ? 'allow' : 'frame-ancestors ')
- + directive.toString();
- // send an nsIURI object to the observers (more interesting than a string)
- this._observerService.notifyObservers(
- ancestors[i],
- CSP_VIOLATION_TOPIC,
- violatedPolicy);
- this.sendReports(ancestors[i].asciiSpec, violatedPolicy);
- // need to lie if we are testing in report-only mode
- return this._reportOnlyMode;
- }
- }
- return true;
- },
-
- /**
- * Delegate method called by the service when sub-elements of the protected
- * document are being loaded. Given a bit of information about the request,
- * decides whether or not the policy is satisfied.
- */
- shouldLoad:
- function csp_shouldLoad(aContentType,
- aContentLocation,
- aRequestOrigin,
- aContext,
- aMimeTypeGuess,
- aExtra) {
-
- // don't filter chrome stuff
- if (aContentLocation.scheme === 'chrome') {
- return Ci.nsIContentPolicy.ACCEPT;
- }
-
- // interpret the context, and then pass off to the decision structure
- CSPdebug("shouldLoad location = " + aContentLocation.asciiSpec);
- CSPdebug("shouldLoad content type = " + aContentType);
- var cspContext = ContentSecurityPolicy._MAPPINGS[aContentType];
- // CSPdebug("shouldLoad CSP directive =" + cspContext);
-
- // if the mapping is null, there's no policy, let it through.
- if (!cspContext) {
- return Ci.nsIContentPolicy.ACCEPT;
- }
-
- // otherwise, honor the translation
- // var source = aContentLocation.scheme + "://" + aContentLocation.hostPort;
- var res = this._policy.permits(aContentLocation, cspContext)
- ? Ci.nsIContentPolicy.ACCEPT
- : Ci.nsIContentPolicy.REJECT_SERVER;
-
- // frame-ancestors is taken care of early on (as this document is loaded)
-
- // If the result is *NOT* ACCEPT, then send report
- if (res != Ci.nsIContentPolicy.ACCEPT) {
- CSPdebug("blocking request for " + aContentLocation.asciiSpec);
- try {
- let directive = this._policy._directives[cspContext];
- let violatedPolicy = (directive._isImplicit
- ? 'allow' : cspContext)
- + ' ' + directive.toString();
- this._observerService.notifyObservers(
- aContentLocation,
- CSP_VIOLATION_TOPIC,
- violatedPolicy);
- this.sendReports(aContentLocation, violatedPolicy);
- } catch(e) {
- CSPdebug('---------------- ERROR: ' + e);
- }
- }
-
- return (this._reportOnlyMode ? Ci.nsIContentPolicy.ACCEPT : res);
- },
-
- shouldProcess:
- function csp_shouldProcess(aContentType,
- aContentLocation,
- aRequestOrigin,
- aContext,
- aMimeType,
- aExtra) {
- // frame-ancestors check is done outside the ContentPolicy
- var res = Ci.nsIContentPolicy.ACCEPT;
- CSPdebug("shouldProcess aContext=" + aContext);
- return res;
- },
-
-};
-
-
-
-function NSGetModule(aComMgr, aFileSpec)
- XPCOMUtils.generateModule([ContentSecurityPolicy]);
deleted file mode 100644
--- a/content/base/src/nsCSPService.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Brandon Sterne <bsterne@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "prlog.h"
-#include "nsString.h"
-#include "nsCOMPtr.h"
-#include "nsIURI.h"
-#include "nsIPrincipal.h"
-#include "nsIObserver.h"
-#include "nsIDocument.h"
-#include "nsIContent.h"
-#include "nsContentUtils.h"
-#include "nsCSPService.h"
-#include "IContentSecurityPolicy.h"
-
-/* Keeps track of whether or not CSP is enabled */
-static PRBool gCSPEnabled = PR_TRUE;
-
-#ifdef PR_LOGGING
-static PRLogModuleInfo* gCspPRLog;
-#endif
-
-CSPService::CSPService()
-{
- nsContentUtils::AddBoolPrefVarCache("security.csp.enable", &gCSPEnabled);
-
-#ifdef PR_LOGGING
- if (!gCspPRLog)
- gCspPRLog = PR_NewLogModule("CSP");
-#endif
-}
-
-CSPService::~CSPService()
-{
-}
-
-NS_IMPL_ISUPPORTS1(CSPService, nsIContentPolicy)
-
-/* nsIContentPolicy implementation */
-NS_IMETHODIMP
-CSPService::ShouldLoad(PRUint32 aContentType,
- nsIURI *aContentLocation,
- nsIURI *aRequestOrigin,
- nsISupports *aRequestContext,
- const nsACString &aMimeTypeGuess,
- nsISupports *aExtra,
- PRInt16 *aDecision)
-{
- if (!aContentLocation)
- return NS_ERROR_FAILURE;
-
-#ifdef PR_LOGGING
- {
- nsCAutoString location;
- aContentLocation->GetSpec(location);
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("CSPService::ShouldLoad called for %s", location.get()));
- }
-#endif
- // 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
- if (!gCSPEnabled)
- return NS_OK;
-
- // find the nsDocument that initiated this request and see if it has a
- // CSP policy object
- nsresult rv;
- nsCOMPtr<nsIDocument> doc;
- nsCOMPtr<nsIPrincipal> principal;
- nsCOMPtr<IContentSecurityPolicy> csp;
- nsCOMPtr<nsIContent> node(do_QueryInterface(aRequestContext));
- if (node) {
- doc = node->GetOwnerDoc();
- }
- if (!doc) {
- doc = do_QueryInterface(aRequestContext);
- }
-
- if (doc) {
- principal = doc->NodePrincipal();
- principal->GetCsp(getter_AddRefs(csp));
-
- if (csp) {
-#ifdef PR_LOGGING
- nsAutoString policy;
- csp->GetPolicy(policy);
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("Document has CSP: %s",
- NS_ConvertUTF16toUTF8(policy).get()));
-#endif
- // obtain the enforcement decision
- csp->ShouldLoad(aContentType,
- aContentLocation,
- aRequestOrigin,
- aRequestContext,
- aMimeTypeGuess,
- aExtra,
- aDecision);
- }
- }
-#ifdef PR_LOGGING
- else {
- nsCAutoString uriSpec;
- aContentLocation->GetSpec(uriSpec);
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("COULD NOT get nsIDocument for location: %s", uriSpec.get()));
- }
-#endif
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CSPService::ShouldProcess(PRUint32 aContentType,
- nsIURI *aContentLocation,
- nsIURI *aRequestOrigin,
- nsISupports *aRequestContext,
- const nsACString &aMimeTypeGuess,
- nsISupports *aExtra,
- PRInt16 *aDecision)
-{
- if (!aContentLocation)
- return NS_ERROR_FAILURE;
-
- // default decision is to accept the item
- *aDecision = nsIContentPolicy::ACCEPT;
-
- // No need to continue processing if CSP is disabled
- if (!gCSPEnabled)
- return NS_OK;
-
- // find the nsDocument that initiated this request and see if it has a
- // CSP policy object
- nsresult rv;
- nsCOMPtr<nsIDocument> doc;
- nsCOMPtr<nsIPrincipal> principal;
- nsCOMPtr<IContentSecurityPolicy> csp;
- nsCOMPtr<nsIContent> node(do_QueryInterface(aRequestContext));
- if (node) {
- doc = node->GetOwnerDoc();
- }
- if (!doc) {
- doc = do_QueryInterface(aRequestContext);
- }
-
- if (doc) {
- principal = doc->NodePrincipal();
- principal->GetCsp(getter_AddRefs(csp));
-
- if (csp) {
-#ifdef PR_LOGGING
- nsAutoString policy;
- csp->GetPolicy(policy);
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("shouldProcess - document has policy: %s",
- NS_ConvertUTF16toUTF8(policy).get()));
-#endif
- // obtain the enforcement decision
- csp->ShouldProcess(aContentType,
- aContentLocation,
- aRequestOrigin,
- aRequestContext,
- aMimeTypeGuess,
- aExtra,
- aDecision);
- }
- }
-#ifdef PR_LOGGING
- else {
- nsCAutoString uriSpec;
- aContentLocation->GetSpec(uriSpec);
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("COULD NOT get nsIDocument for location: %s", uriSpec.get()));
- }
-#endif
- return NS_OK;
-}
deleted file mode 100644
--- a/content/base/src/nsCSPService.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Brandon Sterne <bsterne@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsXPCOM.h"
-#include "nsIContentPolicy.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:
- NS_DECL_ISUPPORTS
- NS_DECL_NSICONTENTPOLICY
-
- CSPService();
- virtual ~CSPService();
-
-private:
- PRBool mEnabled;
-};
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -176,32 +176,25 @@ static NS_DEFINE_CID(kDOMEventGroupCID,
#include "mozAutoDocUpdate.h"
#ifdef MOZ_SMIL
#include "nsSMILAnimationController.h"
#include "imgIContainer.h"
#include "nsSVGUtils.h"
#endif // MOZ_SMIL
-// FOR CSP (autogenerated by xpidl)
-#include "IContentSecurityPolicy.h"
-
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
#define FORCE_PR_LOG 1
#endif
#include "prlog.h"
-/* Keeps track of whether or not CSP is enabled */
-static PRBool gCSPEnabled = PR_TRUE;
-
#ifdef PR_LOGGING
static PRLogModuleInfo* gDocumentLeakPRLog;
-static PRLogModuleInfo* gCspPRLog;
#endif
void
nsUint32ToContentHashEntry::Destroy()
{
HashSet* set = GetHashSet();
if (set) {
delete set;
@@ -1497,23 +1490,18 @@ nsDocument::nsDocument(const char* aCont
#ifdef PR_LOGGING
if (!gDocumentLeakPRLog)
gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
if (gDocumentLeakPRLog)
PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
("DOCUMENT %p created", this));
-
- if (!gCspPRLog)
- gCspPRLog = PR_NewLogModule("CSP");
#endif
- nsContentUtils::AddBoolPrefVarCache("security.csp.enable", &gCSPEnabled);
-
// Start out mLastStyleSheetSet as null, per spec
SetDOMStringToNull(mLastStyleSheetSet);
}
static PLDHashOperator
ClearAllBoxObjects(const void* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
{
if (aBoxObject) {
@@ -2258,121 +2246,17 @@ nsDocument::StartDocumentLoad(const char
semicolon = start;
FindCharInReadable(';', semicolon, end);
mContentType = Substring(start, semicolon);
}
RetrieveRelevantHeaders(aChannel);
mChannel = aChannel;
-
- nsresult rv = InitCSP();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-nsresult
-nsDocument::InitCSP()
-{
- if (gCSPEnabled) {
- nsAutoString cspHeaderValue;
- nsAutoString cspROHeaderValue;
-
- this->GetHeaderData(nsGkAtoms::headerCSP, cspHeaderValue);
- this->GetHeaderData(nsGkAtoms::headerCSPReportOnly, cspROHeaderValue);
-
- PRBool system = PR_FALSE;
- nsIScriptSecurityManager *ssm = nsContentUtils::GetSecurityManager();
-
- if (NS_SUCCEEDED(ssm->IsSystemPrincipal(NodePrincipal(), &system)) && system) {
- // only makes sense to register new CSP if this document is not priviliged
- return NS_OK;
- }
-
- if (cspHeaderValue.IsEmpty() && cspROHeaderValue.IsEmpty()) {
- // no CSP header present, stop processing
- return NS_OK;
- }
-
-#ifdef PR_LOGGING
- PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP header specified for document %p", this));
-#endif
-
- nsresult rv;
- nsCOMPtr<IContentSecurityPolicy> mCSP;
- mCSP = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv);
-
- if (NS_FAILED(rv)) {
-#ifdef PR_LOGGING
- PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("Failed to create CSP object: %x", rv));
-#endif
- return rv;
- }
-
- // Store the request context for violation reports
- nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
- mCSP->ScanRequestData(httpChannel);
-
- // Start parsing the policy
- nsCOMPtr<nsIURI> chanURI;
- mChannel->GetURI(getter_AddRefs(chanURI));
-
-#ifdef PR_LOGGING
- PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP Loaded"));
-#endif
-
- // ReportOnly mode is enabled *only* if there are no regular-strength CSP
- // headers present. If there are, then we ignore the ReportOnly mode and
- // toss a warning into the error console, proceeding with enforcing the
- // regular-strength CSP.
- if (cspHeaderValue.IsEmpty()) {
- mCSP->SetReportOnlyMode(true);
- mCSP->RefinePolicy(cspROHeaderValue, chanURI);
-#ifdef PR_LOGGING
- {
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("CSP (report only) refined, policy: \"%s\"",
- NS_ConvertUTF16toUTF8(cspROHeaderValue).get()));
- }
-#endif
- } else {
- //XXX(sstamm): maybe we should post a warning when both read only and regular
- // CSP headers are present.
- mCSP->RefinePolicy(cspHeaderValue, chanURI);
-#ifdef PR_LOGGING
- {
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("CSP refined, policy: \"%s\"",
- NS_ConvertUTF16toUTF8(cspHeaderValue).get()));
- }
-#endif
- }
-
- //Copy into principal
- nsIPrincipal* principal = GetPrincipal();
-
- if (principal) {
- principal->SetCsp(mCSP);
-#ifdef PR_LOGGING
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("Inserted CSP into principal %p", principal));
- }
- else {
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("Couldn't copy CSP into absent principal %p", principal));
-#endif
- }
- }
-#ifdef PR_LOGGING
- else { //CSP was not enabled!
- PR_LOG(gCspPRLog, PR_LOG_DEBUG,
- ("CSP is disabled, skipping CSP init for document %p", this));
- }
-#endif
+
return NS_OK;
}
void
nsDocument::StopDocumentLoad()
{
if (mParser) {
mParser->Terminate();
@@ -6753,18 +6637,16 @@ nsDocument::RetrieveRelevantHeaders(nsIC
static const char *const headers[] = {
"default-style",
"content-style-type",
"content-language",
"content-disposition",
"refresh",
"x-dns-prefetch-control",
- "x-content-security-policy",
- "x-content-security-policy-read-only",
// add more http headers if you need
// XXXbz don't add content-location support without reading bug
// 238654 and its dependencies/dups first.
0
};
nsCAutoString headerVal;
const char *const *name = headers;
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1206,18 +1206,16 @@ protected:
nsCOMPtr<nsIContent> mFirstBaseNodeWithHref;
private:
friend class nsUnblockOnloadEvent;
void PostUnblockOnloadEvent();
void DoUnblockOnload();
- nsresult InitCSP();
-
/**
* See if aDocument is a child of this. If so, return the frame element in
* this document that holds currentDoc (or an ancestor).
*/
already_AddRefed<nsIDOMElement>
CheckAncestryAndGetFrame(nsIDocument* aDocument) const;
// Just like EnableStyleSheetsForSet, but doesn't check whether
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1002,18 +1002,16 @@ GK_ATOM(where, "where")
GK_ATOM(widget, "widget")
GK_ATOM(width, "width")
GK_ATOM(window, "window")
GK_ATOM(headerWindowTarget, "window-target")
GK_ATOM(withParam, "with-param")
GK_ATOM(wizard, "wizard")
GK_ATOM(wrap, "wrap")
GK_ATOM(headerDNSPrefetchControl,"x-dns-prefetch-control")
-GK_ATOM(headerCSP, "x-content-security-policy")
-GK_ATOM(headerCSPReportOnly, "x-content-security-policy-report-only")
GK_ATOM(xml, "xml")
GK_ATOM(xmlns, "xmlns")
GK_ATOM(xmp, "xmp")
GK_ATOM(xulcontentsgenerated, "xulcontentsgenerated")
GK_ATOM(yes, "yes")
GK_ATOM(z_index, "z-index")
GK_ATOM(zeroDigit, "zero-digit")
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -328,20 +328,16 @@ include $(topsrcdir)/config/rules.mk
test_bug475156.html \
bug475156.sjs \
test_copypaste.html \
test_bug503481.html \
file_bug503481.sjs \
test_bug503481b.html \
file_bug503481b_inner.html \
test_viewport_scroll.html \
- test_CSP.html \
- file_CSP.sjs \
- file_CSP_main.html \
- file_CSP_main.js \
$(NULL)
# Disabled; see bug 492181
# test_plugin_freezing.html
# Disabled for now. Mochitest isn't reliable enough for these.
# test_bug444546.html \
# bug444546.sjs \
deleted file mode 100644
--- a/content/base/test/file_CSP.sjs
+++ /dev/null
@@ -1,44 +0,0 @@
-// SJS file for CSP mochitests
-
-function handleRequest(request, response)
-{
- var query = {};
- request.queryString.split('&').forEach(function (val) {
- var [name, value] = val.split('=');
- query[name] = unescape(value);
- });
-
- var isPreflight = request.method == "OPTIONS";
-
-
- //avoid confusing cache behaviors
- response.setHeader("Cache-Control", "no-cache", false);
-
- if ("main" in query) {
- var xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
- .createInstance(Components.interfaces.nsIXMLHttpRequest);
- //serve the main page with a CSP header!
- // -- anything served from 'self' (localhost:8888) will be allowed,
- // -- anything served from other hosts (example.com:80) will be blocked.
- // -- XHR tests are set up in the file_CSP_main.js file which is sourced.
- response.setHeader("X-Content-Security-Policy",
- "allow 'self'",
- false);
- xhr.open("GET", "http://localhost:8888/tests/content/base/test/file_CSP_main.html", false);
- xhr.send(null);
- if(xhr.status == 200) {
- response.write(xhr.responseText);
- }
- } else {
- if ("type" in query) {
- response.setHeader("Content-Type", unescape(query['type']), false);
- } else {
- response.setHeader("Content-Type", "text/html", false);
- }
-
- if ("content" in query) {
- response.setHeader("Content-Type", "text/html", false);
- response.write(unescape(query['content']));
- }
- }
-}
deleted file mode 100644
--- a/content/base/test/file_CSP_main.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<html>
- <head>
- <link rel='stylesheet' type='text/css'
- href='http://example.org/tests/content/base/test/file_CSP.sjs?testid=style_bad&type=text/css' />
- <link rel='stylesheet' type='text/css'
- href='file_CSP.sjs?testid=style_good&type=text/css' />
-
-
- <style>
- /* CSS font embedding tests */
- @font-face {
- font-family: "arbitrary_good";
- src: url('file_CSP.sjs?testid=font_good&type=application/octet-stream');
- }
- @font-face {
- font-family: "arbitrary_bad";
- src: url('http://example.org/tests/content/base/test/file_CSP.sjs?testid=font_bad&type=application/octet-stream');
- }
-
- .div_arbitrary_good { font-family: "arbitrary_good"; }
- .div_arbitrary_bad { font-family: "arbitrary_bad"; }
- </style>
- </head>
- <body>
- <!-- these should be stopped by CSP. :) -->
- <img src="http://example.org/tests/content/base/test/file_CSP.sjs?testid=img_bad&type=img/png" />
- <audio src="http://example.org/tests/content/base/test/file_CSP.sjs?testid=media_bad&type=audio/vorbis"></audio>
- <script src='http://example.org/tests/content/base/test/file_CSP.sjs?testid=script_bad&type=text/javascript'></script>
- <iframe src='http://example.org/tests/content/base/test/file_CSP.sjs?testid=frame_bad&content=FAIL'></iframe>
- <object width="10" height="10">
- <param name="movie" value="http://example.org/tests/content/base/test/file_CSP.sjs?testid=object_bad&type=application/x-shockwave-flash">
- <embed src="http://example.org/tests/content/base/test/file_CSP.sjs?testid=object_bad&type=application/x-shockwave-flash"></embed>
- </object>
-
- <!-- these should load ok. :) -->
- <img src="file_CSP.sjs?testid=img_good&type=img/png" />
- <audio src="file_CSP.sjs?testid=media_good&type=audio/vorbis"></audio>
- <script src='file_CSP.sjs?testid=script_good&type=text/javascript'></script>
- <iframe src='file_CSP.sjs?testid=frame_good&content=PASS'></iframe>
-
- <object width="10" height="10">
- <param name="movie" value="file_CSP.sjs?testid=object_good&type=application/x-shockwave-flash">
- <embed src="file_CSP.sjs?testid=object_good&type=application/x-shockwave-flash"></embed>
- </object>
-
- <!-- XHR tests... they're taken care of in this script,
- and since the URI doesn't have any 'testid' values,
- it will just be ignored by the test framework. -->
- <script src='file_CSP_main.js'></script>
-
- <!-- Support elements for the @font-face test -->
- <div class="div_arbitrary_good">arbitrary good</div>
- <div class="div_arbitrary_bad">arbitrary_bad</div>
- </body>
-</html>
deleted file mode 100644
--- a/content/base/test/file_CSP_main.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// some javascript for the CSP XHR tests
-//
-
-try {
- var xhr_good = new XMLHttpRequest();
- var xhr_good_uri ="http://localhost:8888/tests/content/base/test/file_CSP.sjs?testid=xhr_good";
- xhr_good.open("GET", xhr_good_uri, true);
- xhr_good.send(null);
-} catch(e) {}
-
-try {
- var xhr_bad = new XMLHttpRequest();
- var xhr_bad_uri ="http://example.com/tests/content/base/test/file_CSP.sjs?testid=xhr_bad";
- xhr_bad.open("GET", xhr_bad_uri, true);
- xhr_bad.send(null);
-} catch(e) {}
deleted file mode 100644
--- a/content/base/test/test_CSP.html
+++ /dev/null
@@ -1,127 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <title>Test for Content Security Policy Connections</title>
- <script type="text/javascript" src="/MochiKit/packed.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-
-</div>
-
-<iframe style="width:200px;height:200px;" id='cspframe'></iframe>
-<script class="testbody" type="text/javascript">
-
-var path = "/tests/content/base/test/";
-
-// These are test results: -1 means it hasn't run,
-// true/false is the pass/fail result.
-window.tests = {
- img_good: -1,
- img_bad: -1,
- style_good: -1,
- style_bad: -1,
- frame_good: -1,
- frame_bad: -1,
- script_good: -1,
- script_bad: -1,
- xhr_good: -1,
- xhr_bad: -1,
- media_good: -1,
- media_bad: -1,
- font_good: -1,
- font_bad: -1,
- object_good: -1,
- object_bad: -1,
-};
-
-
-// This is used to watch the blocked data bounce off CSP and allowed data
-// get sent out to the wire.
-function examiner() {
- netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
- var obsvc = Components.classes['@mozilla.org/observer-service;1']
- .getService(Components.interfaces.nsIObserverService);
- obsvc.addObserver(this, "csp-on-violate-policy", false);
- obsvc.addObserver(this, "http-on-modify-request", false);
-}
-examiner.prototype = {
- observe: function(subject, topic, data) {
- netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
- // subject should be an nsURI, and should be either allowed or blocked.
- if(!subject.QueryInterface)
- return;
-
- var testpat = new RegExp("testid=([a-z0-9_]+)");
-
- //_good things better be allowed!
- //_bad things better be stopped!
-
- if (topic === "http-on-modify-request") {
- //these things were allowed by CSP
- var uri = subject.QueryInterface(Components.interfaces.nsIHttpChannel).URI;
- if (!testpat.test(uri.asciiSpec)) return;
- var testid = testpat.exec(uri.asciiSpec)[1];
- window.testResult(testid,
- /_good/.test(testid),
- uri.asciiSpec + " allowed by csp");
-
- }
-
- if(topic === "csp-on-violate-policy") {
- //these were blocked... record that they were blocked
- var uri = subject.QueryInterface(Components.interfaces.nsIURI);
- if (!testpat.test(uri.asciiSpec)) return;
- var testid = testpat.exec(uri.asciiSpec)[1];
- window.testResult(testid,
- /_bad/.test(testid),
- uri.asciiSpec + " blocked by \"" + data + "\"");
- }
- },
-
- // must eventually call this to remove the listener,
- // or mochitests might get borked.
- remove: function() {
- netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
- var obsvc = Components.classes['@mozilla.org/observer-service;1']
- .getService(Components.interfaces.nsIObserverService);
- obsvc.removeObserver(this, "csp-on-violate-policy");
- obsvc.removeObserver(this, "http-on-modify-request");
- }
-}
-
-window.examiner = new examiner();
-
-window.testResult = function(testname, result, msg) {
-
- //test already complete.... forget it... remember the first result.
- if (window.tests[testname] != -1)
- return;
-
- window.tests[testname] = result;
- is(result, true, testname + ' test: ' + msg);
-
- // if any test is incomplete, keep waiting
- for (var v in window.tests)
- if(tests[v] == -1)
- return;
-
- // ... otherwise, finish
- window.examiner.remove();
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-
-// save this for last so that our listeners are registered.
-// ... this loads the testbed of good and bad requests.
-document.getElementById('cspframe').src = 'file_CSP.sjs?main=1';
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/content/base/test/unit/test_csputils.js
+++ /dev/null
@@ -1,497 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Content Security Policy Data Structures testing code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation
- *
- * Contributor(s):
- * Sid Stamm <sid@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-//load('CSPUtils.jsm');
-Components.utils.import('resource://gre/modules/CSPUtils.jsm');
-
-// load the HTTP server
-do_load_httpd_js();
-
-var httpServer = new nsHttpServer();
-
-const POLICY_FROM_URI = "allow 'self'; img-src *";
-const POLICY_PORT = 9000;
-const POLICY_URI = "http://localhost:" + POLICY_PORT + "/policy";
-
-// helper to assert that an object or array must have a given key
-function do_check_has_key(foo, key, stack) {
- if (!stack)
- stack = Components.stack.caller;
-
- var keys = [];
- for(let k in keys) { keys.push(k); }
- var text = key + " in [" + keys.join(",") + "]";
-
- for(var x in foo) {
- if(x == key) {
- //succeed
- ++_passedChecks;
- dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
- stack.lineNumber + "] " + text + "\n");
- return;
- }
- }
- do_throw(text, stack);
-}
-
-// helper to use .equals on stuff
-function do_check_equivalent(foo, bar, stack) {
- if (!stack)
- stack = Components.stack.caller;
-
- var text = foo + ".equals(" + bar + ")";
-
- if(foo.equals && foo.equals(bar)) {
- ++_passedChecks;
- dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
- stack.lineNumber + "] " + text + "\n");
- return;
- }
- do_throw(text, stack);
-}
-
-var tests = [];
-function test(fcn) {
- tests.push(fcn);
-}
-
-test(
- function test_CSPHost_fromstring() {
- var h;
-
- h = CSPHost.fromString("*");
- do_check_neq(null, h); // "* lone wildcard should work"
-
- h = CSPHost.fromString("foo.bar");
- do_check_neq(null, h); // "standard tuple failed"
-
- h = CSPHost.fromString("*.bar");
- do_check_neq(null, h); // "wildcard failed"
-
- h = CSPHost.fromString("foo.*.bar");
- do_check_eq(null, h); // "wildcard in wrong place worked"
-
- h = CSPHost.fromString("com");
- do_check_eq(null, h); // "lone symbol should fail"
-
- h = CSPHost.fromString("f00b4r.com");
- do_check_neq(null, h); // "Numbers in hosts should work"
-
- h = CSPHost.fromString("foo-bar.com");
- do_check_neq(null, h); // "dashes in hosts should work"
-
- h = CSPHost.fromString("foo!bar.com");
- do_check_eq(null, h); // "special chars in hosts should fail"
- });
-
-test(
- function test_CSPHost_clone() {
- h = CSPHost.fromString("*.a.b.c");
- h2 = h.clone();
- for(var i in h._segments) {
- // "cloned segments should match"
- do_check_eq(h._segments[i], h2._segments[i]);
- }
- });
-
-test(
- function test_CSPHost_permits() {
- var h = CSPHost.fromString("*.b.c");
- var h2 = CSPHost.fromString("a.b.c");
- do_check_true( h.permits(h2)); //"CSPHost *.b.c should allow CSPHost a.b.c"
- do_check_true( h.permits("a.b.c")); //"CSPHost *.b.c should allow string a.b.c"
- do_check_false(h.permits("b.c")); //"CSPHost *.b.c should not allow string b.c"
- do_check_false(h.permits("a.a.c")); //"CSPHost *.b.c should not allow string a.a.c"
- do_check_false(h2.permits(h)); //"CSPHost a.b.c should not allow CSPHost *.b.c"
- do_check_false(h2.permits("b.c")); //"CSPHost a.b.c should not allow string b.c"
- do_check_true( h2.permits("a.b.c")); //"CSPHost a.b.c should allow string a.b.c"
- });
-
-test(
- function test_CSPHost_intersectWith() {
- var h = CSPHost.fromString("*.b.c");
- //"*.a.b.c ^ *.b.c should be *.a.b.c"
- do_check_eq("*.a.b.c", h.intersectWith(CSPHost.fromString("*.a.b.c")).toString());
-
- //"*.b.c ^ *.d.e should not work (null)"
- do_check_eq(null, h.intersectWith(CSPHost.fromString("*.d.e")));
- });
-
-///////////////////// Test the Source object //////////////////////
-
-test(
- function test_CSPSource_fromString() {
- // can't do these tests because "self" is not defined.
- //"basic source should not be null.");
- do_check_neq(null, CSPSource.fromString("a.com"));
-
- //"ldh characters should all work for host.");
- do_check_neq(null, CSPSource.fromString("a2-c.com"));
-
- //"wildcard should work in first token for host.");
- do_check_neq(null, CSPSource.fromString("*.a.com"));
-
- //print(" --- Ignore the following two errors if they print ---");
- //"wildcard should not work in non-first token for host.");
- do_check_eq(null, CSPSource.fromString("x.*.a.com"));
-
- //"funny characters (#) should not work for host.");
- do_check_eq(null, CSPSource.fromString("a#2-c.com"));
- //print(" --- Stop ignoring errors that print ---\n");
-
- //"failed to parse host with port.");
- do_check_neq(null, CSPSource.create("a.com:23"));
- //"failed to parse host with scheme.");
- do_check_neq(null, CSPSource.create("https://a.com"));
- //"failed to parse host with scheme and port.");
- do_check_neq(null, CSPSource.create("https://a.com:200"));
- });
-
-test(
- function test_CSPSource_fromString_withSelf() {
- var src;
- src = CSPSource.create("a.com", "https://foobar.com:443");
- //"src should inherit port *
- do_check_true(src.permits("https://a.com:443"));
- //"src should inherit and require https scheme
- do_check_false(src.permits("http://a.com"));
- //"src should inherit scheme 'https'"
- do_check_true(src.permits("https://a.com"));
-
- src = CSPSource.create("http://a.com", "https://foobar.com:443");
- //"src should inherit and require http scheme"
- do_check_false(src.permits("https://a.com"));
- //"src should inherit scheme 'http'"
- do_check_true(src.permits("http://a.com"));
- //"src should inherit port and scheme from parent"
- //"src should inherit default port for 'http'"
- do_check_true(src.permits("http://a.com:80"));
-
- src = CSPSource.create("'self'", "https://foobar.com:443");
- //"src should inherit port *
- do_check_true(src.permits("https://foobar.com:443"));
- //"src should inherit and require https scheme
- do_check_false(src.permits("http://foobar.com"));
- //"src should inherit scheme 'https'"
- do_check_true(src.permits("https://foobar.com"));
- //"src should reject other hosts"
- do_check_false(src.permits("https://a.com"));
- });
-
-///////////////////// Test the source list //////////////////////
-
-test(
- function test_CSPSourceList_fromString() {
- var sd = CSPSourceList.fromString("'none'");
- //"'none' -- should parse"
- do_check_neq(null,sd);
- // "'none' should be a zero-length list"
- do_check_eq(0, sd._sources.length);
- do_check_true(sd.isNone());
-
- sd = CSPSourceList.fromString("*");
- //"'*' should be a zero-length list"
- do_check_eq(0, sd._sources.length);
-
- //print(" --- Ignore the following three errors if they print ---");
- //"funny char in host"
- do_check_true(CSPSourceList.fromString("f!oo.bar").isNone());
- //"funny char in scheme"
- do_check_true(CSPSourceList.fromString("ht!ps://f-oo.bar").isNone());
- //"funny char in port"
- do_check_true(CSPSourceList.fromString("https://f-oo.bar:3f").isNone());
- //print(" --- Stop ignoring errors that print ---\n");
- });
-
-test(
- function test_CSPSourceList_fromString_twohost() {
- var str = "foo.bar:21 https://ras.bar";
- var parsed = "foo.bar:21 https://ras.bar";
- var sd = CSPSourceList.fromString(str, "http://self.com:80");
- //"two-host list should parse"
- do_check_neq(null,sd);
- //"two-host list should parse to two hosts"
- do_check_eq(2, sd._sources.length);
- //"two-host list should contain original data"
- do_check_eq(parsed, sd.toString());
- });
-
-test(
- function test_CSPSourceList_permits() {
- var nullSourceList = CSPSourceList.fromString("'none'");
- var simpleSourceList = CSPSourceList.fromString("a.com", "http://self.com");
- var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
- "http://self.com:88");
- var allSourceList = CSPSourceList.fromString("*");
-
- //'none' should permit none."
- do_check_false( nullSourceList.permits("http://a.com"));
- //a.com should permit a.com"
- do_check_true( simpleSourceList.permits("http://a.com"));
- //wrong host"
- do_check_false( simpleSourceList.permits("http://b.com"));
- //double list permits http://bar.com:88"
- do_check_true( doubleSourceList.permits("http://bar.com:88"));
- //double list permits https://bar.com:88"
- do_check_false( doubleSourceList.permits("https://bar.com:88"));
- //double list does not permit http://bar.com:443"
- do_check_false( doubleSourceList.permits("http://bar.com:443"));
- //"double list permits https://foo.com:88" (should not inherit port)
- do_check_false( doubleSourceList.permits("https://foo.com:88"));
- //"double list does not permit foo.com on http"
- do_check_false( doubleSourceList.permits("http://foo.com"));
-
- //"* does not permit specific host"
- do_check_true( allSourceList.permits("http://x.com:23"));
- //"* does not permit a long host with no port"
- do_check_true( allSourceList.permits("http://a.b.c.d.e.f.g.h.i.j.k.l.x.com"));
-
- });
-
-test(
- function test_CSPSourceList_intersect() {
- // for this test, 'self' values are irrelevant
- // policy a /\ policy b intersects policies, not context (where 'self'
- // values come into play)
- var nullSourceList = CSPSourceList.fromString("'none'");
- var simpleSourceList = CSPSourceList.fromString("a.com");
- var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88");
- var singleFooSourceList = CSPSourceList.fromString("https://foo.com");
- var allSourceList = CSPSourceList.fromString("*");
-
- //"Intersection of one source with 'none' source list should be none.");
- do_check_true(nullSourceList.intersectWith(simpleSourceList).isNone());
- //"Intersection of two sources with 'none' source list should be none.");
- do_check_true(nullSourceList.intersectWith(doubleSourceList).isNone());
- //"Intersection of '*' with 'none' source list should be none.");
- do_check_true(nullSourceList.intersectWith(allSourceList).isNone());
-
- //"Intersection of one source with '*' source list should be one source.");
- do_check_equivalent(allSourceList.intersectWith(simpleSourceList),
- simpleSourceList);
- //"Intersection of two sources with '*' source list should be two sources.");
- do_check_equivalent(allSourceList.intersectWith(doubleSourceList),
- doubleSourceList);
-
- //"Non-overlapping source lists should intersect to 'none'");
- do_check_true(simpleSourceList.intersectWith(doubleSourceList).isNone());
-
- //"subset and superset should intersect to subset.");
- do_check_equivalent(singleFooSourceList,
- doubleSourceList.intersectWith(singleFooSourceList));
-
- //TODO: write more tests?
-
- });
-
-///////////////////// Test the Whole CSP rep object //////////////////////
-
-test(
- function test_CSPRep_fromString() {
-
- // check default init
- //ASSERT(!(new CSPRep())._isInitialized, "Uninitialized rep thinks it is.")
-
- var cspr;
- var cspr_allowval;
-
- // check default policy "allow *"
- cspr = CSPRep.fromString("allow *", "http://self.com:80");
- //"ALLOW directive is missing when specified in fromString"
- do_check_has_key(cspr._directives, CSPRep.SRC_DIRECTIVES.ALLOW);
-
- // ... and check that the other directives were auto-filled with the
- // ALLOW one.
- var SD = CSPRep.SRC_DIRECTIVES;
- cspr_allowval = cspr._directives[SD.ALLOW];
- for(var d in CSPRep.SRC_DIRECTIVES) {
- //"Missing key " + d
- do_check_has_key(cspr._directives, SD[d]);
- //"Implicit directive " + d + " has non-allow value."
- do_check_eq(cspr._directives[SD[d]].toString(), cspr_allowval.toString());
- }
- });
-
-
-test(
- function test_CSPRep_fromString_oneDir() {
-
- var cspr;
- var SD = CSPRep.SRC_DIRECTIVES;
- var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC,
- SD.FRAME_ANCESTORS, SD.FRAME_SRC];
-
- // check one-directive policies
- cspr = CSPRep.fromString("allow bar.com; script-src https://foo.com",
- "http://self.com");
-
- for(var x in DEFAULTS) {
- //DEFAULTS[x] + " does not use default rule."
- do_check_false(cspr.permits("http://bar.com:22", DEFAULTS[x]));
- //DEFAULTS[x] + " does not use default rule."
- do_check_true(cspr.permits("http://bar.com:80", DEFAULTS[x]));
- //DEFAULTS[x] + " does not use default rule."
- do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
- //DEFAULTS[x] + " does not use default rule."
- do_check_false(cspr.permits("https://foo.com", DEFAULTS[x]));
- }
- //"script-src false positive in policy.
- do_check_false(cspr.permits("http://bar.com:22", SD.SCRIPT_SRC));
- //"script-src false negative in policy.
- do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC));
- });
-
-test(
- function test_CSPRep_fromString_twodir() {
- var cspr;
- var SD = CSPRep.SRC_DIRECTIVES;
- var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_ANCESTORS, SD.FRAME_SRC];
-
- // check two-directive policies
- var polstr = "allow allow.com; "
- + "script-src https://foo.com; "
- + "img-src bar.com:*";
- cspr = CSPRep.fromString(polstr, "http://self.com");
-
- for(var x in DEFAULTS) {
- do_check_true(cspr.permits("http://allow.com", DEFAULTS[x]));
- //DEFAULTS[x] + " does not use default rule.
- do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
- //DEFAULTS[x] + " does not use default rule.
- do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x]));
- //DEFAULTS[x] + " does not use default rule.
- }
- //"img-src does not use default rule.
- do_check_false(cspr.permits("http://allow.com:22", SD.IMG_SRC));
- //"img-src does not use default rule.
- do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
- //"img-src does not use default rule.
- do_check_true(cspr.permits("http://bar.com:88", SD.IMG_SRC));
-
- //"script-src does not use default rule.
- do_check_false(cspr.permits("http://allow.com:22", SD.SCRIPT_SRC));
- //"script-src does not use default rule.
- do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC));
- //"script-src does not use default rule.
- do_check_false(cspr.permits("http://bar.com:400", SD.SCRIPT_SRC));
- });
-
-test(function test_CSPRep_fromString_withself() {
- var cspr;
- var SD = CSPRep.SRC_DIRECTIVES;
- var self = "https://self.com:34";
-
- // check one-directive policies
- cspr = CSPRep.fromString("allow 'self'; script-src 'self' https://*:*",
- self);
- //"img-src does not enforce default rule, 'self'.
- do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
- //"img-src does not allow self
- CSPdebug(cspr);
- do_check_true(cspr.permits(self, SD.IMG_SRC));
- //"script-src is too relaxed
- do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC));
- //"script-src should allow self
- do_check_true(cspr.permits(self, SD.SCRIPT_SRC));
- //"script-src is too strict on host/port
- do_check_true(cspr.permits("https://evil.com:100", SD.SCRIPT_SRC));
- });
-
-///////////////////// TEST POLICY_URI //////////////////////
-test(function test_CSPRep_fromPolicyURI() {
- var cspr;
- var SD = CSPRep.SRC_DIRECTIVES;
- var self = "http://localhost:" + POLICY_PORT;
-
- cspr = CSPRep.fromString("policy-uri " + POLICY_URI, self);
- cspr_static = CSPRep.fromString(POLICY_FROM_URI, self);
-
- //"policy-uri failed to load"
- do_check_neq(null,cspr);
-
- // other directives inherit self
- for(var i in SD) {
- //SD[i] + " parsed wrong from policy uri"
- do_check_equivalent(cspr._directives[SD[i]],
- cspr_static._directives[SD[i]]);
- }
- });
-/*
-
-test(function test_CSPRep_fromPolicyURI_failswhenmixed() {
- var cspr;
- var self = "http://localhost:" + POLICY_PORT;
- var closed_policy = CSPRep.fromString("allow 'none'");
- var my_uri_policy = "policy-uri " + POLICY_URI;
-
- //print(" --- Ignore the following two errors if they print ---");
- cspr = CSPRep.fromString("allow *; " + my_uri_policy, self);
-
- //"Parsing should fail when 'policy-uri' is mixed with allow directive"
- do_check_equivalent(cspr, closed_policy);
- cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, self);
-
- //"Parsing should fail when 'policy-uri' is mixed with other directives"
- do_check_equivalent(cspr, closed_policy);
- //print(" --- Stop ignoring errors that print ---\n");
-
- });
-*/
-
-// TODO: test reporting
-// TODO: test refinements (?)
-// TODO: test 'eval' and 'inline' keywords
-
-function run_test() {
- function policyresponder(request,response) {
- response.setStatusLine(request.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "text/csp", false);
- response.bodyOutputStream.write(POLICY_FROM_URI, POLICY_FROM_URI.length);
- }
- //server.registerDirectory("/", nsILocalFileForBasePath);
- httpServer.registerPathHandler("/policy", policyresponder);
- httpServer.start(POLICY_PORT);
-
- for(let i in tests) {
- tests[i]();
- }
-
- //teardown
- httpServer.stop(function() { });
- do_test_finished();
-}
-
-
-
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -263,17 +263,16 @@ static nsresult Initialize(nsIModule* aS
static void Shutdown();
#ifdef MOZ_XTF
#include "nsIXTFService.h"
#include "nsIXMLContentBuilder.h"
#endif
#include "nsGeolocation.h"
-#include "nsCSPService.h"
// Transformiix
/* {0C351177-0159-4500-86B0-A219DFDE4258} */
#define TRANSFORMIIX_XPATH1_SCHEME_CID \
{ 0xc351177, 0x159, 0x4500, { 0x86, 0xb0, 0xa2, 0x19, 0xdf, 0xde, 0x42, 0x58 } }
/* 5d5d92cd-6bf8-11d9-bf4a-000a95dc234c */
#define TRANSFORMIIX_NODESET_CID \
@@ -844,70 +843,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsBaseDOM
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGeolocation, Init)
#define NS_GEOLOCATION_SERVICE_CID \
{ 0x404d02a, 0x1CA, 0xAAAB, { 0x47, 0x62, 0x94, 0x4b, 0x1b, 0xf2, 0xf7, 0xb5 } }
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationService::GetGeolocationService)
-static NS_METHOD
-CSPServiceRegistration(nsIComponentManager *aCompMgr,
- nsIFile *aPath,
- const char *registryLocation,
- const char *componentType,
- const nsModuleComponentInfo *info)
-{
- nsresult rv;
- nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
- if (NS_FAILED(rv))
- return rv;
-
- nsCOMPtr<nsICategoryManager> catman;
- rv = servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
- NS_GET_IID(nsICategoryManager),
- getter_AddRefs(catman));
- if (NS_FAILED(rv))
- return rv;
-
- nsXPIDLCString previous;
- rv = catman->AddCategoryEntry("content-policy",
- "CSPService",
- CSPSERVICE_CONTRACTID,
- PR_TRUE,
- PR_TRUE,
- getter_Copies(previous));
- return rv;
-}
-
-static NS_METHOD
-CSPServiceUnregistration(nsIComponentManager *aCompMgr,
- nsIFile *aPath,
- const char *registryLocation,
- const nsModuleComponentInfo *info){
- nsresult rv;
-
- nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
- if (NS_FAILED(rv)) return rv;
-
- nsCOMPtr<nsICategoryManager> catman;
- rv = servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
- NS_GET_IID(nsICategoryManager),
- getter_AddRefs(catman));
- if (NS_FAILED(rv)) return rv;
-
- rv = catman->DeleteCategoryEntry("content-policy",
- "CSPService",
- PR_TRUE);
-
- return rv;
-}
-
-NS_GENERIC_FACTORY_CONSTRUCTOR(CSPService)
-
// The list of components we register
static const nsModuleComponentInfo gComponents[] = {
#ifdef DEBUG
{ "Frame utility",
NS_FRAME_UTIL_CID,
nsnull,
CreateNewFrameUtil },
{ "Layout debugger",
@@ -1503,22 +1448,16 @@ static const nsModuleComponentInfo gComp
"@mozilla.org/geolocation;1",
nsGeolocationConstructor },
{ "Focus Manager",
NS_FOCUSMANAGER_CID,
"@mozilla.org/focus-manager;1",
CreateFocusManager },
- { "Content Security Policy Service",
- CSPSERVICE_CID,
- CSPSERVICE_CONTRACTID,
- CSPServiceConstructor,
- CSPServiceRegistration,
- CSPServiceUnregistration },
{ "Event Listener Service",
NS_EVENTLISTENERSERVICE_CID,
NS_EVENTLISTENERSERVICE_CONTRACTID,
CreateEventListenerService }
};
NS_IMPL_NSGETMODULE_WITH_CTOR(nsLayoutModule, gComponents, Initialize)
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -945,18 +945,16 @@ pref("images.dither", "auto");
pref("security.directory", "");
pref("signed.applets.codebase_principal_support", false);
pref("security.checkloaduri", true);
pref("security.xpconnect.plugin.unrestricted", true);
// security-sensitive dialogs should delay button enabling. In milliseconds.
pref("security.dialog_enable_delay", 2000);
-pref("security.csp.enable", true);
-
// Modifier key prefs: default to Windows settings,
// menu access key = alt, accelerator key = control.
// Use 17 for Ctrl, 18 for Alt, 224 for Meta, 0 for none. Mac settings in macprefs.js
pref("ui.key.accelKey", 17);
pref("ui.key.menuAccessKey", 18);
pref("ui.key.generalAccessKey", -1);
// If generalAccessKey is -1, use the following two prefs instead.