From 0318213b63faa71648b1e27baf46ed5660a06cd2 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Tue, 25 Sep 2012 16:06:27 -0700 Subject: [PATCH] Bug 773373 part 2: Use principals instead of URIs when calculating scopes. r=honzab --- dom/src/storage/PStorage.ipdl | 3 +- dom/src/storage/StorageChild.cpp | 12 +-- dom/src/storage/StorageChild.h | 4 +- dom/src/storage/StorageParent.cpp | 3 +- dom/src/storage/StorageParent.h | 1 - dom/src/storage/nsDOMStorage.cpp | 125 ++-------------------- dom/src/storage/nsDOMStorage.h | 12 +-- dom/src/storage/nsDOMStorageDBWrapper.cpp | 63 +++++------ dom/src/storage/nsDOMStorageDBWrapper.h | 15 ++- 9 files changed, 62 insertions(+), 176 deletions(-) diff --git a/dom/src/storage/PStorage.ipdl b/dom/src/storage/PStorage.ipdl index d66f454f5698..ff05e8f90c01 100644 --- a/dom/src/storage/PStorage.ipdl +++ b/dom/src/storage/PStorage.ipdl @@ -36,8 +36,7 @@ parent: __delete__(); Init(bool useDB, bool sessionOnly, bool isPrivate, - nsCString domain, nsCString scopeDBKey, - nsCString quotaDBKey, uint32_t storageType); + nsCString scopeDBKey, nsCString quotaDBKey, uint32_t storageType); sync GetKeys(bool callerSecure) returns (nsString[] keys); diff --git a/dom/src/storage/StorageChild.cpp b/dom/src/storage/StorageChild.cpp index 5ab687eb7f74..ee72b1e5b976 100644 --- a/dom/src/storage/StorageChild.cpp +++ b/dom/src/storage/StorageChild.cpp @@ -83,21 +83,21 @@ StorageChild::InitRemote() ContentChild* child = ContentChild::GetSingleton(); AddIPDLReference(); child->SendPStorageConstructor(this, null_t()); - SendInit(mUseDB, mSessionOnly, mInPrivateBrowsing, mDomain, mScopeDBKey, + SendInit(mUseDB, mSessionOnly, mInPrivateBrowsing, mScopeDBKey, mQuotaDBKey, mStorageType); } void -StorageChild::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate) +StorageChild::InitAsSessionStorage(nsIPrincipal* aPrincipal, bool aPrivate) { - DOMStorageBase::InitAsSessionStorage(aDomainURI, aPrivate); + DOMStorageBase::InitAsSessionStorage(aPrincipal, aPrivate); InitRemote(); } void -StorageChild::InitAsLocalStorage(nsIURI* aDomainURI, bool aPrivate) +StorageChild::InitAsLocalStorage(nsIPrincipal* aPrincipal, bool aPrivate) { - DOMStorageBase::InitAsLocalStorage(aDomainURI, aPrivate); + DOMStorageBase::InitAsLocalStorage(aPrincipal, aPrivate); InitRemote(); } @@ -233,7 +233,7 @@ StorageChild::CloneFrom(bool aCallerSecure, DOMStorageBase* aThat) StorageClone clone(nullptr, other, aCallerSecure); AddIPDLReference(); child->SendPStorageConstructor(this, clone); - SendInit(mUseDB, mSessionOnly, mInPrivateBrowsing, mDomain, + SendInit(mUseDB, mSessionOnly, mInPrivateBrowsing, mScopeDBKey, mQuotaDBKey, mStorageType); return NS_OK; } diff --git a/dom/src/storage/StorageChild.h b/dom/src/storage/StorageChild.h index 3032be2efa66..4f922a32cf27 100644 --- a/dom/src/storage/StorageChild.h +++ b/dom/src/storage/StorageChild.h @@ -26,8 +26,8 @@ public: StorageChild(nsDOMStorage* aOwner); StorageChild(nsDOMStorage* aOwner, StorageChild& aOther); - virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate); - virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aPrivate); + virtual void InitAsSessionStorage(nsIPrincipal* aPrincipal, bool aPrivate); + virtual void InitAsLocalStorage(nsIPrincipal* aPrincipal, bool aPrivate); virtual bool CacheStoragePermissions(); diff --git a/dom/src/storage/StorageParent.cpp b/dom/src/storage/StorageParent.cpp index bc0e995b4f52..87df1f909e06 100644 --- a/dom/src/storage/StorageParent.cpp +++ b/dom/src/storage/StorageParent.cpp @@ -30,12 +30,11 @@ bool StorageParent::RecvInit(const bool& aUseDB, const bool& aSessionOnly, const bool& aPrivate, - const nsCString& aDomain, const nsCString& aScopeDBKey, const nsCString& aQuotaDBKey, const uint32_t& aStorageType) { - mStorage->InitFromChild(aUseDB, aSessionOnly, aPrivate, aDomain, + mStorage->InitFromChild(aUseDB, aSessionOnly, aPrivate, aScopeDBKey, aQuotaDBKey, aStorageType); return true; diff --git a/dom/src/storage/StorageParent.h b/dom/src/storage/StorageParent.h index 5dc822a2ab7a..47f9ff5db15c 100644 --- a/dom/src/storage/StorageParent.h +++ b/dom/src/storage/StorageParent.h @@ -45,7 +45,6 @@ private: bool RecvInit(const bool& aUseDB, const bool& aSessionOnly, const bool& aPrivate, - const nsCString& aDomain, const nsCString& aScopeDBKey, const nsCString& aQuotaDBKey, const uint32_t& aStorageType); diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp index 815f45e79fa2..9b369842c35a 100644 --- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -59,38 +59,6 @@ static const char kStorageEnabled[] = "dom.storage.enabled"; static const char kCookiesBehavior[] = "network.cookie.cookieBehavior"; static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy"; -// The URI returned is the innermost URI that should be used for -// security-check-like stuff. aHost is its hostname, correctly canonicalized. -static nsresult -GetPrincipalURIAndHost(nsIPrincipal* aPrincipal, nsIURI** aURI, nsCString& aHost) -{ - nsresult rv = aPrincipal->GetDomain(aURI); - NS_ENSURE_SUCCESS(rv, rv); - - if (!*aURI) { - rv = aPrincipal->GetURI(aURI); - NS_ENSURE_SUCCESS(rv, rv); - } - - if (!*aURI) { - return NS_OK; - } - - nsCOMPtr innerURI = NS_GetInnermostURI(*aURI); - if (!innerURI) { - return NS_ERROR_UNEXPECTED; - } - - rv = innerURI->GetAsciiHost(aHost); - if (NS_FAILED(rv)) { - return NS_ERROR_DOM_SECURITY_ERR; - } - - innerURI.swap(*aURI); - - return NS_OK; -} - // // Helper that tells us whether the caller is secure or not. // @@ -459,7 +427,6 @@ DOMStorageBase::DOMStorageBase(DOMStorageBase& aThat) : mStorageType(aThat.mStorageType) , mUseDB(false) // Clones don't use the DB , mSessionOnly(true) - , mDomain(aThat.mDomain) , mScopeDBKey(aThat.mScopeDBKey) , mQuotaDBKey(aThat.mQuotaDBKey) , mInPrivateBrowsing(aThat.mInPrivateBrowsing) @@ -467,15 +434,9 @@ DOMStorageBase::DOMStorageBase(DOMStorageBase& aThat) } void -DOMStorageBase::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate) +DOMStorageBase::InitAsSessionStorage(nsIPrincipal* aPrincipal, bool aPrivate) { - // No need to check for a return value. If this would fail we would not get - // here as we call GetPrincipalURIAndHost (nsDOMStorage.cpp:88) from - // nsDOMStorage::CanUseStorage before we query the storage manager for a new - // sessionStorage. It calls GetAsciiHost on innermost URI. If it fails, we - // won't get to InitAsSessionStorage. - aDomainURI->GetAsciiHost(mDomain); - + MOZ_ASSERT(mQuotaDBKey.IsEmpty()); mUseDB = false; mScopeDBKey.Truncate(); mStorageType = nsPIDOMStorage::SessionStorage; @@ -483,18 +444,9 @@ DOMStorageBase::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate) } void -DOMStorageBase::InitAsLocalStorage(nsIURI* aDomainURI, - bool aPrivate) +DOMStorageBase::InitAsLocalStorage(nsIPrincipal* aPrincipal, bool aPrivate) { - // No need to check for a return value. If this would fail we would not get - // here as we call GetPrincipalURIAndHost (nsDOMStorage.cpp:88) from - // nsDOMStorage::CanUseStorage before we query the storage manager for a new - // localStorage. It calls GetAsciiHost on innermost URI. If it fails, we won't - // get to InitAsLocalStorage. Actually, mDomain will get replaced with - // mPrincipal in bug 455070. It is not even used for localStorage. - aDomainURI->GetAsciiHost(mDomain); - - nsDOMStorageDBWrapper::CreateScopeDBKey(aDomainURI, mScopeDBKey); + nsDOMStorageDBWrapper::CreateScopeDBKey(aPrincipal, mScopeDBKey); // XXX Bug 357323, we have to solve the issue how to define // origin for file URLs. In that case CreateOriginScopeDBKey @@ -502,7 +454,7 @@ DOMStorageBase::InitAsLocalStorage(nsIURI* aDomainURI, // in that case because it produces broken entries w/o owner. mUseDB = !mScopeDBKey.IsEmpty(); - nsDOMStorageDBWrapper::CreateQuotaDBKey(mDomain, mQuotaDBKey); + nsDOMStorageDBWrapper::CreateQuotaDBKey(aPrincipal, mQuotaDBKey); mStorageType = nsPIDOMStorage::LocalStorage; mInPrivateBrowsing = aPrivate; } @@ -589,7 +541,6 @@ DOMStorageImpl::InitDB() void DOMStorageImpl::InitFromChild(bool aUseDB, bool aSessionOnly, bool aPrivate, - const nsACString& aDomain, const nsACString& aScopeDBKey, const nsACString& aQuotaDBKey, uint32_t aStorageType) @@ -597,7 +548,6 @@ DOMStorageImpl::InitFromChild(bool aUseDB, mUseDB = aUseDB; mSessionOnly = aSessionOnly; mInPrivateBrowsing = aPrivate; - mDomain = aDomain; mScopeDBKey = aScopeDBKey; mQuotaDBKey = aQuotaDBKey; mStorageType = static_cast(aStorageType); @@ -609,19 +559,6 @@ DOMStorageImpl::SetSessionOnly(bool aSessionOnly) mSessionOnly = aSessionOnly; } -void -DOMStorageImpl::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate) -{ - DOMStorageBase::InitAsSessionStorage(aDomainURI, aPrivate); -} - -void -DOMStorageImpl::InitAsLocalStorage(nsIURI* aDomainURI, - bool aPrivate) -{ - DOMStorageBase::InitAsLocalStorage(aDomainURI, aPrivate); -} - bool DOMStorageImpl::CacheStoragePermissions() { @@ -1122,49 +1059,16 @@ nsDOMStorage::~nsDOMStorage() { } -static -nsresult -GetDomainURI(nsIPrincipal *aPrincipal, bool aIncludeDomain, nsIURI **_domain) -{ - nsCOMPtr uri; - - if (aIncludeDomain) { - nsresult rv = aPrincipal->GetDomain(getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - } - - if (!uri) { - nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - } - - // Check if we really got any URI. System principal doesn't return a URI - // instance and we would crash in NS_GetInnermostURI below. - if (!uri) - return NS_ERROR_NOT_AVAILABLE; - - nsCOMPtr innerURI = NS_GetInnermostURI(uri); - if (!innerURI) - return NS_ERROR_UNEXPECTED; - innerURI.forget(_domain); - - return NS_OK; -} - nsresult nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, bool aPrivate) { - nsCOMPtr domainURI; - nsresult rv = GetDomainURI(aPrincipal, true, getter_AddRefs(domainURI)); - NS_ENSURE_SUCCESS(rv, rv); - mDocumentURI = aDocumentURI; mPrincipal = aPrincipal; mStorageType = SessionStorage; - mStorageImpl->InitAsSessionStorage(domainURI, aPrivate); + mStorageImpl->InitAsSessionStorage(mPrincipal, aPrivate); return NS_OK; } @@ -1172,16 +1076,12 @@ nsresult nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, bool aPrivate) { - nsCOMPtr domainURI; - nsresult rv = GetDomainURI(aPrincipal, false, getter_AddRefs(domainURI)); - NS_ENSURE_SUCCESS(rv, rv); - mDocumentURI = aDocumentURI; mPrincipal = aPrincipal; mStorageType = LocalStorage; - mStorageImpl->InitAsLocalStorage(domainURI, aPrivate); + mStorageImpl->InitAsLocalStorage(aPrincipal, aPrivate); return NS_OK; } @@ -1217,21 +1117,14 @@ nsDOMStorage::CanUseStorage(DOMStorageBase* aStorage /* = NULL */) // if subjectPrincipal were null we'd have returned after // IsCallerChrome(). - nsCOMPtr subjectURI; - nsAutoCString unused; - if (NS_FAILED(GetPrincipalURIAndHost(subjectPrincipal, - getter_AddRefs(subjectURI), - unused))) { - return false; - } - nsCOMPtr permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); if (!permissionManager) return false; uint32_t perm; - permissionManager->TestPermission(subjectURI, kPermissionType, &perm); + permissionManager->TestPermissionFromPrincipal(subjectPrincipal, + kPermissionType, &perm); if (perm == nsIPermissionManager::DENY_ACTION) return false; diff --git a/dom/src/storage/nsDOMStorage.h b/dom/src/storage/nsDOMStorage.h index 81cce9bc8398..935c2eb38f85 100644 --- a/dom/src/storage/nsDOMStorage.h +++ b/dom/src/storage/nsDOMStorage.h @@ -109,8 +109,8 @@ public: DOMStorageBase(); DOMStorageBase(DOMStorageBase&); - virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate); - virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aPrivate); + virtual void InitAsSessionStorage(nsIPrincipal* aPrincipal, bool aPrivate); + virtual void InitAsLocalStorage(nsIPrincipal* aPrincipal, bool aPrivate); virtual nsTArray* GetKeys(bool aCallerSecure) = 0; virtual nsresult GetLength(bool aCallerSecure, uint32_t* aLength) = 0; @@ -190,9 +190,6 @@ protected: // make sure this stays up to date. bool mSessionOnly; - // domain this store is associated with - nsCString mDomain; - // keys are used for database queries. // see comments of the getters bellow. nsCString mScopeDBKey; @@ -213,9 +210,6 @@ public: DOMStorageImpl(nsDOMStorage*, DOMStorageImpl&); ~DOMStorageImpl(); - virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate); - virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aPrivate); - bool SessionOnly() { return mSessionOnly; } @@ -281,7 +275,7 @@ private: // Cross-process storage implementations never have InitAs(Session|Local|Global)Storage // called, so the appropriate initialization needs to happen from the child. void InitFromChild(bool aUseDB, bool aSessionOnly, - bool aPrivate, const nsACString& aDomain, + bool aPrivate, const nsACString& aScopeDBKey, const nsACString& aQuotaDBKey, uint32_t aStorageType); diff --git a/dom/src/storage/nsDOMStorageDBWrapper.cpp b/dom/src/storage/nsDOMStorageDBWrapper.cpp index 9a1ec0fc1aa9..10568f2b8e74 100644 --- a/dom/src/storage/nsDOMStorageDBWrapper.cpp +++ b/dom/src/storage/nsDOMStorageDBWrapper.cpp @@ -19,6 +19,7 @@ #include "mozIStorageFunction.h" #include "nsPrintfCString.h" #include "nsNetUtil.h" +#include "nsIPrincipal.h" void ReverseString(const nsCSubstring& source, nsCSubstring& result) { @@ -226,37 +227,16 @@ nsDOMStorageDBWrapper::GetUsage(const nsACString& aDomain, } nsresult -nsDOMStorageDBWrapper::CreateScopeDBKey(nsIURI* aUri, nsACString& aKey) +nsDOMStorageDBWrapper::CreateScopeDBKey(nsIPrincipal* aPrincipal, + nsACString& aKey) { - nsresult rv; - - rv = CreateReversedDomain(aUri, aKey); - if (NS_FAILED(rv)) - return rv; - - nsAutoCString scheme; - rv = aUri->GetScheme(scheme); + nsCOMPtr uri; + nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); - - aKey.AppendLiteral(":"); - aKey.Append(scheme); - - int32_t port = NS_GetRealPort(aUri); - if (port != -1) { - aKey.AppendLiteral(":"); - aKey.Append(nsPrintfCString("%d", port)); - } - - return NS_OK; -} - -nsresult -nsDOMStorageDBWrapper::CreateReversedDomain(nsIURI* aUri, nsACString& aKey) -{ - nsresult rv; + NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED); nsAutoCString domainScope; - rv = aUri->GetAsciiHost(domainScope); + rv = uri->GetAsciiHost(domainScope); NS_ENSURE_SUCCESS(rv, rv); if (domainScope.IsEmpty()) { @@ -264,16 +244,16 @@ nsDOMStorageDBWrapper::CreateReversedDomain(nsIURI* aUri, nsACString& aKey) // internally by our own redirector, we can trust them and use path as key. // if file:/// protocol, let's make the exact directory the domain bool isScheme = false; - if ((NS_SUCCEEDED(aUri->SchemeIs("about", &isScheme)) && isScheme) || - (NS_SUCCEEDED(aUri->SchemeIs("moz-safe-about", &isScheme)) && isScheme)) { - rv = aUri->GetPath(domainScope); + if ((NS_SUCCEEDED(uri->SchemeIs("about", &isScheme)) && isScheme) || + (NS_SUCCEEDED(uri->SchemeIs("moz-safe-about", &isScheme)) && isScheme)) { + rv = uri->GetPath(domainScope); NS_ENSURE_SUCCESS(rv, rv); // While the host is always canonicalized to lowercase, the path is not, // thus need to force the casing. ToLowerCase(domainScope); } - else if (NS_SUCCEEDED(aUri->SchemeIs("file", &isScheme)) && isScheme) { - nsCOMPtr url = do_QueryInterface(aUri, &rv); + else if (NS_SUCCEEDED(uri->SchemeIs("file", &isScheme)) && isScheme) { + nsCOMPtr url = do_QueryInterface(uri, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = url->GetDirectory(domainScope); NS_ENSURE_SUCCESS(rv, rv); @@ -283,6 +263,17 @@ nsDOMStorageDBWrapper::CreateReversedDomain(nsIURI* aUri, nsACString& aKey) rv = CreateReversedDomain(domainScope, aKey); NS_ENSURE_SUCCESS(rv, rv); + nsAutoCString scheme; + rv = uri->GetScheme(scheme); + NS_ENSURE_SUCCESS(rv, rv); + + aKey.Append(NS_LITERAL_CSTRING(":") + scheme); + + int32_t port = NS_GetRealPort(uri); + if (port != -1) { + aKey.Append(nsPrintfCString(":%d", port)); + } + return NS_OK; } @@ -300,7 +291,7 @@ nsDOMStorageDBWrapper::CreateReversedDomain(const nsACString& aAsciiDomain, } nsresult -nsDOMStorageDBWrapper::CreateQuotaDBKey(const nsACString& aAsciiDomain, +nsDOMStorageDBWrapper::CreateQuotaDBKey(nsIPrincipal* aPrincipal, nsACString& aKey) { nsresult rv; @@ -311,15 +302,15 @@ nsDOMStorageDBWrapper::CreateQuotaDBKey(const nsACString& aAsciiDomain, NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr uri; - rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + aAsciiDomain); + rv = aPrincipal->GetURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED); nsAutoCString eTLDplusOne; rv = eTLDService->GetBaseDomain(uri, 0, eTLDplusOne); if (NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS == rv) { // XXX bug 357323 - what to do for localhost/file exactly? - eTLDplusOne = aAsciiDomain; - rv = NS_OK; + rv = uri->GetAsciiHost(eTLDplusOne); } NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/src/storage/nsDOMStorageDBWrapper.h b/dom/src/storage/nsDOMStorageDBWrapper.h index 77e84a040e77..a20ea18d632e 100644 --- a/dom/src/storage/nsDOMStorageDBWrapper.h +++ b/dom/src/storage/nsDOMStorageDBWrapper.h @@ -173,7 +173,7 @@ public: * i.e. reverses the host, appends a dot, appends the schema * and a port number. */ - static nsresult CreateScopeDBKey(nsIURI* aUri, nsACString& aKey); + static nsresult CreateScopeDBKey(nsIPrincipal* aPrincipal, nsACString& aKey); /** * Turns "http://foo.bar.com" to "moc.rab.oof.", @@ -187,9 +187,20 @@ public: * i.e. extracts eTLD+1 from the host, reverses the result * and appends a dot. */ - static nsresult CreateQuotaDBKey(const nsACString& aAsciiDomain, + static nsresult CreateQuotaDBKey(nsIPrincipal* aPrincipal, nsACString& aKey); + /** + * Turns "foo.bar.com" to "moc.rab.", + * i.e. extracts eTLD+1 from the host, reverses the result + * and appends a dot. + */ + static nsresult CreateQuotaDBKey(const nsACString& aDomain, + nsACString& aKey) + { + return CreateReversedDomain(aDomain, aKey); + } + /** * Ensures the temp table flush timer is running. This is called when we add * data that will need to be flushed.