Bug 1313596 Increase HSTS Priming default cache timeout r?mayhemer draft
authorKate McKinley <kmckinley@mozilla.com>
Tue, 08 Nov 2016 17:45:36 +0900
changeset 437004 0549e5879b1087485a295dd0a2d7eb610217487d
parent 437002 fe91fde5ba7a7ad83b307b5f5a247d861aa76947
child 536513 905f53b559d5ad46f42011ee815a4ea6f6408c6c
push id35278
push userbmo:kmckinley@mozilla.com
push dateThu, 10 Nov 2016 06:44:03 +0000
reviewersmayhemer
bugs1313596
milestone52.0a1
Bug 1313596 Increase HSTS Priming default cache timeout r?mayhemer MozReview-Commit-ID: 6sHuB4wIEu4
dom/security/nsMixedContentBlocker.cpp
dom/security/nsMixedContentBlocker.h
dom/security/test/hsts/browser.ini
dom/security/test/hsts/browser_hsts-priming_cache-timeout.js
dom/security/test/hsts/head.js
modules/libpref/init/all.js
netwerk/protocol/http/nsHttpChannel.cpp
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -53,16 +53,18 @@ bool nsMixedContentBlocker::sBlockMixedS
 
 // Is mixed display content blocking (images, audio, video, <a ping>) enabled?
 bool nsMixedContentBlocker::sBlockMixedDisplay = false;
 
 // Do we move HSTS before mixed-content
 bool nsMixedContentBlocker::sUseHSTS = false;
 // Do we send an HSTS priming request
 bool nsMixedContentBlocker::sSendHSTSPriming = false;
+// Default HSTS Priming failure timeout to 7 days, in seconds
+uint32_t nsMixedContentBlocker::sHSTSPrimingCacheTimeout = (60 * 24 * 7);
 
 // Fired at the document that attempted to load mixed content.  The UI could
 // handle this event, for example, by displaying an info bar that offers the
 // choice to reload the page with mixed content permitted.
 class nsMixedContentEvent : public Runnable
 {
 public:
   nsMixedContentEvent(nsISupports *aContext, MixedContentTypes aType, bool aRootHasSecureConnection)
@@ -203,16 +205,20 @@ nsMixedContentBlocker::nsMixedContentBlo
 
   // Cache the pref for HSTS
   Preferences::AddBoolVarCache(&sUseHSTS,
                                "security.mixed_content.use_hsts");
 
   // Cache the pref for sending HSTS priming
   Preferences::AddBoolVarCache(&sSendHSTSPriming,
                                "security.mixed_content.send_hsts_priming");
+
+  // Cache the pref for HSTS priming failure cache time
+  Preferences::AddUintVarCache(&sHSTSPrimingCacheTimeout,
+                               "security.mixed_content.hsts_priming_cache_seconds");
 }
 
 nsMixedContentBlocker::~nsMixedContentBlocker()
 {
 }
 
 NS_IMPL_ISUPPORTS(nsMixedContentBlocker, nsIContentPolicy, nsIChannelEventSink)
 
--- a/dom/security/nsMixedContentBlocker.h
+++ b/dom/security/nsMixedContentBlocker.h
@@ -89,13 +89,17 @@ public:
   static nsresult GetHSTSPrimingFromRequestingContext(nsIURI* aURI,
                                                       nsISupports* aRequestingContext,
                                                       bool* aSendPrimingRequest,
                                                       bool* aMixedContentWouldBlock);
 
 
   static bool sBlockMixedScript;
   static bool sBlockMixedDisplay;
+  // Do we move HSTS before mixed-content
   static bool sUseHSTS;
+  // Do we send an HSTS priming request
   static bool sSendHSTSPriming;
+  // Default HSTS Priming failure timeout in seconds
+  static uint32_t sHSTSPrimingCacheTimeout;
 };
 
 #endif /* nsMixedContentBlocker_h___ */
--- a/dom/security/test/hsts/browser.ini
+++ b/dom/security/test/hsts/browser.ini
@@ -11,8 +11,9 @@ support-files =
 [browser_hsts-priming_allow_active.js]
 [browser_hsts-priming_block_active.js]
 [browser_hsts-priming_hsts_after_mixed.js]
 [browser_hsts-priming_allow_display.js]
 [browser_hsts-priming_block_display.js]
 [browser_hsts-priming_block_active_css.js]
 [browser_hsts-priming_block_active_with_redir_same.js]
 [browser_hsts-priming_no-duplicates.js]
+[browser_hsts-priming_cache-timeout.js]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/hsts/browser_hsts-priming_cache-timeout.js
@@ -0,0 +1,36 @@
+/*
+ * Description of the test:
+ * Test that the network.hsts_priming.cache_timeout preferene causes the cache
+ * to timeout
+ */
+'use strict';
+
+//jscs:disable
+add_task(function*() {
+  //jscs:enable
+  Observer.add_observers(Services);
+  registerCleanupFunction(do_cleanup);
+
+  let which = "block_display";
+
+  SetupPrefTestEnvironment(which, [["security.mixed_content.hsts_priming_cache_timeout", 1]]);
+
+  yield execute_test("no-ssl", test_settings[which].mimetype);
+
+  let pre_promise = performance.now();
+
+  while ((performance.now() - pre_promise) < 2000) {
+    yield new Promise(function (resolve) {
+      setTimeout(resolve, 2000);
+    });
+  }
+
+  // clear the fact that we saw a priming request
+  test_settings[which].priming = {};
+
+  yield execute_test("no-ssl", test_settings[which].mimetype);
+  is(test_settings[which].priming["no-ssl"], true,
+    "Correctly send a priming request after expiration.");
+
+  SpecialPowers.popPrefEnv();
+});
--- a/dom/security/test/hsts/head.js
+++ b/dom/security/test/hsts/head.js
@@ -250,34 +250,44 @@ function clear_sts_data() {
 
 function do_cleanup() {
   clear_sts_data();
 
   Services.obs.removeObserver(Observer, "console-api-log-event");
   Services.obs.removeObserver(Observer, "http-on-examine-response");
 }
 
-function SetupPrefTestEnvironment(which) {
+function SetupPrefTestEnvironment(which, additional_prefs) {
   which_test = which;
   clear_sts_data();
 
   var settings = test_settings[which];
   // priming counts how many priming requests we saw
   settings.priming = {};
   // priming counts how many tests were finished
   settings.finished= {};
 
-  SpecialPowers.pushPrefEnv({'set': [["security.mixed_content.block_active_content",
-                                      settings.block_active],
-                                     ["security.mixed_content.block_display_content",
-                                      settings.block_display],
-                                     ["security.mixed_content.use_hsts",
-                                      settings.use_hsts],
-                                     ["security.mixed_content.send_hsts_priming",
-                                      settings.send_hsts_priming]]});
+  var prefs = [["security.mixed_content.block_active_content",
+                settings.block_active],
+               ["security.mixed_content.block_display_content",
+                settings.block_display],
+               ["security.mixed_content.use_hsts",
+                settings.use_hsts],
+               ["security.mixed_content.send_hsts_priming",
+                settings.send_hsts_priming]];
+
+  if (additional_prefs) {
+    for (let idx in additional_prefs) {
+      prefs.push(additional_prefs[idx]);
+    }
+  }
+
+  console.log("prefs=%s", prefs);
+
+  SpecialPowers.pushPrefEnv({'set': prefs});
 }
 
 // make the top-level test uri
 function build_test_uri(base_uri, host, test_id, type) {
   return base_uri +
           "?host=" + escape(host) +
           "&id=" + escape(test_id) +
           "&type=" + escape(type);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5510,15 +5510,17 @@ pref("security.mixed_content.send_hsts_p
 // Don't change the order of evaluation of mixed-content and HSTS upgrades in
 // order to be most compatible with current standards
 pref("security.mixed_content.use_hsts", false);
 #else
 // Change the order of evaluation so HSTS upgrades happen before
 // mixed-content blocking
 pref("security.mixed_content.use_hsts", true);
 #endif
+// Approximately 1 week default cache for HSTS priming failures
+pref ("security.mixed_content.hsts_priming_cache_timeout", 10080);
 
 // Disable Storage api in release builds.
 #ifdef NIGHTLY_BUILD
 pref("dom.storageManager.enabled", true);
 #else
 pref("dom.storageManager.enabled", false);
 #endif
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -7973,20 +7973,22 @@ nsHttpChannel::OnHSTSPrimingFailed(nsres
     } else {
         // A priming request was sent, and no HSTS header was found that allows
         // the upgrade.
         Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT,
                 (wouldBlock) ?  HSTSPrimingResult::eHSTS_PRIMING_FAILED_BLOCK :
                                 HSTSPrimingResult::eHSTS_PRIMING_FAILED_ACCEPT);
     }
 
-    // Don't visit again for at least one day
+    // Don't visit again for at least
+    // security.mixed_content.hsts_priming_cache_timeout seconds.
     nsISiteSecurityService* sss = gHttpHandler->GetSSService();
     NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY);
-    nsresult rv = sss->CacheNegativeHSTSResult(mURI, 24 * 60 * 60);
+    nsresult rv = sss->CacheNegativeHSTSResult(mURI,
+            nsMixedContentBlocker::sHSTSPrimingCacheTimeout);
     if (NS_FAILED(rv)) {
         NS_ERROR("nsISiteSecurityService::CacheNegativeHSTSResult failed");
     }
 
     // If we would block, go ahead and abort with the error provided
     if (wouldBlock) {
         CloseCacheEntry(false);
         return AsyncAbort(aError);