Bug 1391506 - per socket intolerance structure draft
authorPatrick McManus <mcmanus@ducksong.com>
Tue, 29 Aug 2017 11:25:34 -0400
changeset 655230 0e8441b3c6bf8d8319cc222053e9167180fb0365
parent 655229 3552bff4c4efb4ef3a3347da39667f4f8bdf746c
child 655231 9637ede1fd7c6c7d4d43f21e44ca0293d027eb75
push id76804
push userbmo:mcmanus@ducksong.com
push dateTue, 29 Aug 2017 19:27:56 +0000
bugs1391506
milestone57.0a1
Bug 1391506 - per socket intolerance structure MozReview-Commit-ID: JEEe3Jetf8p
security/manager/ssl/SharedSSLState.cpp
security/manager/ssl/nsNSSIOLayer.cpp
security/manager/ssl/nsNSSIOLayer.h
--- a/security/manager/ssl/SharedSSLState.cpp
+++ b/security/manager/ssl/SharedSSLState.cpp
@@ -113,25 +113,27 @@ PrivateBrowsingObserver::Observe(nsISupp
 {
   if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) {
     mOwner->ResetStoredData();
   }
   return NS_OK;
 }
 
 SharedSSLState::SharedSSLState(uint32_t aTlsFlags)
-: mClientAuthRemember(new nsClientAuthRememberService)
-, mIOLayerHelpers(aTlsFlags)
+: mIOLayerHelpers(aTlsFlags)
 , mMutex("SharedSSLState::mMutex")
 , mSocketCreated(false)
 , mOCSPStaplingEnabled(false)
 , mOCSPMustStapleEnabled(false)
 {
   mIOLayerHelpers.Init();
-  mClientAuthRemember->Init();
+  if (!aTlsFlags) { // the per socket flags don't need memory
+    mClientAuthRemember = new nsClientAuthRememberService();
+    mClientAuthRemember->Init();
+  }
 }
 
 SharedSSLState::~SharedSSLState()
 {
 }
 
 void
 SharedSSLState::NotePrivateBrowsingStatus()
@@ -140,16 +142,19 @@ SharedSSLState::NotePrivateBrowsingStatu
   mObserver = new PrivateBrowsingObserver(this);
   nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
   obsSvc->AddObserver(mObserver, "last-pb-context-exited", false);
 }
 
 void
 SharedSSLState::ResetStoredData()
 {
+  if (!mClientAuthRemember) {
+    return;
+  }
   MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
   mClientAuthRemember->ClearRememberedDecisions();
   mIOLayerHelpers.clearStoredData();
 }
 
 void
 SharedSSLState::NoteSocketCreated()
 {
--- a/security/manager/ssl/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/nsNSSIOLayer.cpp
@@ -694,16 +694,22 @@ nsNSSSocketInfo::SetCertVerificationResu
 }
 
 SharedSSLState&
 nsNSSSocketInfo::SharedState()
 {
   return mSharedState;
 }
 
+void
+nsNSSSocketInfo::SetSharedOwningReference(SharedSSLState *aRef)
+{
+  mOwningSharedRef = aRef;
+}
+
 void nsSSLIOLayerHelpers::Cleanup()
 {
   MutexAutoLock lock(mutex);
   mTLSIntoleranceInfo.Clear();
   mInsecureFallbackSites.Clear();
 }
 
 static void
@@ -1650,16 +1656,17 @@ nsSSLIOLayerHelpers::~nsSSLIOLayerHelper
         "security.tls.insecure_fallback_hosts");
   }
 }
 
 nsresult
 nsSSLIOLayerHelpers::Init()
 {
   if (!nsSSLIOLayerInitialized) {
+    MOZ_ASSERT(NS_IsMainThread());
     nsSSLIOLayerInitialized = true;
     nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer");
     nsSSLIOLayerMethods  = *PR_GetDefaultIOMethods();
 
     nsSSLIOLayerMethods.available = (PRAvailableFN) PSMAvailable;
     nsSSLIOLayerMethods.available64 = (PRAvailable64FN) PSMAvailable64;
     nsSSLIOLayerMethods.fsync = (PRFsyncFN) _PSM_InvalidStatus;
     nsSSLIOLayerMethods.seek = (PRSeekFN) _PSM_InvalidInt;
@@ -1691,39 +1698,50 @@ nsSSLIOLayerHelpers::Init()
     nsSSLIOLayerMethods.read = nsSSLIOLayerRead;
     nsSSLIOLayerMethods.poll = nsSSLIOLayerPoll;
 
     nsSSLPlaintextLayerIdentity = PR_GetUniqueIdentity("Plaintxext PSM layer");
     nsSSLPlaintextLayerMethods  = *PR_GetDefaultIOMethods();
     nsSSLPlaintextLayerMethods.recv = PlaintextRecv;
   }
 
-  bool enabled = false;
-  Preferences::GetBool("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
-  setTreatUnsafeNegotiationAsBroken(enabled);
-
   loadVersionFallbackLimit();
-  initInsecureFallbackSites();
-
-  mPrefObserver = new PrefObserver(this);
-  Preferences::AddStrongObserver(mPrefObserver,
-                                 "security.ssl.treat_unsafe_negotiation_as_broken");
-  Preferences::AddStrongObserver(mPrefObserver,
-                                 "security.tls.version.fallback-limit");
-  Preferences::AddStrongObserver(mPrefObserver,
-                                 "security.tls.insecure_fallback_hosts");
+
+  // non main thread helpers will need to use defaults
+  if (NS_IsMainThread()) {
+    bool enabled = false;
+    Preferences::GetBool("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
+    setTreatUnsafeNegotiationAsBroken(enabled);
+
+    initInsecureFallbackSites();
+
+    mPrefObserver = new PrefObserver(this);
+    Preferences::AddStrongObserver(mPrefObserver,
+                                   "security.ssl.treat_unsafe_negotiation_as_broken");
+    Preferences::AddStrongObserver(mPrefObserver,
+                                   "security.tls.version.fallback-limit");
+    Preferences::AddStrongObserver(mPrefObserver,
+                                   "security.tls.insecure_fallback_hosts");
+  } else {
+    MOZ_ASSERT(mTlsFlags, "Only per socket version can ignore prefs");
+  }
+
   return NS_OK;
 }
 
 void
 nsSSLIOLayerHelpers::loadVersionFallbackLimit()
 {
   // see nsNSSComponent::setEnabledTLSVersions for pref handling rules
-  uint32_t limit = Preferences::GetUint("security.tls.version.fallback-limit",
-                                        3); // 3 = TLS 1.2
+  uint32_t limit = 3; // TLS 1.2
+
+  if (NS_IsMainThread()) {
+    limit = Preferences::GetUint("security.tls.version.fallback-limit",
+                                 3); // 3 = TLS 1.2
+  }
 
   // set fallback limit if it is set in the tls flags
   uint32_t tlsFlagsFallbackLimit = getTLSProviderFlagFallbackLimit(mTlsFlags);
     
   if (tlsFlagsFallbackLimit) {
     limit = tlsFlagsFallbackLimit;
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
             ("loadVersionFallbackLimit overriden by tlsFlags %d\n", limit));
@@ -2644,31 +2662,35 @@ nsSSLIOLayerAddToSocket(int32_t family,
 {
   nsNSSShutDownPreventionLock locker;
   PRFileDesc* layer = nullptr;
   PRFileDesc* plaintextLayer = nullptr;
   nsresult rv;
   PRStatus stat;
 
   SharedSSLState* sharedState = nullptr;
-
+  RefPtr<SharedSSLState> allocatedState;
   if (providerTlsFlags) {
-    sharedState = new SharedSSLState(providerTlsFlags);
+    allocatedState = new SharedSSLState(providerTlsFlags);  
+    sharedState = allocatedState.get();
   } else {
     sharedState = (providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE) ? PrivateSSLState() : PublicSSLState();
   }
 
   nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(*sharedState, providerFlags, providerTlsFlags);
   if (!infoObject) return NS_ERROR_FAILURE;
 
   NS_ADDREF(infoObject);
   infoObject->SetForSTARTTLS(forSTARTTLS);
   infoObject->SetHostName(host);
   infoObject->SetPort(port);
   infoObject->SetOriginAttributes(originAttributes);
+  if (allocatedState) {
+    infoObject->SetSharedOwningReference(allocatedState);
+  }
 
   bool haveProxy = false;
   if (proxy) {
     nsCString proxyHost;
     proxy->GetHost(proxyHost);
     haveProxy = !proxyHost.IsEmpty();
   }
 
--- a/security/manager/ssl/nsNSSIOLayer.h
+++ b/security/manager/ssl/nsNSSIOLayer.h
@@ -115,16 +115,18 @@ public:
 
   void SetSSLVersionUsed(int16_t version)
   {
     mSSLVersionUsed = version;
   }
 
   void SetMACAlgorithmUsed(int16_t mac) { mMACAlgorithmUsed = mac; }
 
+  void SetSharedOwningReference(mozilla::psm::SharedSSLState *ref);
+
 protected:
   virtual ~nsNSSSocketInfo();
 
 private:
   PRFileDesc* mFd;
 
   CertVerificationState mCertVerificationState;
 
@@ -158,16 +160,17 @@ private:
   bool    mBypassAuthentication;
 
   uint32_t mProviderFlags;
   uint32_t mProviderTlsFlags;
   mozilla::TimeStamp mSocketCreationTimestamp;
   uint64_t mPlaintextBytesRead;
 
   nsCOMPtr<nsIX509Cert> mClientCert;
+  RefPtr<mozilla::psm::SharedSSLState> mOwningSharedRef;
 };
 
 class nsSSLIOLayerHelpers
 {
 public:
   nsSSLIOLayerHelpers() : nsSSLIOLayerHelpers(0) {}
   explicit nsSSLIOLayerHelpers(uint32_t aTlsFlags);
   ~nsSSLIOLayerHelpers();