Bug 663570 - MetaCSP Part 3: Upgrade insecure requests changes (r=bz)

This commit is contained in:
Christoph Kerschbaumer 2015-11-14 19:28:38 -08:00
parent b3ceaf938c
commit 745806b307
9 changed files with 106 additions and 26 deletions

View File

@ -1441,6 +1441,7 @@ nsIDocument::nsIDocument()
mReferrerPolicySet(false),
mReferrerPolicy(mozilla::net::RP_Default),
mUpgradeInsecureRequests(false),
mUpgradeInsecurePreloads(false),
mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
mNodeInfoManager(nullptr),
mCompatMode(eCompatibility_FullStandards),
@ -2574,6 +2575,8 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
if (sameTypeParent) {
mUpgradeInsecureRequests =
sameTypeParent->GetDocument()->GetUpgradeInsecureRequests();
mUpgradeInsecurePreloads =
sameTypeParent->GetDocument()->GetUpgradeInsecurePreloads();
}
}
@ -2653,6 +2656,58 @@ nsDocument::IsLoopDocument(nsIChannel *aChannel)
return isLoop;
}
void
nsDocument::ApplySettingsFromCSP(bool aSpeculative)
{
nsresult rv = NS_OK;
if (!aSpeculative) {
// 1) apply settings from regular CSP
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS_VOID(rv);
if (csp) {
// Set up any Referrer Policy specified by CSP
bool hasReferrerPolicy = false;
uint32_t referrerPolicy = mozilla::net::RP_Default;
rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
NS_ENSURE_SUCCESS_VOID(rv);
if (hasReferrerPolicy) {
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
mReferrerPolicySet = true;
}
// Set up 'upgrade-insecure-requests' if not already inherited
// from the parent context or set by any other CSP.
if (!mUpgradeInsecureRequests) {
rv = csp->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests);
NS_ENSURE_SUCCESS_VOID(rv);
}
}
return;
}
// 2) apply settings from speculative csp
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
if (preloadCsp) {
// Set up any Referrer Policy specified by CSP
bool hasReferrerPolicy = false;
uint32_t referrerPolicy = mozilla::net::RP_Default;
rv = preloadCsp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
NS_ENSURE_SUCCESS_VOID(rv);
if (hasReferrerPolicy) {
// please note that referrer policy spec defines that the latest
// policy awlays wins, hence we can safely overwrite the policy here.
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
mReferrerPolicySet = true;
}
if (!mUpgradeInsecurePreloads) {
rv = preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
NS_ENSURE_SUCCESS_VOID(rv);
}
}
}
nsresult
nsDocument::InitCSP(nsIChannel* aChannel)
{
@ -2815,34 +2870,13 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
}
// ----- Set up any Referrer Policy specified by CSP
bool hasReferrerPolicy = false;
uint32_t referrerPolicy = mozilla::net::RP_Default;
rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
NS_ENSURE_SUCCESS(rv, rv);
if (hasReferrerPolicy) {
// Referrer policy spec (section 6.1) says that we always use the newest
// referrer policy we find
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
mReferrerPolicySet = true;
// Referrer Policy is set separately for the speculative parser in
// nsHTMLDocument::StartDocumentLoad() so there's nothing to do here for
// speculative loads.
}
// ------ Set flag for 'upgrade-insecure-requests' if not already
// inherited from the parent context.
if (!mUpgradeInsecureRequests) {
rv = csp->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = principal->SetCsp(csp);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("Inserted CSP into principal %p", principal));
ApplySettingsFromCSP(false);
return NS_OK;
}

View File

@ -717,6 +717,8 @@ public:
virtual void SetChromeXHRDocBaseURI(nsIURI* aURI) override;
virtual void ApplySettingsFromCSP(bool aSpeculative) override;
/**
* Set the principal responsible for this document.
*/

View File

@ -296,6 +296,11 @@ public:
*/
virtual void SetChromeXHRDocBaseURI(nsIURI* aURI) = 0;
/**
* Set referrer policy and upgrade-insecure-requests flags
*/
virtual void ApplySettingsFromCSP(bool aSpeculative) = 0;
/**
* Return the referrer policy of the document. Return "default" if there's no
* valid meta referrer tag found in the document.
@ -325,6 +330,14 @@ public:
return mUpgradeInsecureRequests;
}
/**
* Same as GetUpgradeInsecureRequests() but *only* for preloads.
*/
bool GetUpgradeInsecurePreloads() const
{
return mUpgradeInsecurePreloads;
}
/**
* Set the principal responsible for this document.
*/
@ -2713,6 +2726,7 @@ protected:
ReferrerPolicyEnum mReferrerPolicy;
bool mUpgradeInsecureRequests;
bool mUpgradeInsecurePreloads;
mozilla::WeakPtr<nsDocShell> mDocumentContainer;

View File

@ -243,6 +243,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
aLoadInfo->GetSecurityFlags(),
aLoadInfo->InternalContentPolicyType(),
aLoadInfo->GetUpgradeInsecureRequests(),
aLoadInfo->GetUpgradeInsecurePreloads(),
aLoadInfo->GetInnerWindowID(),
aLoadInfo->GetOuterWindowID(),
aLoadInfo->GetParentOuterWindowID(),
@ -297,6 +298,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
loadInfoArgs.securityFlags(),
loadInfoArgs.contentPolicyType(),
loadInfoArgs.upgradeInsecureRequests(),
loadInfoArgs.upgradeInsecurePreloads(),
loadInfoArgs.innerWindowID(),
loadInfoArgs.outerWindowID(),
loadInfoArgs.parentOuterWindowID(),

View File

@ -33,6 +33,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
, mInternalContentPolicyType(aContentPolicyType)
, mTainting(LoadTainting::Basic)
, mUpgradeInsecureRequests(false)
, mUpgradeInsecurePreloads(false)
, mInnerWindowID(0)
, mOuterWindowID(0)
, mParentOuterWindowID(0)
@ -79,6 +80,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
}
mUpgradeInsecureRequests = aLoadingContext->OwnerDoc()->GetUpgradeInsecureRequests();
mUpgradeInsecurePreloads = aLoadingContext->OwnerDoc()->GetUpgradeInsecurePreloads();
}
mOriginAttributes = BasePrincipal::Cast(mLoadingPrincipal)->OriginAttributesRef();
@ -92,6 +94,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
, mInternalContentPolicyType(rhs.mInternalContentPolicyType)
, mTainting(rhs.mTainting)
, mUpgradeInsecureRequests(rhs.mUpgradeInsecureRequests)
, mUpgradeInsecurePreloads(rhs.mUpgradeInsecurePreloads)
, mInnerWindowID(rhs.mInnerWindowID)
, mOuterWindowID(rhs.mOuterWindowID)
, mParentOuterWindowID(rhs.mParentOuterWindowID)
@ -109,6 +112,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
bool aUpgradeInsecureRequests,
bool aUpgradeInsecurePreloads,
uint64_t aInnerWindowID,
uint64_t aOuterWindowID,
uint64_t aParentOuterWindowID,
@ -122,6 +126,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
, mSecurityFlags(aSecurityFlags)
, mInternalContentPolicyType(aContentPolicyType)
, mUpgradeInsecureRequests(aUpgradeInsecureRequests)
, mUpgradeInsecurePreloads(aUpgradeInsecurePreloads)
, mInnerWindowID(aInnerWindowID)
, mOuterWindowID(aOuterWindowID)
, mParentOuterWindowID(aParentOuterWindowID)
@ -292,6 +297,13 @@ LoadInfo::GetUpgradeInsecureRequests(bool* aResult)
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetUpgradeInsecurePreloads(bool* aResult)
{
*aResult = mUpgradeInsecurePreloads;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetInnerWindowID(uint64_t* aResult)
{

View File

@ -70,6 +70,7 @@ private:
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
bool aUpgradeInsecureRequests,
bool aUpgradeInsecurePreloads,
uint64_t aInnerWindowID,
uint64_t aOuterWindowID,
uint64_t aParentOuterWindowID,
@ -101,6 +102,7 @@ private:
nsContentPolicyType mInternalContentPolicyType;
LoadTainting mTainting;
bool mUpgradeInsecureRequests;
bool mUpgradeInsecurePreloads;
uint64_t mInnerWindowID;
uint64_t mOuterWindowID;
uint64_t mParentOuterWindowID;

View File

@ -26,7 +26,7 @@ typedef unsigned long nsSecurityFlags;
/**
* An nsILoadOwner represents per-load information about who started the load.
*/
[scriptable, builtinclass, uuid(45a4a9e1-b50d-468a-a01c-43de5c38c8db)]
[scriptable, builtinclass, uuid(542b38c6-1c7b-4630-bd6b-9fee0d1b474d)]
interface nsILoadInfo : nsISupports
{
/**
@ -295,6 +295,11 @@ interface nsILoadInfo : nsISupports
*/
[infallible] readonly attribute boolean upgradeInsecureRequests;
/**
* Same as upgradeInsecureRequests but for preloads.
*/
[infallible] readonly attribute boolean upgradeInsecurePreloads;
/**
* Typically these are the window IDs of the window in which the element being
* loaded lives. However, if the element being loaded is <frame

View File

@ -31,6 +31,7 @@ struct LoadInfoArgs
uint32_t securityFlags;
uint32_t contentPolicyType;
bool upgradeInsecureRequests;
bool upgradeInsecurePreloads;
uint64_t innerWindowID;
uint64_t outerWindowID;
uint64_t parentOuterWindowID;

View File

@ -332,7 +332,15 @@ nsHttpChannel::Connect()
// the CSP directive 'upgrade-insecure-requests', then it's time to fulfill
// the promise to CSP and mixed content blocking to upgrade the channel
// from http to https.
if (mLoadInfo && mLoadInfo->GetUpgradeInsecureRequests()) {
if (mLoadInfo) {
bool isPreload =
(mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD ||
mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD);
bool upgradeRequests =
((isPreload && mLoadInfo->GetUpgradeInsecurePreloads()) ||
(mLoadInfo->GetUpgradeInsecureRequests()));
// Please note that cross origin top level navigations are not subject
// to upgrade-insecure-requests, see:
// http://www.w3.org/TR/upgrade-insecure-requests/#examples
@ -343,7 +351,7 @@ nsHttpChannel::Connect()
(mLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT) &&
(!resultPrincipal->Equals(mLoadInfo->LoadingPrincipal()));
if (!crossOriginNavigation) {
if (upgradeRequests && !crossOriginNavigation) {
// let's log a message to the console that we are upgrading a request
nsAutoCString spec, scheme;
mURI->GetSpec(spec);