Bug 802557 - Do more direct comparisons with the outer window. r=bz a=akeybl
authorBobby Holley <bobbyholley@gmail.com>
Fri, 19 Oct 2012 01:37:14 +0200
changeset 109642 cc904411ff4396e0c2914fb5fbfa50580a9ef40f
parent 109641 2dc642d4daef3adada5dcc66ad9cecf06e4f129e
child 109643 a00a19219da236bd1fd889d49ca5a8a4044d945a
push id1588
push userbobbyholley@gmail.com
push dateTue, 23 Oct 2012 13:49:19 +0000
treeherdermozilla-beta@a00a19219da2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, akeybl
bugs802557
milestone17.0
Bug 802557 - Do more direct comparisons with the outer window. r=bz a=akeybl
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
dom/base/nsLocation.cpp
dom/base/nsLocation.h
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -501,16 +501,20 @@ public:
    * Get the cache security manager service. Can return null if the layout
    * module has been shut down.
    */
   static nsIScriptSecurityManager* GetSecurityManager()
   {
     return sSecurityManager;
   }
 
+  // Returns the subject principal. Guaranteed to return non-null. May only
+  // be called when nsContentUtils is initialized.
+  static nsIPrincipal* GetSubjectPrincipal();
+
   static nsresult GenerateStateKey(nsIContent* aContent,
                                    const nsIDocument* aDocument,
                                    nsIStatefulFrame::SpecialStateID aID,
                                    nsACString& aKey);
 
   /**
    * Create a new nsIURI from aSpec, using aBaseURI as the base.  The
    * origin charset of the new nsIURI will be the document charset of
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2380,16 +2380,30 @@ nsContentUtils::GenerateStateKey(nsICont
       parent = content->GetNodeParent();
     }
   }
 
   return NS_OK;
 }
 
 // static
+nsIPrincipal*
+nsContentUtils::GetSubjectPrincipal()
+{
+  nsCOMPtr<nsIPrincipal> subject;
+  sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subject));
+
+  // When the ssm says the subject is null, that means system principal.
+  if (!subject)
+    sSecurityManager->GetSystemPrincipal(getter_AddRefs(subject));
+
+  return subject;
+}
+
+// static
 nsresult
 nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
                                           const nsAString& aSpec,
                                           nsIDocument* aDocument,
                                           nsIURI* aBaseURI)
 {
   return NS_NewURI(aResult, aSpec,
                    aDocument ? aDocument->GetDocumentCharacterSet().get() : nullptr,
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsLocation.h"
 #include "nsIScriptSecurityManager.h"
+#include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellLoadInfo.h"
 #include "nsIWebNavigation.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIURIFixup.h"
 #include "nsIURL.h"
 #include "nsIJARURI.h"
@@ -101,16 +102,18 @@ GetDocumentCharacterSetForURI(const nsAS
   }
 
   return NS_OK;
 }
 
 nsLocation::nsLocation(nsIDocShell *aDocShell)
 {
   mDocShell = do_GetWeakReference(aDocShell);
+  nsCOMPtr<nsIDOMWindow> outer = do_GetInterface(aDocShell);
+  mOuter = do_GetWeakReference(outer);
 }
 
 nsLocation::~nsLocation()
 {
 }
 
 DOMCI_DATA(Location, nsLocation)
 
@@ -335,16 +338,19 @@ nsLocation::SetURI(nsIURI* aURI, bool aR
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLocation::GetHash(nsAString& aHash)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   aHash.SetLength(0);
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = GetURI(getter_AddRefs(uri));
   if (NS_FAILED(rv) || !uri) {
     return rv;
   }
 
@@ -407,16 +413,19 @@ nsLocation::SetHash(const nsAString& aHa
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsLocation::GetHost(nsAString& aHost)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   aHost.Truncate();
 
   nsCOMPtr<nsIURI> uri;
   nsresult result;
 
   result = GetURI(getter_AddRefs(uri), true);
 
   if (uri) {
@@ -430,32 +439,38 @@ nsLocation::GetHost(nsAString& aHost)
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLocation::SetHost(const nsAString& aHost)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   nsCOMPtr<nsIURI> uri;
   nsresult rv = GetWritableURI(getter_AddRefs(uri));
 
   if (uri) {
     rv = uri->SetHostPort(NS_ConvertUTF16toUTF8(aHost));
     if (NS_SUCCEEDED(rv)) {
       SetURI(uri);
     }
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsLocation::GetHostname(nsAString& aHostname)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   aHostname.Truncate();
 
   nsCOMPtr<nsIURI> uri;
   nsresult result;
 
   result = GetURI(getter_AddRefs(uri), true);
 
   if (uri) {
@@ -469,32 +484,38 @@ nsLocation::GetHostname(nsAString& aHost
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLocation::SetHostname(const nsAString& aHostname)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   nsCOMPtr<nsIURI> uri;
   nsresult rv = GetWritableURI(getter_AddRefs(uri));
 
   if (uri) {
     rv = uri->SetHost(NS_ConvertUTF16toUTF8(aHostname));
     if (NS_SUCCEEDED(rv)) {
       SetURI(uri);
     }
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsLocation::GetHref(nsAString& aHref)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   aHref.Truncate();
 
   nsCOMPtr<nsIURI> uri;
   nsresult result;
 
   result = GetURI(getter_AddRefs(uri));
 
   if (uri) {
@@ -617,16 +638,19 @@ nsLocation::SetHrefWithBase(const nsAStr
   }
 
   return result;
 }
 
 NS_IMETHODIMP
 nsLocation::GetPathname(nsAString& aPathname)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   aPathname.Truncate();
 
   nsCOMPtr<nsIURI> uri;
   nsresult result = NS_OK;
 
   result = GetURI(getter_AddRefs(uri));
 
   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
@@ -641,32 +665,38 @@ nsLocation::GetPathname(nsAString& aPath
   }
 
   return result;
 }
 
 NS_IMETHODIMP
 nsLocation::SetPathname(const nsAString& aPathname)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   nsCOMPtr<nsIURI> uri;
   nsresult rv = GetWritableURI(getter_AddRefs(uri));
 
   if (uri) {
     rv = uri->SetPath(NS_ConvertUTF16toUTF8(aPathname));
     if (NS_SUCCEEDED(rv)) {
       SetURI(uri);
     }
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsLocation::GetPort(nsAString& aPort)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   aPort.SetLength(0);
 
   nsCOMPtr<nsIURI> uri;
   nsresult result = NS_OK;
 
   result = GetURI(getter_AddRefs(uri), true);
 
   if (uri) {
@@ -684,16 +714,19 @@ nsLocation::GetPort(nsAString& aPort)
   }
 
   return result;
 }
 
 NS_IMETHODIMP
 nsLocation::SetPort(const nsAString& aPort)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   nsCOMPtr<nsIURI> uri;
   nsresult rv = GetWritableURI(getter_AddRefs(uri));
 
   if (uri) {
     // perhaps use nsReadingIterators at some point?
     NS_ConvertUTF16toUTF8 portStr(aPort);
     const char *buf = portStr.get();
     int32_t port = -1;
@@ -714,16 +747,19 @@ nsLocation::SetPort(const nsAString& aPo
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsLocation::GetProtocol(nsAString& aProtocol)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   aProtocol.SetLength(0);
 
   nsCOMPtr<nsIURI> uri;
   nsresult result = NS_OK;
 
   result = GetURI(getter_AddRefs(uri));
 
   if (uri) {
@@ -738,32 +774,38 @@ nsLocation::GetProtocol(nsAString& aProt
   }
 
   return result;
 }
 
 NS_IMETHODIMP
 nsLocation::SetProtocol(const nsAString& aProtocol)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   nsCOMPtr<nsIURI> uri;
   nsresult rv = GetWritableURI(getter_AddRefs(uri));
 
   if (uri) {
     rv = uri->SetScheme(NS_ConvertUTF16toUTF8(aProtocol));
     if (NS_SUCCEEDED(rv)) {
       SetURI(uri);
     }
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsLocation::GetSearch(nsAString& aSearch)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   aSearch.SetLength(0);
 
   nsCOMPtr<nsIURI> uri;
   nsresult result = NS_OK;
 
   result = GetURI(getter_AddRefs(uri));
 
   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
@@ -780,16 +822,19 @@ nsLocation::GetSearch(nsAString& aSearch
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLocation::SetSearch(const nsAString& aSearch)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   nsCOMPtr<nsIURI> uri;
   nsresult rv = GetWritableURI(getter_AddRefs(uri));
 
   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
   if (url) {
     rv = url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
     if (NS_SUCCEEDED(rv)) {
       SetURI(uri);
@@ -797,16 +842,19 @@ nsLocation::SetSearch(const nsAString& a
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsLocation::Reload(bool aForceget)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   nsresult rv;
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
   nsCOMPtr<nsPIDOMWindow> window(do_GetInterface(docShell));
 
   if (window && window->IsHandlingResizeEvent()) {
     // location.reload() was called on a window that is handling a
     // resize event. Sites do this since Netscape 4.x needed it, but
@@ -877,16 +925,19 @@ nsLocation::Replace(const nsAString& aUr
   NS_ENSURE_SUCCESS(rv, rv);
 
   return SetHrefWithBase(aUrl, oldUri, true);
 }
 
 NS_IMETHODIMP
 nsLocation::Assign(const nsAString& aUrl)
 {
+  if (!CallerSubsumes())
+    return NS_ERROR_DOM_SECURITY_ERR;
+
   nsAutoString oldHref;
   nsresult result = NS_OK;
 
   result = GetHref(oldHref);
 
   if (NS_SUCCEEDED(result)) {
     nsCOMPtr<nsIURI> oldUri;
 
@@ -898,16 +949,17 @@ nsLocation::Assign(const nsAString& aUrl
   }
 
   return result;
 }
 
 NS_IMETHODIMP
 nsLocation::ToString(nsAString& aReturn)
 {
+  // NB: GetHref checks CallerSubsumes().
   return GetHref(aReturn);
 }
 
 nsresult
 nsLocation::GetSourceDocument(JSContext* cx, nsIDocument** aDocument)
 {
   // XXX Code duplicated from nsHTMLDocument
   // XXX Tom said this reminded him of the "Six Degrees of
@@ -947,8 +999,22 @@ nsLocation::GetSourceBaseURL(JSContext* 
   if (doc) {
     *sourceURL = doc->GetBaseURI().get();
   } else {
     *sourceURL = nullptr;
   }
 
   return rv;
 }
+
+bool
+nsLocation::CallerSubsumes()
+{
+  // Get the principal associated with the location object.
+  nsCOMPtr<nsIDOMWindow> outer = do_QueryReferent(mOuter);
+  if (NS_UNLIKELY(!outer))
+    return false;
+  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(outer);
+  bool subsumes = false;
+  nsresult rv = nsContentUtils::GetSubjectPrincipal()->Subsumes(sop->GetPrincipal(), &subsumes);
+  NS_ENSURE_SUCCESS(rv, false);
+  return subsumes;
+}
--- a/dom/base/nsLocation.h
+++ b/dom/base/nsLocation.h
@@ -47,15 +47,17 @@ protected:
                            bool aReplace);
   nsresult SetHrefWithContext(JSContext* cx, const nsAString& aHref,
                               bool aReplace);
 
   nsresult GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL);
   nsresult GetSourceDocument(JSContext* cx, nsIDocument** aDocument);
 
   nsresult CheckURL(nsIURI *url, nsIDocShellLoadInfo** aLoadInfo);
+  bool CallerSubsumes();
 
   nsString mCachedHash;
   nsWeakPtr mDocShell;
+  nsWeakPtr mOuter;
 };
 
 #endif // nsLocation_h__