Bug 1227970 - Perform preference checks to allow OCSP Bypass for OneCRL via Kinto r=keeler
authorMark Goodwin <mgoodwin@mozilla.com>
Thu, 26 Nov 2015 16:57:21 +0000
changeset 308535 beb1ebb12542681c7ad55f8ba1f69e26a01d1d25
parent 308534 98fb5254f78840c629f9c4d603a0c9de3555aada
child 308536 e921b3682fbf3a90c77cfb1093b2ecfb67124bd4
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1227970
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1227970 - Perform preference checks to allow OCSP Bypass for OneCRL via Kinto r=keeler
security/manager/ssl/CertBlocklist.cpp
security/manager/ssl/CertBlocklist.h
security/manager/ssl/tests/unit/test_ev_certs.js
--- a/security/manager/ssl/CertBlocklist.cpp
+++ b/security/manager/ssl/CertBlocklist.cpp
@@ -25,22 +25,24 @@
 #include "prtime.h"
 
 NS_IMPL_ISUPPORTS(CertBlocklist, nsICertBlocklist)
 
 using namespace mozilla;
 using namespace mozilla::pkix;
 
 #define PREF_BACKGROUND_UPDATE_TIMER "app.update.lastUpdateTime.blocklist-background-update-timer"
+#define PREF_KINTO_ONECRL_CHECKED "services.kinto.onecrl.checked"
 #define PREF_MAX_STALENESS_IN_SECONDS "security.onecrl.maximum_staleness_in_seconds"
 #define PREF_ONECRL_VIA_AMO "security.onecrl.via.amo"
 
 static PRLogModuleInfo* gCertBlockPRLog;
 
 uint32_t CertBlocklist::sLastBlocklistUpdate = 0U;
+uint32_t CertBlocklist::sLastKintoUpdate = 0U;
 uint32_t CertBlocklist::sMaxStaleness = 0U;
 bool CertBlocklist::sUseAMO = true;
 
 CertBlocklistItem::CertBlocklistItem(const uint8_t* DNData,
                                      size_t DNLength,
                                      const uint8_t* otherData,
                                      size_t otherLength,
                                      CertBlocklistItemMechanism itemMechanism)
@@ -139,16 +141,19 @@ CertBlocklist::~CertBlocklist()
                                   PREF_BACKGROUND_UPDATE_TIMER,
                                   this);
   Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
                                   PREF_MAX_STALENESS_IN_SECONDS,
                                   this);
   Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
                                   PREF_ONECRL_VIA_AMO,
                                   this);
+  Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
+                                  PREF_KINTO_ONECRL_CHECKED,
+                                  this);
 }
 
 nsresult
 CertBlocklist::Init()
 {
   MOZ_LOG(gCertBlockPRLog, LogLevel::Debug, ("CertBlocklist::Init"));
 
   // Init must be on main thread for getting the profile directory
@@ -173,16 +178,22 @@ CertBlocklist::Init()
     return rv;
   }
   rv = Preferences::RegisterCallbackAndCall(CertBlocklist::PreferenceChanged,
                                             PREF_ONECRL_VIA_AMO,
                                             this);
   if (NS_FAILED(rv)) {
     return rv;
   }
+  rv = Preferences::RegisterCallbackAndCall(CertBlocklist::PreferenceChanged,
+                                            PREF_KINTO_ONECRL_CHECKED,
+                                            this);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
 
   // Get the profile directory
   rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
                               getter_AddRefs(mBackingFile));
   if (NS_FAILED(rv) || !mBackingFile) {
     MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
            ("CertBlocklist::Init - couldn't get profile dir"));
     // Since we're returning NS_OK here, set mBackingFile to a safe value.
@@ -612,26 +623,25 @@ CertBlocklist::IsCertRevoked(const uint8
   return NS_OK;
 }
 
 NS_IMETHODIMP
 CertBlocklist::IsBlocklistFresh(bool* _retval)
 {
   MutexAutoLock lock(mMutex);
   *_retval = false;
-  if (!sUseAMO) {
-    // for the time being, if we're not using AMO data, assume the blocklist is
-    // not fresh (in particular, prevent OneCRL OCSP bypass).
-    return NS_OK;
-  }
 
   uint32_t now = uint32_t(PR_Now() / PR_USEC_PER_SEC);
+  uint32_t lastUpdate = sUseAMO ? sLastBlocklistUpdate : sLastKintoUpdate;
+  MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
+          ("CertBlocklist::IsBlocklistFresh using AMO? %i lastUpdate is %i",
+           sUseAMO, lastUpdate));
 
-  if (now > sLastBlocklistUpdate) {
-    int64_t interval = now - sLastBlocklistUpdate;
+  if (now > lastUpdate) {
+    int64_t interval = now - lastUpdate;
     MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
            ("CertBlocklist::IsBlocklistFresh we're after the last BlocklistUpdate "
             "interval is %i, staleness %u", interval, sMaxStaleness));
     *_retval = sMaxStaleness > interval;
   }
   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
          ("CertBlocklist::IsBlocklistFresh ? %s", *_retval ? "true" : "false"));
   return NS_OK;
@@ -646,15 +656,18 @@ CertBlocklist::PreferenceChanged(const c
   CertBlocklist* blocklist = reinterpret_cast<CertBlocklist*>(aClosure);
   MutexAutoLock lock(blocklist->mMutex);
 
   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
          ("CertBlocklist::PreferenceChanged %s changed", aPref));
   if (strcmp(aPref, PREF_BACKGROUND_UPDATE_TIMER) == 0) {
     sLastBlocklistUpdate = Preferences::GetUint(PREF_BACKGROUND_UPDATE_TIMER,
                                                 uint32_t(0));
+  } else if (strcmp(aPref, PREF_KINTO_ONECRL_CHECKED) == 0) {
+    sLastKintoUpdate = Preferences::GetUint(PREF_KINTO_ONECRL_CHECKED,
+                                            uint32_t(0));
   } else if (strcmp(aPref, PREF_MAX_STALENESS_IN_SECONDS) == 0) {
     sMaxStaleness = Preferences::GetUint(PREF_MAX_STALENESS_IN_SECONDS,
                                          uint32_t(0));
   } else if (strcmp(aPref, PREF_ONECRL_VIA_AMO) == 0) {
     sUseAMO = Preferences::GetBool(PREF_ONECRL_VIA_AMO, true);
   }
 }
--- a/security/manager/ssl/CertBlocklist.h
+++ b/security/manager/ssl/CertBlocklist.h
@@ -75,14 +75,15 @@ private:
   // call EnsureBackingFileInitialized before operations that read or
   // modify CertBlocklist data
   nsresult EnsureBackingFileInitialized(mozilla::MutexAutoLock& lock);
   nsCOMPtr<nsIFile> mBackingFile;
 
 protected:
   static void PreferenceChanged(const char* aPref, void* aClosure);
   static uint32_t sLastBlocklistUpdate;
+  static uint32_t sLastKintoUpdate;
   static uint32_t sMaxStaleness;
   static bool sUseAMO;
   virtual ~CertBlocklist();
 };
 
 #endif // CertBlocklist_h
--- a/security/manager/ssl/tests/unit/test_ev_certs.js
+++ b/security/manager/ssl/tests/unit/test_ev_certs.js
@@ -183,31 +183,55 @@ function run_test() {
                           gEVExpected ? ["int-ev-valid", "ev-valid"]
                                       : ["ev-valid"]);
     check_ee_for_ev("ev-valid", gEVExpected);
     Services.prefs.clearUserPref("security.onecrl.maximum_staleness_in_seconds");
     ocspResponder.stop(run_next_test);
   });
 
   add_test(function () {
-    // test that setting "security.onecrl.via.amo" to false will prevent
-    // OCSP skipping
+    // test that setting "security.onecrl.via.amo" results in the correct
+    // OCSP behavior when services.kinto.onecrl.checked is in the distant past
+    // and blacklist-background-update-timer is recent
     Services.prefs.setBoolPref("security.onecrl.via.amo", false);
     // enable OneCRL OCSP skipping - allow staleness of up to 30 hours
     Services.prefs.setIntPref("security.onecrl.maximum_staleness_in_seconds", 108000);
     // set the blocklist-background-update-timer value to the recent past
+    // (services.kinto.onecrl.checked defaults to 0)
     Services.prefs.setIntPref("app.update.lastUpdateTime.blocklist-background-update-timer",
                               Math.floor(Date.now() / 1000) - 1);
     clearOCSPCache();
     // the intermediate should have an associated OCSP request
     let ocspResponder = start_ocsp_responder(
                           gEVExpected ? ["int-ev-valid", "ev-valid"]
                                       : ["ev-valid"]);
     check_ee_for_ev("ev-valid", gEVExpected);
-    Services.prefs.clearUserPref("security.onecrl.maximum_staleness_in_seconds");
+    ocspResponder.stop(run_next_test);
+  });
+
+  add_test(function () {
+    // test that setting "security.onecrl.via.amo" results in the correct
+    // OCSP behavior when services.kinto.onecrl.checked is recent
+    Services.prefs.setBoolPref("security.onecrl.via.amo", false);
+
+    // enable OneCRL OCSP skipping - allow staleness of up to 30 hours
+    Services.prefs.setIntPref("security.onecrl.maximum_staleness_in_seconds", 108000);
+
+    // now set services.kinto.onecrl.checked to a recent value
+    Services.prefs.setIntPref("services.kinto.onecrl.checked",
+                              Math.floor(Date.now() / 1000) - 1);
+
+    clearOCSPCache();
+    // the intermediate should not have an associated OCSP request
+    let ocspResponder = start_ocsp_responder(["ev-valid"]);
+    check_ee_for_ev("ev-valid", gEVExpected);
+    // The tests following this assume no OCSP bypass
+    Services.prefs.setIntPref("security.onecrl.maximum_staleness_in_seconds", 0);
+    Services.prefs.clearUserPref("security.onecrl.via.amo");
+    Services.prefs.clearUserPref("services.kinto.onecrl.checked");
     ocspResponder.stop(run_next_test);
   });
 
   // Test the EV continues to work with flags after successful EV verification
   add_test(function () {
     clearOCSPCache();
     let ocspResponder = start_ocsp_responder(
                           gEVExpected ? ["int-ev-valid", "ev-valid"]