bug 1289865 - look in more registry locations for enterprise roots r?Cykesiopka,mhowell draft
authorDavid Keeler <dkeeler@mozilla.com>
Thu, 06 Oct 2016 16:14:06 -0700
changeset 421845 454af89a3d0cb5a765587eab729e0d0cdbda5bbd
parent 419507 5ffed033557e5b6f9694123f1948f867f913ede3
child 533186 a032178f9515906758f57a2c24ae86e61ea3022a
push id31615
push userbmo:dkeeler@mozilla.com
push dateThu, 06 Oct 2016 23:23:16 +0000
reviewersCykesiopka, mhowell
bugs1289865
milestone52.0a1
bug 1289865 - look in more registry locations for enterprise roots r?Cykesiopka,mhowell This adds the following locations: HKLM\SOFTWARE\Policies\Microsoft\SystemCertificates\Root\Certificates HKLM\SOFTWARE\Microsoft\EnterpriseCertificates\Root\Certificates to the location that was already being searched, which is: HKLM\SOFTWARE\Microsoft\SystemCertificates MozReview-Commit-ID: LGOT4YNEqLV
security/manager/ssl/nsNSSComponent.cpp
security/manager/ssl/nsNSSComponent.h
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -966,33 +966,73 @@ nsNSSComponent::MaybeImportEnterpriseRoo
     return;
   }
   UnloadEnterpriseRoots();
   bool importEnterpriseRoots = Preferences::GetBool(kEnterpriseRootModePref,
                                                     false);
   if (!importEnterpriseRoots) {
     return;
   }
-  DWORD flags = CERT_SYSTEM_STORE_LOCAL_MACHINE |
+
+  MOZ_ASSERT(!mEnterpriseRoots);
+  mEnterpriseRoots.reset(CERT_NewCertList());
+  if (!mEnterpriseRoots) {
+    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+            ("failed to allocate a new CERTCertList for mEnterpriseRoots"));
+    return;
+  }
+
+  ImportEnterpriseRootsForLocation(CERT_SYSTEM_STORE_LOCAL_MACHINE);
+  ImportEnterpriseRootsForLocation(CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY);
+  ImportEnterpriseRootsForLocation(CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE);
+#endif // XP_WIN
+}
+
+#ifdef XP_WIN
+// Loads the enterprise roots at the registry location corresponding to the
+// given location flag.
+// Supported flags are:
+//   CERT_SYSTEM_STORE_LOCAL_MACHINE
+//     (for HKLM\SOFTWARE\Microsoft\SystemCertificates)
+//   CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
+//     (for HKLM\SOFTWARE\Policies\Microsoft\SystemCertificates\Root\Certificates)
+//   CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
+//     (for HKLM\SOFTWARE\Microsoft\EnterpriseCertificates\Root\Certificates)
+void
+nsNSSComponent::ImportEnterpriseRootsForLocation(DWORD locationFlag)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (!NS_IsMainThread()) {
+    return;
+  }
+  MOZ_ASSERT(locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE ||
+             locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY ||
+             locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
+             "unexpected locationFlag for ImportEnterpriseRootsForLocation");
+  if (!(locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE ||
+        locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY ||
+        locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE)) {
+    return;
+  }
+
+  DWORD flags = locationFlag |
                 CERT_STORE_OPEN_EXISTING_FLAG |
                 CERT_STORE_READONLY_FLAG;
   // The certificate store being opened should consist only of certificates
   // added by a user or administrator and not any certificates that are part
   // of Microsoft's root store program.
   // The 3rd parameter to CertOpenStore should be NULL according to
   // https://msdn.microsoft.com/en-us/library/windows/desktop/aa376559%28v=vs.85%29.aspx
   ScopedCertStore enterpriseRootStore(CertOpenStore(
     CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, NULL, flags,
     kWindowsDefaultRootStoreName));
   if (!enterpriseRootStore.get()) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to open enterprise root store"));
     return;
   }
-  MOZ_ASSERT(!mEnterpriseRoots);
-  mEnterpriseRoots.reset(CERT_NewCertList());
   CERTCertTrust trust = {
     CERTDB_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_USER,
     0,
     0
   };
   PCCERT_CONTEXT certificate = nullptr;
   uint32_t numImported = 0;
   while ((certificate = CertFindCertificateInStore(enterpriseRootStore.get(),
@@ -1014,34 +1054,38 @@ nsNSSComponent::MaybeImportEnterpriseRoo
     // Enterprise Roots feature from interacting poorly with the Family
     // Safety support).
     UniquePORTString subjectName(
       CERT_GetCommonName(&nssCertificate->subject));
     if (nsCRT::strcmp(subjectName.get(), kMicrosoftFamilySafetyCN) == 0) {
       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("skipping Family Safety Root"));
       continue;
     }
+    MOZ_ASSERT(mEnterpriseRoots, "mEnterpriseRoots unexpectedly NULL?");
+    if (!mEnterpriseRoots) {
+      return;
+    }
     if (CERT_AddCertToListTail(mEnterpriseRoots.get(), nssCertificate.get())
           != SECSuccess) {
       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't add cert to list"));
       continue;
     }
     if (CERT_ChangeCertTrust(nullptr, nssCertificate.get(), &trust)
           != SECSuccess) {
       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
               ("couldn't trust certificate for TLS server auth"));
     }
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Imported '%s'", subjectName.get()));
     numImported++;
     // now owned by mEnterpriseRoots
     Unused << nssCertificate.release();
   }
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("imported %u roots", numImported));
+}
 #endif // XP_WIN
-}
 
 void
 nsNSSComponent::LoadLoadableRoots()
 {
   nsNSSShutDownPreventionLock locker;
   SECMODModule* RootsModule = nullptr;
 
   // In the past we used SECMOD_AddNewModule to load our module containing
--- a/security/manager/ssl/nsNSSComponent.h
+++ b/security/manager/ssl/nsNSSComponent.h
@@ -183,16 +183,17 @@ private:
   nsresult ConfigureInternalPKCS11Token();
   nsresult RegisterObservers();
 
   void DoProfileBeforeChange();
 
   void MaybeEnableFamilySafetyCompatibility();
   void MaybeImportEnterpriseRoots();
 #ifdef XP_WIN
+  void ImportEnterpriseRootsForLocation(DWORD locationFlag);
   nsresult MaybeImportFamilySafetyRoot(PCCERT_CONTEXT certificate,
                                        bool& wasFamilySafetyRoot);
   nsresult LoadFamilySafetyRoot();
   void UnloadFamilySafetyRoot();
 
   void UnloadEnterpriseRoots();
 
   mozilla::UniqueCERTCertificate mFamilySafetyRoot;