Bug 1187335 - P2 - Modify the way to report to console for worker and use LoadTainting to decide CORS or not. r=bkelly. r=francois.

This commit is contained in:
Tom Tung 2016-09-08 09:59:40 +08:00
Родитель c34ee7095c
Коммит 78670a91d5
6 изменённых файлов: 148 добавлений и 88 удалений

Просмотреть файл

@ -51,6 +51,7 @@
#include "nsINetworkPredictor.h"
#include "ImportManager.h"
#include "mozilla/dom/EncodingUtils.h"
#include "mozilla/ConsoleReportCollector.h"
#include "mozilla/Attributes.h"
#include "mozilla/Unused.h"
@ -514,7 +515,8 @@ nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
mEnabled(true),
mDeferEnabled(false),
mDocumentParsingDone(false),
mBlockingDOMContentLoaded(false)
mBlockingDOMContentLoaded(false),
mReporter(new ConsoleReportCollector())
{
}
@ -1279,7 +1281,12 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
nsAutoPtr<mozilla::dom::SRICheckDataVerifier> sriDataVerifier;
if (!aRequest->mIntegrity.IsEmpty()) {
sriDataVerifier = new SRICheckDataVerifier(aRequest->mIntegrity, mDocument);
nsAutoCString sourceUri;
if (mDocument && mDocument->GetDocumentURI()) {
mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
}
sriDataVerifier = new SRICheckDataVerifier(aRequest->mIntegrity, sourceUri,
mReporter);
}
RefPtr<nsScriptLoadHandler> handler =
@ -1505,7 +1512,12 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
("nsScriptLoader::ProcessScriptElement, integrity=%s",
NS_ConvertUTF16toUTF8(integrity).get()));
SRICheck::IntegrityMetadata(integrity, mDocument, &sriMetadata);
nsAutoCString sourceUri;
if (mDocument && mDocument->GetDocumentURI()) {
mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
}
SRICheck::IntegrityMetadata(integrity, sourceUri, mReporter,
&sriMetadata);
}
}
@ -2451,8 +2463,16 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
if (!request->mIntegrity.IsEmpty() &&
NS_SUCCEEDED((rv = aSRIStatus))) {
MOZ_ASSERT(aSRIDataVerifier);
if (NS_FAILED(aSRIDataVerifier->Verify(request->mIntegrity, channel,
request->mCORSMode, mDocument))) {
MOZ_ASSERT(mReporter);
nsAutoCString sourceUri;
if (mDocument && mDocument->GetDocumentURI()) {
mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
}
rv = aSRIDataVerifier->Verify(request->mIntegrity, channel, sourceUri,
mReporter);
mReporter->FlushConsoleReports(mDocument);
if (NS_FAILED(rv)) {
rv = NS_ERROR_SRI_CORRUPT;
}
} else {
@ -2757,7 +2777,11 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
("nsScriptLoader::PreloadURI, integrity=%s",
NS_ConvertUTF16toUTF8(aIntegrity).get()));
SRICheck::IntegrityMetadata(aIntegrity, mDocument, &sriMetadata);
nsAutoCString sourceUri;
if (mDocument && mDocument->GetDocumentURI()) {
mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
}
SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, &sriMetadata);
}
RefPtr<nsScriptLoadRequest> request =

Просмотреть файл

@ -638,6 +638,8 @@ private:
// Module map
nsRefPtrHashtable<nsURIHashKey, mozilla::GenericPromise::Private> mFetchingModules;
nsRefPtrHashtable<nsURIHashKey, nsModuleScript> mFetchedModules;
nsCOMPtr<nsIConsoleReportCollector> mReporter;
};
class nsScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver

Просмотреть файл

@ -7,15 +7,15 @@
#include "SRICheck.h"
#include "mozilla/Base64.h"
#include "mozilla/LoadTainting.h"
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/SRILogHelper.h"
#include "nsContentUtils.h"
#include "nsIChannel.h"
#include "nsIDocument.h"
#include "nsIConsoleReportCollector.h"
#include "nsIProtocolHandler.h"
#include "nsIScriptError.h"
#include "nsIScriptSecurityManager.h"
#include "nsIIncrementalStreamLoader.h"
#include "nsIUnicharStreamLoader.h"
#include "nsIURI.h"
@ -36,10 +36,11 @@ namespace dom {
* sub-resource will be loaded.
*/
static nsresult
IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode,
const nsIDocument* aDocument)
IsEligible(nsIChannel* aChannel, mozilla::LoadTainting aTainting,
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter)
{
NS_ENSURE_ARG_POINTER(aDocument);
NS_ENSURE_ARG_POINTER(aReporter);
if (!aChannel) {
SRILOG(("SRICheck::IsEligible, null channel"));
@ -47,7 +48,7 @@ IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode,
}
// Was the sub-resource loaded via CORS?
if (aCORSMode != CORS_NONE) {
if (aTainting == LoadTainting::CORS) {
SRILOG(("SRICheck::IsEligible, CORS mode"));
return NS_OK;
}
@ -63,40 +64,38 @@ IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode,
NS_ENSURE_SUCCESS(rv, rv);
if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
nsAutoCString documentSpec;
aDocument->GetDocumentURI()->GetAsciiSpec(documentSpec);
SRILOG(("SRICheck::IsEligible, documentURI=%s; requestURI=%s; finalURI=%s",
documentSpec.get(), requestSpec.get(),
SRILOG(("SRICheck::IsEligible, requestURI=%s; finalURI=%s",
requestSpec.get(),
finalURI ? finalURI->GetSpecOrDefault().get() : ""));
}
// Is the sub-resource same-origin?
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
if (NS_SUCCEEDED(ssm->CheckSameOriginURI(aDocument->GetDocumentURI(),
finalURI, false))) {
if (aTainting == LoadTainting::Basic) {
SRILOG(("SRICheck::IsEligible, same-origin"));
return NS_OK;
}
SRILOG(("SRICheck::IsEligible, NOT same origin"));
NS_ConvertUTF8toUTF16 requestSpecUTF16(requestSpec);
const char16_t* params[] = { requestSpecUTF16.get() };
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
aDocument,
nsContentUtils::eSECURITY_PROPERTIES,
"IneligibleResource",
params, ArrayLength(params));
nsTArray<nsString> params;
params.AppendElement(requestSpecUTF16);
aReporter->AddConsoleReport(nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
nsContentUtils::eSECURITY_PROPERTIES,
aSourceFileURI, 0, 0,
NS_LITERAL_CSTRING("IneligibleResource"),
const_cast<const nsTArray<nsString>&>(params));
return NS_ERROR_SRI_NOT_ELIGIBLE;
}
/* static */ nsresult
SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
const nsIDocument* aDocument,
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter,
SRIMetadata* outMetadata)
{
NS_ENSURE_ARG_POINTER(outMetadata);
NS_ENSURE_ARG_POINTER(aDocument);
NS_ENSURE_ARG_POINTER(aReporter);
MOZ_ASSERT(outMetadata->IsEmpty()); // caller must pass empty metadata
if (!Preferences::GetBool("security.sri.enable", false)) {
@ -123,24 +122,26 @@ SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
SRIMetadata metadata(token);
if (metadata.IsMalformed()) {
NS_ConvertUTF8toUTF16 tokenUTF16(token);
const char16_t* params[] = { tokenUTF16.get() };
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
aDocument,
nsContentUtils::eSECURITY_PROPERTIES,
"MalformedIntegrityHash",
params, ArrayLength(params));
nsTArray<nsString> params;
params.AppendElement(tokenUTF16);
aReporter->AddConsoleReport(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
nsContentUtils::eSECURITY_PROPERTIES,
aSourceFileURI, 0, 0,
NS_LITERAL_CSTRING("MalformedIntegrityHash"),
const_cast<const nsTArray<nsString>&>(params));
} else if (!metadata.IsAlgorithmSupported()) {
nsAutoCString alg;
metadata.GetAlgorithm(&alg);
NS_ConvertUTF8toUTF16 algUTF16(alg);
const char16_t* params[] = { algUTF16.get() };
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
aDocument,
nsContentUtils::eSECURITY_PROPERTIES,
"UnsupportedHashAlg",
params, ArrayLength(params));
nsTArray<nsString> params;
params.AppendElement(algUTF16);
aReporter->AddConsoleReport(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
nsContentUtils::eSECURITY_PROPERTIES,
aSourceFileURI, 0, 0,
NS_LITERAL_CSTRING("UnsupportedHashAlg"),
const_cast<const nsTArray<nsString>&>(params));
}
nsAutoCString alg1, alg2;
@ -176,11 +177,12 @@ SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
/* static */ nsresult
SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
nsIUnicharStreamLoader* aLoader,
const CORSMode aCORSMode,
const nsAString& aString,
const nsIDocument* aDocument)
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter)
{
NS_ENSURE_ARG_POINTER(aLoader);
NS_ENSURE_ARG_POINTER(aReporter);
NS_ConvertUTF16toUTF8 utf8Hash(aString);
nsCOMPtr<nsIChannel> channel;
@ -197,19 +199,20 @@ SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
SRILOG(("SRICheck::VerifyIntegrity (unichar stream)"));
}
SRICheckDataVerifier verifier(aMetadata, aDocument);
SRICheckDataVerifier verifier(aMetadata, aSourceFileURI, aReporter);
nsresult rv;
rv = verifier.Update(utf8Hash.Length(), (uint8_t*)utf8Hash.get());
NS_ENSURE_SUCCESS(rv, rv);
return verifier.Verify(aMetadata, channel, aCORSMode, aDocument);
return verifier.Verify(aMetadata, channel, aSourceFileURI, aReporter);
}
//////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////
SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata,
const nsIDocument* aDocument)
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter)
: mCryptoHash(nullptr),
mBytesHashed(0),
mInvalidMetadata(false),
@ -220,13 +223,16 @@ SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata,
// IntegrityMetadata() checks this and returns "no metadata" if
// it's disabled so we should never make it this far
MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false));
MOZ_ASSERT(aReporter);
if (!aMetadata.IsValid()) {
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
aDocument,
nsContentUtils::eSECURITY_PROPERTIES,
"NoValidMetadata");
nsTArray<nsString> params;
aReporter->AddConsoleReport(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
nsContentUtils::eSECURITY_PROPERTIES,
aSourceFileURI, 0, 0,
NS_LITERAL_CSTRING("NoValidMetadata"),
const_cast<const nsTArray<nsString>&>(params));
mInvalidMetadata = true;
return; // ignore invalid metadata for forward-compatibility
}
@ -292,9 +298,10 @@ SRICheckDataVerifier::Finish()
nsresult
SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata,
uint32_t aHashIndex,
const nsIDocument* aDocument)
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter)
{
NS_ENSURE_ARG_POINTER(aDocument);
NS_ENSURE_ARG_POINTER(aReporter);
nsAutoCString base64Hash;
aMetadata.GetHash(aHashIndex, &base64Hash);
@ -302,11 +309,13 @@ SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata,
nsAutoCString binaryHash;
if (NS_WARN_IF(NS_FAILED(Base64Decode(base64Hash, binaryHash)))) {
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
aDocument,
nsContentUtils::eSECURITY_PROPERTIES,
"InvalidIntegrityBase64");
nsTArray<nsString> params;
aReporter->AddConsoleReport(nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
nsContentUtils::eSECURITY_PROPERTIES,
aSourceFileURI, 0, 0,
NS_LITERAL_CSTRING("InvalidIntegrityBase64"),
const_cast<const nsTArray<nsString>&>(params));
return NS_ERROR_SRI_CORRUPT;
}
@ -314,11 +323,13 @@ SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata,
int8_t hashType;
aMetadata.GetHashType(&hashType, &hashLength);
if (binaryHash.Length() != hashLength) {
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
aDocument,
nsContentUtils::eSECURITY_PROPERTIES,
"InvalidIntegrityLength");
nsTArray<nsString> params;
aReporter->AddConsoleReport(nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
nsContentUtils::eSECURITY_PROPERTIES,
aSourceFileURI, 0, 0,
NS_LITERAL_CSTRING("InvalidIntegrityLength"),
const_cast<const nsTArray<nsString>&>(params));
return NS_ERROR_SRI_CORRUPT;
}
@ -343,10 +354,10 @@ SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata,
nsresult
SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata,
nsIChannel* aChannel,
const CORSMode aCORSMode,
const nsIDocument* aDocument)
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter)
{
NS_ENSURE_ARG_POINTER(aDocument);
NS_ENSURE_ARG_POINTER(aReporter);
if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
nsAutoCString requestURL;
@ -360,7 +371,11 @@ SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata,
nsresult rv = Finish();
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(IsEligible(aChannel, aCORSMode, aDocument))) {
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
LoadTainting tainting = loadInfo->GetTainting();
if (NS_FAILED(IsEligible(aChannel, tainting, aSourceFileURI, aReporter))) {
return NS_ERROR_SRI_NOT_ELIGIBLE;
}
@ -369,7 +384,7 @@ SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata,
}
for (uint32_t i = 0; i < aMetadata.HashCount(); i++) {
if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aDocument))) {
if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aSourceFileURI, aReporter))) {
return NS_OK; // stop at the first valid hash
}
}
@ -377,13 +392,14 @@ SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata,
nsAutoCString alg;
aMetadata.GetAlgorithm(&alg);
NS_ConvertUTF8toUTF16 algUTF16(alg);
const char16_t* params[] = { algUTF16.get() };
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
aDocument,
nsContentUtils::eSECURITY_PROPERTIES,
"IntegrityMismatch",
params, ArrayLength(params));
nsTArray<nsString> params;
params.AppendElement(algUTF16);
aReporter->AddConsoleReport(nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Sub-resource Integrity"),
nsContentUtils::eSECURITY_PROPERTIES,
aSourceFileURI, 0, 0,
NS_LITERAL_CSTRING("IntegrityMismatch"),
const_cast<const nsTArray<nsString>&>(params));
return NS_ERROR_SRI_CORRUPT;
}

Просмотреть файл

@ -7,14 +7,13 @@
#ifndef mozilla_dom_SRICheck_h
#define mozilla_dom_SRICheck_h
#include "mozilla/CORSMode.h"
#include "nsCOMPtr.h"
#include "nsICryptoHash.h"
#include "SRIMetadata.h"
class nsIChannel;
class nsIDocument;
class nsIUnicharStreamLoader;
class nsIConsoleReportCollector;
namespace mozilla {
namespace dom {
@ -30,7 +29,8 @@ public:
* return the strongest supported hash.
*/
static nsresult IntegrityMetadata(const nsAString& aMetadataList,
const nsIDocument* aDocument,
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter,
SRIMetadata* outMetadata);
/**
@ -39,20 +39,22 @@ public:
*/
static nsresult VerifyIntegrity(const SRIMetadata& aMetadata,
nsIUnicharStreamLoader* aLoader,
const CORSMode aCORSMode,
const nsAString& aString,
const nsIDocument* aDocument);
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter);
};
class SRICheckDataVerifier final
{
public:
SRICheckDataVerifier(const SRIMetadata& aMetadata,
const nsIDocument* aDocument);
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter);
nsresult Update(uint32_t aStringLen, const uint8_t* aString);
nsresult Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel,
const CORSMode aCORSMode, const nsIDocument* aDocument);
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter);
private:
nsCOMPtr<nsICryptoHash> mCryptoHash;
@ -65,7 +67,8 @@ class SRICheckDataVerifier final
nsresult EnsureCryptoHash();
nsresult Finish();
nsresult VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex,
const nsIDocument* aDocument);
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter);
};
} // namespace dom

Просмотреть файл

@ -55,6 +55,7 @@
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/StyleSheetHandle.h"
#include "mozilla/StyleSheetHandleInlines.h"
#include "mozilla/ConsoleReportCollector.h"
#ifdef MOZ_XUL
#include "nsXULPrototypeCache.h"
@ -520,6 +521,7 @@ Loader::Loader(StyleBackendType aType)
, mCompatMode(eCompatibility_FullStandards)
, mStyleBackendType(Some(aType))
, mEnabled(true)
, mReporter(new ConsoleReportCollector())
#ifdef DEBUG
, mSyncCallback(false)
#endif
@ -531,6 +533,7 @@ Loader::Loader(nsIDocument* aDocument)
, mDatasToNotifyOn(0)
, mCompatMode(eCompatibility_FullStandards)
, mEnabled(true)
, mReporter(new ConsoleReportCollector())
#ifdef DEBUG
, mSyncCallback(false)
#endif
@ -955,9 +958,13 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
return NS_OK;
}
} else {
nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader,
mSheet->GetCORSMode(), aBuffer,
mLoader->mDocument);
nsAutoCString sourceUri;
if (mLoader->mDocument && mLoader->mDocument->GetDocumentURI()) {
mLoader->mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
}
nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader, aBuffer,
sourceUri, mLoader->mReporter);
mLoader->mReporter->FlushConsoleReports(mLoader->mDocument);
if (NS_FAILED(rv)) {
LOG((" Load was blocked by SRI"));
MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
@ -1236,7 +1243,12 @@ Loader::CreateSheet(nsIURI* aURI,
MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
("css::Loader::CreateSheet, integrity=%s",
NS_ConvertUTF16toUTF8(aIntegrity).get()));
SRICheck::IntegrityMetadata(aIntegrity, mDocument, &sriMetadata);
nsAutoCString sourceUri;
if (mDocument && mDocument->GetDocumentURI()) {
mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
}
SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter,
&sriMetadata);
}
if (GetStyleBackendType() == StyleBackendType::Gecko) {

Просмотреть файл

@ -28,6 +28,7 @@
#include "mozilla/net/ReferrerPolicy.h"
class nsICSSLoaderObserver;
class nsIConsoleReportCollector;
class nsIContent;
class nsIDocument;
class nsMediaList;
@ -584,6 +585,8 @@ private:
bool mEnabled; // is enabled to load new styles
nsCOMPtr<nsIConsoleReportCollector> mReporter;
#ifdef DEBUG
bool mSyncCallback;
#endif