Bug 1490874: Log Principal based Security Errors to the Security pane in the console. r=smaug

This commit is contained in:
Christoph Kerschbaumer 2018-09-25 07:25:05 +02:00
parent c00db8b8f6
commit 60e3239dee
20 changed files with 109 additions and 53 deletions

View File

@ -80,7 +80,8 @@ class ClickHandlerChild extends ActorChild {
const sm = Services.scriptSecurityManager;
try {
let targetURI = Services.io.newURI(href);
sm.checkSameOriginURI(docshell.mixedContentChannel.URI, targetURI, false);
let isPrivateWin = ownerDoc.nodePrincipal.originAttributes.privateBrowsingId > 0;
sm.checkSameOriginURI(docshell.mixedContentChannel.URI, targetURI, false, isPrivateWin);
json.allowMixedContent = true;
} catch (e) {}
}

View File

@ -6141,7 +6141,8 @@ function handleLinkClick(event, href, linkNode) {
const sm = Services.scriptSecurityManager;
try {
var targetURI = makeURI(href);
sm.checkSameOriginURI(referrerURI, targetURI, false);
let isPrivateWin = doc.nodePrincipal.originAttributes.privateBrowsingId > 0;
sm.checkSameOriginURI(referrerURI, targetURI, false, isPrivateWin);
persistAllowMixedContentInChildTab = true;
} catch (e) { }
}

View File

@ -806,7 +806,8 @@ nsContextMenu.prototype = {
const sm = Services.scriptSecurityManager;
try {
let targetURI = this.linkURI;
sm.checkSameOriginURI(referrerURI, targetURI, false);
let isPrivateWin = this.browser.contentPrincipal.originAttributes.privateBrowsingId > 0;
sm.checkSameOriginURI(referrerURI, targetURI, false, isPrivateWin);
persistAllowMixedContentInChildTab = true;
} catch (e) { }
}

View File

@ -166,8 +166,8 @@ BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPri
nsCOMPtr<nsIURI> prinURI;
rv = GetURI(getter_AddRefs(prinURI));
if (NS_SUCCEEDED(rv) && prinURI) {
nsScriptSecurityManager::ReportError(nullptr, "CheckSameOriginError",
prinURI, aURI);
nsScriptSecurityManager::ReportError("CheckSameOriginError", prinURI, aURI,
mOriginAttributes.mPrivateBrowsingId > 0);
}
}

View File

@ -182,10 +182,13 @@ interface nsIScriptSecurityManager : nsISupports
* (scheme, host, and port).
* ReportError flag suppresses error reports for functions that
* don't need reporting.
* FromPrivateWindow indicates whether the error occurs in a private
* window or not.
*/
void checkSameOriginURI(in nsIURI aSourceURI,
in nsIURI aTargetURI,
in boolean reportError);
in boolean reportError,
in boolean fromPrivateWindow);
/**
* Get the principal for the given channel. This will typically be the
* channel owner if there is one, and the codebase principal for the

View File

@ -15,6 +15,7 @@
#include "nsIServiceManager.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptContext.h"
#include "nsIScriptError.h"
#include "nsIURL.h"
#include "nsIURIMutator.h"
#include "nsINestedURI.h"
@ -29,6 +30,7 @@
#include "nsCRTGlue.h"
#include "nsDocShell.h"
#include "nsError.h"
#include "nsGlobalWindowInner.h"
#include "nsDOMCID.h"
#include "nsTextFormatter.h"
#include "nsIStringBundle.h"
@ -541,13 +543,16 @@ nsScriptSecurityManager::JSPrincipalsSubsume(JSPrincipals *first,
NS_IMETHODIMP
nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
nsIURI* aTargetURI,
bool reportError)
bool reportError,
bool aFromPrivateWindow)
{
// Please note that aFromPrivateWindow is only 100% accurate if
// reportError is true.
if (!SecurityCompareURIs(aSourceURI, aTargetURI))
{
if (reportError) {
ReportError(nullptr, "CheckSameOriginError",
aSourceURI, aTargetURI);
ReportError("CheckSameOriginError",
aSourceURI, aTargetURI, aFromPrivateWindow);
}
return NS_ERROR_DOM_BAD_URI;
}
@ -732,7 +737,8 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
// check nothing else in the URI chain has flags that prevent
// access:
rv = CheckLoadURIFlags(sourceURI, aTargetURI, sourceBaseURI,
targetBaseURI, aFlags);
targetBaseURI, aFlags,
aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0);
NS_ENSURE_SUCCESS(rv, rv);
// Check the principal is allowed to load the target.
return aPrincipal->CheckMayLoad(targetBaseURI, true, false);
@ -861,7 +867,8 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
// The policy is specified by the protocol flags on both URIs.
if (!schemesMatch || (denySameSchemeLinks && !isSamePage)) {
return CheckLoadURIFlags(currentURI, currentOtherURI,
sourceBaseURI, targetBaseURI, aFlags);
sourceBaseURI, targetBaseURI, aFlags,
aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0);
}
// Otherwise... check if we can nest another level:
nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(currentURI);
@ -898,7 +905,8 @@ nsScriptSecurityManager::CheckLoadURIFlags(nsIURI *aSourceURI,
nsIURI *aTargetURI,
nsIURI *aSourceBaseURI,
nsIURI *aTargetBaseURI,
uint32_t aFlags)
uint32_t aFlags,
bool aFromPrivateWindow)
{
// Note that the order of policy checks here is very important!
// We start from most restrictive and work our way down.
@ -915,7 +923,7 @@ nsScriptSecurityManager::CheckLoadURIFlags(nsIURI *aSourceURI,
if (NS_FAILED(rv)) {
// Deny access, since the origin principal is not system
if (reportErrors) {
ReportError(nullptr, errorTag, aSourceURI, aTargetURI);
ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow);
}
return rv;
}
@ -994,7 +1002,7 @@ nsScriptSecurityManager::CheckLoadURIFlags(nsIURI *aSourceURI,
}
if (reportErrors) {
ReportError(nullptr, errorTag, aSourceURI, aTargetURI);
ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow);
}
return NS_ERROR_DOM_BAD_URI;
}
@ -1021,7 +1029,7 @@ nsScriptSecurityManager::CheckLoadURIFlags(nsIURI *aSourceURI,
// Nothing else.
if (reportErrors) {
ReportError(nullptr, errorTag, aSourceURI, aTargetURI);
ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow);
}
return NS_ERROR_DOM_BAD_URI;
}
@ -1066,8 +1074,8 @@ nsScriptSecurityManager::CheckLoadURIFlags(nsIURI *aSourceURI,
}
nsresult
nsScriptSecurityManager::ReportError(JSContext* cx, const char* aMessageTag,
nsIURI* aSource, nsIURI* aTarget)
nsScriptSecurityManager::ReportError(const char* aMessageTag, nsIURI* aSource,
nsIURI* aTarget, bool aFromPrivateWindow)
{
nsresult rv;
NS_ENSURE_TRUE(aSource && aTarget, NS_ERROR_NULL_POINTER);
@ -1098,21 +1106,18 @@ nsScriptSecurityManager::ReportError(JSContext* cx, const char* aMessageTag,
message);
NS_ENSURE_SUCCESS(rv, rv);
// If a JS context was passed in, set a JS exception.
// Otherwise, print the error message directly to the JS console
// and to standard output
if (cx)
{
SetPendingException(cx, message.get());
}
else // Print directly to the console
{
nsCOMPtr<nsIConsoleService> console(
do_GetService("@mozilla.org/consoleservice;1"));
NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
NS_ENSURE_TRUE(error, NS_ERROR_FAILURE);
console->LogStringMessage(message.get());
}
// using category of "SOP" so we can link to MDN
rv = error->Init(message, EmptyString(),
EmptyString(), 0, 0,
nsIScriptError::errorFlag,
"SOP", aFromPrivateWindow);
NS_ENSURE_SUCCESS(rv, rv);
console->LogMessage(error);
return NS_OK;
}

View File

@ -63,8 +63,8 @@ public:
static uint32_t SecurityHashURI(nsIURI* aURI);
static nsresult
ReportError(JSContext* cx, const char* aMessageTag,
nsIURI* aSource, nsIURI* aTarget);
ReportError(const char* aMessageTag, nsIURI* aSource,
nsIURI* aTarget, bool aFromPrivateWindow);
static uint32_t
HashPrincipalByOrigin(nsIPrincipal* aPrincipal);
@ -108,7 +108,7 @@ private:
nsresult
CheckLoadURIFlags(nsIURI* aSourceURI, nsIURI* aTargetURI, nsIURI* aSourceBaseURI,
nsIURI* aTargetBaseURI, uint32_t aFlags);
nsIURI* aTargetBaseURI, uint32_t aFlags, bool aFromPrivateWindow);
// Returns the file URI whitelist, initializing it if it has not been
// initialized.

View File

@ -11605,7 +11605,9 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
NS_ENSURE_SUCCESS(currentURI->GetUserPass(currentUserPass),
NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(newURI->GetUserPass(newUserPass), NS_ERROR_FAILURE);
if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true)) ||
bool isPrivateWin =
document->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true, isPrivateWin)) ||
!currentUserPass.Equals(newUserPass)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
@ -12970,10 +12972,18 @@ nsDocShell::IsOKToLoadURI(nsIURI* aURI)
return false;
}
bool isPrivateWin = false;
nsIDocument *doc = GetDocument();
if (doc) {
isPrivateWin =
doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
}
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
return secMan &&
NS_SUCCEEDED(secMan->CheckSameOriginURI(aURI, mLoadingURI, false));
NS_SUCCEEDED(secMan->CheckSameOriginURI(aURI, mLoadingURI, false, isPrivateWin));
}
//

View File

@ -168,8 +168,14 @@ SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
// Default to sending less data if NS_URIChainHasFlags() fails.
referrerIsSecure = NS_FAILED(rv) || referrerIsSecure;
bool isPrivateWin = false;
if (doc) {
isPrivateWin =
doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
}
bool sameOrigin =
NS_SUCCEEDED(sm->CheckSameOriginURI(info->referrer, aURI, false));
NS_SUCCEEDED(sm->CheckSameOriginURI(info->referrer, aURI, false, isPrivateWin));
// If both the address of the document containing the hyperlink being
// audited and "ping URL" have the same origin or the document containing

View File

@ -334,7 +334,9 @@ mozilla::TimeStamp
nsDOMNavigationTiming::GetUnloadEventStartTimeStamp() const
{
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
// todo: if you intend to update CheckSameOriginURI to log the error to the
// console you also need to update the 'aFromPrivateWindow' argument.
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false, false);
if (NS_SUCCEEDED(rv)) {
return mUnloadStart;
}
@ -345,7 +347,9 @@ mozilla::TimeStamp
nsDOMNavigationTiming::GetUnloadEventEndTimeStamp() const
{
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
// todo: if you intend to update CheckSameOriginURI to log the error to the
// console you also need to update the 'aFromPrivateWindow' argument.
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false, false);
if (NS_SUCCEEDED(rv)) {
return mUnloadEnd;
}

View File

@ -102,7 +102,8 @@ nsDataDocumentContentPolicy::ShouldLoad(nsIURI *aContentLocation,
requestingPrincipal->GetURI(getter_AddRefs(principalURI));
if (NS_SUCCEEDED(rv) && principalURI) {
nsScriptSecurityManager::ReportError(
nullptr, "ExternalDataError", principalURI, aContentLocation);
"ExternalDataError", principalURI, aContentLocation,
requestingPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0);
}
}
} else if ((contentType == nsIContentPolicy::TYPE_IMAGE ||

View File

@ -73,7 +73,9 @@ public:
// If the resulting window is not same origin, then resolve immediately
// without returning any information about the new Client. This is
// step 6.10 in the Client.navigate(url) spec.
rv = ssm->CheckSameOriginURI(mBaseURL, channelURL, false);
// todo: if you intend to update CheckSameOriginURI to log the error to the
// console you also need to update the 'aFromPrivateWindow' argument.
rv = ssm->CheckSameOriginURI(mBaseURL, channelURL, false, false);
if (NS_FAILED(rv)) {
mPromise->Resolve(NS_OK, __func__);
return NS_OK;

View File

@ -73,8 +73,10 @@ public:
// Check same origin.
nsCOMPtr<nsIScriptSecurityManager> securityManager =
nsContentUtils::GetSecurityManager();
bool isPrivateWin =
doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
nsresult rv = securityManager->CheckSameOriginURI(doc->GetOriginalURI(),
mBaseURI, false);
mBaseURI, false, isPrivateWin);
if (NS_FAILED(rv)) {
mPromise->Resolve(NS_OK, __func__);
mPromise = nullptr;

View File

@ -110,9 +110,12 @@ nsDOMOfflineResourceList::Init()
}
mManifestURI->GetAsciiSpec(mManifestSpec);
bool isPrivateWin = mLoadingPrincipal
? mLoadingPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0
: false;
nsresult rv = nsContentUtils::GetSecurityManager()->
CheckSameOriginURI(mManifestURI, mDocumentURI, true);
CheckSameOriginURI(mManifestURI, mDocumentURI, true, isPrivateWin);
NS_ENSURE_SUCCESS(rv, rv);
// Dynamically-managed resources are stored as a separate ownership list

View File

@ -168,10 +168,18 @@ Presentation::HasReceiverSupport() const
return false;
}
bool isPrivateWin = false;
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
if (doc) {
isPrivateWin =
doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
}
nsCOMPtr<nsIURI> docURI = mWindow->GetDocumentURI();
return NS_SUCCEEDED(securityManager->CheckSameOriginURI(presentationURI,
docURI,
false));
false,
isPrivateWin));
}
bool

View File

@ -107,7 +107,9 @@ FramingChecker::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
if (checkSameOrigin) {
topDoc->NodePrincipal()->GetURI(getter_AddRefs(topUri));
rv = ssm->CheckSameOriginURI(uri, topUri, true);
bool isPrivateWin =
topDoc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
rv = ssm->CheckSameOriginURI(uri, topUri, true, isPrivateWin);
// one of the ancestors is not same origin as this document
if (NS_FAILED(rv)) {
@ -151,8 +153,9 @@ FramingChecker::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
if (NS_FAILED(rv)) {
return false;
}
rv = ssm->CheckSameOriginURI(uri, topUri, true);
bool isPrivateWin =
topDoc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
rv = ssm->CheckSameOriginURI(uri, topUri, true, isPrivateWin);
if (NS_FAILED(rv)) {
ReportXFOViolation(curDocShellItem, uri, eALLOWFROM);
return false;

View File

@ -1691,7 +1691,8 @@ HttpBaseChannel::IsCrossOriginWithReferrer()
LOG(("triggeringURI=%s\n", triggeringURISpec.get()));
}
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
rv = ssm->CheckSameOriginURI(triggeringURI, mURI, false);
bool isPrivateWin = mLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
rv = ssm->CheckSameOriginURI(triggeringURI, mURI, false, isPrivateWin);
return (NS_FAILED(rv));
}
@ -3919,7 +3920,8 @@ bool
HttpBaseChannel::SameOriginWithOriginalUri(nsIURI *aURI)
{
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(aURI, mOriginalURI, false);
bool isPrivateWin = mLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
nsresult rv = ssm->CheckSameOriginURI(aURI, mOriginalURI, false, isPrivateWin);
return (NS_SUCCEEDED(rv));
}

View File

@ -1524,7 +1524,8 @@ EnsureMIMEOfScript(nsIURI* aURI, nsHttpResponseHead* aResponseHead, nsILoadInfo*
aLoadInfo->LoadingPrincipal()->GetURI(getter_AddRefs(requestURI));
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(requestURI, aURI, false);
bool isPrivateWin = aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
nsresult rv = ssm->CheckSameOriginURI(requestURI, aURI, false, isPrivateWin);
if (NS_SUCCEEDED(rv)) {
//same origin
AccumulateCategorical(Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_2::same_origin);
@ -1539,7 +1540,8 @@ EnsureMIMEOfScript(nsIURI* aURI, nsHttpResponseHead* aResponseHead, nsILoadInfo*
nsCOMPtr<nsIURI> corsOriginURI;
rv = NS_NewURI(getter_AddRefs(corsOriginURI), corsOrigin);
if (NS_SUCCEEDED(rv)) {
rv = ssm->CheckSameOriginURI(requestURI, corsOriginURI, false);
bool isPrivateWin = aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
rv = ssm->CheckSameOriginURI(requestURI, corsOriginURI, false, isPrivateWin);
if (NS_SUCCEEDED(rv)) {
cors = true;
}

View File

@ -39,7 +39,7 @@ function run_test()
var equal;
try {
secman.checkSameOriginURI(uri1, uri2, false);
secman.checkSameOriginURI(uri1, uri2, false, false);
equal = true;
} catch (e) {
equal = false

View File

@ -66,7 +66,9 @@ function validatedWebRemoteType(aPreferredRemoteType, aTargetUri, aCurrentUri) {
if (aCurrentUri) {
try {
// checkSameOriginURI throws when not same origin.
sm.checkSameOriginURI(aCurrentUri, aTargetUri, false);
// todo: if you intend to update CheckSameOriginURI to log the error to the
// console you also need to update the 'aFromPrivateWindow' argument.
sm.checkSameOriginURI(aCurrentUri, aTargetUri, false, false);
return FILE_REMOTE_TYPE;
} catch (e) {
return WEB_REMOTE_TYPE;