From: Gavin Sharp <gavin@gavinsharp.com>
Date: Mon, 5 Mar 2012 16:24:38 -0800
Subject: Bug 723808: disallow inheriting of system principal in type=content
 docshells, r=bz, a=lsblakk

---
 docshell/base/nsDocShell.cpp                   |   14 ++++-
 docshell/test/chrome/Makefile.in               |    1 +
 docshell/test/chrome/test_principalInherit.xul |   92 ++++++++++++++++++++++++
 3 files changed, 106 insertions(+), 1 deletions(-)
 create mode 100644 docshell/test/chrome/test_principalInherit.xul

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 7b9d6d6..1edf23a 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7525,6 +7525,7 @@ nsIPrincipal*
 nsDocShell::GetInheritedPrincipal(PRBool aConsiderCurrentDocument)
 {
     nsCOMPtr<nsIDocument> document;
+    PRBool inheritedFromCurrent = PR_FALSE;
 
     if (aConsiderCurrentDocument && mContentViewer) {
         nsCOMPtr<nsIDocumentViewer>
@@ -7532,6 +7533,7 @@ nsDocShell::GetInheritedPrincipal(PRBool aConsiderCurrentDocument)
         if (!docViewer)
             return nsnull;
         docViewer->GetDocument(getter_AddRefs(document));
+        inheritedFromCurrent = PR_TRUE;
     }
 
     if (!document) {
@@ -7562,7 +7564,17 @@ nsDocShell::GetInheritedPrincipal(PRBool aConsiderCurrentDocument)
 
     //-- Get the document's principal
     if (document) {
-        return document->NodePrincipal();
+        nsIPrincipal *docPrincipal = document->NodePrincipal();
+
+        // Don't allow loads in typeContent docShells to inherit the system
+        // principal from existing documents.
+        if (inheritedFromCurrent &&
+            mItemType == typeContent &&
+            nsContentUtils::IsSystemPrincipal(docPrincipal)) {
+            return nsnull;
+        }
+
+        return docPrincipal;
     }
 
     return nsnull;
diff --git a/docshell/test/chrome/Makefile.in b/docshell/test/chrome/Makefile.in
index a60061b..61aca53 100644
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -79,6 +79,7 @@ _TEST_FILES =	\
 		test_bug454235.xul \
 		bug454235-subframe.xul \
 		test_bug456980.xul \
+		test_principalInherit.xul \
 		$(NULL)
 		
 _DOCSHELL_SUBHARNESS = \
diff --git a/docshell/test/chrome/test_principalInherit.xul b/docshell/test/chrome/test_principalInherit.xul
new file mode 100644
index 0000000..9e7ae9c
--- /dev/null
+++ b/docshell/test/chrome/test_principalInherit.xul
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+  href="chrome://mochikit/content/tests/SimpleTest/test.css"
+  type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=719994
+-->
+<window title="Test principal inheriting"
+  xmlns:html="http://www.w3.org/1999/xhtml"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <title>Test principal inheriting</title>
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 719994 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var gFrame;
+
+// This test file is loaded in a type=content docshell whose principal is
+// the system principal.
+
+// Using data: URIs here instead of javascript: URIs, since javascript: URIs
+// fail to load when there's no principal to load them against. This only
+// matters when these tests fail (produces better error messages).
+var tests = [
+  function testInheritFromParent(cb) {
+    gFrame = document.createElement("iframe");
+    loadListener(gFrame, function () {
+      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+      is(window.inheritedFromParent, true, "load in type=content iframe inherited principal of same type parent");
+      cb();
+    });
+    gFrame.setAttribute("type", "content");
+    gFrame.setAttribute("src", "data:text/html,<script>parent.inheritedFromParent = true;</script>");
+    document.documentElement.appendChild(gFrame);
+  },
+  function testInheritFromCurrent_system(cb) {
+    loadListener(gFrame, function () {
+      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+      is(window.inheritedSystem, undefined, "load in type=content iframe shouldn't inherit system principal from current document");
+      cb();
+    }, true);
+    gFrame.setAttribute("src", "data:text/html,<script>parent.inheritedSystem = true;</script>");
+  }
+];
+
+addLoadEvent(function onLoad() {
+  SimpleTest.executeSoon(nextTest);
+});
+
+function loadListener(target, func) {
+  target.addEventListener("load", function lis() {
+    target.removeEventListener("load", lis, true);
+    func();
+  }, true);
+}
+
+function nextTest() {
+  if (tests.length) {
+    let test = tests.shift();
+    SimpleTest.executeSoon(function () {
+      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+      ok(Components.stack, "this test must be run with the system principal");
+      test(nextTest);
+    });
+  } else
+    SimpleTest.executeSoon(SimpleTest.finish);
+}
+
+]]>
+</script>
+
+</window>
