Attachment #390366: CSP Work in Progress (v5) for bug #493857

View | Details | Raw Unified | Return to bug 493857
Collapse All | Expand All

(-)944b2cd986d9 (+139 lines)
Added Link Here 
Added Link Here 
1
/* ***** BEGIN LICENSE BLOCK *****
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3
 *
4
 * The contents of this file are subject to the Mozilla Public License Version
5
 * 1.1 (the "License"); you may not use this file except in compliance with
6
 * the License. You may obtain a copy of the License at
7
 * http://www.mozilla.org/MPL/
8
 *
9
 * Software distributed under the License is distributed on an "AS IS" basis,
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
 * for the specific language governing rights and limitations under the
12
 * License.
13
 *
14
 * The Original Code is the Content Security Policy IDL definition.
15
 *
16
 * The Initial Developer of the Original Code is
17
 *   Mozilla Corporation
18
 *
19
 * Contributor(s):
20
 *   Sid Stamm <sid@mozilla.com>
21
 *   Brandon Sterne <bsterne@mozilla.com>
22
 *   Daniel Veditz <dveditz@mozilla.com>
23
 *
24
 * Alternatively, the contents of this file may be used under the terms of
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
28
 * of those above. If you wish to allow use of your version of this file only
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
30
 * use your version of this file under the terms of the MPL, indicate your
31
 * decision by deleting the provisions above and replace them with the notice
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
33
 * the provisions above, a recipient may use your version of this file under
34
 * the terms of any one of the MPL, the GPL or the LGPL.
35
 *
36
 * ***** END LICENSE BLOCK ***** */
37
38
#include "nsISupports.idl"
39
40
interface nsIURI;
41
interface nsIHttpChannel;
42
interface nsIDocShell;
43
44
/**
45
 * IContentSecurityPolicy  
46
 * Describes an XPCOM component used to model an enforce CSPs.
47
 */
48
49
[scriptable, uuid(AB36A2BF-CB32-4AA6-AB41-6B4E4444A221)]
50
interface IContentSecurityPolicy : nsISupports
51
{
52
53
  /**
54
   * Set to true when the CSP has been read in and parsed and is ready to
55
   * enforce.  This is a barrier for the nsDocument so it doesn't load any
56
   * sub-content until either it knows that a CSP is ready or will not be used.
57
   */
58
  attribute boolean isInitialized;
59
60
  /**
61
   * When set to true, content load-blocking and fail-closed are disabled: CSP
62
   * will ONLY send reports, and not modify behavior.
63
   */
64
  attribute boolean reportOnlyMode;
65
66
  /**
67
   * A read-only string version of the policy for debugging.
68
   */
69
  readonly attribute AString policy;
70
71
  /**
72
   * Whether this policy allows in-page script
73
   */
74
  readonly attribute boolean allowsInlineScript;
75
76
  /**
77
   * whether this policy allows eval and eval-like functions
78
   * such as setTimeout("code string", time)
79
   */
80
  readonly attribute boolean allowsEval;
81
82
  /**
83
   * Triggers violation report sending given a URI and reason.
84
   * The URI may be null, in which case "self" is sent.
85
   * @param blockedURI
86
   *     the URI that violated the policy
87
   * @param violatedDirective
88
   *     the directive that was violated.
89
   * @return 
90
   *     nothing.
91
   */
92
  void sendReports(in AString blockedURI, in AString violatedDirective);
93
94
  /**
95
   * Called after the CSP object is created to fill in the appropriate request
96
   * and request header information needed in case a report needs to be sent.
97
   */
98
  void scanRequestData(in nsIHttpChannel aChannel);
99
100
  /**
101
   * Updates the policy currently stored in the CSP to be "refined" or
102
   * tightened by the one specified in the string policyString.
103
   */
104
  void refinePolicy(in AString policyString, in nsIURI selfURI);
105
106
  /**
107
   * Verifies ancestry as permitted by the policy.
108
   * @param docShell
109
   *    containing the protected resource
110
   * @return
111
   *    true if the frame's ancestors are all permitted by policy
112
   */
113
  boolean permitsAncestry(in nsIDocShell docShell);
114
115
  /**
116
   * Delegate method called by the service when sub-elements of the protected
117
   * document are being loaded.  Given a bit of information about the request,
118
   * decides whether or not the policy is satisfied.
119
   */
120
  short shouldLoad(in unsigned long   aContentType, 
121
                   in nsIURI          aContentLocation, 
122
                   in nsIURI          aRequestOrigin, 
123
                   in nsISupports     aContext, 
124
                   in ACString        aMimeTypeGuess, 
125
                   in nsISupports     aExtra);
126
127
  /**
128
   * Delegate method called by the service when sub-elements of the protected
129
   * document are being processed.  Given a bit of information about the request,
130
   * decides whether or not the policy is satisfied.
131
   */
132
  short shouldProcess(in unsigned long   aContentType, 
133
                      in nsIURI          aContentLocation, 
134
                      in nsIURI          aRequestOrigin, 
135
                      in nsISupports     aContext, 
136
                      in ACString        aMimeType,
137
                      in nsISupports     aExtra);
138
139
};
(-)a/content/base/public/Makefile.in (+1 lines)
Line     Link Here 
 Lines 106-117   XPIDLSRCS = \ Link Here 
106
		nsISyncLoadDOMService.idl  \
106
		nsISyncLoadDOMService.idl  \
107
		nsIDragDropHandler.idl \
107
		nsIDragDropHandler.idl \
108
		nsIScriptEventHandler.idl \
108
		nsIScriptEventHandler.idl \
109
		nsIScriptEventManager.idl \
109
		nsIScriptEventManager.idl \
110
		nsIImageLoadingContent.idl \
110
		nsIImageLoadingContent.idl \
111
		nsIObjectLoadingContent.idl \
111
		nsIObjectLoadingContent.idl \
112
		nsIFrameLoader.idl \
112
		nsIFrameLoader.idl \
113
		nsIXMLHttpRequest.idl \
113
		nsIXMLHttpRequest.idl \
114
		IContentSecurityPolicy.idl \
114
		$(NULL)
115
		$(NULL)
115
116
116
include $(topsrcdir)/config/rules.mk
117
include $(topsrcdir)/config/rules.mk
117
118
(-)a/content/base/public/nsIDocument.h (+12 lines)
Line     Link Here 
 Lines 52-67    Link Here 
52
#include "nsCompatibility.h"
52
#include "nsCompatibility.h"
53
#include "nsTObserverArray.h"
53
#include "nsTObserverArray.h"
54
#include "nsTHashtable.h"
54
#include "nsTHashtable.h"
55
#include "nsHashKeys.h"
55
#include "nsHashKeys.h"
56
#include "nsNodeInfoManager.h"
56
#include "nsNodeInfoManager.h"
57
#include "nsIStreamListener.h"
57
#include "nsIStreamListener.h"
58
#include "nsIObserver.h"
58
#include "nsIObserver.h"
59
#include "nsAutoPtr.h"
59
#include "nsAutoPtr.h"
60
#include "IContentSecurityPolicy.h"
60
#ifdef MOZ_SMIL
61
#ifdef MOZ_SMIL
61
class nsSMILAnimationController;
62
class nsSMILAnimationController;
62
#endif // MOZ_SMIL
63
#endif // MOZ_SMIL
63
64
64
class nsIContent;
65
class nsIContent;
65
class nsPresContext;
66
class nsPresContext;
66
class nsIPresShell;
67
class nsIPresShell;
67
class nsIDocShell;
68
class nsIDocShell;
 Lines 1057-1072   public: Link Here 
1057
                    "have a presentation or a docshell or a window");
1058
                    "have a presentation or a docshell or a window");
1058
    NS_PRECONDITION(aDisplayDocument != this, "Should be different document");
1059
    NS_PRECONDITION(aDisplayDocument != this, "Should be different document");
1059
    NS_PRECONDITION(!aDisplayDocument->GetDisplayDocument(),
1060
    NS_PRECONDITION(!aDisplayDocument->GetDisplayDocument(),
1060
                    "Display documents should not nest");
1061
                    "Display documents should not nest");
1061
    mDisplayDocument = aDisplayDocument;
1062
    mDisplayDocument = aDisplayDocument;
1062
  }
1063
  }
1063
1064
1064
  /**
1065
  /**
1066
   * Return the Content Security Policy object for the document
1067
   */
1068
  IContentSecurityPolicy* GetContentSecurityPolicy() const
1069
  {
1070
    return mCSP;
1071
  }
1072
1073
  /**
1065
   * A class that represents an external resource load that has begun but
1074
   * A class that represents an external resource load that has begun but
1066
   * doesn't have a document yet.  Observers can be registered on this object,
1075
   * doesn't have a document yet.  Observers can be registered on this object,
1067
   * and will be notified after the document is created.  Observers registered
1076
   * and will be notified after the document is created.  Observers registered
1068
   * after the document has been created will NOT be notified.  When observers
1077
   * after the document has been created will NOT be notified.  When observers
1069
   * are notified, the subject will be the newly-created document, the topic
1078
   * are notified, the subject will be the newly-created document, the topic
1070
   * will be "external-resource-document-created", and the data will be null.
1079
   * will be "external-resource-document-created", and the data will be null.
1071
   * If document creation fails for some reason, observers will still be
1080
   * If document creation fails for some reason, observers will still be
1072
   * notified, with a null document pointer.
1081
   * notified, with a null document pointer.
 Lines 1266-1281   protected: Link Here 
1266
  PRUint32            mSubtreeModifiedDepth;
1275
  PRUint32            mSubtreeModifiedDepth;
1267
1276
1268
  // If we're an external resource document, this will be non-null and will
1277
  // If we're an external resource document, this will be non-null and will
1269
  // point to our "display document": the one that all resource lookups should
1278
  // point to our "display document": the one that all resource lookups should
1270
  // go to.
1279
  // go to.
1271
  nsCOMPtr<nsIDocument> mDisplayDocument;
1280
  nsCOMPtr<nsIDocument> mDisplayDocument;
1272
1281
1273
  PRUint32 mEventsSuppressed;
1282
  PRUint32 mEventsSuppressed;
1283
1284
  // CSP policy object/data
1285
  nsCOMPtr<IContentSecurityPolicy> mCSP;
1274
};
1286
};
1275
1287
1276
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
1288
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
1277
1289
1278
/**
1290
/**
1279
 * mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
1291
 * mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
1280
 * event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
1292
 * event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
1281
 * object is deleted.
1293
 * object is deleted.
(-)944b2cd986d9 (+969 lines)
Added Link Here 
Added Link Here 
1
/* ***** BEGIN LICENSE BLOCK *****
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3
 *
4
 * The contents of this file are subject to the Mozilla Public License Version
5
 * 1.1 (the "License"); you may not use this file except in compliance with
6
 * the License. You may obtain a copy of the License at
7
 * http://www.mozilla.org/MPL/
8
 *
9
 * Software distributed under the License is distributed on an "AS IS" basis,
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
 * for the specific language governing rights and limitations under the
12
 * License.
13
 *
14
 * The Original Code is the Content Security Policy data structures.
15
 *
16
 * The Initial Developer of the Original Code is
17
 *   Mozilla Corporation
18
 *
19
 * Contributor(s):
20
 *   Sid Stamm <sid@mozilla.com>
21
 *
22
 * Alternatively, the contents of this file may be used under the terms of
23
 * either the GNU General Public License Version 2 or later (the "GPL"), or
24
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25
 * in which case the provisions of the GPL or the LGPL are applicable instead
26
 * of those above. If you wish to allow use of your version of this file only
27
 * under the terms of either the GPL or the LGPL, and not to allow others to
28
 * use your version of this file under the terms of the MPL, indicate your
29
 * decision by deleting the provisions above and replace them with the notice
30
 * and other provisions required by the GPL or the LGPL. If you do not delete
31
 * the provisions above, a recipient may use your version of this file under
32
 * the terms of any one of the MPL, the GPL or the LGPL.
33
 *
34
 * ***** END LICENSE BLOCK ***** */
35
36
/**
37
 * Content Security Policy Utilities
38
 * 
39
 * Overview
40
 * This contains a set of classes and utilities for CSP.  It is in this
41
 * separate file for testing purposes.
42
 */
43
44
// Module stuff
45
var EXPORTED_SYMBOLS = ["CSPRep", "CSPSourceList", "CSPSource", 
46
                        "CSPHost", "CSPWarning", "CSPError", "CSPdebug"];
47
48
function CSPWarning(aMsg) {
49
  //customize this to redirect output.
50
  aMsg = 'CSP WARN:  ' + aMsg + "\n";
51
  dump(aMsg);
52
  Components.classes["@mozilla.org/consoleservice;1"]
53
                    .getService(Components.interfaces.nsIConsoleService)
54
                    .logStringMessage(aMsg);
55
}
56
function CSPError(aMsg) {
57
  aMsg = 'CSP ERROR: ' + aMsg + "\n";
58
  dump(aMsg);
59
  Components.classes["@mozilla.org/consoleservice;1"]
60
                    .getService(Components.interfaces.nsIConsoleService)
61
                    .logStringMessage(aMsg);
62
}
63
function CSPdebug(aMsg) {
64
  aMsg = 'CSP debug: ' + aMsg + "\n";
65
  dump(aMsg);
66
  Components.classes["@mozilla.org/consoleservice;1"]
67
                    .getService(Components.interfaces.nsIConsoleService)
68
                    .logStringMessage(aMsg);
69
}
70
71
72
//:::::::::::::::::::::::: CLASSES ::::::::::::::::::::::::::// 
73
74
/**
75
 * Class that represents a parsed policy structure.
76
 */
77
function CSPRep() {
78
  // this gets set to true when the policy is done parsing, or when a
79
  // URI-borne policy has finished loading.
80
  this._isInitialized = false;
81
82
  this._allowEval = false;
83
  this._allowInlineScripts = false;
84
85
  // don't auto-populate _directives, so it is easier to find bugs
86
  this._directives = {};
87
88
}
89
CSPRep.SRC_DIRECTIVES = {
90
  ALLOW:            "allow",
91
  SCRIPT_SRC:       "script-src",
92
  STYLE_SRC:        "style-src",
93
  MEDIA_SRC:        "media-src",
94
  IMG_SRC:          "img-src",
95
  OBJECT_SRC:       "object-src",
96
  FRAME_SRC:        "frame-src",
97
  FRAME_ANCESTORS:  "frame-ancestors",
98
  FONT_SRC:         "font-src",
99
  XHR_SRC:          "xhr-src"
100
};
101
CSPRep.URI_DIRECTIVES = {
102
  REPORT_URI:       "report-uri",
103
  POLICY_URI:       "policy-uri"
104
};
105
106
107
/**
108
  * Factory to create a new CSPRep, parsed from a string.
109
  *
110
  * @param aStr
111
  *        string rep of a CSP
112
  * @param self (optional)
113
  *        string or CSPSource representing the "self" source
114
  * @returns
115
  *        an instance of CSPRep
116
  */
117
CSPRep.fromString = function(aStr, self) {
118
  var SD = CSPRep.SRC_DIRECTIVES;
119
  var UD = CSPRep.URI_DIRECTIVES;
120
  var pieces = aStr.split(/;\s*/);
121
  var aCSPR = new CSPRep();
122
  piece:for(var i in pieces) {
123
    //split off first token and figure out what to do
124
    var dirname = pieces[i].match(/(\S+)/)[0];
125
126
    //careful to trim the stuff so there's no extra tokens 
127
    var dirvalue = pieces[i].substring(dirname.length)
128
                            .replace(/^\s+/,'')
129
                            .replace(/\s+$/,'');
130
131
    //If it is the script-src directive, pull out "eval" and "inline"
132
    if(dirname == SD.STYLE_SRC) {
133
      let listchunks = dirvalue.split(/\s+/);
134
      for(let i in listchunks) {
135
        if(listchunks[i] == "eval") {
136
          listchunks.splice(i,1);
137
          aCSPR._allowEval = true;
138
        }
139
        if(listchunks[i] == "inline") {
140
          listchunks.splice(i,1);
141
          aCSPR._allowInlineScripts = true;
142
        }
143
      }
144
      // repair source list without the keywords
145
      dirvalue = listchunks.join(" ");
146
    }
147
148
    //is it a SRC directive?
149
    for(var sdi in SD) {
150
      if(dirname == SD[sdi]) {
151
        var dv = CSPSourceList.fromString(dirvalue, self);
152
        //TODO: more robust check for errors in making DV
153
        aCSPR._directives[SD[sdi]] = dv;
154
        continue piece;
155
      }
156
    }
157
158
    //not a SRC directive, check URI directives
159
    if(dirname == UD.POLICY_URI) {
160
      // POLICY_URI can only be alone
161
      if(aCSPR._directives.length > 0 || pieces.length > 1) {
162
        CSPError("policy-uri directive can only appear alone");
163
        return CSPRep.fromString("allow 'none'");
164
      }
165
166
      //return;
167
      //TODO: verify that policy URI is same-origin
168
      var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]  
169
                  .createInstance(Components.interfaces.nsIXMLHttpRequest);  
170
171
      // insert error hook
172
      req.onerror = CSPError;
173
174
      // synchronous -- otherwise we need to architect a callback into the
175
      // xpcom component so that whomever creates the policy object gets
176
      // notified when it's loaded and ready to go.
177
      req.open("GET", dirvalue, false);
178
179
      // make request anonymous
180
      // This prevents sending cookies with the request, in case the policy URI
181
      // is injected, it can't be abused for CSRF.
182
      req.channel.loadFlags |= Components.interfaces.nsIChannel.LOAD_ANONYMOUS;
183
184
      //CSPdebug("Fetching URI " + dirvalue);
185
      req.send(null);  
186
      if(req.status == 200) {
187
        //CSPdebug("XHR returned: " + req.responseText);
188
        aCSPR = CSPRep.fromString(req.responseText, self);
189
        //remember where we got the policy
190
        aCSPR._directives[UD.POLICY_URI] = dirvalue;
191
        return aCSPR;
192
      }
193
      CSPError("Error fetching policy URI: server response was " + req.status);
194
      return CSPRep.fromString("allow 'none'");
195
    }
196
    if(dirname == UD.REPORT_URI) {
197
      //TODO: do we want to support multiple URIs?  Yes
198
      //TODO: verify that report URI(s) is(are) compatible ETLD+1
199
      aCSPR._directives[UD.REPORT_URI] = dirvalue;
200
      continue piece;
201
    }
202
203
    //no directives matched
204
    CSPWarning("Couldn't process unknown directive '" + dirname + "'");
205
  }
206
207
  if(aCSPR._directives.length < 1) {
208
    CSPError("invalid policy -- no recognized directives");
209
    return CSPRep.fromString("allow 'none'");
210
  }
211
212
  if(!aCSPR._directives[SD.ALLOW]) {
213
    CSPWarning("allow directive is not present, using \"allow 'none'\"");
214
    aCSPR._directives[SD.ALLOW] = CSPSourceList.fromString("'none'");
215
  }
216
217
  aCSPR.makeExplicit();
218
  return aCSPR;
219
};
220
221
CSPRep.prototype = {
222
  /**
223
   * Returns array of all report uris defined, or 'none' if there are none.
224
   */
225
  getReportURIs:
226
  function() {
227
    if(!this._directives[CSPRep.URI_DIRECTIVES.REPORT_URI])
228
      return [];
229
230
    var uris = this._directives[CSPRep.URI_DIRECTIVES.REPORT_URI].split(",");
231
    for(let i in uris) {
232
      //trim off surrounding whitespace
233
      uris[i] = uris[i].replace(/^\s+/, "").replace(/\s+$/, "");
234
    }
235
    return uris;
236
  },
237
238
  /**
239
   * Compares this CSPRep instance to another.
240
   */
241
  equals:
242
  function(that) {
243
    if(this._directives.length != that._directives.length) {
244
      return false;
245
    }
246
    for(var i in this._directives) {
247
      if(!that._directives[i] || !this._directives[i].equals(that._directives[i])) {
248
        return false;
249
      }
250
    }
251
    return true;
252
  },
253
254
  /**
255
   * Generates string representation of the policy.  Should be fairly similar
256
   * to the original.
257
   */
258
  toString:
259
  function csp_toString() {
260
    var dirs = [];
261
    for(var i in this._directives) {
262
      if(this._directives[i]) {
263
        dirs.push(i + " " + this._directives[i].toString());
264
      }
265
    }
266
    return dirs.join("; ");
267
  },
268
269
270
  /**
271
   * Determines if this policy accepts a URI.
272
   * @param aContext
273
   *        one of the SRC_DIRECTIVES defined above
274
   * @returns 
275
   *        true if the policy permits the URI in given context.
276
   */
277
  permits:
278
  function csp_permits(aURI, aContext) {
279
280
    // GLOBALLY ALLOW "about:" SCHEME
281
    if(aURI instanceof String && aURI.substring(0,6) == "about:") {
282
      return true;
283
    }
284
    if(aURI instanceof Components.interfaces.nsIURI
285
        && aURI.scheme == "about") {
286
      return true;
287
    }
288
289
    //make sure the context is valid
290
    for(var i in CSPRep.SRC_DIRECTIVES) {
291
      if(CSPRep.SRC_DIRECTIVES[i] == aContext) {
292
        return this._directives[aContext].permits(aURI);
293
      }
294
    }
295
    return false;
296
  },
297
298
  /**
299
   * Intersects with another CSPRep, deciding the subset policy 
300
   * that should be enforced, and returning a new instance.
301
   * @param aCSPRep
302
   *        a CSPRep instance to use as "other" CSP
303
   * @returns
304
   *        a new CSPRep instance of the intersection
305
   */
306
  intersectWith:
307
  function cspsd_intersectWith(aCSPRep) {
308
    var newRep = new CSPRep();
309
310
    for(var dir in CSPRep.SRC_DIRECTIVES) {
311
      var dirv = CSPRep.SRC_DIRECTIVES[dir];
312
      newRep._directives[dirv] = this._directives[dirv]
313
               .intersectWith(aCSPRep._directives[dirv]);
314
    }
315
    return newRep;
316
  },
317
318
319
  /**
320
   * Copies default source list to each unspecified directive.
321
   * @returns
322
   *      true  if the makeExplicit succeeds
323
   *      false if it fails (for some weird reason)
324
   */
325
  makeExplicit:
326
  function cspsd_makeExplicit() {
327
    var SD = CSPRep.SRC_DIRECTIVES;
328
    var allowDir = this._directives[SD.ALLOW];
329
    if(!allowDir) {
330
      return false;
331
    }
332
333
    for(var dir in SD) {
334
      var dirv = SD[dir];
335
      if(dirv == SD.ALLOW) {
336
        continue;
337
      }
338
      if(!this._directives[dirv]) {
339
        //implicit directive, make explicit
340
        this._directives[dirv] = allowDir.clone();
341
      }
342
    }
343
    this._isInitialized = true;
344
    return true;
345
  },
346
347
  /**
348
   * Returns true if "eval" is enabled through the "eval" keyword.
349
   */
350
  get allowsEvalInScripts () {
351
    return this._allowEval;
352
  },
353
354
  /**
355
   * Returns true if inline scripts are enabled through the "inline"
356
   * keyword.
357
   */
358
  get allowsInlineScripts () {
359
    return this._allowInlineScripts;
360
  },
361
};
362
363
364
//////////////////////////////////////////////////////////////////////
365
/**
366
 * Class to represent a list of sources 
367
 */
368
function CSPSourceList() {
369
  this._sources = [];
370
  this._permitAllSources = false;
371
}
372
373
/**
374
 * Factory to create a new CSPSourceList, parsed from a string.
375
 *
376
 * @param aStr
377
 *        string rep of a CSP Source List
378
 * @param self (optional)
379
 *        string or CSPSource representing the "self" source
380
 * @returns
381
 *        an instance of CSPSourceList 
382
 */
383
CSPSourceList.fromString = function(aStr, self) {
384
  //Source list is:
385
  //    <host-dir-value> ::= <source-list>
386
  //                       | "'none'"
387
  //    <source-list>    ::= <source>
388
  //                       | <source-list>" "<source>
389
390
  var slObj = new CSPSourceList();
391
  if(aStr == "'none'") {
392
    return slObj;
393
  }
394
395
  var ss = aStr.split(/\s+/);
396
  for(var i in ss) {
397
    var o = CSPSource.fromString(ss[i], self);
398
    //make sure none came back undefined
399
    if(!o) { return null; }
400
    slObj._sources[i] = o;
401
  }
402
  return slObj;
403
};
404
405
CSPSourceList.prototype = {
406
407
  /**
408
   * Compares one CSPSourceList to another.
409
   *
410
   * @param that
411
   *        another CSPSourceList
412
   * @returns 
413
   *        true if they have the same data
414
   */
415
  equals:
416
  function(that) {
417
    if(that._sources.length != this._sources.length) {
418
      return false;
419
    }
420
    //sort both arrays and compare like a zipper
421
    //XXX (sid): I think we can make this more efficient
422
    var sortfn = function(a,b) {
423
      return a.toString() > b.toString();
424
    };
425
    var a_sorted = this._sources.sort(sortfn);
426
    var b_sorted = that._sources.sort(sortfn);
427
    for(var i in a_sorted) {
428
      if(!a_sorted[i].equals(b_sorted[i])) {
429
        return false;
430
      }
431
    }
432
    return true;
433
  },
434
435
  /**
436
   * Generates string representation of the Source List.
437
   * Should be fairly similar to the original.
438
   */
439
  toString:
440
  function() {
441
    if(this.isNone()) {
442
      return "'none'";
443
    }
444
    return this._sources.map(function(x) { return x.toString(); }).join(" ");
445
  },
446
447
  /**
448
   * Returns whether or not this source list represents the "'none'" special
449
   * case.
450
   */
451
  isNone:
452
  function() {
453
    return (!this._permitAllSources) && (this._sources.length < 1);
454
  },
455
456
  /**
457
   * Makes a new instance that resembles this object.
458
   * @returns
459
   *      a new CSPSourceList
460
   */
461
  clone:
462
  function() {
463
    var aSL = new CSPSourceList();
464
    aSL._permitAllSources = this._permitAllSources;
465
    for(var i in this._sources) {
466
      aSL._sources[i] = this._sources[i].clone();
467
    }
468
    return aSL;
469
  },
470
471
472
  /**
473
   * Determines if this directive accepts a URI.
474
   * @param aURI
475
   *        the URI in question
476
   * @returns
477
   *        true if the URI matches a source in this source list.
478
   */
479
  permits:
480
  function cspsd_permits(aURI) {
481
    if(this.isNone()) {
482
      return false;
483
    }
484
    for(var i in this._sources) {
485
      if(this._sources[i].permits(aURI)) {
486
        return true;
487
      }
488
    }
489
    return false;
490
  },
491
492
493
  /**
494
   * Intersects with another CSPSourceList, deciding the subset directive
495
   * that should be enforced, and returning a new instance.
496
   * @param that 
497
   *        the other CSPSourceList to intersect "this" with
498
   * @returns
499
   *        a new instance of a CSPSourceList representing the intersection
500
   */
501
  intersectWith:
502
  function cspsd_intersectWith(that) {
503
    if(this._permitAllSources) {
504
      return that.clone();
505
    }
506
    if(that._permitAllSources) {
507
      return this.clone();
508
    }
509
510
    // "'none'" case
511
    if(this.isNone() || that.isNone()) {
512
      return CSPSourceList.fromString("'none'");
513
    }
514
515
    // --  find only common sources
516
517
    //XXX (sid): figure out a good algorithm for this.
518
    // This is horribly inefficient. O(n^2)
519
    var isrcs = [];
520
    for(var i in this._sources) {
521
      for(var j in that._sources) {
522
        var s = that._sources[j].intersectWith(this._sources[i]);
523
        if(s) {
524
          isrcs.push(s);
525
        }
526
      }
527
    }
528
    //Next, remove duplicates
529
    dup:for(var i = 0; i < isrcs.length; i++) {
530
      for(var j = 0; j < i; j++) {
531
        if(isrcs[i].equals(isrcs[j])) {
532
          isrcs.splice(i, 1);
533
          i--;
534
          continue dup;
535
        }
536
      }
537
    }
538
    var newCSPSrcList = new CSPSourceList();
539
    newCSPSrcList._sources = isrcs;
540
    return newCSPSrcList;
541
  }
542
}
543
544
545
//////////////////////////////////////////////////////////////////////
546
/**
547
 * Class to model a source (scheme, host, port)
548
 */
549
function CSPSource() {
550
  this._scheme = "*";
551
  this._port = "*";
552
  this._host = CSPHost.fromString("*");
553
}
554
555
/**
556
 * Factory to create a new CSPSource, from a nsIURI.
557
 *
558
 * @param aURI
559
 *        nsIURI rep of a URI
560
 * @param self (optional)
561
 *        string or CSPSource representing the "self" source
562
 * @returns
563
 *        an instance of CSPSource 
564
 */
565
CSPSource.fromURI = function(aURI, self) {
566
567
  if( !(aURI instanceof Components.interfaces.nsIURI) ){
568
    CSPError("Provided argument is not an nsIURI");
569
    return null;
570
  }
571
572
  if(typeof self === "string") {
573
    self = CSPSource.fromString(self);
574
  }
575
576
  var sObj = new CSPSource();
577
578
  try {
579
    //if there was a scheme...
580
    sObj._scheme = aURI.scheme;
581
  } catch (e) {
582
    // aaah!  No scheme even though we tried two methods to force a scheme into
583
    // the source.
584
      CSPError("failed parsing source: '" + aURI.asciiSpec + "'");
585
      return null;
586
  }
587
588
  //now, check if there was a host
589
  try {
590
    sObj._host = CSPHost.fromString(aURI.host);
591
592
    //and if there was a host, copy the port (if present)
593
    if(aURI.port > 0) {
594
      sObj._port = aURI.port;
595
    } else {
596
      // either port was absent or *.
597
      // If empty, the port is inherited from "self"
598
      if(aStr.substr(-2) === ":*")
599
        sObj._port = "*";
600
      else 
601
        sObj._port = self._port;
602
    }
603
  } catch(e) {
604
    // no host! (or an error getting the port)
605
    // It's ok if there's no host (scheme-only sources like javascript:
606
    // allowed).
607
    // Copy in any data that needs to be inherited, but if there's no 
608
    // host, there's no need for a port either.  "*" as host _WILL_ be 
609
    // parsed correctly by newURI(), and won't throw an exception 
610
    // putting us here.
611
    if(sObj._host && !sObj._port)
612
      sObj._port = self._port;
613
  }
614
  return sObj;
615
};
616
617
/**
618
 * Factory to create a new CSPSource, parsed from a string.
619
 *
620
 * @param aStr
621
 *        string rep of a CSP Source
622
 * @param self (optional)
623
 *        string or CSPSource representing the "self" source
624
 * @returns
625
 *        an instance of CSPSource 
626
 */
627
CSPSource.fromString = function(aStr, self) {
628
  //take care of 'self' keyword
629
  if(aStr == "'self'") {
630
    if(typeof self === 'undefined') {
631
      CSPError("self keyword used, but no self data specified");
632
      return null;
633
    } 
634
    if(self == "'self'") {
635
      CSPError("self reference cannot be 'self'");
636
      return null;
637
    }
638
    if(self instanceof CSPSource) { 
639
      return self.clone();
640
    }
641
    return CSPSource.fromString(self);
642
  }
643
644
  if(typeof self === "string") {
645
    self = CSPSource.fromString(self);
646
  }
647
648
649
  let chunks = aStr.split(":");
650
  // Workaround for problems:
651
  // - "*" not parsed right by the URI parser
652
  //    ... solution: special case for the * source
653
  if(aStr == "*")
654
    return new CSPSource(); //default is *://*:*
655
    
656
  // - a.com is not easily parsed by ios.newURI(), need to add a scheme
657
  // - a.com:20 is ambiguous.  Could mean scheme = a.com, or host = a.com to
658
  //   the io-service URI parser
659
  //    ... but since :20 is not a valid host, CSP should treat it as a
660
  //        host:port combination.
661
  //    ... not a problem for three-chunk values like x:a.com:20
662
  //    ... solution: prepend self's scheme
663
  if(chunks.length == 1 || chunks.length == 2 && chunks[1].match(/^\d+$/)) {
664
    if(!self) {
665
      CSPError("can't parse ambiguous source: '" + aStr + "' without 'self' defined");
666
      return null;
667
    }
668
    aStr = self._scheme + "://" + aStr;
669
  }
670
671
  // - ports are not validated ('3f' is turned into '-1')
672
  //    ... solution: validate ports manually
673
  if(chunks.length == 3 && !(chunks[2].match(/^\d+$/) || chunks[2] === "*")) {
674
    CSPError("invalid port string: '" + chunks[2] + "' not entirely numeric.");
675
    return null;
676
  }
677
678
  // Try to parse the URI 
679
  var uriSource;
680
  var ios = Components.classes["@mozilla.org/network/io-service;1"]
681
                      .getService(Components.interfaces.nsIIOService);
682
683
  try {
684
    uriSource = ios.newURI(aStr, null, null);
685
  } catch(e) {
686
    try {
687
      //this means there was no scheme specified, or the URI was malformed.
688
      // Need to use backup parsing mechanism here, with "self" defining the
689
      // scheme.
690
      let bStr = self._scheme + "://" + aStr;
691
      uriSource = ios.newURI(bStr, null, null);
692
    } catch(e) {
693
      //fatal error!  Can't parse.. there must be a scheme or at least a
694
      //parseable host!
695
      CSPError("failed parsing source: '" + aStr + "'");
696
      return null;
697
    }
698
  }
699
  return CSPSource.fromURI(uriSource);
700
};
701
702
CSPSource.prototype = {
703
704
  /**
705
   * Generates string representation of the Source.
706
   * Should be fairly similar to the original.
707
   */
708
  toString:
709
  function() {
710
    var s = this._host;
711
    if(this._port && this._port != "*") {
712
      s = s + ":" + this._port;
713
    }
714
    if(this._scheme && this._scheme != "*") {
715
      s = this._scheme + "://" + s;
716
    }
717
    return s;
718
  },
719
720
  /**
721
   * Makes a new instance that resembles this object.
722
   * @returns
723
   *      a new CSPSource
724
   */
725
  clone:
726
  function() {
727
    var aClone = new CSPSource();
728
    aClone._scheme = this._scheme;
729
    aClone._port = this._port;
730
    aClone._host = this._host.clone();
731
    return aClone;
732
  },
733
734
  /**
735
   * Determines if this Source accepts a URI.
736
   * @param aURI
737
   *        the URI in question
738
   * @returns
739
   *        true if the URI matches a source in this source list.
740
   */
741
  permits:
742
  function(aSource) {
743
    if(aSource instanceof Components.interfaces.nsIURI) {
744
      //figure out based on URI
745
      return this.permits(CSPSource.fromURI(aSource));
746
    }
747
    if(!(aSource instanceof CSPSource)) {
748
      //convert to CSPSource first
749
      return this.permits(CSPSource.fromString(aSource));
750
    }
751
752
    //verify scheme, host, and port
753
    if(    (this._scheme == "*" || this._scheme == aSource._scheme)
754
        && (this._port == "*"   || this._port == aSource._port)    ){
755
      return this._host === "*" ||
756
             this._host.permits(aSource._host);
757
    }
758
    // something didn't match.
759
    return false;
760
  },
761
762
  /**
763
   * Determines the intersection of two sources.
764
   * Returns a null object if intersection generates no
765
   * hosts that satisfy it.
766
   * @param that 
767
   *        the other CSPSource to intersect "this" with
768
   * @returns
769
   *        a new instance of a CSPSource representing the intersection
770
   */
771
  intersectWith:
772
  function(that) {
773
    var newSource = new CSPSource();
774
775
    //port
776
    if(this._port == "*") { 
777
      newSource._port = that._port;
778
    } else if(that._port == "*") { 
779
      newSource._port = this._port;
780
    } else if(that._port == this._port) {
781
      newSource._port = this._port;
782
    } else {
783
      //CSPError("Could not intersect " + this + " with " + that
784
      //         + " due to port problems.");
785
      return null;
786
    }
787
788
    //scheme
789
    if(this._scheme == "*") { 
790
      newSource._scheme = that._scheme;
791
    } else if(that._scheme == "*") { 
792
      newSource._scheme = this._scheme;
793
    } else if(that._scheme == this._scheme) {
794
      newSource._scheme = this._scheme;
795
    } else {
796
      //CSPError("Could not intersect " + this + " with " + that
797
      //         + " due to scheme problems.");
798
      return null;
799
    }
800
801
    //host
802
    newSource._host = this._host.intersectWith(that._host);
803
804
    return newSource._host ? newSource : null;
805
  },
806
807
  /**
808
   * Compares one CSPSource to another.
809
   *
810
   * @param that
811
   *        another CSPSource
812
   * @returns 
813
   *        true if they have the same data
814
   */
815
  equals:
816
  function(aSrc) {
817
    return this._scheme == aSrc._scheme
818
        && this._port == aSrc._port
819
        && this._host.equals(aSrc._host);
820
  }
821
};
822
  
823
824
//////////////////////////////////////////////////////////////////////
825
/**
826
 * Class to model a host *.x.y.
827
 */
828
function CSPHost() {
829
  this._segments = [];
830
}
831
832
/**
833
 * Factory to create a new CSPHost, parsed from a string.
834
 *
835
 * @param aStr
836
 *        string rep of a CSP Host 
837
 * @returns
838
 *        an instance of CSPHost
839
 */
840
CSPHost.fromString = function(aStr) {
841
  var hObj = new CSPHost();
842
  hObj._segments = aStr.split(/\./);
843
  if(hObj._segments.length < 1 ||
844
     hObj._segments.length == 1 && hObj._segments[0] != "*"
845
                                && hObj._segments[0] != "localhost") {
846
    //only short hosts allowed are "*" and "localhost"
847
    return null;
848
  }
849
  //TODO: double-check that each segment is appropriate.
850
  return hObj;
851
};
852
853
CSPHost.prototype = {
854
  /**
855
   * Generates string representation of the Source.
856
   * Should be fairly similar to the original.
857
   */
858
  toString:
859
  function() {
860
    return this._segments.join(".");
861
  },
862
863
  /**
864
   * Makes a new instance that resembles this object.
865
   * @returns
866
   *      a new CSPHost
867
   */
868
  clone:
869
  function() {
870
    var aHost = new CSPHost();
871
    for(var i in this._segments) {
872
      aHost._segments[i] = this._segments[i];
873
    }
874
    return aHost;
875
  },
876
877
  /**
878
   * Returns true if this host accepts the provided host (or the other way
879
   * around).
880
   * @param aHost
881
   *        the FQDN in question (CSPHost or String)
882
   * @returns
883
   */
884
  permits:
885
  function(aHost) {
886
    if(!(aHost instanceof CSPHost)) {
887
      // -- compare CSPHost to String
888
      return this.permits(CSPHost.fromString(aHost));
889
    }
890
    var thislen = this._segments.length;
891
    var thatlen = aHost._segments.length;
892
893
    // don't accept a less specific host: 
894
    //   \--> *.b.a doesn't accept b.a.
895
    if(thatlen < thislen) { return false; }
896
897
    // check for more specific host (and wildcard):
898
    //   \--> *.b.a accepts d.c.b.a.
899
    //   \--> c.b.a doesn't accept d.c.b.a.
900
    if((thatlen > thislen) && this._segments[0] != "*") {
901
      return false;
902
    }
903
904
    // Given the wildcard condition (from above), 
905
    // only necessary to compare elements that are present
906
    // in this host.  Extra tokens in aHost are ok. 
907
    // * Compare from right to left.
908
    for(var i=1; i <= thislen; i++) {
909
      if( this._segments[thislen-i] != "*" && 
910
          (this._segments[thislen-i] != aHost._segments[thatlen-i]) ) {
911
        return false;
912
      }
913
    }
914
915
    //at this point, all conditions are met, so the host is allowed
916
    return true;
917
  },
918
919
  /**
920
   * Determines the intersection of two Hosts.
921
   * Basically, they must be the same, or one must have a wildcard.
922
   * @param that 
923
   *        the other CSPHost to intersect "this" with
924
   * @returns
925
   *        a new instance of a CSPHost representing the intersection
926
   *        (or null, if they can't be intersected)
927
   */
928
  intersectWith:
929
  function(that) {
930
    if(!(this.permits(that) || that.permits(this))) {
931
      // host definitions cannot co-exist without a more general host
932
      // ... one must be a subset of the other, or intersection makes no sense.
933
      return null;
934
    } 
935
936
    // pick the more specific one, if both are same length.
937
    if(this._segments.length == that._segments.length) {
938
      // *.a vs b.a : b.a
939
      return (this._segments[0] == "*") ? that.clone() : this.clone();
940
    }
941
942
    //different lengths...
943
    // *.b.a vs *.a : *.b.a
944
    // *.b.a vs d.c.b.a : d.c.b.a
945
    return (this._segments.length > that._segments.length) 
946
            ? this.clone() : that.clone();
947
  },
948
949
  /**
950
   * Compares one CSPHost to another.
951
   *
952
   * @param that
953
   *        another CSPHost
954
   * @returns 
955
   *        true if they have the same data
956
   */
957
  equals:
958
  function(that) {
959
    if(this._segments.length != that._segments.length) {
960
      return false;
961
    }
962
    for(var i=0; i<this._segments.length; i++) {
963
      if(this._segments[i] != that._segments[i]) {
964
        return false;
965
      }
966
    }
967
    return true;
968
  }
969
};
(-)a/content/base/src/Makefile.in (-1 / +9 lines)
Line     Link Here 
 Lines 117-132   CPPSRCS = \ Link Here 
117
		nsContentAreaDragDrop.cpp \
117
		nsContentAreaDragDrop.cpp \
118
		nsContentIterator.cpp \
118
		nsContentIterator.cpp \
119
		nsContentList.cpp \
119
		nsContentList.cpp \
120
		nsContentPolicy.cpp \
120
		nsContentPolicy.cpp \
121
		nsContentSink.cpp \
121
		nsContentSink.cpp \
122
		nsContentUtils.cpp \
122
		nsContentUtils.cpp \
123
		nsCopySupport.cpp \
123
		nsCopySupport.cpp \
124
		nsCrossSiteListenerProxy.cpp \
124
		nsCrossSiteListenerProxy.cpp \
125
		nsCSPService.cpp \
125
		nsDataDocumentContentPolicy.cpp \
126
		nsDataDocumentContentPolicy.cpp \
126
		nsDOMAttribute.cpp \
127
		nsDOMAttribute.cpp \
127
		nsDOMAttributeMap.cpp \
128
		nsDOMAttributeMap.cpp \
128
		nsDOMDocumentType.cpp \
129
		nsDOMDocumentType.cpp \
129
		nsDOMFile.cpp \
130
		nsDOMFile.cpp \
130
		nsDOMLists.cpp \
131
		nsDOMLists.cpp \
131
		nsDOMParser.cpp \
132
		nsDOMParser.cpp \
132
		nsDOMSerializer.cpp \
133
		nsDOMSerializer.cpp \
 Lines 176-192   CPPSRCS = \ Link Here 
176
		$(NULL)
177
		$(NULL)
177
178
178
GQI_SRCS = contentbase.gqi
179
GQI_SRCS = contentbase.gqi
179
180
180
# we don't want the shared lib, but we want to force the creation of a
181
# we don't want the shared lib, but we want to force the creation of a
181
# static lib.
182
# static lib.
182
FORCE_STATIC_LIB = 1
183
FORCE_STATIC_LIB = 1
183
184
184
EXTRA_COMPONENTS = $(srcdir)/nsBadCertHandler.js
185
EXTRA_COMPONENTS = \
186
		$(srcdir)/nsBadCertHandler.js \
187
		contentSecurityPolicy.js \
188
		$(NULL)
189
190
EXTRA_JS_MODULES = \
191
		CSPUtils.jsm \
192
		$(NULL)
185
193
186
include $(topsrcdir)/config/rules.mk
194
include $(topsrcdir)/config/rules.mk
187
195
188
INCLUDES	+= \
196
INCLUDES	+= \
189
		-I$(srcdir)/../../events/src \
197
		-I$(srcdir)/../../events/src \
190
		-I$(srcdir)/../../xml/content/src \
198
		-I$(srcdir)/../../xml/content/src \
191
		-I$(srcdir)/../../xul/base/src \
199
		-I$(srcdir)/../../xul/base/src \
192
		-I$(srcdir)/../../xul/content/src \
200
		-I$(srcdir)/../../xul/content/src \
(-)944b2cd986d9 (+371 lines)
Added Link Here 
Added Link Here 
1
/* ***** BEGIN LICENSE BLOCK *****
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3
 *
4
 * The contents of this file are subject to the Mozilla Public License Version
5
 * 1.1 (the "License"); you may not use this file except in compliance with
6
 * the License. You may obtain a copy of the License at
7
 * http://www.mozilla.org/MPL/
8
 *
9
 * Software distributed under the License is distributed on an "AS IS" basis,
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
 * for the specific language governing rights and limitations under the
12
 * License.
13
 *
14
 * The Original Code is the ContentSecurityPolicy module.
15
 *
16
 * The Initial Developer of the Original Code is
17
 *   Mozilla Corporation
18
 *
19
 * Contributor(s):
20
 *   Sid Stamm <sid@mozilla.com>
21
 *   Brandon Sterne <bsterne@mozilla.com>
22
 *
23
 * Alternatively, the contents of this file may be used under the terms of
24
 * either the GNU General Public License Version 2 or later (the "GPL"), or
25
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
 * in which case the provisions of the GPL or the LGPL are applicable instead
27
 * of those above. If you wish to allow use of your version of this file only
28
 * under the terms of either the GPL or the LGPL, and not to allow others to
29
 * use your version of this file under the terms of the MPL, indicate your
30
 * decision by deleting the provisions above and replace them with the notice
31
 * and other provisions required by the GPL or the LGPL. If you do not delete
32
 * the provisions above, a recipient may use your version of this file under
33
 * the terms of any one of the MPL, the GPL or the LGPL.
34
 *
35
 * ***** END LICENSE BLOCK ***** */
36
37
38
/**
39
 * Content Security Policy
40
 * 
41
 * Overview
42
 * This is a stub component that will be fleshed out to do all the fancy stuff
43
 * that ContentSecurityPolicy has to do.
44
 */
45
46
/* :::::::: Constants and Helpers ::::::::::::::: */
47
48
const Cc = Components.classes;
49
const Ci = Components.interfaces;
50
const Cr = Components.results;
51
const Cu = Components.utils;
52
53
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
54
Cu.import("resource://gre/modules/CSPUtils.jsm");
55
56
/* ::::: Policy Parsing & Data structures :::::: */
57
58
function ContentSecurityPolicy() {
59
  CSPdebug("CSP CREATED");
60
  this._isInitialized = false;
61
  this._reportOnlyMode = false;
62
  this._policy = CSPRep.fromString("allow *");
63
  this._requestHeaders = []; 
64
  this._request = "";
65
  CSPdebug("CSP POLICY INITED TO 'allow *'");
66
}
67
68
/*
69
 * Set up mappings from nsIContentPolicy content types to CSP directives.
70
 */
71
with(Ci.nsIContentPolicy) {
72
  let csp = ContentSecurityPolicy;
73
  let cspr_sd = CSPRep.SRC_DIRECTIVES;
74
75
  csp._MAPPINGS=[];
76
77
  /* default, catch-all case */
78
  csp._MAPPINGS[TYPE_OTHER]             =  cspr_sd.ALLOW;
79
80
  /* self */
81
  csp._MAPPINGS[TYPE_DOCUMENT]          =  null;
82
83
  /* shouldn't see this one */
84
  csp._MAPPINGS[TYPE_REFRESH]           =  null;
85
86
  /* categorized content types */
87
  csp._MAPPINGS[TYPE_SCRIPT]            = cspr_sd.SCRIPT_SRC;
88
  csp._MAPPINGS[TYPE_IMAGE]             = cspr_sd.IMG_SRC;
89
  csp._MAPPINGS[TYPE_STYLESHEET]        = cspr_sd.STYLE_SRC;
90
  csp._MAPPINGS[TYPE_OBJECT]            = cspr_sd.OBJECT_SRC;
91
  csp._MAPPINGS[TYPE_SUBDOCUMENT]       = cspr_sd.FRAME_SRC;
92
  csp._MAPPINGS[TYPE_MEDIA]             = cspr_sd.MEDIA_SRC;
93
  csp._MAPPINGS[TYPE_FONT]              = cspr_sd.FONT_SRC;
94
  csp._MAPPINGS[TYPE_XMLHTTPREQUEST]    = cspr_sd.XHR_SRC;
95
96
97
  /* These must go through the catch-all */
98
  csp._MAPPINGS[TYPE_XBL]               = cspr_sd.ALLOW;
99
  csp._MAPPINGS[TYPE_PING]              = cspr_sd.ALLOW;
100
  csp._MAPPINGS[TYPE_OBJECT_SUBREQUEST] = cspr_sd.ALLOW;
101
  csp._MAPPINGS[TYPE_DTD]               = cspr_sd.ALLOW;
102
}
103
104
ContentSecurityPolicy.prototype = {
105
  classDescription: "Content Security Policy Component",
106
  contractID:       "@mozilla.org/contentsecuritypolicy;1",
107
  classID:          Components.ID("{AB36A2BF-CB32-4AA6-AB41-6B4E4444A221}"),
108
  QueryInterface:   XPCOMUtils.generateQI([Ci.IContentSecurityPolicy]),
109
110
  // get this contractID registered for certain categories via XPCOMUtils
111
  _xpcom_categories: [ ],
112
113
  get isInitialized() {
114
    return this._isInitialized;
115
  },
116
117
  set isInitialized (foo) {
118
    this._isInitialized = foo;
119
  },
120
121
  get policy () {
122
    return this._policy.toString();
123
  },
124
125
  get allowsInlineScript() {
126
    return this._policy.allowsInlineScripts;
127
  },
128
129
  get allowsEval() {
130
    return this._policy.allowsEvalInScripts;
131
  },
132
133
  set reportOnlyMode(val) {
134
    this._reportOnlyMode = val;
135
  },
136
137
  get reportOnlyMode () {
138
    return this._reportOnlyMode;
139
  },
140
141
  /*
142
  // Having a setter is a bad idea... opens up the policy to "loosening"
143
  // Instead, use "refinePolicy."
144
  set policy (aStr) {
145
    this._policy = CSPRep.fromString(aStr);
146
  },
147
  */
148
149
  /**
150
   * Given an nsIHttpChannel, fill out the appropriate data.
151
   */
152
  scanRequestData:
153
  function(aChannel) {
154
    // grab the request line
155
    var internalChannel = aChannel.QueryInterface(Ci.nsIHttpChannelInternal);
156
    var reqMaj = {};
157
    var reqMin = {};
158
    var reqVersion = internalChannel.getRequestVersion(reqMaj, reqMin);
159
    this._request = aChannel.requestMethod + " " 
160
                  + aChannel.URI 
161
                  + " HTTP/" + reqMaj.value + "." + reqMin.value;
162
163
    // grab the request headers
164
    var self = this;
165
    aChannel.visitRequestHeaders({
166
      visitHeader: function(aHeader, aValue) {
167
        self._requestHeaders.push(aHeader + ": " + aValue);
168
      }});
169
  },
170
171
/* ........ Methods .............. */
172
173
  /**
174
   * Given a new policy, intersects the currently enforced policy with the new
175
   * one and stores the result.  The effect is a "tightening" or refinement of
176
   * an old policy.  This is called any time a new policy is encountered and
177
   * the effective policy has to be refined.
178
   */
179
  refinePolicy:
180
  function csp_refinePolicy(aPolicy, selfURI) {
181
    CSPdebug("REFINE POLICY: " + aPolicy);
182
    CSPdebug("         SELF: " + selfURI.asciiSpec);
183
184
    // stay uninitialized until policy merging is done
185
    this._isInitialized = false;
186
187
    // If there is a policy-uri, fetch the policy, then re-call this function.
188
    // (1) parse and create a CSPRep object
189
    var newpolicy = CSPRep.fromString(aPolicy,
190
                                      selfURI.scheme + "://" + selfURI.hostPort);
191
192
    // (2) Intersect the currently installed CSPRep object with the new one
193
    var intersect = this._policy.intersectWith(newpolicy);
194
    //TODO: make sure intersect worked
195
 
196
    // (3) Save the result
197
    this._policy = intersect;
198
    this._isInitialized = true;
199
  },
200
201
  /**
202
   * Generates and sends a violation report to the specified report URIs.
203
   */
204
  sendReports:
205
  function(blockedUri, violatedDirective) {
206
    var uris = this._policy.getReportURIs();
207
    if(uris.length > 0) {
208
      // Generate report to send composed of:
209
      // <csp-report>
210
      //   <request>GET /index.html HTTP/1.1</request>
211
      //   <request-headers>Host: example.com
212
      //            User-Agent: ...
213
      //            ...
214
      //   </request-headers>
215
      //   <blocked-uri>...</blocked-uri>
216
      //   <violated-directive>...</violated-directive>
217
      // </csp-report>
218
      //   
219
      var strHeaders = "";
220
      for(let i in this._requestHeaders) {
221
        strHeaders += this._requestHeaders[i] + "\n";
222
      }
223
224
      var report = "<csp-report>\n" +
225
        " <request>" + this._request + "</request>\n" +
226
        "   <request-headers><![CDATA[\n" +
227
        strHeaders +
228
        "   ]]></request-headers>\n" +
229
        "   <blocked-uri>" + blockedUri + "</blocked-uri>\n" +
230
        "   <violated-directive>" + violatedDirective + "</violated-directive>\n" +
231
        "</csp-report>\n";
232
233
      // For each URI in the report list, send out a report.
234
      for(let i in uris) {
235
        var failure = function(aEvt) {  
236
          if(req.readyState == 4 && req.status != 200) {
237
            CSPError("Failed to send report to " + reportURI);
238
          }  
239
        };  
240
        var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]  
241
                    .createInstance(Ci.nsIXMLHttpRequest);  
242
243
        req.open("POST", uris[i], true);
244
        req.setRequestHeader('Content-Type', 'application/xml');
245
        req.upload.addEventListener("error", failure, false);  
246
        req.upload.addEventListener("abort", failure, false);  
247
        //req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
248
 
249
        // make request anonymous
250
        // This prevents sending cookies with the request, 
251
        // in case the policy URI is injected, it can't be
252
        // abused for CSRF.
253
        req.channel.loadFlags |= Ci.nsIChannel.LOAD_ANONYMOUS;
254
255
        req.send(report);
256
      }
257
    }
258
  },
259
260
  /**
261
   * Exposed Method to analyze docShell for approved frame ancestry.
262
   * Also sends violation reports if necessary.
263
   * @param docShell
264
   *    the docShell for this policy's resource.
265
   * @return
266
   *    true if the frame ancestry is allowed by this policy.
267
   */
268
  permitsAncestry:
269
  function(docShell) {
270
    if(!docShell) { return false; }
271
    CSPdebug(" in permitsAncestry(), docShell = " + docShell);
272
273
    // walk up this docShell tree until we hit chrome
274
    var dst = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
275
                      .getInterface(Ci.nsIDocShellTreeItem);
276
277
    // collect ancestors and make sure they're allowed.
278
    var ancestors = [];
279
    while(dst.parent) {
280
      dst = dst.parent;
281
      let it = dst.QueryInterface(Ci.nsIInterfaceRequestor)
282
                  .getInterface(Ci.nsIWebNavigation);
283
      if(it.currentURI) {
284
        if(it.currentURI.scheme == "chrome") {
285
          break;
286
        }
287
        let ancestor = it.currentURI.scheme + "://" + it.currentURI.hostPort;
288
        CSPdebug(" found frame ancestor " + ancestor);
289
        ancestors.push(ancestor);
290
      }
291
    } 
292
293
    // scan the discovered ancestors
294
    let cspContext = CSPRep.SRC_DIRECTIVES.FRAME_ANCESTORS;
295
    for(let i in ancestors) {
296
      if(!this._policy.permits(ancestors[i], cspContext)) {
297
        // report the frame-ancestor violation
298
        this.sendReports("self", cspContext +" "+ this._policy._directives[cspContext]);
299
        // need to lie if we are testing in report-only mode
300
        return this._reportOnlyMode;
301
      }
302
    }
303
    return true;
304
  },
305
306
  /**
307
   * Delegate method called by the service when sub-elements of the protected
308
   * document are being loaded.  Given a bit of information about the request,
309
   * decides whether or not the policy is satisfied.
310
   */
311
  shouldLoad:
312
  function csp_shouldLoad(aContentType, 
313
                          aContentLocation, 
314
                          aRequestOrigin, 
315
                          aContext, 
316
                          aMimeTypeGuess, 
317
                          aExtra) {
318
319
    //don't filter chrome stuff
320
    if(aContentLocation.scheme == 'chrome') {
321
      return Ci.nsIContentPolicy.ACCEPT;
322
    }
323
324
    //interpret the context, and then pass off to the decision structure
325
    CSPdebug("shouldLoad location = " + aContentLocation.asciiSpec);
326
    CSPdebug("shouldLoad content type = " + aContentType);
327
    var cspContext = ContentSecurityPolicy._MAPPINGS[aContentType];
328
    //CSPdebug("shouldLoad CSP directive =" + cspContext);
329
330
    // if the mapping is null, there's no policy, let it through.
331
    if(!cspContext) {
332
      return Ci.nsIContentPolicy.ACCEPT;
333
    }
334
335
    // otherwise, honor the translation
336
    //var source = aContentLocation.scheme + "://" + aContentLocation.hostPort; 
337
    var res = this._policy.permits(aContentLocation, cspContext)
338
              ? Ci.nsIContentPolicy.ACCEPT 
339
              : Ci.nsIContentPolicy.REJECT_SERVER;
340
341
    // frame-ancestors is taken care of early on (as this document is loaded)
342
343
    // If the result is *NOT* ACCEPT, then send report
344
    if(res != Ci.nsIContentPolicy.ACCEPT) { 
345
      CSPdebug("blocking request for " + aContentLocation.asciiSpec);
346
      this.sendReports(aContentLocation,
347
                       cspContext + " " + this._policy._directives[cspContext]);
348
    }
349
350
    return (this._reportOnlyMode ? Ci.nsIContentPolicy.ACCEPT : res);
351
  },
352
  
353
  shouldProcess:
354
  function csp_shouldProcess(aContentType,
355
                             aContentLocation,
356
                             aRequestOrigin,
357
                             aContext,
358
                             aMimeType,
359
                             aExtra) {
360
    // frame-ancestors check is done outside the ContentPolicy
361
    var res = Ci.nsIContentPolicy.ACCEPT;
362
    CSPdebug("shouldProcess aContext=" + aContext);
363
    return res;
364
  },
365
366
};
367
368
369
370
function NSGetModule(aComMgr, aFileSpec)
371
  XPCOMUtils.generateModule([ContentSecurityPolicy]);
(-)944b2cd986d9 (+203 lines)
Added Link Here 
Added Link Here 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
 *
5
 * The contents of this file are subject to the Mozilla Public License Version
6
 * 1.1 (the "License"); you may not use this file except in compliance with
7
 * the License. You may obtain a copy of the License at
8
 * http://www.mozilla.org/MPL/
9
 *
10
 * Software distributed under the License is distributed on an "AS IS" basis,
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
 * for the specific language governing rights and limitations under the
13
 * License.
14
 *
15
 * The Original Code is mozilla.org code.
16
 *
17
 * The Initial Developer of the Original Code is
18
 * Mozilla Corporation.
19
 * Portions created by the Initial Developer are Copyright (C) 2009
20
 * the Initial Developer. All Rights Reserved.
21
 *
22
 * Contributor(s):
23
 *   Brandon Sterne <bsterne@mozilla.com>
24
 *
25
 * Alternatively, the contents of this file may be used under the terms of
26
 * either of the GNU General Public License Version 2 or later (the "GPL"),
27
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
 * in which case the provisions of the GPL or the LGPL are applicable instead
29
 * of those above. If you wish to allow use of your version of this file only
30
 * under the terms of either the GPL or the LGPL, and not to allow others to
31
 * use your version of this file under the terms of the MPL, indicate your
32
 * decision by deleting the provisions above and replace them with the notice
33
 * and other provisions required by the GPL or the LGPL. If you do not delete
34
 * the provisions above, a recipient may use your version of this file under
35
 * the terms of any one of the MPL, the GPL or the LGPL.
36
 *
37
 * ***** END LICENSE BLOCK ***** */
38
39
#include "nsIURI.h"
40
#include "nsString.h"
41
#include "nsCSPService.h"
42
#include "nsIDocument.h"
43
#include "nsIContent.h"
44
#include "IContentSecurityPolicy.h"
45
#include "nsContentUtils.h"
46
#include "prlog.h"
47
48
/* Keeps track of whether or not CSP is enabled */
49
static PRBool gCSPEnabled = PR_FALSE;
50
51
#ifdef PR_LOGGING
52
static PRLogModuleInfo* gCspPRLog;
53
#endif
54
55
CSPService::CSPService()
56
{
57
  gCSPEnabled = nsContentUtils::GetBoolPref("security.csp.enable", PR_TRUE);
58
  nsContentUtils::AddBoolPrefVarCache("security.csp.enable", &gCSPEnabled);
59
60
#ifdef PR_LOGGING
61
  if (!gCspPRLog)
62
    gCspPRLog = PR_NewLogModule("CSP");
63
#endif
64
}
65
66
CSPService::~CSPService()
67
{
68
}
69
70
NS_IMPL_ISUPPORTS1(CSPService, nsIContentPolicy)
71
72
/* nsIContentPolicy implementation */
73
NS_IMETHODIMP
74
CSPService::ShouldLoad(PRUint32 aContentType,
75
                       nsIURI *aContentLocation,
76
                       nsIURI *aRequestOrigin,
77
                       nsISupports *aRequestContext,
78
                       const nsACString &aMimeTypeGuess,
79
                       nsISupports *aExtra,
80
                       PRInt16 *aDecision)
81
{
82
  if (!aContentLocation)
83
    return NS_ERROR_FAILURE;
84
85
#ifdef PR_LOGGING 
86
  {
87
    nsCAutoString location("None");
88
    aContentLocation->GetSpec(location);
89
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
90
           ("CSPService::ShouldLoad called for %s", location.get()));
91
  }
92
#endif
93
  // default decision, CSP can revise it if there's a policy to enforce
94
  *aDecision = nsIContentPolicy::ACCEPT;
95
96
  // No need to continue processing if CSP is disabled
97
  if (!gCSPEnabled) {
98
    //printf(" *** CSPService -- CSP is disabled, returning.\n");
99
    return NS_OK;
100
  }
101
102
  // find the nsDocument that initiated this request and see if it has a
103
  // CSP policy object
104
  nsCOMPtr<nsIDocument> doc;
105
  nsCOMPtr<nsIContent> node(do_QueryInterface(aRequestContext));
106
  if (node) {
107
    doc = node->GetOwnerDoc();
108
  }
109
  if (!doc) {
110
    doc = do_QueryInterface(aRequestContext);
111
  }
112
  
113
  if (doc) {
114
    IContentSecurityPolicy* csp = doc->GetContentSecurityPolicy();
115
    if (csp) {
116
#ifdef PR_LOGGING 
117
      nsAutoString policy;
118
      csp->GetPolicy(policy);
119
      PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
120
             ("Document has CSP: %s", ToNewCString(policy)));
121
#endif
122
      // obtain the enforcement decision
123
      csp->ShouldLoad(aContentType,
124
                      aContentLocation,
125
                      aRequestOrigin,
126
                      aRequestContext,
127
                      aMimeTypeGuess,
128
                      aExtra,
129
                      aDecision);
130
    }
131
  }
132
#ifdef PR_LOGGING
133
  else {
134
    nsCAutoString uriSpec("None");
135
    aContentLocation->GetSpec(uriSpec);
136
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
137
           ("COULD NOT get nsIDocument for location: %s", uriSpec.get()));
138
  }
139
#endif
140
	
141
  return NS_OK;
142
}
143
144
NS_IMETHODIMP
145
CSPService::ShouldProcess(PRUint32         aContentType,
146
                          nsIURI           *aContentLocation,
147
                          nsIURI           *aRequestOrigin,
148
                          nsISupports      *aRequestContext,
149
                          const nsACString &aMimeTypeGuess,
150
                          nsISupports      *aExtra,
151
                          PRInt16          *aDecision)
152
{
153
  if (!aContentLocation)
154
    return NS_ERROR_FAILURE;
155
156
  // default decision is to accept the item
157
  *aDecision = nsIContentPolicy::ACCEPT;
158
159
  // No need to continue processing if CSP is disabled
160
  if (!gCSPEnabled) {
161
    //printf(" *** CSPService -- CSP is disabled, returning.\n");
162
    return NS_OK;
163
  }
164
165
  // find the nsDocument that initiated this request and see if it has a
166
  // CSP policy object
167
  nsCOMPtr<nsIDocument> doc;
168
  nsCOMPtr<nsIContent> node(do_QueryInterface(aRequestContext));
169
  if (node) {
170
    doc = node->GetOwnerDoc();
171
  }
172
  if (!doc) {
173
    doc = do_QueryInterface(aRequestContext);
174
  }
175
  if (doc) {
176
    IContentSecurityPolicy* csp = doc->GetContentSecurityPolicy();
177
    if (csp) {
178
#ifdef PR_LOGGING
179
      nsAutoString policy;
180
      csp->GetPolicy(policy);
181
      PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
182
             ("shouldProcess - document has policy: %s", ToNewCString(policy)));
183
#endif
184
      // obtain the enforcement decision
185
      csp->ShouldProcess(aContentType,
186
                         aContentLocation,
187
                         aRequestOrigin,
188
                         aRequestContext,
189
                         aMimeTypeGuess,
190
                         aExtra,
191
                         aDecision);
192
    }
193
  }
194
#ifdef PR_LOGGING
195
  else {
196
    nsCAutoString uriSpec("None");
197
    aContentLocation->GetSpec(uriSpec);
198
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
199
           ("COULD NOT get nsIDocument for location: %s", uriSpec.get()));
200
  }
201
#endif
202
  return NS_OK;
203
}
(-)944b2cd986d9 (+67 lines)
Added Link Here 
Added Link Here 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
 *
5
 * The contents of this file are subject to the Mozilla Public License Version
6
 * 1.1 (the "License"); you may not use this file except in compliance with
7
 * the License. You may obtain a copy of the License at
8
 * http://www.mozilla.org/MPL/
9
 *
10
 * Software distributed under the License is distributed on an "AS IS" basis,
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
 * for the specific language governing rights and limitations under the
13
 * License.
14
 *
15
 * The Original Code is mozilla.org code.
16
 *
17
 * The Initial Developer of the Original Code is
18
 * Mozilla Corporation.
19
 * Portions created by the Initial Developer are Copyright (C) 2009
20
 * the Initial Developer. All Rights Reserved.
21
 *
22
 * Contributor(s):
23
 *   Brandon Sterne <bsterne@mozilla.com>
24
 *
25
 * Alternatively, the contents of this file may be used under the terms of
26
 * either of the GNU General Public License Version 2 or later (the "GPL"),
27
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
 * in which case the provisions of the GPL or the LGPL are applicable instead
29
 * of those above. If you wish to allow use of your version of this file only
30
 * under the terms of either the GPL or the LGPL, and not to allow others to
31
 * use your version of this file under the terms of the MPL, indicate your
32
 * decision by deleting the provisions above and replace them with the notice
33
 * and other provisions required by the GPL or the LGPL. If you do not delete
34
 * the provisions above, a recipient may use your version of this file under
35
 * the terms of any one of the MPL, the GPL or the LGPL.
36
 *
37
 * ***** END LICENSE BLOCK ***** */
38
39
#include "nsIGenericFactory.h"
40
41
#include "nsCOMPtr.h"
42
#include "nsXPCOM.h"
43
#include "nsIServiceManager.h"
44
#include "nsICategoryManager.h"
45
46
#include "nsMemory.h"
47
48
#include "nsIContentPolicy.h"
49
#include "nsIObserver.h"
50
51
#define CSPSERVICE_CONTRACTID "@mozilla.org/cspservice;1"
52
#define CSPSERVICE_CID \
53
{ 0x8d2f40b2, 0x4875, 0x4c95, \
54
  { 0x97, 0xd9, 0x3f, 0x7d, 0xca, 0x2c, 0xb4, 0x60 } }
55
56
class CSPService : public nsIContentPolicy
57
{
58
public:
59
  NS_DECL_ISUPPORTS
60
  NS_DECL_NSICONTENTPOLICY
61
  
62
  CSPService();
63
  virtual ~CSPService();
64
65
private:
66
  PRBool mEnabled;
67
};
(-)a/content/base/src/nsDocument.cpp (+122 lines)
Line     Link Here 
 Lines 174-198   static NS_DEFINE_CID(kDOMEventGroupCID, Link Here 
174
#include "mozAutoDocUpdate.h"
174
#include "mozAutoDocUpdate.h"
175
175
176
#ifdef MOZ_SMIL
176
#ifdef MOZ_SMIL
177
#include "nsSMILAnimationController.h"
177
#include "nsSMILAnimationController.h"
178
#include "imgIContainer.h"
178
#include "imgIContainer.h"
179
#include "nsSVGUtils.h"
179
#include "nsSVGUtils.h"
180
#endif // MOZ_SMIL
180
#endif // MOZ_SMIL
181
181
182
// FOR CSP (autogenerated by xpidl)
183
#include "IContentSecurityPolicy.h"
184
182
185
183
#ifdef MOZ_LOGGING
186
#ifdef MOZ_LOGGING
184
// so we can get logging even in release builds
187
// so we can get logging even in release builds
185
#define FORCE_PR_LOG 1
188
#define FORCE_PR_LOG 1
186
#endif
189
#endif
187
#include "prlog.h"
190
#include "prlog.h"
188
191
189
#ifdef PR_LOGGING
192
#ifdef PR_LOGGING
190
static PRLogModuleInfo* gDocumentLeakPRLog;
193
static PRLogModuleInfo* gDocumentLeakPRLog;
194
static PRLogModuleInfo* gCspPRLog;
191
#endif
195
#endif
192
196
193
void
197
void
194
nsUint32ToContentHashEntry::Destroy()
198
nsUint32ToContentHashEntry::Destroy()
195
{
199
{
196
  HashSet* set = GetHashSet();
200
  HashSet* set = GetHashSet();
197
  if (set) {
201
  if (set) {
198
    delete set;
202
    delete set;
 Lines 1473-1488   nsDocument::nsDocument(const char* aCont Link Here 
1473
  
1477
  
1474
#ifdef PR_LOGGING
1478
#ifdef PR_LOGGING
1475
  if (!gDocumentLeakPRLog)
1479
  if (!gDocumentLeakPRLog)
1476
    gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
1480
    gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
1477
1481
1478
  if (gDocumentLeakPRLog)
1482
  if (gDocumentLeakPRLog)
1479
    PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
1483
    PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
1480
           ("DOCUMENT %p created", this));
1484
           ("DOCUMENT %p created", this));
1485
1486
  if (!gCspPRLog)
1487
    gCspPRLog = PR_NewLogModule("CSP");
1488
1481
#endif
1489
#endif
1482
1490
1483
  // Start out mLastStyleSheetSet as null, per spec
1491
  // Start out mLastStyleSheetSet as null, per spec
1484
  SetDOMStringToNull(mLastStyleSheetSet);
1492
  SetDOMStringToNull(mLastStyleSheetSet);
1485
}
1493
}
1486
1494
1487
static PLDHashOperator
1495
static PLDHashOperator
1488
ClearAllBoxObjects(const void* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
1496
ClearAllBoxObjects(const void* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
 Lines 2230-2245   nsDocument::StartDocumentLoad(const char Link Here 
2230
    semicolon = start;
2238
    semicolon = start;
2231
    FindCharInReadable(';', semicolon, end);
2239
    FindCharInReadable(';', semicolon, end);
2232
    mContentType = Substring(start, semicolon);
2240
    mContentType = Substring(start, semicolon);
2233
  }
2241
  }
2234
2242
2235
  RetrieveRelevantHeaders(aChannel);
2243
  RetrieveRelevantHeaders(aChannel);
2236
2244
2237
  mChannel = aChannel;
2245
  mChannel = aChannel;
2246
  
2247
// --------------  Initialize CSP
2248
2249
  PRBool cspEnabled;
2250
  cspEnabled = nsContentUtils::GetBoolPref("security.csp.enable", PR_FALSE);
2251
  
2252
  if(!cspEnabled) {
2253
    // CSP not enabled, don't do all this CSP init stuff.
2254
#ifdef PR_LOGGING
2255
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
2256
           ("CSP is disabled, skipping CSP init for document %p", this));
2257
#endif
2258
    return NS_OK;
2259
  }
2260
2261
  nsresult rv;
2262
  PRBool system;
2263
  nsIScriptSecurityManager *ssm = nsContentUtils::GetSecurityManager();
2264
  nsAutoString cspHeaderValue;
2265
  nsAutoString cspROHeaderValue;
2266
  nsIAtom* cspHeaderAtom = NS_NewAtom("x-content-security-policy");
2267
  nsIAtom* cspROHeaderAtom = NS_NewAtom("x-content-security-policy-report-only");
2268
2269
  this->GetHeaderData(cspHeaderAtom, cspHeaderValue);
2270
  this->GetHeaderData(cspROHeaderAtom, cspROHeaderValue);
2271
2272
  if(NS_SUCCEEDED(ssm->IsSystemPrincipal(NodePrincipal(), &system)) && system) {
2273
    //only makes sense to register new CSP if this document is not priviliged
2274
    return NS_OK;
2275
  }
2276
2277
  if(cspHeaderValue.IsEmpty() && cspROHeaderValue.IsEmpty()) {
2278
    // no CSP header present
2279
    return NS_OK;
2280
  }
2281
2282
2283
2284
#ifdef PR_LOGGING 
2285
  PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
2286
          ("CSP header specified for document %p", this));
2287
#endif
2288
2289
  mCSP = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv);
2290
2291
  if(NS_FAILED(rv)) {
2292
#ifdef PR_LOGGING 
2293
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("Failed to create CSP object: %6x", rv));
2294
#endif
2295
    return rv;
2296
  }
2297
2298
#ifdef PR_LOGGING 
2299
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP attached to document"));
2300
#endif
2301
2302
  // Store the request context for violation reports
2303
  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
2304
  mCSP->ScanRequestData(httpChannel);
2305
2306
  // Start parsing the policy
2307
  nsCOMPtr<nsIURI> chanURI;
2308
  aChannel->GetURI(getter_AddRefs(chanURI));
2309
2310
  // ReportOnly mode is enabled *only* if there are no regular-strength CSP
2311
  // headers present.  If there are, then we ignore the ReportOnly mode and
2312
  // toss a warning into the error console, proceeding with enforcing the
2313
  // regular-strength CSP.
2314
  if(cspHeaderValue.IsEmpty()) {
2315
    mCSP->SetReportOnlyMode(true);
2316
    mCSP->RefinePolicy(cspROHeaderValue, chanURI);
2317
#ifdef PR_LOGGING 
2318
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
2319
          ("CSP (report only) refined, policy: \"%s\"", 
2320
           ToNewCString(cspROHeaderValue)));
2321
#endif
2322
2323
  } else {
2324
    //if(!cspROHeaderValue.IsEmpty()) {
2325
      //TODO: post warning that both read only and regular CSP headers are
2326
      //present.
2327
    //}
2328
    mCSP->RefinePolicy(cspHeaderValue, chanURI);
2329
#ifdef PR_LOGGING 
2330
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
2331
          ("CSP refined, policy: \"%s\"", ToNewCString(cspHeaderValue)));
2332
#endif
2333
  }
2334
2335
  // Check for frame-ancestor violation
2336
  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
2337
  if(docShell != NULL) {
2338
    //PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP has a doc shell!"));
2339
2340
    PRBool safeAncestry = false;
2341
    // PermitsAncestry sends violation reports when necessary
2342
    rv = mCSP->PermitsAncestry(docShell, &safeAncestry);
2343
    if(NS_FAILED(rv)) { return rv; }
2344
2345
    if(!safeAncestry) {
2346
#ifdef PR_LOGGING
2347
      PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP doesn't like frame's ancestry, not loading."));
2348
#endif
2349
      // stop!  ERROR page!
2350
      aChannel->Cancel( NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, 99) );
2351
    }
2352
  }
2353
2354
// -------------- CSP initialized
2238
2355
2239
  return NS_OK;
2356
  return NS_OK;
2240
}
2357
}
2241
2358
2242
void
2359
void
2243
nsDocument::StopDocumentLoad()
2360
nsDocument::StopDocumentLoad()
2244
{
2361
{
2245
  if (mParser) {
2362
  if (mParser) {
 Lines 6567-6582   nsDocument::RetrieveRelevantHeaders(nsIC Link Here 
6567
6684
6568
    static const char *const headers[] = {
6685
    static const char *const headers[] = {
6569
      "default-style",
6686
      "default-style",
6570
      "content-style-type",
6687
      "content-style-type",
6571
      "content-language",
6688
      "content-language",
6572
      "content-disposition",
6689
      "content-disposition",
6573
      "refresh",
6690
      "refresh",
6574
      "x-dns-prefetch-control",
6691
      "x-dns-prefetch-control",
6692
      "x-content-security-policy",
6693
      "x-content-security-policy-read-only",
6575
      // add more http headers if you need
6694
      // add more http headers if you need
6576
      // XXXbz don't add content-location support without reading bug
6695
      // XXXbz don't add content-location support without reading bug
6577
      // 238654 and its dependencies/dups first.
6696
      // 238654 and its dependencies/dups first.
6578
      0
6697
      0
6579
    };
6698
    };
6580
    
6699
    
6581
    nsCAutoString headerVal;
6700
    nsCAutoString headerVal;
6582
    const char *const *name = headers;
6701
    const char *const *name = headers;
 Lines 6870-6885   nsDocument::CanSavePresentation(nsIReque Link Here 
6870
6989
6871
void
6990
void
6872
nsDocument::Destroy()
6991
nsDocument::Destroy()
6873
{
6992
{
6874
  // The ContentViewer wants to release the document now.  So, tell our content
6993
  // The ContentViewer wants to release the document now.  So, tell our content
6875
  // to drop any references to the document so that it can be destroyed.
6994
  // to drop any references to the document so that it can be destroyed.
6876
  if (mIsGoingAway)
6995
  if (mIsGoingAway)
6877
    return;
6996
    return;
6997
	
6998
  // Take down CSP
6999
  mCSP = 0;
6878
7000
6879
  mIsGoingAway = PR_TRUE;
7001
  mIsGoingAway = PR_TRUE;
6880
7002
6881
  RemovedFromDocShell();
7003
  RemovedFromDocShell();
6882
7004
6883
  PRUint32 i, count = mChildren.ChildCount();
7005
  PRUint32 i, count = mChildren.ChildCount();
6884
  for (i = 0; i < count; ++i) {
7006
  for (i = 0; i < count; ++i) {
6885
    mChildren.ChildAt(i)->DestroyContent();
7007
    mChildren.ChildAt(i)->DestroyContent();
(-)a/content/base/src/nsScriptLoader.cpp (-1 / +60 lines)
Line     Link Here 
 Lines 65-80    Link Here 
65
#include "nsUnicharUtils.h"
65
#include "nsUnicharUtils.h"
66
#include "nsAutoPtr.h"
66
#include "nsAutoPtr.h"
67
#include "nsIXPConnect.h"
67
#include "nsIXPConnect.h"
68
#include "nsContentErrors.h"
68
#include "nsContentErrors.h"
69
#include "nsIParser.h"
69
#include "nsIParser.h"
70
#include "nsThreadUtils.h"
70
#include "nsThreadUtils.h"
71
#include "nsIChannelClassifier.h"
71
#include "nsIChannelClassifier.h"
72
#include "nsDocShellCID.h"
72
#include "nsDocShellCID.h"
73
#include "prlog.h"
74
75
#ifdef PR_LOGGING
76
static PRLogModuleInfo* gCspPRLog;
77
#endif
78
73
79
74
//////////////////////////////////////////////////////////////
80
//////////////////////////////////////////////////////////////
75
// Per-request data structure
81
// Per-request data structure
76
//////////////////////////////////////////////////////////////
82
//////////////////////////////////////////////////////////////
77
83
78
class nsScriptLoadRequest : public nsISupports {
84
class nsScriptLoadRequest : public nsISupports {
79
public:
85
public:
80
  nsScriptLoadRequest(nsIScriptElement* aElement,
86
  nsScriptLoadRequest(nsIScriptElement* aElement,
 Lines 122-139   NS_IMPL_THREADSAFE_ISUPPORTS0(nsScriptLo Link Here 
122
//
128
//
123
//////////////////////////////////////////////////////////////
129
//////////////////////////////////////////////////////////////
124
130
125
nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
131
nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
126
  : mDocument(aDocument),
132
  : mDocument(aDocument),
127
    mBlockerCount(0),
133
    mBlockerCount(0),
128
    mEnabled(PR_TRUE),
134
    mEnabled(PR_TRUE),
129
    mDeferEnabled(PR_FALSE),
135
    mDeferEnabled(PR_FALSE),
130
    mUnblockOnloadWhenDoneProcessing(PR_FALSE)
136
    mUnblockOnloadWhenDoneProcessing(PR_FALSE),
137
    mInlineScriptsAllowed(PR_TRUE)
131
{
138
{
139
  // enable logging for CSP
140
#ifdef PR_LOGGING
141
  if (!gCspPRLog)
142
    gCspPRLog = PR_NewLogModule("CSP");
143
#endif
144
145
  IContentSecurityPolicy *csp = mDocument->GetContentSecurityPolicy();
146
  if (csp) {
147
#ifdef PR_LOGGING
148
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("New ScriptLoader i ****with CSP****"));
149
#endif
150
    PRBool inlineOK;
151
    PRBool reportOnly;
152
    if (   NS_SUCCEEDED(csp->GetAllowsInlineScript(&inlineOK))
153
        && NS_SUCCEEDED(csp->GetReportOnlyMode(&reportOnly)) ) {
154
      mInlineScriptsAllowed = inlineOK || reportOnly;
155
    }
156
  }
157
#ifdef PR_LOGGING
158
    PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("New ScriptLoader i NO CSP"));
159
#endif
132
}
160
}
133
161
134
nsScriptLoader::~nsScriptLoader()
162
nsScriptLoader::~nsScriptLoader()
135
{
163
{
136
  mObservers.Clear();
164
  mObservers.Clear();
137
165
138
  for (PRInt32 i = 0; i < mRequests.Count(); i++) {
166
  for (PRInt32 i = 0; i < mRequests.Count(); i++) {
139
    mRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
167
    mRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
 Lines 518-533   nsScriptLoader::ProcessScriptElement(nsI Link Here 
518
          !request->mDefer) {
546
          !request->mDefer) {
519
        nsContentUtils::AddScriptRunner(new nsRunnableMethod<nsScriptLoader>(this,
547
        nsContentUtils::AddScriptRunner(new nsRunnableMethod<nsScriptLoader>(this,
520
          &nsScriptLoader::ProcessPendingRequests));
548
          &nsScriptLoader::ProcessPendingRequests));
521
      }
549
      }
522
550
523
      return request->mDefer ? NS_OK : NS_ERROR_HTMLPARSER_BLOCK;
551
      return request->mDefer ? NS_OK : NS_ERROR_HTMLPARSER_BLOCK;
524
    }
552
    }
525
  }
553
  }
554
  else {
555
    // in-line script
556
    IContentSecurityPolicy *csp = mDocument->GetContentSecurityPolicy();
557
    if (csp) {
558
#ifdef PR_LOGGING
559
      PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("ScriptLoader's document has CSP"));
560
#endif
561
      PRBool inlineOK = PR_TRUE;
562
      PRBool reportOnly = PR_FALSE;
563
      rv = csp->GetAllowsInlineScript(&inlineOK);
564
      NS_ENSURE_SUCCESS(rv, rv);
565
      rv = csp->GetReportOnlyMode(&reportOnly);
566
      NS_ENSURE_SUCCESS(rv, rv);
567
      if (!inlineOK && !reportOnly) {
568
#ifdef PR_LOGGING
569
        PR_LOG(gCspPRLog, PR_LOG_DEBUG, (" CSP blocked inline scripts"));
570
#endif
571
        return NS_ERROR_FAILURE;
572
      }
573
    }
574
#ifdef PR_LOGGING
575
    else PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("ScriptLoader's document NO CSP"));
576
#endif
577
  }
526
578
527
  // Create a request object for this script
579
  // Create a request object for this script
528
  request = new nsScriptLoadRequest(aElement, version);
580
  request = new nsScriptLoadRequest(aElement, version);
529
  NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
581
  NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
530
582
531
  request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
583
  request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
532
584
533
  // First check to see if this is an external script
585
  // First check to see if this is an external script
 Lines 536-551   nsScriptLoader::ProcessScriptElement(nsI Link Here 
536
    request->mIsInline = PR_FALSE;
588
    request->mIsInline = PR_FALSE;
537
    request->mLoading = PR_TRUE;
589
    request->mLoading = PR_TRUE;
538
590
539
    rv = StartLoad(request, type);
591
    rv = StartLoad(request, type);
540
    if (NS_FAILED(rv)) {
592
    if (NS_FAILED(rv)) {
541
      return rv;
593
      return rv;
542
    }
594
    }
543
  } else {
595
  } else {
596
    // in-line script
597
    if (!mInlineScriptsAllowed) {
598
#ifdef PR_LOGGING
599
      PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP blocked inline scripts --2nd chance!"));
600
#endif
601
      return NS_ERROR_FAILURE;
602
    }
544
    request->mLoading = PR_FALSE;
603
    request->mLoading = PR_FALSE;
545
    request->mIsInline = PR_TRUE;
604
    request->mIsInline = PR_TRUE;
546
    request->mURI = mDocument->GetDocumentURI();
605
    request->mURI = mDocument->GetDocumentURI();
547
606
548
    request->mLineNo = aElement->GetScriptLineNumber();
607
    request->mLineNo = aElement->GetScriptLineNumber();
549
608
550
    // If we've got existing pending requests, add ourselves
609
    // If we've got existing pending requests, add ourselves
551
    // to this list.
610
    // to this list.
(-)a/content/base/src/nsScriptLoader.h (+1 lines)
Line     Link Here 
 Lines 321-331   protected: Link Here 
321
321
322
  nsCOMPtr<nsIScriptElement> mCurrentScript;
322
  nsCOMPtr<nsIScriptElement> mCurrentScript;
323
  // XXXbz do we want to cycle-collect these or something?  Not sure.
323
  // XXXbz do we want to cycle-collect these or something?  Not sure.
324
  nsTArray< nsRefPtr<nsScriptLoader> > mPendingChildLoaders;
324
  nsTArray< nsRefPtr<nsScriptLoader> > mPendingChildLoaders;
325
  PRUint32 mBlockerCount;
325
  PRUint32 mBlockerCount;
326
  PRPackedBool mEnabled;
326
  PRPackedBool mEnabled;
327
  PRPackedBool mDeferEnabled;
327
  PRPackedBool mDeferEnabled;
328
  PRPackedBool mUnblockOnloadWhenDoneProcessing;
328
  PRPackedBool mUnblockOnloadWhenDoneProcessing;
329
  PRPackedBool mInlineScriptsAllowed;
329
};
330
};
330
331
331
#endif //__nsScriptLoader_h__
332
#endif //__nsScriptLoader_h__
(-)944b2cd986d9 (+477 lines)
Added Link Here 
Added Link Here 
1
/* ***** BEGIN LICENSE BLOCK *****
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3
 *
4
 * The contents of this file are subject to the Mozilla Public License Version
5
 * 1.1 (the "License"); you may not use this file except in compliance with
6
 * the License. You may obtain a copy of the License at
7
 * http://www.mozilla.org/MPL/
8
 *
9
 * Software distributed under the License is distributed on an "AS IS" basis,
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
 * for the specific language governing rights and limitations under the
12
 * License.
13
 *
14
 * The Original Code is the Content Security Policy Data Structures testing code.
15
 *
16
 * The Initial Developer of the Original Code is
17
 *   Mozilla Corporation
18
 *
19
 * Contributor(s):
20
 *   Sid Stamm <sid@mozilla.com>
21
 *
22
 * Alternatively, the contents of this file may be used under the terms of
23
 * either the GNU General Public License Version 2 or later (the "GPL"), or
24
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25
 * in which case the provisions of the GPL or the LGPL are applicable instead
26
 * of those above. If you wish to allow use of your version of this file only
27
 * under the terms of either the GPL or the LGPL, and not to allow others to
28
 * use your version of this file under the terms of the MPL, indicate your
29
 * decision by deleting the provisions above and replace them with the notice
30
 * and other provisions required by the GPL or the LGPL. If you do not delete
31
 * the provisions above, a recipient may use your version of this file under
32
 * the terms of any one of the MPL, the GPL or the LGPL.
33
 *
34
 * ***** END LICENSE BLOCK ***** */
35
36
//load('CSPUtils.jsm');
37
Components.utils.import('resource://gre/modules/CSPUtils.jsm');
38
39
// load the HTTP server
40
do_load_httpd_js();
41
42
var httpServer = new nsHttpServer();
43
44
const POLICY_FROM_URI = "allow 'self'; img-src *";
45
const POLICY_PORT = 9000;
46
const POLICY_URI = "http://localhost:" + POLICY_PORT + "/policy";
47
48
// helper to assert that an object or array must have a given key
49
function do_check_has_key(foo, key, stack) {
50
  if (!stack) 
51
    stack = Components.stack.caller;
52
53
  var keys = [];
54
  for(let k in keys) { keys.push(k); }
55
  var text = key + " in [" + keys.join(",") + "]";
56
57
  for(var x in foo) {
58
    if(x == key) {
59
      //succeed
60
      ++_passedChecks;
61
      dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
62
           stack.lineNumber + "] " + text + "\n");
63
      return;
64
    }
65
  }
66
  do_throw(text, stack);
67
}
68
69
// helper to use .equals on stuff
70
function do_check_equivalent(foo, bar, stack) {
71
  if (!stack) 
72
    stack = Components.stack.caller;
73
74
  var text = foo + ".equals(" + bar + ")";
75
76
  if(foo.equals && foo.equals(bar)) {
77
    ++_passedChecks;
78
      dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
79
           stack.lineNumber + "] " + text + "\n");
80
      return;
81
  }
82
  do_throw(text, stack);
83
}
84
85
var tests = [];
86
function test(fcn) {
87
  tests.push(fcn);
88
}
89
90
test(
91
  function test_CSPHost_fromstring() {
92
    var h;
93
94
    h = CSPHost.fromString("*");
95
    do_check_neq(null, h); // "* lone wildcard should work"
96
97
    h = CSPHost.fromString("foo.bar");
98
    do_check_neq(null, h); // "standard tuple failed"
99
100
    h = CSPHost.fromString("*.bar");
101
    do_check_neq(null, h); // "wildcard failed"
102
103
    h = CSPHost.fromString("com");
104
    do_check_eq(null, h); // "lone symbol should fail"
105
106
    h = CSPHost.fromString("f00b4r.com");
107
    do_check_neq(null, h); // "Numbers in hosts should work"
108
109
    h = CSPHost.fromString("foo-bar.com");
110
    do_check_neq(null, h); // "dashes in hosts should work"
111
112
    // Not enforced in CSPHost
113
    //h = CSPHost.fromString("foo!bar.com");
114
    //ASSERT_NULL(h, "special chars in hosts should fail");
115
  });
116
117
test(
118
  function test_CSPHost_clone() {
119
    h = CSPHost.fromString("*.a.b.c");
120
    h2 = h.clone();
121
    for(var i in h._segments) {
122
      // "cloned segments should match"
123
      do_check_eq(h._segments[i], h2._segments[i]);
124
    }
125
  });
126
127
test(
128
  function test_CSPHost_permits() {
129
    var h = CSPHost.fromString("*.b.c");
130
    var h2 = CSPHost.fromString("a.b.c");
131
    do_check_true( h.permits(h2));       //"CSPHost *.b.c should allow CSPHost a.b.c"
132
    do_check_true( h.permits("a.b.c"));  //"CSPHost *.b.c should allow string a.b.c"
133
    do_check_true(!h.permits("b.c"));    //"CSPHost *.b.c should not allow string b.c"
134
    do_check_true(!h.permits("a.a.c"));  //"CSPHost *.b.c should not allow string a.a.c"
135
    do_check_true(!h2.permits(h));       //"CSPHost a.b.c should not allow CSPHost *.b.c"
136
    do_check_true(!h2.permits("b.c"));   //"CSPHost a.b.c should not allow string b.c"
137
    do_check_true( h2.permits("a.b.c")); //"CSPHost a.b.c should allow string a.b.c"
138
  });
139
140
test(
141
    function test_CSPHost_intersectWith() {
142
      var h = CSPHost.fromString("*.b.c");
143
      //"*.a.b.c ^ *.b.c should be *.a.b.c"
144
      do_check_eq("*.a.b.c", h.intersectWith(CSPHost.fromString("*.a.b.c")).toString());
145
146
      //"*.b.c ^ *.d.e should not work (null)"
147
      do_check_eq(null, h.intersectWith(CSPHost.fromString("*.d.e")));
148
    });
149
150
///////////////////// Test the Source object //////////////////////
151
152
test(
153
    function test_CSPSource_fromString() {
154
      //"basic source should not be null.");
155
      /*
156
      do_check_neq(null, CSPSource.fromString("a.com"));
157
158
      //"ldh characters should all work for host.");
159
      do_check_neq(null, CSPSource.fromString("a2-c.com"));
160
161
      //"wildcard should work in first token for host.");
162
      do_check_neq(null, CSPSource.fromString("*.a.com"));
163
164
      //print(" --- Ignore the following two errors if they print ---");
165
      //"wildcard should not work in non-first token for host.");
166
      do_check_eq(null, CSPSource.fromString("x.*.a.com"));
167
168
      //"funny characters (#) should not work for host, _HOST_RE is probably broken.");
169
      do_check_eq(null, CSPSource.fromString("a#2-c.com"));
170
      //print(" --- Stop ignoring errors that print ---\n");
171
      */
172
173
      //"failed to parse host with port.");
174
      do_check_neq(null, CSPSource.fromString("http://a.com:23"));
175
      //"failed to parse host with scheme.");
176
      do_check_neq(null, CSPSource.fromString("https://a.com"));
177
      //"failed to parse host with scheme and port.");
178
      do_check_neq(null, CSPSource.fromString("https://a.com:200"));
179
    });
180
181
test(
182
    function test_CSPSource_fromString_withSelf() {
183
      var src;
184
      src = CSPSource.fromString("a.com", "https://foobar.com");
185
      CSPdebug("IN TEST: " + src.toString());
186
      //"src should inherit port *
187
      do_check_true(src.permits("https://a.com:443"));
188
      //"src should inherit and require https scheme
189
      do_check_false(src.permits("http://a.com"));
190
      //"src should inherit scheme 'https'"
191
      do_check_true(src.permits("https://a.com"));
192
      
193
      src = CSPSource.fromString("'self'", "https://foobar.com");
194
      //"src should inherit port *
195
      do_check_true(src.permits("https://foobar.com:443"));
196
      //"src should inherit and require https scheme
197
      do_check_false(src.permits("http://foobar.com"));
198
      //"src should inherit scheme 'https'"
199
      do_check_true(src.permits("https://foobar.com"));
200
      //"src should reject other hosts"
201
      do_check_false(src.permits("https://a.com"));
202
    });
203
204
///////////////////// Test the source list //////////////////////
205
206
test(
207
    function test_CSPSourceList_fromString() {
208
      var sd = CSPSourceList.fromString("'none'");
209
      //"'none' -- should parse"
210
      do_check_neq(null,sd);
211
      // "'none' should be a zero-length list"
212
      do_check_eq(0, sd._sources.length);
213
214
      sd = CSPSourceList.fromString("*");
215
      //"'*' should be a one-length list"
216
      do_check_eq(1, sd._sources.length);
217
218
      //print(" --- Ignore the following three errors if they print ---");
219
      //"funny char in host"
220
      do_check_eq(null,CSPSourceList.fromString("f!oo.bar"));
221
      //"funny char in scheme"
222
      do_check_eq(null,CSPSourceList.fromString("ht!ps://f-oo.bar"));
223
      //"funny char in port"
224
      do_check_eq(null,CSPSourceList.fromString("https://f-oo.bar:3f"));
225
      //print(" --- Stop ignoring errors that print ---\n");
226
    });
227
228
test(
229
    function test_CSPSourceList_fromString_twohost() {
230
      var str = "foo.bar:21 https://ras.bar";
231
      var parsed = "http://foo.bar:21 https://ras.bar";
232
      var sd = CSPSourceList.fromString(str, "http://self.com");
233
      //"two-host list should parse"
234
      do_check_neq(null,sd);
235
      //"two-host list should parse to two hosts"
236
      do_check_eq(2, sd._sources.length);
237
      //"two-host list should contain original data"
238
      do_check_eq(parsed, sd.toString());
239
    });
240
241
test(
242
    function test_CSPSourceList_permits() {
243
      var nullSourceList = CSPSourceList.fromString("'none'");
244
      var simpleSourceList = CSPSourceList.fromString("a.com", "http://self.com");
245
      var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88");
246
      var allSourceList = CSPSourceList.fromString("*");
247
248
      //'none' should permit none."
249
      do_check_true( !nullSourceList.permits("http://a.com"));
250
      //a.com should permit a.com"
251
      do_check_true( simpleSourceList.permits("http://a.com"));
252
      //wrong host"
253
      do_check_true( !simpleSourceList.permits("http://b.com"));
254
      //double list permits http://bar.com:88"
255
      do_check_true( doubleSourceList.permits("http://bar.com:88"));
256
      //double list permits https://bar.com:88"
257
      do_check_true( !doubleSourceList.permits("https://bar.com:88"));
258
      //double list does not permit http://bar.com:443"
259
      do_check_true( !doubleSourceList.permits("http://bar.com:443"));
260
      //"double list permits https://foo.com:88"
261
      do_check_true( doubleSourceList.permits("https://foo.com:88"));
262
      //"double list does not permit foo.com"
263
      do_check_true( !doubleSourceList.permits("http://foo.com"));
264
265
      //"* does not permit specific host"
266
      do_check_true( allSourceList.permits("http://x.com:23"));
267
      //"* does not permit a long host with no port"
268
      do_check_true( allSourceList.permits("http://a.b.c.d.e.f.x.com"));
269
270
    });
271
272
test(
273
    function test_CSPSourceList_intersect() {
274
      var nullSourceList = CSPSourceList.fromString("'none'");
275
      var simpleSourceList = CSPSourceList.fromString("a.com", "http://self.com");
276
      var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88");
277
      var singleFooSourceList = CSPSourceList.fromString("https://foo.com");
278
      var allSourceList = CSPSourceList.fromString("*");
279
280
      //"Intersection of one source with 'none' source list should be none.");
281
      do_check_true(nullSourceList.intersectWith(simpleSourceList).isNone());
282
      //"Intersection of two sources with 'none' source list should be none.");
283
      do_check_true(nullSourceList.intersectWith(doubleSourceList).isNone());
284
      //"Intersection of '*' with 'none' source list should be none.");
285
      do_check_true(nullSourceList.intersectWith(allSourceList).isNone());
286
287
      //"Intersection of one source with '*' source list should be one source.");
288
      do_check_equivalent(allSourceList.intersectWith(simpleSourceList),
289
                          simpleSourceList);
290
      //"Intersection of two sources with '*' source list should be two sources.");
291
      do_check_equivalent(allSourceList.intersectWith(doubleSourceList),
292
                          doubleSourceList);
293
294
      //"Non-overlapping source lists should intersect to 'none'");
295
      do_check_true(simpleSourceList.intersectWith(doubleSourceList).isNone());
296
297
      //"subset and superset should intersect to subset.");
298
      do_check_equivalent(singleFooSourceList,
299
                          doubleSourceList.intersectWith(singleFooSourceList));
300
301
      //TODO: write more tests?
302
303
    });
304
305
///////////////////// Test the Whole CSP rep object //////////////////////
306
307
test(
308
    function test_CSPRep_fromString() {
309
310
      // check default init
311
      //ASSERT(!(new CSPRep())._isInitialized, "Uninitialized rep thinks it is.")
312
313
      var cspr;
314
      var cspr_allowval;
315
316
      // check default policy "allow *"
317
      cspr = CSPRep.fromString("allow *");
318
      //"ALLOW directive is missing when specified in fromString"
319
      do_check_has_key(cspr._directives, CSPRep.SRC_DIRECTIVES.ALLOW);
320
321
      // ... and check that the other directives were auto-filled with the
322
      // ALLOW one.
323
      var SD = CSPRep.SRC_DIRECTIVES;
324
      cspr_allowval = cspr._directives[SD.ALLOW];
325
      for(var d in CSPRep.SRC_DIRECTIVES) {
326
        //"Missing key " + d
327
        do_check_has_key(cspr._directives, SD[d]);
328
        //"Implicit directive " + d + " has non-allow value."
329
        do_check_eq(cspr._directives[SD[d]].toString(), cspr_allowval.toString());
330
      }
331
    });
332
333
334
test(
335
    function test_CSPRep_fromString_oneDir() {
336
337
      var cspr;
338
      var SD = CSPRep.SRC_DIRECTIVES;
339
      var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC,
340
                      SD.FRAME_ANCESTORS, SD.FRAME_SRC];
341
342
      // check one-directive policies
343
      cspr = CSPRep.fromString("allow bar.com; script-src https://foo.com", 
344
                               "http://self.com");
345
346
      for(var x in DEFAULTS) {
347
        //DEFAULTS[x] + " does not use default rule."
348
        do_check_true(cspr.permits("http://bar.com:22", DEFAULTS[x]));
349
        //DEFAULTS[x] + " does not use default rule."
350
        do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
351
      }
352
      //"script-src false positive in policy.
353
      do_check_false(cspr.permits("http://bar.com:22", SD.SCRIPT_SRC));
354
      //"script-src false negative in policy.
355
      do_check_true(cspr.permits("https://foo.com:400", SD.SCRIPT_SRC));
356
    });
357
358
test(
359
    function test_CSPRep_fromString_twodir() {
360
      var cspr;
361
      var SD = CSPRep.SRC_DIRECTIVES;
362
      var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_ANCESTORS, SD.FRAME_SRC];
363
364
      // check two-directive policies
365
      cspr = CSPRep.fromString("allow allow.com; "
366
                             + "script-src https://foo.com; "
367
                             + "img-src bar.com",
368
                             "http://self.com");
369
      for(var x in DEFAULTS) {
370
        do_check_true(cspr.permits("http://allow.com:22", DEFAULTS[x]));
371
        //DEFAULTS[x] + " does not use default rule.
372
        do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
373
        //DEFAULTS[x] + " does not use default rule.
374
        do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x]));
375
        //DEFAULTS[x] + " does not use default rule.
376
      }
377
      //"img-src does not use default rule.
378
      do_check_false(cspr.permits("http://allow.com:22", SD.IMG_SRC));
379
      //"img-src does not use default rule.
380
      do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
381
      //"img-src does not use default rule.
382
      do_check_true(cspr.permits("http://bar.com:400", SD.IMG_SRC));
383
384
      //"script-src does not use default rule.
385
      do_check_false(cspr.permits("http://allow.com:22", SD.SCRIPT_SRC));
386
      //"script-src does not use default rule.
387
      do_check_true(cspr.permits("https://foo.com:400", SD.SCRIPT_SRC));
388
      //"script-src does not use default rule.
389
      do_check_false(cspr.permits("http://bar.com:400", SD.SCRIPT_SRC));
390
    });
391
392
test(function test_CSPRep_fromString_withself() {
393
      var cspr;
394
      var SD = CSPRep.SRC_DIRECTIVES;
395
      var self = "https://self.com:34";
396
397
      // check one-directive policies
398
      cspr = CSPRep.fromString("allow 'self'; script-src 'self' https://*:*",
399
                              self);
400
      //"img-src does not enforce default rule, 'self'.
401
      do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
402
      //"img-src does not allow self
403
      do_check_true(cspr.permits(self, SD.IMG_SRC));
404
      //"script-src is too relaxed
405
      do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC));
406
      //"script-src should allow self
407
      do_check_true(cspr.permits(self, SD.SCRIPT_SRC));
408
      //"script-src is too strict on host/port
409
      do_check_true(cspr.permits("https://evil.com:100", SD.SCRIPT_SRC));
410
     });
411
412
///////////////////// TEST POLICY_URI //////////////////////
413
test(function test_CSPRep_fromPolicyURI() {
414
        var cspr;
415
        var SD = CSPRep.SRC_DIRECTIVES;
416
        var self = "http://localhost:" + POLICY_PORT;
417
418
        cspr = CSPRep.fromString("policy-uri " + POLICY_URI, self);
419
        cspr_static = CSPRep.fromString(POLICY_FROM_URI, self);
420
421
        //"policy-uri failed to load"
422
        do_check_neq(null,cspr);
423
424
        // other directives inherit self
425
        for(var i in SD) {
426
          //SD[i] + " parsed wrong from policy uri"
427
          do_check_equivalent(cspr._directives[SD[i]],
428
                              cspr_static._directives[SD[i]]);
429
        }
430
    });
431
/*
432
433
test(function test_CSPRep_fromPolicyURI_failswhenmixed() {
434
        var cspr;
435
        var self = "http://localhost:" + POLICY_PORT;
436
        var closed_policy = CSPRep.fromString("allow 'none'");
437
        var my_uri_policy = "policy-uri " + POLICY_URI;
438
439
        //print(" --- Ignore the following two errors if they print ---");
440
        cspr = CSPRep.fromString("allow *; " + my_uri_policy, self);
441
442
        //"Parsing should fail when 'policy-uri' is mixed with allow directive"
443
        do_check_equivalent(cspr, closed_policy);
444
        cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, self);
445
446
        //"Parsing should fail when 'policy-uri' is mixed with other directives"
447
        do_check_equivalent(cspr, closed_policy);
448
        //print(" --- Stop ignoring errors that print ---\n");
449
450
    });
451
*/
452
453
// TODO: test reporting
454
// TODO: test refinements (?)
455
// TODO: test 'eval' and 'inline' keywords
456
457
function run_test() {
458
  function policyresponder(request,response) {
459
    response.setStatusLine(request.httpVersion, 200, "OK");
460
    response.setHeader("Content-Type", "text/csp", false);
461
    response.bodyOutputStream.write(POLICY_FROM_URI, POLICY_FROM_URI.length);
462
  }
463
  //server.registerDirectory("/", nsILocalFileForBasePath);
464
  httpServer.registerPathHandler("/policy", policyresponder);
465
  httpServer.start(POLICY_PORT);
466
467
  for(let i in tests) {
468
    tests[i]();
469
  }
470
471
  //teardown
472
  httpServer.stop(function() { });
473
  do_test_finished();
474
}
475
476
477
(-)a/content/events/src/nsEventListenerManager.cpp (-1 / +26 lines)
Line     Link Here 
 Lines 87-102    Link Here 
87
#include "nsContentUtils.h"
87
#include "nsContentUtils.h"
88
#include "nsJSUtils.h"
88
#include "nsJSUtils.h"
89
#include "nsIDOMEventGroup.h"
89
#include "nsIDOMEventGroup.h"
90
#include "nsContentCID.h"
90
#include "nsContentCID.h"
91
#include "nsEventDispatcher.h"
91
#include "nsEventDispatcher.h"
92
#include "nsDOMJSUtils.h"
92
#include "nsDOMJSUtils.h"
93
#include "nsDOMScriptObjectHolder.h"
93
#include "nsDOMScriptObjectHolder.h"
94
#include "nsDataHashtable.h"
94
#include "nsDataHashtable.h"
95
#include "IContentSecurityPolicy.h"
95
96
96
#define EVENT_TYPE_EQUALS( ls, type, userType ) \
97
#define EVENT_TYPE_EQUALS( ls, type, userType ) \
97
  (ls->mEventType && ls->mEventType == type && \
98
  (ls->mEventType && ls->mEventType == type && \
98
  (ls->mEventType != NS_USER_DEFINED_EVENT || ls->mTypeAtom == userType))
99
  (ls->mEventType != NS_USER_DEFINED_EVENT || ls->mTypeAtom == userType))
99
100
100
#define EVENT_TYPE_DATA_EQUALS( type1, type2 ) \
101
#define EVENT_TYPE_DATA_EQUALS( type1, type2 ) \
101
  (type1 && type2 && type1->iid && type2->iid && \
102
  (type1 && type2 && type1->iid && type2->iid && \
102
   type1->iid->Equals(*(type2->iid)))
103
   type1->iid->Equals(*(type2->iid)))
 Lines 684-712   nsEventListenerManager::AddScriptEventLi Link Here 
684
    }
685
    }
685
  }
686
  }
686
687
687
  if (!global) {
688
  if (!global) {
688
    // This can happen; for example this document might have been
689
    // This can happen; for example this document might have been
689
    // loaded as data.
690
    // loaded as data.
690
    return NS_OK;
691
    return NS_OK;
691
  }
692
  }
693
694
  nsresult rv;
695
696
  // return early preventing the event listener from being added
697
  if (doc) {
698
    IContentSecurityPolicy* csp = doc->GetContentSecurityPolicy();
699
    if (csp) {
700
      PRBool inlineOK;
701
      PRBool reportOnly;
702
      rv = csp->GetAllowsInlineScript(&inlineOK);
703
      NS_ENSURE_SUCCESS(rv, rv);
704
      rv = csp->GetReportOnlyMode(&reportOnly);
705
      NS_ENSURE_SUCCESS(rv, rv);
706
      if( !inlineOK ) {
707
        nsAutoString attr;
708
        aName->ToString(attr);
709
        //printf(" *** CSP bailing on adding event listener for: %s\n",
710
        //       ToNewCString(attr));
711
        //TODO: send CSP error report
712
        if( !reportOnly ) {
713
          return NS_OK;
714
        }
715
      }
716
    }
717
  }
692
  
718
  
693
  // This might be the first reference to this language in the global
719
  // This might be the first reference to this language in the global
694
  // We must init the language before we attempt to fetch its context.
720
  // We must init the language before we attempt to fetch its context.
695
  if (NS_FAILED(global->EnsureScriptEnvironment(aLanguage))) {
721
  if (NS_FAILED(global->EnsureScriptEnvironment(aLanguage))) {
696
    NS_WARNING("Failed to setup script environment for this language");
722
    NS_WARNING("Failed to setup script environment for this language");
697
    // but fall through and let the inevitable failure below handle it.
723
    // but fall through and let the inevitable failure below handle it.
698
  }
724
  }
699
725
700
  context = global->GetScriptContext(aLanguage);
726
  context = global->GetScriptContext(aLanguage);
701
  NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
727
  NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
702
728
703
  void *scope = global->GetScriptGlobal(aLanguage);
729
  void *scope = global->GetScriptGlobal(aLanguage);
704
  nsresult rv;
705
730
706
  if (!aDeferCompilation) {
731
  if (!aDeferCompilation) {
707
    nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
732
    nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
708
      do_QueryInterface(aObject);
733
      do_QueryInterface(aObject);
709
734
710
    nsScriptObjectHolder handler(context);
735
    nsScriptObjectHolder handler(context);
711
    PRBool done = PR_FALSE;
736
    PRBool done = PR_FALSE;
712
737
(-)a/docshell/base/nsDocShell.cpp (+8 lines)
Line     Link Here 
 Lines 3559-3574   nsDocShell::DisplayLoadError(nsresult aE Link Here 
3559
        NS_ENSURE_ARG_POINTER(aURI);
3559
        NS_ENSURE_ARG_POINTER(aURI);
3560
        // Get the host
3560
        // Get the host
3561
        nsCAutoString host;
3561
        nsCAutoString host;
3562
        aURI->GetHost(host);
3562
        aURI->GetHost(host);
3563
        CopyUTF8toUTF16(host, formatStrs[0]);
3563
        CopyUTF8toUTF16(host, formatStrs[0]);
3564
        formatStrCount = 1;
3564
        formatStrCount = 1;
3565
        error.AssignLiteral("netTimeout");
3565
        error.AssignLiteral("netTimeout");
3566
    }
3566
    }
3567
    else if ( NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY
3568
             && NS_ERROR_GET_CODE(aError) == 99) {
3569
        // CSP error
3570
        error.AssignLiteral("forbiddenFrameAncestor"); 
3571
        cssClass.AssignLiteral("neterror");
3572
        // TODO: localize this, or at least put the message into a resource
3573
        messageStr.AssignLiteral("CSP Blocked loading of this page because it doesn't trust the page embedding it.");
3574
    } 
3567
    else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY) {
3575
    else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY) {
3568
        nsCOMPtr<nsINSSErrorsService> nsserr =
3576
        nsCOMPtr<nsINSSErrorsService> nsserr =
3569
            do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID);
3577
            do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID);
3570
3578
3571
        PRUint32 errorClass;
3579
        PRUint32 errorClass;
3572
        if (!nsserr ||
3580
        if (!nsserr ||
3573
            NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))) {
3581
            NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))) {
3574
          errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3582
          errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
(-)a/dom/base/nsJSTimeoutHandler.cpp (+30 lines)
Line     Link Here 
 Lines 238-253   nsJSScriptTimeoutHandler::Init(nsGlobalW Link Here 
238
    ::JS_ReportError(cx, "useless %s call (missing quotes around argument?)",
238
    ::JS_ReportError(cx, "useless %s call (missing quotes around argument?)",
239
                     *aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
239
                     *aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
240
240
241
    // Return an error that nsGlobalWindow can recognize and turn into NS_OK.
241
    // Return an error that nsGlobalWindow can recognize and turn into NS_OK.
242
    return NS_ERROR_DOM_TYPE_ERR;
242
    return NS_ERROR_DOM_TYPE_ERR;
243
  }
243
  }
244
244
245
  if (expr) {
245
  if (expr) {
246
    // if CSP is enabled, and setTimeout/setInterval was called with a string
247
    // or object, disable the registration and log an error
248
    nsCOMPtr<nsIDOMDocument> domdoc;
249
    aWindow->GetDocument(getter_AddRefs(domdoc));
250
    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
251
    
252
    if (doc) {
253
      IContentSecurityPolicy* csp = doc->GetContentSecurityPolicy();
254
      if(csp) {
255
        PRBool allowsEval;
256
        PRBool reportOnly;
257
        rv = csp->GetAllowsEval(&allowsEval);
258
        NS_ENSURE_SUCCESS(rv, rv);
259
        rv = csp->GetReportOnlyMode(&reportOnly);
260
        NS_ENSURE_SUCCESS(rv, rv);
261
        if (csp && !allowsEval) {
262
          // CSP policy does NOT allow "eval"
263
          // XXX: we should make this error report a little more informative.
264
          csp->SendReports(
265
                NS_LITERAL_STRING("self"),
266
                NS_LITERAL_STRING("setInterval or setTimeout with string"));
267
          //don't actually fail unless we're not in reportOnly mode
268
          if (!reportOnly) {
269
            return NS_OK;
270
          }
271
        }
272
      }
273
    } // if there's no document, we don't have to do anything.
274
275
      
246
    rv = NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
276
    rv = NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
247
    NS_ENSURE_SUCCESS(rv, rv);
277
    NS_ENSURE_SUCCESS(rv, rv);
248
278
249
    mExpr = expr;
279
    mExpr = expr;
250
280
251
    nsIPrincipal *prin = aWindow->GetPrincipal();
281
    nsIPrincipal *prin = aWindow->GetPrincipal();
252
282
253
    // Get the calling location.
283
    // Get the calling location.
(-)a/layout/build/nsLayoutModule.cpp (-1 / +82 lines)
Line     Link Here 
 Lines 268-283   static nsresult Initialize(nsIModule* aS Link Here 
268
static void Shutdown();
268
static void Shutdown();
269
269
270
#ifdef MOZ_XTF
270
#ifdef MOZ_XTF
271
#include "nsIXTFService.h"
271
#include "nsIXTFService.h"
272
#include "nsIXMLContentBuilder.h"
272
#include "nsIXMLContentBuilder.h"
273
#endif
273
#endif
274
274
275
#include "nsGeolocation.h"
275
#include "nsGeolocation.h"
276
#include "nsCSPService.h"
276
277
277
// Transformiix
278
// Transformiix
278
/* {0C351177-0159-4500-86B0-A219DFDE4258} */
279
/* {0C351177-0159-4500-86B0-A219DFDE4258} */
279
#define TRANSFORMIIX_XPATH1_SCHEME_CID \
280
#define TRANSFORMIIX_XPATH1_SCHEME_CID \
280
{ 0xc351177, 0x159, 0x4500, { 0x86, 0xb0, 0xa2, 0x19, 0xdf, 0xde, 0x42, 0x58 } }
281
{ 0xc351177, 0x159, 0x4500, { 0x86, 0xb0, 0xa2, 0x19, 0xdf, 0xde, 0x42, 0x58 } }
281
282
282
/* 5d5d92cd-6bf8-11d9-bf4a-000a95dc234c */
283
/* 5d5d92cd-6bf8-11d9-bf4a-000a95dc234c */
283
#define TRANSFORMIIX_NODESET_CID \
284
#define TRANSFORMIIX_NODESET_CID \
 Lines 850-865   CreateWindowControllerWithSingletonComma Link Here 
850
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMScriptObjectFactory)
851
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMScriptObjectFactory)
851
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBaseDOMException)
852
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBaseDOMException)
852
853
853
#define NS_GEOLOCATION_SERVICE_CID \
854
#define NS_GEOLOCATION_SERVICE_CID \
854
  { 0x404d02a, 0x1CA, 0xAAAB, { 0x47, 0x62, 0x94, 0x4b, 0x1b, 0xf2, 0xf7, 0xb5 } }
855
  { 0x404d02a, 0x1CA, 0xAAAB, { 0x47, 0x62, 0x94, 0x4b, 0x1b, 0xf2, 0xf7, 0xb5 } }
855
856
856
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationService::GetGeolocationService)
857
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationService::GetGeolocationService)
857
858
859
static NS_METHOD
860
CSPServiceRegistration(nsIComponentManager *aCompMgr,
861
                       nsIFile *aPath,
862
                       const char *registryLocation,
863
                       const char *componentType,
864
                       const nsModuleComponentInfo *info)
865
{
866
  nsresult rv;
867
  nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
868
  if (NS_FAILED(rv))
869
    return rv;
870
871
  nsCOMPtr<nsICategoryManager> catman;
872
  rv = servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
873
                                       NS_GET_IID(nsICategoryManager),
874
                                       getter_AddRefs(catman));
875
  if (NS_FAILED(rv))
876
    return rv;
877
  
878
  char* previous = nsnull;
879
  rv = catman->AddCategoryEntry("xpcom-startup",
880
                                "CSPService",
881
                                CSPSERVICE_CONTRACTID,
882
                                PR_TRUE,
883
                                PR_TRUE,
884
                                &previous);
885
  if (previous)
886
    nsMemory::Free(previous);
887
888
  rv = catman->AddCategoryEntry("content-policy",
889
                                "CSPService",
890
                                CSPSERVICE_CONTRACTID,
891
                                PR_TRUE,
892
                                PR_TRUE,
893
                                &previous);
894
  if (previous)
895
    nsMemory::Free(previous);
896
897
  return rv;
898
}
899
900
static NS_METHOD
901
CSPServiceUnregistration(nsIComponentManager *aCompMgr,
902
                         nsIFile *aPath,
903
                         const char *registryLocation,
904
                         const nsModuleComponentInfo *info){
905
  nsresult rv;
906
907
  nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
908
  if (NS_FAILED(rv))
909
    return rv;
910
911
  nsCOMPtr<nsICategoryManager> catman;
912
  rv = servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
913
                                       NS_GET_IID(nsICategoryManager),
914
                                       getter_AddRefs(catman));
915
  if (NS_FAILED(rv))
916
    return rv;
917
918
  rv = catman->DeleteCategoryEntry("xpcom-startup",
919
                                   "CSPService",
920
                                   PR_TRUE);
921
922
  rv = catman->DeleteCategoryEntry("content-policy",
923
                                   "CSPService",
924
                                   PR_TRUE);
925
926
  return rv;
927
}
928
929
NS_GENERIC_FACTORY_CONSTRUCTOR(CSPService)
930
931
932
858
// The list of components we register
933
// The list of components we register
859
static const nsModuleComponentInfo gComponents[] = {
934
static const nsModuleComponentInfo gComponents[] = {
860
#ifdef DEBUG
935
#ifdef DEBUG
861
  { "Frame utility",
936
  { "Frame utility",
862
    NS_FRAME_UTIL_CID,
937
    NS_FRAME_UTIL_CID,
863
    nsnull,
938
    nsnull,
864
    CreateNewFrameUtil },
939
    CreateNewFrameUtil },
865
  { "Layout debugger",
940
  { "Layout debugger",
 Lines 1454-1470   static const nsModuleComponentInfo gComp Link Here 
1454
      nsTextServicesDocumentConstructor },
1529
      nsTextServicesDocumentConstructor },
1455
#endif
1530
#endif
1456
1531
1457
    { "Geolocation Service",
1532
    { "Geolocation Service",
1458
      NS_GEOLOCATION_SERVICE_CID,
1533
      NS_GEOLOCATION_SERVICE_CID,
1459
      "@mozilla.org/geolocation/service;1",
1534
      "@mozilla.org/geolocation/service;1",
1460
      nsGeolocationServiceConstructor },
1535
      nsGeolocationServiceConstructor },
1461
1536
1462
1537
    { "Content Security Policy Service",
1538
      CSPSERVICE_CID,
1539
      CSPSERVICE_CONTRACTID,
1540
      CSPServiceConstructor,
1541
      CSPServiceRegistration,
1542
      CSPServiceUnregistration
1543
    },
1463
1544
1464
  { "Focus Manager",
1545
  { "Focus Manager",
1465
    NS_FOCUSMANAGER_CID,
1546
    NS_FOCUSMANAGER_CID,
1466
    "@mozilla.org/focus-manager;1",
1547
    "@mozilla.org/focus-manager;1",
1467
    CreateFocusManager },
1548
    CreateFocusManager },
1468
};
1549
};
1469
1550
1470
NS_IMPL_NSGETMODULE_WITH_CTOR(nsLayoutModule, gComponents, Initialize)
1551
NS_IMPL_NSGETMODULE_WITH_CTOR(nsLayoutModule, gComponents, Initialize)
(-)a/modules/libpref/src/init/all.js (+2 lines)
Line     Link Here 
 Lines 919-934   pref("images.dither", "auto"); Link Here 
919
pref("security.directory",              "");
919
pref("security.directory",              "");
920
920
921
pref("signed.applets.codebase_principal_support", false);
921
pref("signed.applets.codebase_principal_support", false);
922
pref("security.checkloaduri", true);
922
pref("security.checkloaduri", true);
923
pref("security.xpconnect.plugin.unrestricted", true);
923
pref("security.xpconnect.plugin.unrestricted", true);
924
// security-sensitive dialogs should delay button enabling. In milliseconds.
924
// security-sensitive dialogs should delay button enabling. In milliseconds.
925
pref("security.dialog_enable_delay", 2000);
925
pref("security.dialog_enable_delay", 2000);
926
926
927
pref("security.csp.enable", true);
928
927
// Modifier key prefs: default to Windows settings,
929
// Modifier key prefs: default to Windows settings,
928
// menu access key = alt, accelerator key = control.
930
// menu access key = alt, accelerator key = control.
929
// Use 17 for Ctrl, 18 for Alt, 224 for Meta, 0 for none. Mac settings in macprefs.js
931
// Use 17 for Ctrl, 18 for Alt, 224 for Meta, 0 for none. Mac settings in macprefs.js
930
pref("ui.key.accelKey", 17);
932
pref("ui.key.accelKey", 17);
931
pref("ui.key.menuAccessKey", 18);
933
pref("ui.key.menuAccessKey", 18);
932
pref("ui.key.generalAccessKey", -1);
934
pref("ui.key.generalAccessKey", -1);
933
935
934
// If generalAccessKey is -1, use the following two prefs instead.
936
// If generalAccessKey is -1, use the following two prefs instead.

Return to bug 493857