зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1530854: Always create CSP on Principal so the explicit CSP in the nsISHEntry holds a reference to the potentially dynamically modified CSP in case of a meta CSP. r=bzbarsky
Differential Revision: https://phabricator.services.mozilla.com/D21919 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
9ccb997cf4
Коммит
980f75a172
|
@ -289,12 +289,69 @@ static void InheritAndSetCSPOnPrincipalIfNeeded(nsIChannel* aChannel,
|
|||
nsCOMPtr<nsIContentSecurityPolicy> nullPrincipalCSP;
|
||||
aPrincipal->GetCsp(getter_AddRefs(nullPrincipalCSP));
|
||||
if (nullPrincipalCSP) {
|
||||
MOZ_ASSERT(nullPrincipalCSP == originalCSP,
|
||||
"There should be no other CSP here.");
|
||||
#ifdef DEBUG
|
||||
{
|
||||
uint32_t nullPrincipalCSPCount = 0;
|
||||
nullPrincipalCSP->GetPolicyCount(&nullPrincipalCSPCount);
|
||||
|
||||
uint32_t originalCSPCount = 0;
|
||||
originalCSP->GetPolicyCount(&originalCSPCount);
|
||||
|
||||
MOZ_ASSERT(nullPrincipalCSPCount == originalCSPCount,
|
||||
"There should be no other CSP here.");
|
||||
|
||||
nsAutoString nullPrincipalCSPStr, originalCSPStr;
|
||||
for (uint32_t i = 0; i < originalCSPCount; ++i) {
|
||||
originalCSP->GetPolicyString(i, originalCSPStr);
|
||||
nullPrincipalCSP->GetPolicyString(i, nullPrincipalCSPStr);
|
||||
MOZ_ASSERT(originalCSPStr.Equals(nullPrincipalCSPStr),
|
||||
"There should be no other CSP string here.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// CSPs are equal, no need to set it again.
|
||||
return;
|
||||
}
|
||||
aPrincipal->SetCsp(originalCSP);
|
||||
|
||||
// After 965637 all that magical CSP inheritance goes away. For now,
|
||||
// we have to create a clone of the current CSP and have to manually
|
||||
// set it on the Principal.
|
||||
uint32_t count = 0;
|
||||
rv = originalCSP->GetPolicyCount(&count);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
// fast path: if there is nothing to inherit, we can return here.
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<nsCSPContext> newCSP = new nsCSPContext();
|
||||
nsWeakPtr loadingContext =
|
||||
static_cast<nsCSPContext*>(originalCSP.get())->GetLoadingContext();
|
||||
nsCOMPtr<Document> doc = do_QueryReferent(loadingContext);
|
||||
|
||||
rv = doc ? newCSP->SetRequestContext(doc, nullptr)
|
||||
: newCSP->SetRequestContext(nullptr, aPrincipal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const nsCSPPolicy* policy = originalCSP->GetPolicy(i);
|
||||
MOZ_ASSERT(policy);
|
||||
|
||||
nsAutoString policyString;
|
||||
policy->toString(policyString);
|
||||
|
||||
rv = newCSP->AppendPolicy(policyString, policy->getReportOnlyFlag(),
|
||||
policy->getDeliveredViaMetaTagFlag());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
aPrincipal->SetCsp(newCSP);
|
||||
}
|
||||
|
||||
nsresult nsScriptSecurityManager::GetChannelResultPrincipal(
|
||||
|
|
|
@ -2545,14 +2545,11 @@ nsresult Document::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
|||
}
|
||||
}
|
||||
|
||||
// If this is not a data document, set CSP.
|
||||
if (!mLoadedAsData) {
|
||||
nsresult rv = InitCSP(aChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
nsresult rv = InitCSP(aChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Initialize FeaturePolicy
|
||||
nsresult rv = InitFeaturePolicy(aChannel);
|
||||
rv = InitFeaturePolicy(aChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XFO needs to be checked after CSP because it is ignored if
|
||||
|
@ -2650,6 +2647,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// If this is a data document - no need to set CSP.
|
||||
if (mLoadedAsData) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString tCspHeaderValue, tCspROHeaderValue;
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel;
|
||||
|
@ -2673,6 +2675,20 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
|
||||
auto addonPolicy = BasePrincipal::Cast(principal)->AddonPolicy();
|
||||
|
||||
// Unless the NodePrincipal is a SystemPrincipal, which currently can not
|
||||
// hold a CSP, we always call EnsureCSP() on the Principal. We do this
|
||||
// so that a Meta CSP does not have to create a new CSP object. This is
|
||||
// important because history entries hold a reference to the CSP object,
|
||||
// which then gets dynamically updated in case a meta CSP is present.
|
||||
// Note that after Bug 965637 we can remove that carve out, because the
|
||||
// CSP will hang off the Client/Document and not the Principal anymore.
|
||||
if (principal->IsSystemPrincipal()) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = principal->EnsureCSP(this, getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Check if this is a signed content to apply default CSP.
|
||||
bool applySignedContentCSP = false;
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
|
@ -2698,10 +2714,6 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
MOZ_LOG(gCspPRLog, LogLevel::Debug,
|
||||
("Document is an add-on or CSP header specified %p", this));
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = principal->EnsureCSP(this, getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// ----- if the doc is an addon, apply its CSP.
|
||||
if (addonPolicy) {
|
||||
nsCOMPtr<nsIAddonPolicyService> aps =
|
||||
|
|
|
@ -382,7 +382,14 @@ nsCSPContext::AppendPolicy(const nsAString& aPolicyString, bool aReportOnly,
|
|||
}
|
||||
|
||||
mPolicies.AppendElement(policy);
|
||||
|
||||
// set the flag on the document for CSP telemetry
|
||||
nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
|
||||
if (doc) {
|
||||
doc->SetHasCSP(true);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -672,9 +679,6 @@ nsCSPContext::SetRequestContext(Document* aDocument, nsIPrincipal* aPrincipal) {
|
|||
// console messages until it becomes available, see flushConsoleMessages
|
||||
mQueueUpMessages = !mInnerWindowID;
|
||||
mCallingChannelLoadGroup = aDocument->GetDocumentLoadGroup();
|
||||
|
||||
// set the flag on the document for CSP telemetry
|
||||
aDocument->SetHasCSP(true);
|
||||
mEventTarget = aDocument->EventTargetFor(TaskCategory::Other);
|
||||
} else {
|
||||
CSPCONTEXTLOG(
|
||||
|
|
|
@ -26,7 +26,7 @@ function receiveMessage(event) {
|
|||
var frame = document.getElementById("testframe");
|
||||
var principal = SpecialPowers.wrap(frame.contentDocument).nodePrincipal;
|
||||
var cspJSON = principal.cspJSON;
|
||||
is(cspJSON, "{}", "there should be no CSP attached to the iframe");
|
||||
is(cspJSON, "{\"csp-policies\":[]}", "there should be no CSP attached to the iframe");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче