diff --git a/dom/localstorage/ActorsParent.cpp b/dom/localstorage/ActorsParent.cpp index 2c7f1dabe8cd..eab8845dbd63 100644 --- a/dom/localstorage/ActorsParent.cpp +++ b/dom/localstorage/ActorsParent.cpp @@ -3056,16 +3056,25 @@ void ForceKillAllDatabases() { } bool VerifyPrincipalInfo(const PrincipalInfo& aPrincipalInfo, - const PrincipalInfo& aStoragePrincipalInfo) { + const PrincipalInfo& aStoragePrincipalInfo, + bool aCheckClientPrincipal) { AssertIsOnBackgroundThread(); if (NS_WARN_IF(!QuotaManager::IsPrincipalInfoValid(aPrincipalInfo))) { return false; } + // Note that the client prinicpal could have a different spec than the node + // principal but they should have the same origin. It's because the client + // could be initialized when opening the initial about:blank document and pass + // to the newly opened window and reuse over there if the new window has the + // same origin as the initial about:blank document. But, the FilePath could be + // different. Therefore, we have to ignore comparing the Spec of the + // principals if we are verifying clinet principal here. if (NS_WARN_IF(!StoragePrincipalHelper:: - VerifyValidStoragePrincipalInfoForPrincipalInfo( - aStoragePrincipalInfo, aPrincipalInfo))) { + VerifyValidPartitionedPrincipalInfoForPrincipalInfo( + aStoragePrincipalInfo, aPrincipalInfo, + aCheckClientPrincipal))) { return false; } @@ -3073,7 +3082,7 @@ bool VerifyPrincipalInfo(const PrincipalInfo& aPrincipalInfo, } bool VerifyClientId(const Maybe& aContentParentId, - const PrincipalInfo& aPrincipalInfo, + const Maybe& aPrincipalInfo, const Maybe& aClientId) { AssertIsOnBackgroundThread(); @@ -3082,9 +3091,13 @@ bool VerifyClientId(const Maybe& aContentParentId, return false; } + if (NS_WARN_IF(aPrincipalInfo.isNothing())) { + return false; + } + RefPtr svc = ClientManagerService::GetInstance(); - if (svc && NS_WARN_IF(!svc->HasWindow(aContentParentId, aPrincipalInfo, - aClientId.ref()))) { + if (svc && NS_WARN_IF(!svc->HasWindow( + aContentParentId, aPrincipalInfo.ref(), aClientId.ref()))) { return false; } } @@ -6114,8 +6127,8 @@ bool LSRequestBase::VerifyRequestParams() { const LSRequestCommonParams& params = mParams.get_LSRequestPreloadDatastoreParams().commonParams(); - if (NS_WARN_IF(!VerifyPrincipalInfo(params.principalInfo(), - params.storagePrincipalInfo()))) { + if (NS_WARN_IF(!VerifyPrincipalInfo( + params.principalInfo(), params.storagePrincipalInfo(), false))) { return false; } @@ -6133,14 +6146,21 @@ bool LSRequestBase::VerifyRequestParams() { const LSRequestCommonParams& commonParams = params.commonParams(); - if (NS_WARN_IF( - !VerifyPrincipalInfo(commonParams.principalInfo(), - commonParams.storagePrincipalInfo()))) { + if (NS_WARN_IF(!VerifyPrincipalInfo(commonParams.principalInfo(), + commonParams.storagePrincipalInfo(), + false))) { + return false; + } + + if (params.clientPrincipalInfo() && + NS_WARN_IF(!VerifyPrincipalInfo(commonParams.principalInfo(), + params.clientPrincipalInfo().ref(), + true))) { return false; } if (NS_WARN_IF(!VerifyClientId(mContentParentId, - commonParams.principalInfo(), + params.clientPrincipalInfo(), params.clientId()))) { return false; } @@ -6157,12 +6177,20 @@ bool LSRequestBase::VerifyRequestParams() { const LSRequestPrepareObserverParams& params = mParams.get_LSRequestPrepareObserverParams(); - if (NS_WARN_IF(!VerifyPrincipalInfo(params.principalInfo(), - params.storagePrincipalInfo()))) { + if (NS_WARN_IF(!VerifyPrincipalInfo( + params.principalInfo(), params.storagePrincipalInfo(), false))) { return false; } - if (NS_WARN_IF(!VerifyClientId(mContentParentId, params.principalInfo(), + if (params.clientPrincipalInfo() && + NS_WARN_IF(!VerifyPrincipalInfo(params.principalInfo(), + params.clientPrincipalInfo().ref(), + true))) { + return false; + } + + if (NS_WARN_IF(!VerifyClientId(mContentParentId, + params.clientPrincipalInfo(), params.clientId()))) { return false; } @@ -7782,8 +7810,8 @@ bool LSSimpleRequestBase::VerifyRequestParams() { const LSSimpleRequestPreloadedParams& params = mParams.get_LSSimpleRequestPreloadedParams(); - if (NS_WARN_IF(!VerifyPrincipalInfo(params.principalInfo(), - params.storagePrincipalInfo()))) { + if (NS_WARN_IF(!VerifyPrincipalInfo( + params.principalInfo(), params.storagePrincipalInfo(), false))) { return false; } diff --git a/dom/localstorage/LSObject.cpp b/dom/localstorage/LSObject.cpp index 6c89bc177aae..de3256a68f41 100644 --- a/dom/localstorage/LSObject.cpp +++ b/dom/localstorage/LSObject.cpp @@ -363,6 +363,9 @@ nsresult LSObject::CreateForWindow(nsPIDOMWindowInner* aWindow, Maybe clientId = Some(clientInfo.ref().Id()); + Maybe clientPrincipalInfo = + Some(clientInfo.ref().PrincipalInfo()); + nsString documentURI; if (nsCOMPtr doc = aWindow->GetExtantDoc()) { rv = doc->GetDocumentURI(documentURI); @@ -376,6 +379,7 @@ nsresult LSObject::CreateForWindow(nsPIDOMWindowInner* aWindow, object->mStoragePrincipalInfo = std::move(storagePrincipalInfo); object->mPrivateBrowsingId = privateBrowsingId; object->mClientId = clientId; + object->mClientPrincipalInfo = clientPrincipalInfo; object->mOrigin = origin; object->mOriginKey = originKey; object->mDocumentURI = documentURI; @@ -932,6 +936,7 @@ nsresult LSObject::EnsureDatabase() { LSRequestPrepareDatastoreParams params; params.commonParams() = commonParams; params.clientId() = mClientId; + params.clientPrincipalInfo() = mClientPrincipalInfo; LSRequestResponse response; @@ -992,6 +997,7 @@ nsresult LSObject::EnsureObserver() { params.principalInfo() = *mPrincipalInfo; params.storagePrincipalInfo() = *mStoragePrincipalInfo; params.clientId() = mClientId; + params.clientPrincipalInfo() = mClientPrincipalInfo; LSRequestResponse response; diff --git a/dom/localstorage/LSObject.h b/dom/localstorage/LSObject.h index 451e83d43bd8..68faf4de5966 100644 --- a/dom/localstorage/LSObject.h +++ b/dom/localstorage/LSObject.h @@ -82,6 +82,7 @@ class LSObject final : public Storage { uint32_t mPrivateBrowsingId; Maybe mClientId; + Maybe mClientPrincipalInfo; nsCString mOrigin; nsCString mOriginKey; nsString mDocumentURI; diff --git a/dom/localstorage/PBackgroundLSSharedTypes.ipdlh b/dom/localstorage/PBackgroundLSSharedTypes.ipdlh index e460ebaae033..5802cc821a9c 100644 --- a/dom/localstorage/PBackgroundLSSharedTypes.ipdlh +++ b/dom/localstorage/PBackgroundLSSharedTypes.ipdlh @@ -29,13 +29,30 @@ struct LSRequestPrepareDatastoreParams { LSRequestCommonParams commonParams; nsID? clientId; + PrincipalInfo? clientPrincipalInfo; }; +/** + * In order to validate the principal with the client, we need to provide an + * additional principalInfo for the client. The client is using the foreign + * principal, see StoragePrincipalHelper.h for details, which is different from + * the principalInfo. So, we need to pass the principalInfo from the client So + * that we can verify it with the given client Id. + * + * Note that the storagePrincipalInfo is used to access the right cookie jar + * according to the Storage Access. This is passed in order to access the + * correct local storage. Essentially, the storage principal and the client + * principal are using the PartitionKey in their OriginAttributes. But, the + * existence of the PartitionKey between them is depending on different + * conditions. Namely, the storage principal depends on the Storage Access but + * the client principal depends on whether it's in a third party. + */ struct LSRequestPrepareObserverParams { PrincipalInfo principalInfo; PrincipalInfo storagePrincipalInfo; nsID? clientId; + PrincipalInfo? clientPrincipalInfo; }; union LSRequestParams diff --git a/toolkit/components/antitracking/StoragePrincipalHelper.cpp b/toolkit/components/antitracking/StoragePrincipalHelper.cpp index 4fec2463e252..bac2573a109c 100644 --- a/toolkit/components/antitracking/StoragePrincipalHelper.cpp +++ b/toolkit/components/antitracking/StoragePrincipalHelper.cpp @@ -155,23 +155,26 @@ StoragePrincipalHelper::PrepareEffectiveStoragePrincipalOriginAttributes( } // static -bool StoragePrincipalHelper::VerifyValidStoragePrincipalInfoForPrincipalInfo( - const mozilla::ipc::PrincipalInfo& aStoragePrincipalInfo, - const mozilla::ipc::PrincipalInfo& aPrincipalInfo) { - if (aStoragePrincipalInfo.type() != aPrincipalInfo.type()) { +bool StoragePrincipalHelper:: + VerifyValidPartitionedPrincipalInfoForPrincipalInfo( + const mozilla::ipc::PrincipalInfo& aPartitionedPrincipalInfo, + const mozilla::ipc::PrincipalInfo& aPrincipalInfo, + bool aIgnoreSpecForContentPrincipal) { + if (aPartitionedPrincipalInfo.type() != aPrincipalInfo.type()) { return false; } - if (aStoragePrincipalInfo.type() == + if (aPartitionedPrincipalInfo.type() == mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) { const mozilla::ipc::ContentPrincipalInfo& spInfo = - aStoragePrincipalInfo.get_ContentPrincipalInfo(); + aPartitionedPrincipalInfo.get_ContentPrincipalInfo(); const mozilla::ipc::ContentPrincipalInfo& pInfo = aPrincipalInfo.get_ContentPrincipalInfo(); - if (!spInfo.attrs().EqualsIgnoringFPD(pInfo.attrs()) || + if (!spInfo.attrs().EqualsIgnoringPartitionKey(pInfo.attrs()) || spInfo.originNoSuffix() != pInfo.originNoSuffix() || - spInfo.spec() != pInfo.spec() || spInfo.domain() != pInfo.domain() || + (!aIgnoreSpecForContentPrincipal && spInfo.spec() != pInfo.spec()) || + spInfo.domain() != pInfo.domain() || spInfo.baseDomain() != pInfo.baseDomain()) { return false; } @@ -179,31 +182,31 @@ bool StoragePrincipalHelper::VerifyValidStoragePrincipalInfoForPrincipalInfo( return true; } - if (aStoragePrincipalInfo.type() == + if (aPartitionedPrincipalInfo.type() == mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo) { // Nothing to check here. return true; } - if (aStoragePrincipalInfo.type() == + if (aPartitionedPrincipalInfo.type() == mozilla::ipc::PrincipalInfo::TNullPrincipalInfo) { const mozilla::ipc::NullPrincipalInfo& spInfo = - aStoragePrincipalInfo.get_NullPrincipalInfo(); + aPartitionedPrincipalInfo.get_NullPrincipalInfo(); const mozilla::ipc::NullPrincipalInfo& pInfo = aPrincipalInfo.get_NullPrincipalInfo(); return spInfo.spec() == pInfo.spec() && - spInfo.attrs().EqualsIgnoringFPD(pInfo.attrs()); + spInfo.attrs().EqualsIgnoringPartitionKey(pInfo.attrs()); } - if (aStoragePrincipalInfo.type() == + if (aPartitionedPrincipalInfo.type() == mozilla::ipc::PrincipalInfo::TExpandedPrincipalInfo) { const mozilla::ipc::ExpandedPrincipalInfo& spInfo = - aStoragePrincipalInfo.get_ExpandedPrincipalInfo(); + aPartitionedPrincipalInfo.get_ExpandedPrincipalInfo(); const mozilla::ipc::ExpandedPrincipalInfo& pInfo = aPrincipalInfo.get_ExpandedPrincipalInfo(); - if (!spInfo.attrs().EqualsIgnoringFPD(pInfo.attrs())) { + if (!spInfo.attrs().EqualsIgnoringPartitionKey(pInfo.attrs())) { return false; } @@ -212,8 +215,9 @@ bool StoragePrincipalHelper::VerifyValidStoragePrincipalInfoForPrincipalInfo( } for (uint32_t i = 0; i < spInfo.allowlist().Length(); ++i) { - if (!VerifyValidStoragePrincipalInfoForPrincipalInfo( - spInfo.allowlist()[i], pInfo.allowlist()[i])) { + if (!VerifyValidPartitionedPrincipalInfoForPrincipalInfo( + spInfo.allowlist()[i], pInfo.allowlist()[i], + aIgnoreSpecForContentPrincipal)) { return false; } } diff --git a/toolkit/components/antitracking/StoragePrincipalHelper.h b/toolkit/components/antitracking/StoragePrincipalHelper.h index e6e79a690d71..6fbee6173f5d 100644 --- a/toolkit/components/antitracking/StoragePrincipalHelper.h +++ b/toolkit/components/antitracking/StoragePrincipalHelper.h @@ -242,9 +242,10 @@ class StoragePrincipalHelper final { static nsresult PrepareEffectiveStoragePrincipalOriginAttributes( nsIChannel* aChannel, OriginAttributes& aOriginAttributes); - static bool VerifyValidStoragePrincipalInfoForPrincipalInfo( - const mozilla::ipc::PrincipalInfo& aStoragePrincipalInfo, - const mozilla::ipc::PrincipalInfo& aPrincipalInfo); + static bool VerifyValidPartitionedPrincipalInfoForPrincipalInfo( + const mozilla::ipc::PrincipalInfo& aPartitionedPrincipalInfo, + const mozilla::ipc::PrincipalInfo& aPrincipalInfo, + bool aIgnoreSpecForContentPrincipal); enum PrincipalType { // This is the first-party principal.