Bug 1657583: Simplify TestSitePermission within nsHTTPSOnlyUtils r=necko-reviewers,JulianWels,dragana

Differential Revision: https://phabricator.services.mozilla.com/D86178
This commit is contained in:
Christoph Kerschbaumer 2020-08-07 11:27:56 +00:00
parent 155b24b9c7
commit b6387305a4
4 changed files with 56 additions and 59 deletions

View File

@ -9183,23 +9183,6 @@ nsIPrincipal* nsDocShell::GetInheritedPrincipal(
aLoadInfo->SetIsFormSubmission(true); aLoadInfo->SetIsFormSubmission(true);
} }
// If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
// HTTPS by default. This behavior can be disabled through the loadinfo flag
// HTTPS_ONLY_EXEMPT.
bool isPrivateWin = attrs.mPrivateBrowsingId > 0;
if (nsHTTPSOnlyUtils::IsHttpsOnlyModeEnabled(isPrivateWin)) {
// Let's create a new content principal based on the URI for the
// PermissionManager
nsCOMPtr<nsIPrincipal> permissionPrincipal =
BasePrincipal::CreateContentPrincipal(aLoadState->URI(), attrs);
if (nsHTTPSOnlyUtils::TestHttpsOnlySitePermission(permissionPrincipal)) {
uint32_t httpsOnlyStatus = aLoadInfo->GetHttpsOnlyStatus();
httpsOnlyStatus |= nsILoadInfo::HTTPS_ONLY_EXEMPT;
aLoadInfo->SetHttpsOnlyStatus(httpsOnlyStatus);
}
}
nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsIChannel> channel;
aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(), aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
aLoadInfo, aCallbacks, aLoadFlags, srcdoc, aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
@ -9210,6 +9193,11 @@ nsIPrincipal* nsDocShell::GetInheritedPrincipal(
return false; return false;
} }
// If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
// HTTPS by default. This behavior can be disabled through the loadinfo flag
// HTTPS_ONLY_EXEMPT.
nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
if (nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel = if (nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
do_QueryInterface(channel)) { do_QueryInterface(channel)) {
// Any document load should not inherit application cache. // Any document load should not inherit application cache.

View File

@ -9,6 +9,7 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsHTTPSOnlyUtils.h" #include "nsHTTPSOnlyUtils.h"
#include "nsIConsoleService.h" #include "nsIConsoleService.h"
#include "nsIHttpChannel.h"
#include "nsIHttpsOnlyModePermission.h" #include "nsIHttpsOnlyModePermission.h"
#include "nsIPermissionManager.h" #include "nsIPermissionManager.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
@ -164,23 +165,57 @@ bool nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(nsIChannel* aChannel,
} }
/* static */ /* static */
bool nsHTTPSOnlyUtils::TestHttpsOnlySitePermission(nsIPrincipal* aPrincipal) { void nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(
if (!aPrincipal) { nsIChannel* aChannel) {
// We always deny the permission if we don't have a principal. NS_ENSURE_TRUE_VOID(aChannel);
return false;
// if https-only mode is not enabled, then there is nothing to do here.
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
bool isPrivateWin = loadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
if (!IsHttpsOnlyModeEnabled(isPrivateWin)) {
return;
} }
// if it's not a top-level or iframe load then there is nothing to here.
nsContentPolicyType type = loadInfo->GetExternalContentPolicyType();
if (type != nsIContentPolicy::TYPE_DOCUMENT &&
type != nsIContentPolicy::TYPE_SUBDOCUMENT) {
return;
}
// it it's not an http channel, then there is nothing to do here.
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
if (!httpChannel) {
return;
}
nsCOMPtr<nsIPrincipal> principal;
nsresult rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
aChannel, getter_AddRefs(principal));
NS_ENSURE_SUCCESS_VOID(rv);
nsCOMPtr<nsIPermissionManager> permMgr = nsCOMPtr<nsIPermissionManager> permMgr =
mozilla::services::GetPermissionManager(); mozilla::services::GetPermissionManager();
NS_ENSURE_TRUE(permMgr, false); NS_ENSURE_TRUE_VOID(permMgr);
uint32_t perm; uint32_t perm;
nsresult rv = permMgr->TestExactPermissionFromPrincipal( rv = permMgr->TestExactPermissionFromPrincipal(
aPrincipal, "https-only-load-insecure"_ns, &perm); principal, "https-only-load-insecure"_ns, &perm);
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS_VOID(rv);
return perm == nsIHttpsOnlyModePermission::LOAD_INSECURE_ALLOW || bool isHttpsOnlyExempt =
perm == nsIHttpsOnlyModePermission::LOAD_INSECURE_ALLOW_SESSION; perm == nsIHttpsOnlyModePermission::LOAD_INSECURE_ALLOW ||
perm == nsIHttpsOnlyModePermission::LOAD_INSECURE_ALLOW_SESSION;
// We explicitly add or also remove the exemption flag, because this
// function is also consulted after redirects.
uint32_t httpsOnlyStatus = loadInfo->GetHttpsOnlyStatus();
if (isHttpsOnlyExempt) {
httpsOnlyStatus |= nsILoadInfo::HTTPS_ONLY_EXEMPT;
} else {
httpsOnlyStatus &= ~nsILoadInfo::HTTPS_ONLY_EXEMPT;
}
loadInfo->SetHttpsOnlyStatus(httpsOnlyStatus);
} }
/* ------ Logging ------ */ /* ------ Logging ------ */

View File

@ -66,11 +66,12 @@ class nsHTTPSOnlyUtils {
nsIURI* aURI = nullptr); nsIURI* aURI = nullptr);
/** /**
* Tests is the HTTPS-Only Mode upgrade exception is set for a given principal * Tests if the HTTPS-Only Mode upgrade exception is set for a given channel.
* @param aPrincipal Principal to check permission for * Note: This function only adds an exemption for loads of TYPE_DOCUMENT.
* @return true if exempt from upgrade * @param aChannel The channel to be checked
*/ */
static bool TestHttpsOnlySitePermission(nsIPrincipal* aPrincipal); static void TestSitePermissionAndPotentiallyAddExemption(
nsIChannel* aChannel);
private: private:
/** /**

View File

@ -21,7 +21,6 @@
#include "mozilla/dom/ClientChannelHelper.h" #include "mozilla/dom/ClientChannelHelper.h"
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentProcessManager.h" #include "mozilla/dom/ContentProcessManager.h"
#include "mozilla/dom/nsHTTPSOnlyUtils.h"
#include "mozilla/dom/SessionHistoryEntry.h" #include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/dom/WindowGlobalParent.h" #include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/ipc/IdType.h" #include "mozilla/dom/ipc/IdType.h"
@ -2275,33 +2274,7 @@ DocumentLoadListener::AsyncOnChannelRedirect(
// If HTTPS-Only mode is enabled, we need to check whether the exception-flag // If HTTPS-Only mode is enabled, we need to check whether the exception-flag
// needs to be removed or set, by asking the PermissionManager. // needs to be removed or set, by asking the PermissionManager.
RefPtr<CanonicalBrowsingContext> bc = nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(mChannel);
mParentChannelListener->GetBrowsingContext();
nsCOMPtr<nsILoadInfo> channelLoadInfo = mChannel->LoadInfo();
bool isPrivateWin =
channelLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
if (nsHTTPSOnlyUtils::IsHttpsOnlyModeEnabled(isPrivateWin) && bc &&
bc->IsTop()) {
bool isHttpsOnlyExempt = false;
if (httpChannel) {
nsCOMPtr<nsIPrincipal> resultPrincipal;
nsresult rv =
nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
mChannel, getter_AddRefs(resultPrincipal));
if (NS_SUCCEEDED(rv)) {
isHttpsOnlyExempt =
nsHTTPSOnlyUtils::TestHttpsOnlySitePermission(resultPrincipal);
}
}
uint32_t httpsOnlyStatus = channelLoadInfo->GetHttpsOnlyStatus();
if (isHttpsOnlyExempt) {
httpsOnlyStatus |= nsILoadInfo::HTTPS_ONLY_EXEMPT;
} else {
httpsOnlyStatus &= ~nsILoadInfo::HTTPS_ONLY_EXEMPT;
}
channelLoadInfo->SetHttpsOnlyStatus(httpsOnlyStatus);
}
// We don't need to confirm internal redirects or record any // We don't need to confirm internal redirects or record any
// history for them, so just immediately verify and return. // history for them, so just immediately verify and return.