diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index aff9c9a9bd9..1ea89ea71c0 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -142,6 +142,7 @@ #include "nsIXULRuntime.h" #include "gfxDrawable.h" #include "ImageOps.h" +#include "mozilla/dom/nsMixedContentBlocker.h" #include "nsMemoryInfoDumper.h" #include "nsMemoryReporterManager.h" #include "nsServiceManagerUtils.h" @@ -4175,6 +4176,17 @@ ContentParent::RecvIsSecureURI(const uint32_t& type, return NS_SUCCEEDED(rv); } +bool +ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive) +{ + nsCOMPtr ourURI = DeserializeURI(aURI); + if (!ourURI) { + return false; + } + nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive); + return true; +} + bool ContentParent::RecvLoadURIExternal(const URIParams& uri) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index ac881edeea0..d65cdca423e 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -626,6 +626,8 @@ private: virtual bool RecvIsSecureURI(const uint32_t& aType, const URIParams& aURI, const uint32_t& aFlags, bool* aIsSecureURI) override; + virtual bool RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive) override; + virtual bool DeallocPHalParent(PHalParent*) override; virtual PIccParent* AllocPIccParent(const uint32_t& aServiceId) override; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 8934cf05f88..a8dcf6ea2b8 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -751,6 +751,8 @@ parent: sync IsSecureURI(uint32_t type, URIParams uri, uint32_t flags) returns (bool isSecureURI); + async AccumulateMixedContentHSTS(URIParams uri, bool active); + sync GetLookAndFeelCache() returns (LookAndFeelInt[] lookAndFeelIntCache); @@ -788,7 +790,7 @@ parent: PFMRadio(); PWebrtcGlobal(); - + PPresentation(); // Services remoting diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index cf3981b490e..6bb479b9511 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -134,6 +134,7 @@ LOCAL_INCLUDES += [ '/dom/geolocation', '/dom/media/webspeech/synth/ipc', '/dom/mobilemessage/ipc', + '/dom/security', '/dom/storage', '/dom/workers', '/editor/libeditor', diff --git a/dom/security/moz.build b/dom/security/moz.build index 8c99bd4366b..80890f46f29 100644 --- a/dom/security/moz.build +++ b/dom/security/moz.build @@ -33,6 +33,8 @@ UNIFIED_SOURCES += [ 'SRIMetadata.cpp', ] +include('/ipc/chromium/chromium-config.mozbuild') + FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '/caps', @@ -40,5 +42,5 @@ LOCAL_INCLUDES += [ ] if CONFIG['GNU_CC']: - CFLAGS += ['-Wshadow', '-Wformat-security'] - CXXFLAGS += ['-Wshadow', '-Wformat-security'] + CFLAGS += ['-Wformat-security'] + CXXFLAGS += ['-Wformat-security'] diff --git a/dom/security/nsMixedContentBlocker.cpp b/dom/security/nsMixedContentBlocker.cpp index 5f6c47dddc9..59d8d662398 100644 --- a/dom/security/nsMixedContentBlocker.cpp +++ b/dom/security/nsMixedContentBlocker.cpp @@ -32,8 +32,13 @@ #include "nsIChannelEventSink.h" #include "nsAsyncRedirectVerifyHelper.h" #include "mozilla/LoadInfo.h" +#include "nsISiteSecurityService.h" #include "mozilla/Logging.h" +#include "mozilla/Telemetry.h" +#include "mozilla/dom/ContentChild.h" +#include "mozilla/ipc/URIUtils.h" + using namespace mozilla; @@ -342,7 +347,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType, // callers of this method don't know whether the load went through cached // image redirects. This is handled by direct callers of the static // ShouldLoad. - nsresult rv = ShouldLoad(false, //aHadInsecureImageRedirect + nsresult rv = ShouldLoad(false, // aHadInsecureImageRedirect aContentType, aContentLocation, aRequestingLocation, @@ -381,7 +386,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, // Make decision to block/reject by default *aDecision = REJECT_REQUEST; - // Notes on non-obvious decisions: // // TYPE_DTD: A DTD can contain entity definitions that expand to scripts. @@ -718,6 +722,33 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, } nsresult stateRV = securityUI->GetState(&state); + // At this point we know that the request is mixed content, and the only + // question is whether we block it. Record telemetry at this point as to + // whether HSTS would have fixed things by making the content location + // into an HTTPS URL. + // + // Note that we count this for redirects as well as primary requests. This + // will cause some degree of double-counting, especially when mixed content + // is not blocked (e.g., for images). For more detail, see: + // https://bugzilla.mozilla.org/show_bug.cgi?id=1198572#c19 + // + // We do not count requests aHadInsecureImageRedirect=true, since these are + // just an artifact of the image caching system. + bool active = (classification == eMixedScript); + if (!aHadInsecureImageRedirect) { + if (XRE_IsParentProcess()) { + AccumulateMixedContentHSTS(aContentLocation, active); + } else { + // Ask the parent process to do the same call + mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton(); + if (cc) { + mozilla::ipc::URIParams uri; + SerializeURI(aContentLocation, uri); + cc->SendAccumulateMixedContentHSTS(uri, active); + } + } + } + // If the content is display content, and the pref says display content should be blocked, block it. if (sBlockMixedDisplay && classification == eMixedDisplay) { if (allowMixedContent) { @@ -857,3 +888,54 @@ nsMixedContentBlocker::ShouldProcess(uint32_t aContentType, aRequestingContext, aMimeGuess, aExtra, aRequestPrincipal, aDecision); } + +enum MixedContentHSTSState { + MCB_HSTS_PASSIVE_NO_HSTS = 0, + MCB_HSTS_PASSIVE_WITH_HSTS = 1, + MCB_HSTS_ACTIVE_NO_HSTS = 2, + MCB_HSTS_ACTIVE_WITH_HSTS = 3 +}; + +// Record information on when HSTS would have made mixed content not mixed +// content (regardless of whether it was actually blocked) +void +nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive) +{ + // This method must only be called in the parent, because + // nsSiteSecurityService is only available in the parent + if (!XRE_IsParentProcess()) { + MOZ_ASSERT(false); + return; + } + + bool hsts; + nsresult rv; + nsCOMPtr sss = do_GetService(NS_SSSERVICE_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + return; + } + rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, 0, &hsts); + if (NS_FAILED(rv)) { + return; + } + + if (!aActive) { + if (!hsts) { + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS, + MCB_HSTS_PASSIVE_NO_HSTS); + } + else { + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS, + MCB_HSTS_PASSIVE_WITH_HSTS); + } + } else { + if (!hsts) { + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS, + MCB_HSTS_ACTIVE_NO_HSTS); + } + else { + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS, + MCB_HSTS_ACTIVE_WITH_HSTS); + } + } +} diff --git a/dom/security/nsMixedContentBlocker.h b/dom/security/nsMixedContentBlocker.h index e77189c2a6b..216466fd83b 100644 --- a/dom/security/nsMixedContentBlocker.h +++ b/dom/security/nsMixedContentBlocker.h @@ -59,6 +59,7 @@ public: nsISupports* aExtra, nsIPrincipal* aRequestPrincipal, int16_t* aDecision); + static void AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive); static bool sBlockMixedScript; static bool sBlockMixedDisplay; }; diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 1731e0eccf5..841bb2d18d7 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -7334,6 +7334,13 @@ "n_values": 3, "description": "A simple counter of daily mixed-content unblock operations and top documents loaded" }, + "MIXED_CONTENT_HSTS": { + "alert_emails": ["seceng@mozilla.org"], + "expires_in_version": "never", + "kind": "enumerated", + "n_values": 10, + "description": "How often would blocked mixed content be allowed if HSTS upgrades were allowed? 0=display/no-HSTS, 1=display/HSTS, 2=active/no-HSTS, 3=active/HSTS" + }, "NTLM_MODULE_USED_2": { "expires_in_version": "never", "kind": "enumerated",