From e9c33fe76eeaa7f37e83cd4605d7e3f47f88b571 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Thu, 23 Feb 2012 18:41:25 +0100 Subject: [PATCH] Bug 495337 - Make sessionStorage use principals instead of string domains, r=bz+bclary --- caps/idl/nsIPrincipal.idl | 8 +- caps/src/nsNullPrincipal.cpp | 6 ++ caps/src/nsPrincipal.cpp | 6 ++ caps/src/nsSystemPrincipal.cpp | 7 ++ docshell/base/nsDocShell.cpp | 87 ++++++++----------- dom/src/storage/nsDOMStorage.cpp | 5 +- .../test_sessionStorageFromChrome.xhtml | 2 +- .../tests/ecma/ExecutionContexts/jstests.list | 4 +- js/src/tests/ecma_2/Statements/jstests.list | 2 +- js/src/tests/js1_5/Array/jstests.list | 2 +- js/src/tests/js1_6/extensions/jstests.list | 10 +-- js/src/tests/js1_7/extensions/jstests.list | 4 +- js/src/tests/js1_8/extensions/jstests.list | 4 +- 13 files changed, 77 insertions(+), 70 deletions(-) diff --git a/caps/idl/nsIPrincipal.idl b/caps/idl/nsIPrincipal.idl index 1a6ee520cb6..3a09ca8db51 100644 --- a/caps/idl/nsIPrincipal.idl +++ b/caps/idl/nsIPrincipal.idl @@ -52,7 +52,7 @@ interface nsIContentSecurityPolicy; [ptr] native JSContext(JSContext); [ptr] native JSPrincipals(JSPrincipals); -[scriptable, uuid(B406A2DB-E547-4C95-B8E2-AD09ECB54CE0)] +[scriptable, uuid(1f83b0e0-6b63-4bdc-a50a-b9afe256bd25)] interface nsIPrincipal : nsISerializable { /** @@ -206,6 +206,12 @@ interface nsIPrincipal : nsISerializable */ boolean subsumes(in nsIPrincipal other); + /** + * Same as the previous method, subsumes(), but for codebase principals + * ignores changes to document.domain. + */ + boolean subsumesIgnoringDomain(in nsIPrincipal other); + /** * Checks whether this principal is allowed to load the network resource * located at the given URI under the same-origin policy. This means that diff --git a/caps/src/nsNullPrincipal.cpp b/caps/src/nsNullPrincipal.cpp index 421bc866446..8851652d71c 100644 --- a/caps/src/nsNullPrincipal.cpp +++ b/caps/src/nsNullPrincipal.cpp @@ -336,6 +336,12 @@ nsNullPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult) return NS_OK; } +NS_IMETHODIMP +nsNullPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult) +{ + return Subsumes(aOther, aResult); +} + NS_IMETHODIMP nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport) { diff --git a/caps/src/nsPrincipal.cpp b/caps/src/nsPrincipal.cpp index 6cbc4fa376d..97005d838ad 100644 --- a/caps/src/nsPrincipal.cpp +++ b/caps/src/nsPrincipal.cpp @@ -377,6 +377,12 @@ nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult) return Equals(aOther, aResult); } +NS_IMETHODIMP +nsPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult) +{ + return EqualsIgnoringDomain(aOther, aResult); +} + static bool URIIsLocalFile(nsIURI *aURI) { diff --git a/caps/src/nsSystemPrincipal.cpp b/caps/src/nsSystemPrincipal.cpp index da692682357..690a429a8b6 100644 --- a/caps/src/nsSystemPrincipal.cpp +++ b/caps/src/nsSystemPrincipal.cpp @@ -120,6 +120,13 @@ nsSystemPrincipal::EqualsIgnoringDomain(nsIPrincipal *other, bool *result) NS_IMETHODIMP nsSystemPrincipal::Subsumes(nsIPrincipal *other, bool *result) +{ + *result = PR_TRUE; + return NS_OK; +} + +NS_IMETHODIMP +nsSystemPrincipal::SubsumesIgnoringDomain(nsIPrincipal *other, bool *result) { *result = true; return NS_OK; diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 04227a98612..d4e40f78b05 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -2310,34 +2310,6 @@ nsDocShell::HistoryTransactionRemoved(PRInt32 aIndex) return NS_OK; } -static -nsresult -GetPrincipalDomain(nsIPrincipal* aPrincipal, nsACString& aDomain) -{ - aDomain.Truncate(); - - nsCOMPtr codebaseURI; - nsresult rv = aPrincipal->GetDomain(getter_AddRefs(codebaseURI)); - NS_ENSURE_SUCCESS(rv, rv); - if (!codebaseURI) { - rv = aPrincipal->GetURI(getter_AddRefs(codebaseURI)); - NS_ENSURE_SUCCESS(rv, rv); - } - - if (!codebaseURI) - return NS_OK; - - nsCOMPtr innerURI = NS_GetInnermostURI(codebaseURI); - NS_ASSERTION(innerURI, "Failed to get innermost URI"); - NS_ENSURE_SUCCESS(rv, rv); - - rv = innerURI->GetAsciiHost(aDomain); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - NS_IMETHODIMP nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aDocumentURI, @@ -2367,15 +2339,15 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal, aCreate, aStorage); - nsCAutoString currentDomain; - rv = GetPrincipalDomain(aPrincipal, currentDomain); + nsXPIDLCString origin; + rv = aPrincipal->GetOrigin(getter_Copies(origin)); if (NS_FAILED(rv)) return rv; - if (currentDomain.IsEmpty()) + if (origin.IsEmpty()) return NS_OK; - if (!mStorages.Get(currentDomain, aStorage) && aCreate) { + if (!mStorages.Get(origin, aStorage) && aCreate) { nsCOMPtr newstorage = do_CreateInstance("@mozilla.org/dom/storage;2"); if (!newstorage) @@ -2384,11 +2356,12 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal, nsCOMPtr pistorage = do_QueryInterface(newstorage); if (!pistorage) return NS_ERROR_FAILURE; + rv = pistorage->InitAsSessionStorage(aPrincipal, aDocumentURI); if (NS_FAILED(rv)) return rv; - if (!mStorages.Put(currentDomain, newstorage)) + if (!mStorages.Put(origin, newstorage)) return NS_ERROR_OUT_OF_MEMORY; newstorage.swap(*aStorage); @@ -2399,22 +2372,32 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal, #endif } else if (*aStorage) { - nsCOMPtr piStorage = do_QueryInterface(*aStorage); - if (piStorage) { - bool canAccess = piStorage->CanAccess(aPrincipal); - NS_ASSERTION(canAccess, - "GetSessionStorageForPrincipal got a storage " - "that could not be accessed!"); - if (!canAccess) { - NS_RELEASE(*aStorage); - return NS_ERROR_DOM_SECURITY_ERR; - } - } + nsCOMPtr piStorage = do_QueryInterface(*aStorage); + if (piStorage) { + nsCOMPtr storagePrincipal = piStorage->Principal(); + + // The origin string used to map items in the hash table is + // an implicit security check. That check is double-confirmed + // by checking the principal a storage was demanded for + // really is the principal for which that storage was originally + // created. Originally, the check was hidden in the CanAccess + // method but it's implementation has changed. + bool equals; + nsresult rv = aPrincipal->EqualsIgnoringDomain(storagePrincipal, &equals); + NS_ASSERTION(NS_SUCCEEDED(rv) && equals, + "GetSessionStorageForPrincipal got a storage " + "that could not be accessed!"); + + if (NS_FAILED(rv) || !equals) { + NS_RELEASE(*aStorage); + return NS_ERROR_DOM_SECURITY_ERR; + } + } #if defined(PR_LOGGING) && defined(DEBUG) - PR_LOG(gDocShellLog, PR_LOG_DEBUG, - ("nsDocShell[%p]: returns existing sessionStorage %p", - this, *aStorage)); + PR_LOG(gDocShellLog, PR_LOG_DEBUG, + ("nsDocShell[%p]: returns existing sessionStorage %p", + this, *aStorage)); #endif } @@ -2499,16 +2482,16 @@ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal, if (topItem) { nsCOMPtr topDocShell = do_QueryInterface(topItem); if (topDocShell == this) { - nsCAutoString currentDomain; - rv = GetPrincipalDomain(aPrincipal, currentDomain); + nsXPIDLCString origin; + rv = aPrincipal->GetOrigin(getter_Copies(origin)); if (NS_FAILED(rv)) return rv; - if (currentDomain.IsEmpty()) + if (origin.IsEmpty()) return NS_ERROR_FAILURE; // Do not replace an existing session storage. - if (mStorages.GetWeak(currentDomain)) + if (mStorages.GetWeak(origin)) return NS_ERROR_NOT_AVAILABLE; #if defined(PR_LOGGING) && defined(DEBUG) @@ -2516,7 +2499,7 @@ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal, ("nsDocShell[%p]: was added a sessionStorage %p", this, aStorage)); #endif - if (!mStorages.Put(currentDomain, aStorage)) + if (!mStorages.Put(origin, aStorage)) return NS_ERROR_OUT_OF_MEMORY; } else { diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp index 36422822962..29f329f379a 100644 --- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -1848,8 +1848,7 @@ nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring if (!mStorage) return NS_ERROR_OUT_OF_MEMORY; - // Leave security checks only for domain (nsDOMStorage implementation) - mStorage->mSecurityChecker = mStorage; + mStorage->mSecurityChecker = this; mPrincipal = aPrincipal; mDocumentURI = aDocumentURI; @@ -1949,7 +1948,7 @@ nsDOMStorage2::CanAccess(nsIPrincipal *aPrincipal) // Allow more powerful principals (e.g. system) to access the storage bool subsumes; - nsresult rv = aPrincipal->Subsumes(mPrincipal, &subsumes); + nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes); if (NS_FAILED(rv)) return false; diff --git a/dom/tests/mochitest/sessionstorage/test_sessionStorageFromChrome.xhtml b/dom/tests/mochitest/sessionstorage/test_sessionStorageFromChrome.xhtml index 51651f8940a..79a5a92808d 100644 --- a/dom/tests/mochitest/sessionstorage/test_sessionStorageFromChrome.xhtml +++ b/dom/tests/mochitest/sessionstorage/test_sessionStorageFromChrome.xhtml @@ -16,7 +16,7 @@ function startTest() sessionStorage; } catch (e) { - is(e.result, 2152923145, + is(e.result, Components.results.NS_ERROR_NOT_AVAILABLE, "Testing that we get the expected exception."); exceptionCaught = true; } diff --git a/js/src/tests/ecma/ExecutionContexts/jstests.list b/js/src/tests/ecma/ExecutionContexts/jstests.list index c1c80c44565..3ea22b45e7a 100644 --- a/js/src/tests/ecma/ExecutionContexts/jstests.list +++ b/js/src/tests/ecma/ExecutionContexts/jstests.list @@ -18,7 +18,7 @@ script 10.1.5-4.js script 10.1.8-2.js script 10.1.8-3.js script 10.2.1.js -skip-if(!xulRuntime.shell) script 10.2.2-1.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR Line 91 -skip-if(!xulRuntime.shell) script 10.2.2-2.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR Line 177 +skip-if(Android) script 10.2.2-1.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android +skip-if(Android) script 10.2.2-2.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android script 10.2.3-1.js script 10.2.3-2.js diff --git a/js/src/tests/ecma_2/Statements/jstests.list b/js/src/tests/ecma_2/Statements/jstests.list index 1ff55589ad2..c906535bc02 100644 --- a/js/src/tests/ecma_2/Statements/jstests.list +++ b/js/src/tests/ecma_2/Statements/jstests.list @@ -7,7 +7,7 @@ script dowhile-005.js script dowhile-006.js script dowhile-007.js script forin-001.js -fails-if(!xulRuntime.shell) script forin-002.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 112 +skip-if(Android) script forin-002.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android script if-001.js script label-001.js script label-002.js diff --git a/js/src/tests/js1_5/Array/jstests.list b/js/src/tests/js1_5/Array/jstests.list index 52f795e0906..2197ad88f21 100644 --- a/js/src/tests/js1_5/Array/jstests.list +++ b/js/src/tests/js1_5/Array/jstests.list @@ -3,7 +3,7 @@ script 11.1.4.js script array-001.js random script regress-101964.js # bogus perf test (bug 467263) script regress-107138.js -fails-if(!xulRuntime.shell) script regress-108440.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 74 +skip-if(Android) script regress-108440.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android script regress-154338.js skip-if(xulRuntime.XPCOMABI.match(/x86_64/)||Android) script regress-157652.js # No test results script regress-178722.js diff --git a/js/src/tests/js1_6/extensions/jstests.list b/js/src/tests/js1_6/extensions/jstests.list index 9edc018ee15..c613e9e9a98 100644 --- a/js/src/tests/js1_6/extensions/jstests.list +++ b/js/src/tests/js1_6/extensions/jstests.list @@ -3,15 +3,15 @@ script regress-312385-01.js script regress-352392.js script regress-385393-08.js script regress-414098.js -fails-if(!xulRuntime.shell) script regress-455464-01.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 1 -fails-if(!xulRuntime.shell) script regress-455464-02.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 49 -fails-if(!xulRuntime.shell) script regress-455464-03.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 1 -fails-if(!xulRuntime.shell&&!isDebugBuild) skip-if((!xulRuntime.shell&&isDebugBuild)||Android) script regress-455464-04.js # bug xxx - hangs reftests in debug, ### bug xxx - NS_ERROR_DOM_NOT_SUPPORTED_ERR in opt +skip-if(Android) script regress-455464-01.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android +skip-if(Android) script regress-455464-02.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android +skip-if(Android) script regress-455464-03.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android +skip-if(Android) script regress-455464-04.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android skip-if(!xulRuntime.shell||Android) slow script regress-456826.js # bug 504632 script regress-457521.js script regress-465443.js script regress-470310.js script regress-472508.js -fails-if(!xulRuntime.shell) script regress-475144.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR +skip-if(Android) script regress-475144.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android script regress-479567.js script regress-565521.js diff --git a/js/src/tests/js1_7/extensions/jstests.list b/js/src/tests/js1_7/extensions/jstests.list index 200de49581e..441323598fa 100644 --- a/js/src/tests/js1_7/extensions/jstests.list +++ b/js/src/tests/js1_7/extensions/jstests.list @@ -51,8 +51,8 @@ script regress-392308.js script regress-396326.js script regress-429266.js script regress-453955.js -fails-if(!xulRuntime.shell) script regress-455982-01.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR -fails-if(!xulRuntime.shell) script regress-455982-02.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR +skip-if(Android) script regress-455982-01.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android +skip-if(Android) script regress-455982-02.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android skip-if(!xulRuntime.shell||xulRuntime.shell&&xulRuntime.XPCOMABI.match(/x86_64/)) slow script regress-458679.js script regress-469234.js script regress-469405-01.js diff --git a/js/src/tests/js1_8/extensions/jstests.list b/js/src/tests/js1_8/extensions/jstests.list index d5cbee130bf..818f441856d 100644 --- a/js/src/tests/js1_8/extensions/jstests.list +++ b/js/src/tests/js1_8/extensions/jstests.list @@ -20,7 +20,7 @@ script regress-422269.js skip script regress-445818.js skip script regress-446169-01.js skip script regress-446169-02.js -fails-if(!xulRuntime.shell) script regress-452476.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR +skip-if(Android) script regress-452476.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android script regress-452913.js script regress-454744.js script regress-455973.js @@ -34,7 +34,7 @@ script regress-473040.js skip script regress-475971.js skip-if(!xulRuntime.shell) slow script regress-476414-01.js skip-if(!xulRuntime.shell) slow script regress-476414-02.js -fails-if(!xulRuntime.shell) script regress-476427.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR +skip-if(Android) script regress-476427.js # bug - nsIDOMWindow.crypto throws NS_ERROR_NOT_IMPLEMENTED on Android script regress-476653.js skip-if(Android) script regress-476869.js script regress-476871-02.js