Bug 1282279 - Make user certificates Origin Attribute aware. r=keeler draft
authorJonathan Hao <jhao@mozilla.com>
Fri, 25 Nov 2016 17:28:22 +0800
changeset 446299 10fae1f2cb24ebf7cccfe1296e7d51a825a7b5e5
parent 446255 cd4cdcc9ad6c45dad8b8d8c0d40e459db2bca8a1
child 446300 e72f9935adf501fb7ed8a2af537ff807565177f4
push id37752
push userbmo:jhao@mozilla.com
push dateThu, 01 Dec 2016 07:46:08 +0000
reviewerskeeler
bugs1282279
milestone53.0a1
Bug 1282279 - Make user certificates Origin Attribute aware. r=keeler
security/manager/ssl/nsClientAuthRemember.cpp
security/manager/ssl/nsClientAuthRemember.h
security/manager/ssl/nsNSSIOLayer.cpp
--- a/security/manager/ssl/nsClientAuthRemember.cpp
+++ b/security/manager/ssl/nsClientAuthRemember.cpp
@@ -3,16 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #include "nsClientAuthRemember.h"
 
 #include "nsIX509Cert.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/BasePrincipal.h"
 #include "nsCRT.h"
 #include "nsNSSCertHelper.h"
 #include "nsIObserverService.h"
 #include "nsNetUtil.h"
 #include "nsISupportsPrimitives.h"
 #include "nsPromiseFlatString.h"
 #include "nsThreadUtils.h"
 #include "nsStringBuffer.h"
@@ -92,18 +93,19 @@ void nsClientAuthRememberService::ClearA
 
 void
 nsClientAuthRememberService::RemoveAllFromMemory()
 {
   mSettingsTable.Clear();
 }
 
 nsresult
-nsClientAuthRememberService::RememberDecision(const nsACString & aHostName, 
-                                              CERTCertificate *aServerCert, CERTCertificate *aClientCert)
+nsClientAuthRememberService::RememberDecision(
+  const nsACString& aHostName, const NeckoOriginAttributes& aOriginAttributes,
+  CERTCertificate* aServerCert, CERTCertificate* aClientCert)
 {
   // aClientCert == nullptr means: remember that user does not want to use a cert
   NS_ENSURE_ARG_POINTER(aServerCert);
   if (aHostName.IsEmpty()) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsAutoCString fpStr;
@@ -114,95 +116,98 @@ nsClientAuthRememberService::RememberDec
 
   {
     ReentrantMonitorAutoEnter lock(monitor);
     if (aClientCert) {
       RefPtr<nsNSSCertificate> pipCert(new nsNSSCertificate(aClientCert));
       nsAutoCString dbkey;
       rv = pipCert->GetDbKey(dbkey);
       if (NS_SUCCEEDED(rv)) {
-        AddEntryToList(aHostName, fpStr, dbkey);
+        AddEntryToList(aHostName, aOriginAttributes, fpStr, dbkey);
       }
     } else {
       nsCString empty;
-      AddEntryToList(aHostName, fpStr, empty);
+      AddEntryToList(aHostName, aOriginAttributes, fpStr, empty);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
-nsClientAuthRememberService::HasRememberedDecision(const nsACString & aHostName, 
-                                                   CERTCertificate *aCert, 
-                                                   nsACString & aCertDBKey,
-                                                   bool *_retval)
+nsClientAuthRememberService::HasRememberedDecision(
+  const nsACString& aHostName, const NeckoOriginAttributes& aOriginAttributes,
+  CERTCertificate* aCert, nsACString& aCertDBKey, bool* aRetVal)
 {
   if (aHostName.IsEmpty())
     return NS_ERROR_INVALID_ARG;
 
   NS_ENSURE_ARG_POINTER(aCert);
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = false;
+  NS_ENSURE_ARG_POINTER(aRetVal);
+  *aRetVal = false;
 
   nsresult rv;
   nsAutoCString fpStr;
   rv = GetCertFingerprintByOidTag(aCert, SEC_OID_SHA256, fpStr);
   if (NS_FAILED(rv))
     return rv;
 
-  nsAutoCString hostCert;
-  GetHostWithCert(aHostName, fpStr, hostCert);
+  nsAutoCString entryKey;
+  GetEntryKey(aHostName, aOriginAttributes, fpStr, entryKey);
   nsClientAuthRemember settings;
 
   {
     ReentrantMonitorAutoEnter lock(monitor);
-    nsClientAuthRememberEntry *entry = mSettingsTable.GetEntry(hostCert.get());
+    nsClientAuthRememberEntry* entry = mSettingsTable.GetEntry(entryKey.get());
     if (!entry)
       return NS_OK;
     settings = entry->mSettings; // copy
   }
 
   aCertDBKey = settings.mDBKey;
-  *_retval = true;
+  *aRetVal = true;
   return NS_OK;
 }
 
 nsresult
-nsClientAuthRememberService::AddEntryToList(const nsACString &aHostName, 
-                                      const nsACString &fingerprint,
-                                      const nsACString &db_key)
-
+nsClientAuthRememberService::AddEntryToList(
+  const nsACString& aHostName, const NeckoOriginAttributes& aOriginAttributes,
+  const nsACString& aFingerprint, const nsACString& aDBKey)
 {
-  nsAutoCString hostCert;
-  GetHostWithCert(aHostName, fingerprint, hostCert);
+  nsAutoCString entryKey;
+  GetEntryKey(aHostName, aOriginAttributes, aFingerprint, entryKey);
 
   {
     ReentrantMonitorAutoEnter lock(monitor);
-    nsClientAuthRememberEntry *entry = mSettingsTable.PutEntry(hostCert.get());
+    nsClientAuthRememberEntry* entry = mSettingsTable.PutEntry(entryKey.get());
 
     if (!entry) {
       NS_ERROR("can't insert a null entry!");
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    entry->mHostWithCert = hostCert;
+    entry->mHostWithCert = entryKey;
 
-    nsClientAuthRemember &settings = entry->mSettings;
+    nsClientAuthRemember& settings = entry->mSettings;
     settings.mAsciiHost = aHostName;
-    settings.mFingerprint = fingerprint;
-    settings.mDBKey = db_key;
+    settings.mFingerprint = aFingerprint;
+    settings.mDBKey = aDBKey;
   }
 
   return NS_OK;
 }
 
 void
-nsClientAuthRememberService::GetHostWithCert(const nsACString & aHostName, 
-                                             const nsACString & fingerprint, 
-                                             nsACString& _retval)
+nsClientAuthRememberService::GetEntryKey(
+  const nsACString& aHostName,
+  const NeckoOriginAttributes& aOriginAttributes,
+  const nsACString& aFingerprint,
+  nsACString& aEntryKey)
 {
   nsAutoCString hostCert(aHostName);
+  nsAutoCString suffix;
+  aOriginAttributes.CreateSuffix(suffix);
+  hostCert.Append(suffix);
   hostCert.Append(':');
-  hostCert.Append(fingerprint);
-  
-  _retval.Assign(hostCert);
+  hostCert.Append(aFingerprint);
+
+  aEntryKey.Assign(hostCert);
 }
--- a/security/manager/ssl/nsClientAuthRemember.h
+++ b/security/manager/ssl/nsClientAuthRemember.h
@@ -11,16 +11,22 @@
 #include "nsTHashtable.h"
 #include "nsIObserver.h"
 #include "nsIX509Cert.h"
 #include "nsNSSCertificate.h"
 #include "nsString.h"
 #include "nsWeakReference.h"
 #include "mozilla/Attributes.h"
 
+namespace mozilla {
+  class NeckoOriginAttributes;
+}
+
+using mozilla::NeckoOriginAttributes;
+
 class nsClientAuthRemember
 {
 public:
 
   nsClientAuthRemember()
   {
   }
   
@@ -110,33 +116,40 @@ class nsClientAuthRememberService final 
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   nsClientAuthRememberService();
 
   nsresult Init();
 
-  static void GetHostWithCert(const nsACString & aHostName, 
-                              const nsACString & nickname, nsACString& _retval);
+  static void GetEntryKey(const nsACString& aHostName,
+                          const NeckoOriginAttributes& aOriginAttributes,
+                          const nsACString& aFingerprint,
+                          /* out */ nsACString& aEntryKey);
 
-  nsresult RememberDecision(const nsACString & aHostName, 
-                            CERTCertificate *aServerCert, CERTCertificate *aClientCert);
-  nsresult HasRememberedDecision(const nsACString & aHostName, 
-                                 CERTCertificate *aServerCert, 
-                                 nsACString & aCertDBKey, bool *_retval);
+  nsresult RememberDecision(const nsACString& aHostName,
+                            const NeckoOriginAttributes& aOriginAttributes,
+                            CERTCertificate* aServerCert,
+                            CERTCertificate* aClientCert);
+
+  nsresult HasRememberedDecision(const nsACString& aHostName,
+                                 const NeckoOriginAttributes& aOriginAttributes,
+                                 CERTCertificate* aServerCert,
+                                 nsACString& aCertDBKey, bool* aRetVal);
 
   void ClearRememberedDecisions();
   static void ClearAllRememberedDecisions();
 
 protected:
     ~nsClientAuthRememberService();
 
     mozilla::ReentrantMonitor monitor;
     nsTHashtable<nsClientAuthRememberEntry> mSettingsTable;
 
     void RemoveAllFromMemory();
-    nsresult AddEntryToList(const nsACString &host, 
-                            const nsACString &server_fingerprint,
-                            const nsACString &db_key);
+    nsresult AddEntryToList(const nsACString& aHost,
+                            const NeckoOriginAttributes& aOriginAttributes,
+                            const nsACString& aServerFingerprint,
+                            const nsACString& aDBKey);
 };
 
 #endif
--- a/security/manager/ssl/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/nsNSSIOLayer.cpp
@@ -2246,18 +2246,19 @@ ClientAuthDataRunnable::RunOnTargetThrea
 
     RefPtr<nsClientAuthRememberService> cars =
       mSocketInfo->SharedState().GetClientAuthRememberService();
 
     bool hasRemembered = false;
     nsCString rememberedDBKey;
     if (cars) {
       bool found;
-      rv = cars->HasRememberedDecision(hostname, mServerCert,
-        rememberedDBKey, &found);
+      rv = cars->HasRememberedDecision(hostname,
+                                       mSocketInfo->GetOriginAttributes(),
+                                       mServerCert, rememberedDBKey, &found);
       if (NS_SUCCEEDED(rv) && found) {
         hasRemembered = true;
       }
     }
 
     if (hasRemembered && !rememberedDBKey.IsEmpty()) {
       nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
       if (certdb) {
@@ -2361,18 +2362,18 @@ ClientAuthDataRunnable::RunOnTargetThrea
                                                                selectedIndex);
         if (!selectedCert) {
           goto loser;
         }
         cert.reset(selectedCert->GetCert());
       }
 
       if (cars && wantRemember) {
-        cars->RememberDecision(hostname, mServerCert,
-                               certChosen ? cert.get() : nullptr);
+        cars->RememberDecision(hostname, mSocketInfo->GetOriginAttributes(),
+                               mServerCert, certChosen ? cert.get() : nullptr);
       }
     }
 
     if (!cert) {
       goto loser;
     }
 
     // go get the private key