bug 800444 - disable HSTS preload list if firefox has not updated in 18 weeks r=bsmith, mayhemer
authorDavid Keeler <dkeeler@mozilla.com>
Fri, 26 Oct 2012 09:50:23 -0700
changeset 111664 78cf3c6d8fc51a664b76c4f8caeed3252549899f
parent 111663 4d180e495354298b838ea855cda5bab9389bd145
child 111665 eac41b17bc5230b56b9a089a3bbfd1e62532d2a0
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersbsmith, mayhemer
bugs800444
milestone19.0a1
bug 800444 - disable HSTS preload list if firefox has not updated in 18 weeks r=bsmith, mayhemer
security/manager/boot/src/Makefile.in
security/manager/boot/src/nsSTSPreloadList.errors
security/manager/boot/src/nsSTSPreloadList.inc
security/manager/boot/src/nsStrictTransportSecurityService.cpp
security/manager/ssl/tests/unit/test_sts_preloadlist_selfdestruct.js
security/manager/ssl/tests/unit/xpcshell.ini
security/manager/tools/getHSTSPreloadList.js
--- a/security/manager/boot/src/Makefile.in
+++ b/security/manager/boot/src/Makefile.in
@@ -21,15 +21,16 @@ FAIL_ON_WARNINGS = 1
 CPPSRCS = \
 	nsEntropyCollector.cpp \
 	nsSecureBrowserUIImpl.cpp \
 	nsBOOTModule.cpp \
 	nsSecurityWarningDialogs.cpp \
 	nsStrictTransportSecurityService.cpp \
 	$(NULL)
 
+DEFINES += -D__STDC_CONSTANT_MACROS
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES	+= \
 		-I$(DIST)/public/nss \
 		$(NULL)
 
--- a/security/manager/boot/src/nsSTSPreloadList.errors
+++ b/security/manager/boot/src/nsSTSPreloadList.errors
@@ -36,50 +36,52 @@ irccloud.com: did not receive HSTS heade
 jitsi.org: did not receive HSTS header
 jottit.com: could not connect to host
 kyps.net: did not receive HSTS header
 lastpass.com: max-age too low: 8640000
 ledgerscope.net: max-age too low: 86400
 linx.net: could not connect to host
 lists.mayfirst.org: did not receive HSTS header
 login.persona.org: max-age too low: 2592000
-lookout.com: did not receive HSTS header
 mail.google.com: did not receive HSTS header
 market.android.com: did not receive HSTS header
 mydigipass.com: did not receive HSTS header
-mylookout.com: did not receive HSTS header
 neonisi.com: could not connect to host
+openshift.redhat.com: did not receive HSTS header
 ottospora.nl: could not connect to host
 packagist.org: max-age too low: 2592000
 plus.google.com: did not receive HSTS header
 profiles.google.com: did not receive HSTS header
+rhcloud.com: could not connect to host
 romab.com: max-age too low: 2628000
 script.google.com: did not receive HSTS header
 shops.neonisi.com: could not connect to host
 simon.butcher.name: max-age too low: 2629743
 sites.google.com: did not receive HSTS header
 sol.io: could not connect to host
 spreadsheets.google.com: did not receive HSTS header
 squareup.com: max-age too low: 1296000
 ssl.google-analytics.com: did not receive HSTS header
 sunshinepress.org: could not connect to host
 talk.google.com: did not receive HSTS header
 talkgadget.google.com: did not receive HSTS header
 torproject.org: did not receive HSTS header
 uprotect.it: could not connect to host
 www.developer.mydigipass.com: did not receive HSTS header
 www.dropcam.com: max-age too low: 2592000
+www.elanex.biz: did not receive HSTS header
 www.entropia.de: max-age too low: 2678402
 www.gmail.com: did not receive HSTS header
 www.googlemail.com: did not receive HSTS header
 www.greplin.com: did not receive HSTS header
 www.irccloud.com: did not receive HSTS header
 www.jitsi.org: did not receive HSTS header
 www.kyps.net: did not receive HSTS header
 www.lastpass.com: did not receive HSTS header
 www.ledgerscope.net: max-age too low: 86400
 www.logentries.com: did not receive HSTS header
 www.makeyourlaws.org: did not receive HSTS header
 www.moneybookers.com: did not receive HSTS header
 www.neonisi.com: could not connect to host
 www.paycheckrecords.com: did not receive HSTS header
 www.paypal.com: max-age too low: 14400
 www.sandbox.mydigipass.com: did not receive HSTS header
+www.twitter.com: did not receive HSTS header
--- a/security/manager/boot/src/nsSTSPreloadList.inc
+++ b/security/manager/boot/src/nsSTSPreloadList.inc
@@ -2,16 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*****************************************************************************/
 /* This is an automatically generated file. If you're not                    */
 /* nsStrictTransportSecurityService.cpp, you shouldn't be #including it.     */
 /*****************************************************************************/
 
+#include "mozilla/StandardInteger.h"
+const PRTime gPreloadListExpirationTime = INT64_C(1362156597190000);
+
 class nsSTSPreload
 {
   public:
     const char *mHost;
     const bool mIncludeSubdomains;
 };
 
 static const nsSTSPreload kSTSPreloadList[] = {
@@ -29,37 +32,41 @@ static const nsSTSPreload kSTSPreloadLis
   { "csawctf.poly.edu", true },
   { "developer.mydigipass.com", false },
   { "dm.lookout.com", false },
   { "dm.mylookout.com", false },
   { "ebanking.indovinabank.com.vn", false },
   { "factor.cc", false },
   { "id.mayfirst.org", false },
   { "intercom.io", false },
+  { "itriskltd.com", true },
   { "keyerror.com", true },
   { "logentries.com", false },
   { "login.sapo.pt", true },
+  { "lookout.com", false },
   { "luneta.nearbuysystems.com", false },
   { "makeyourlaws.org", false },
   { "mattmccutchen.net", true },
   { "members.mayfirst.org", false },
+  { "mylookout.com", false },
   { "neg9.org", false },
   { "passwd.io", true },
   { "piratenlogin.de", true },
   { "pixi.me", true },
   { "riseup.net", true },
   { "sandbox.mydigipass.com", false },
+  { "stocktrade.de", false },
   { "stripe.com", true },
   { "support.mayfirst.org", false },
   { "surfeasy.com", false },
+  { "twitter.com", false },
   { "ubertt.org", true },
   { "www.apollo-auto.com", true },
   { "www.braintreepayments.com", false },
   { "www.cueup.com", false },
-  { "www.elanex.biz", false },
   { "www.intercom.io", false },
   { "www.lookout.com", false },
   { "www.mydigipass.com", false },
   { "www.mylookout.com", false },
   { "www.noisebridge.net", false },
   { "www.surfeasy.com", false },
   { "www.torproject.org", false },
 };
--- a/security/manager/boot/src/nsStrictTransportSecurityService.cpp
+++ b/security/manager/boot/src/nsStrictTransportSecurityService.cpp
@@ -369,26 +369,33 @@ int STSPreloadCompare(const void *key, c
 }
 
 // Returns the preload list entry for the given host, if it exists.
 // Only does exact host matching - the user must decide how to use the returned
 // data. May return null.
 const nsSTSPreload *
 nsStrictTransportSecurityService::GetPreloadListEntry(const char *aHost)
 {
-  if (mUsePreloadList) {
+  PRTime currentTime = PR_Now();
+  int32_t timeOffset = 0;
+  nsresult rv = mozilla::Preferences::GetInt("test.currentTimeOffsetSeconds",
+                                             &timeOffset);
+  if (NS_SUCCEEDED(rv)) {
+    currentTime += (PRTime(timeOffset) * PR_USEC_PER_SEC);
+  }
+
+  if (mUsePreloadList && currentTime < gPreloadListExpirationTime) {
     return (const nsSTSPreload *) bsearch(aHost,
                                           kSTSPreloadList,
                                           PR_ARRAY_SIZE(kSTSPreloadList),
                                           sizeof(nsSTSPreload),
                                           STSPreloadCompare);
   }
-  else {
-    return nullptr;
-  }
+
+  return nullptr;
 }
 
 NS_IMETHODIMP
 nsStrictTransportSecurityService::IsStsURI(nsIURI* aURI, bool* aResult)
 {
   // Should be called on the main thread (or via proxy) since the permission
   // manager is used and it's not threadsafe.
   NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_UNEXPECTED);
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_sts_preloadlist_selfdestruct.js
@@ -0,0 +1,24 @@
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+function run_test() {
+  let STSService = Cc["@mozilla.org/stsservice;1"]
+                     .getService(Ci.nsIStrictTransportSecurityService);
+
+  // check that a host on the preload list is identified as an sts host
+  do_check_true(STSService.isStsHost("alpha.irccloud.com"));
+
+  // now simulate that it's 19 weeks later than it actually is
+  let offsetSeconds = 19 * 7 * 24 * 60 * 60;
+  Services.prefs.setIntPref("test.currentTimeOffsetSeconds", offsetSeconds);
+
+  // check that the preloaded host is no longer considered sts
+  do_check_false(STSService.isStsHost("alpha.irccloud.com"));
+
+  // just make sure we can get everything back to normal
+  Services.prefs.clearUserPref("test.currentTimeOffsetSeconds");
+  do_check_true(STSService.isStsHost("alpha.irccloud.com"));
+}
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -8,8 +8,9 @@ skip-if = os == "android"
 [test_hash_algorithms.js]
 # Bug 676972: test hangs consistently on Android
 skip-if = os == "android"
 [test_hmac.js]
 # Bug 676972: test hangs consistently on Android
 skip-if = os == "android"
 [test_bug627234.js]
 [test_sts_preloadlist.js]
+[test_sts_preloadlist_selfdestruct.js]
--- a/security/manager/tools/getHSTSPreloadList.js
+++ b/security/manager/tools/getHSTSPreloadList.js
@@ -22,25 +22,27 @@ resHandler.setSubstitution("app", mozDir
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource:///modules/XPCOMUtils.jsm");
 
 const SOURCE = "https://src.chromium.org/viewvc/chrome/trunk/src/net/base/transport_security_state_static.json";
 const OUTPUT = "nsSTSPreloadList.inc";
 const ERROR_OUTPUT = "nsSTSPreloadList.errors";
 const MINIMUM_REQUIRED_MAX_AGE = 60 * 60 * 24 * 7 * 18;
-const PREFIX = "/* This Source Code Form is subject to the terms of the Mozilla Public\n" +
+const HEADER = "/* This Source Code Form is subject to the terms of the Mozilla Public\n" +
 " * License, v. 2.0. If a copy of the MPL was not distributed with this\n" +
 " * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n" +
 "\n" +
 "/*****************************************************************************/\n" +
 "/* This is an automatically generated file. If you're not                    */\n" +
 "/* nsStrictTransportSecurityService.cpp, you shouldn't be #including it.     */\n" +
 "/*****************************************************************************/\n" +
 "\n" +
+"#include \"mozilla/StandardInteger.h\"\n";
+const PREFIX = "\n" +
 "class nsSTSPreload\n" +
 "{\n" +
 "  public:\n" +
 "    const char *mHost;\n" +
 "    const bool mIncludeSubdomains;\n" +
 "};\n" +
 "\n" +
 "static const nsSTSPreload kSTSPreloadList[] = {\n";
@@ -166,22 +168,36 @@ function getHSTSStatus(host, resultList)
 function compareHSTSStatus(a, b) {
   return (a.hostname > b.hostname ? 1 : (a.hostname < b.hostname ? -1 : 0));
 }
 
 function writeTo(string, fos) {
   fos.write(string, string.length);
 }
 
+// Determines and returns a string representing a declaration of when this
+// preload list should no longer be used.
+// This is the current time plus MINIMUM_REQUIRED_MAX_AGE.
+function getExpirationTimeString() {
+  var now = new Date();
+  var nowMillis = now.getTime();
+  // MINIMUM_REQUIRED_MAX_AGE is in seconds, so convert to milliseconds
+  var expirationMillis = nowMillis + (MINIMUM_REQUIRED_MAX_AGE * 1000);
+  var expirationMicros = expirationMillis * 1000;
+  return "const PRTime gPreloadListExpirationTime = INT64_C(" + expirationMicros + ");\n";
+}
+
 function output(sortedStatuses) {
   try {
     var file = FileUtils.getFile("CurWorkD", [OUTPUT]);
     var errorFile = FileUtils.getFile("CurWorkD", [ERROR_OUTPUT]);
     var fos = FileUtils.openSafeFileOutputStream(file);
     var eos = FileUtils.openSafeFileOutputStream(errorFile);
+    writeTo(HEADER, fos);
+    writeTo(getExpirationTimeString(), fos);
     writeTo(PREFIX, fos);
     for (var status of hstsStatuses) {
       if (status.maxAge >= MINIMUM_REQUIRED_MAX_AGE) {
         writeTo("  { \"" + status.hostname + "\", " +
                  (status.includeSubdomains ? "true" : "false") + " },\n", fos);
         dump("INFO: " + status.hostname + " ON the preload list\n");
       }
       else {