security/manager/ssl/src/SharedSSLState.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/manager/ssl/src/SharedSSLState.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,237 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set ts=2 et sw=2 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "SharedSSLState.h"
    1.11 +#include "nsClientAuthRemember.h"
    1.12 +#include "nsComponentManagerUtils.h"
    1.13 +#include "nsICertOverrideService.h"
    1.14 +#include "nsIObserverService.h"
    1.15 +#include "mozilla/Services.h"
    1.16 +#include "nsThreadUtils.h"
    1.17 +#include "nsCRT.h"
    1.18 +#include "nsServiceManagerUtils.h"
    1.19 +#include "nsRecentBadCerts.h"
    1.20 +#include "PSMRunnable.h"
    1.21 +#include "PublicSSL.h"
    1.22 +#include "ssl.h"
    1.23 +#include "nsNetCID.h"
    1.24 +#include "mozilla/Atomics.h"
    1.25 +#include "mozilla/unused.h"
    1.26 +
    1.27 +using mozilla::psm::SyncRunnableBase;
    1.28 +using mozilla::Atomic;
    1.29 +using mozilla::unused;
    1.30 +
    1.31 +namespace {
    1.32 +
    1.33 +static Atomic<bool> sCertOverrideSvcExists(false);
    1.34 +static Atomic<bool> sCertDBExists(false);
    1.35 +
    1.36 +class MainThreadClearer : public SyncRunnableBase
    1.37 +{
    1.38 +public:
    1.39 +  MainThreadClearer() : mShouldClearSessionCache(false) {}
    1.40 +
    1.41 +  void RunOnTargetThread() {
    1.42 +    // In some cases it's possible to cause PSM/NSS to initialize while XPCOM shutdown
    1.43 +    // is in progress. We want to avoid this, since they do not handle the situation well,
    1.44 +    // hence the flags to avoid instantiating the services if they don't already exist.
    1.45 +
    1.46 +    bool certOverrideSvcExists = sCertOverrideSvcExists.exchange(false);
    1.47 +    if (certOverrideSvcExists) {
    1.48 +      sCertOverrideSvcExists = true;
    1.49 +      nsCOMPtr<nsICertOverrideService> icos = do_GetService(NS_CERTOVERRIDE_CONTRACTID);
    1.50 +      if (icos) {
    1.51 +        icos->ClearValidityOverride(
    1.52 +          NS_LITERAL_CSTRING("all:temporary-certificates"),
    1.53 +          0);
    1.54 +      }
    1.55 +    }
    1.56 +
    1.57 +    bool certDBExists = sCertDBExists.exchange(false);
    1.58 +    if (certDBExists) {
    1.59 +      sCertDBExists = true;
    1.60 +      nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
    1.61 +      if (certdb) {
    1.62 +        nsCOMPtr<nsIRecentBadCerts> badCerts;
    1.63 +        certdb->GetRecentBadCerts(true, getter_AddRefs(badCerts));
    1.64 +        if (badCerts) {
    1.65 +          badCerts->ResetStoredCerts();
    1.66 +        }
    1.67 +      }
    1.68 +    }
    1.69 +
    1.70 +    // This needs to be checked on the main thread to avoid racing with NSS
    1.71 +    // initialization.
    1.72 +    mShouldClearSessionCache = mozilla::psm::PrivateSSLState() &&
    1.73 +                               mozilla::psm::PrivateSSLState()->SocketCreated();
    1.74 +  }
    1.75 +  bool mShouldClearSessionCache;
    1.76 +};
    1.77 +
    1.78 +} // anonymous namespace
    1.79 +
    1.80 +namespace mozilla {
    1.81 +
    1.82 +void ClearPrivateSSLState()
    1.83 +{
    1.84 +  // This only works if it is called on the socket transport
    1.85 +  // service thread immediately after closing all private SSL
    1.86 +  // connections.
    1.87 +#ifdef DEBUG
    1.88 +  nsresult rv;
    1.89 +  nsCOMPtr<nsIEventTarget> sts
    1.90 +    = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
    1.91 +  MOZ_ASSERT(NS_SUCCEEDED(rv));
    1.92 +  bool onSTSThread;
    1.93 +  rv = sts->IsOnCurrentThread(&onSTSThread);
    1.94 +  MOZ_ASSERT(NS_SUCCEEDED(rv) && onSTSThread);
    1.95 +#endif
    1.96 +
    1.97 +  RefPtr<MainThreadClearer> runnable = new MainThreadClearer;
    1.98 +  runnable->DispatchToMainThreadAndWait();
    1.99 +
   1.100 +  // If NSS isn't initialized, this throws an assertion. We guard it by checking if
   1.101 +  // the session cache might even have anything worth clearing.
   1.102 +  if (runnable->mShouldClearSessionCache) {
   1.103 +    SSL_ClearSessionCache();
   1.104 +  }
   1.105 +}
   1.106 +
   1.107 +namespace psm {
   1.108 +
   1.109 +namespace {
   1.110 +class PrivateBrowsingObserver : public nsIObserver {
   1.111 +public:
   1.112 +  NS_DECL_ISUPPORTS
   1.113 +  NS_DECL_NSIOBSERVER
   1.114 +  PrivateBrowsingObserver(SharedSSLState* aOwner) : mOwner(aOwner) {}
   1.115 +  virtual ~PrivateBrowsingObserver() {}
   1.116 +private:
   1.117 +  SharedSSLState* mOwner;
   1.118 +};
   1.119 +
   1.120 +SharedSSLState* gPublicState;
   1.121 +SharedSSLState* gPrivateState;
   1.122 +} // anonymous namespace
   1.123 +
   1.124 +NS_IMPL_ISUPPORTS(PrivateBrowsingObserver, nsIObserver)
   1.125 +
   1.126 +NS_IMETHODIMP
   1.127 +PrivateBrowsingObserver::Observe(nsISupports     *aSubject,
   1.128 +                                 const char      *aTopic,
   1.129 +                                 const char16_t *aData)
   1.130 +{
   1.131 +  if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) {
   1.132 +    mOwner->ResetStoredData();
   1.133 +  }
   1.134 +  return NS_OK;
   1.135 +}
   1.136 +
   1.137 +SharedSSLState::SharedSSLState()
   1.138 +: mClientAuthRemember(new nsClientAuthRememberService)
   1.139 +, mMutex("SharedSSLState::mMutex")
   1.140 +, mSocketCreated(false)
   1.141 +, mOCSPStaplingEnabled(false)
   1.142 +{
   1.143 +  mIOLayerHelpers.Init();
   1.144 +  mClientAuthRemember->Init();
   1.145 +}
   1.146 +
   1.147 +SharedSSLState::~SharedSSLState()
   1.148 +{
   1.149 +}
   1.150 +
   1.151 +void
   1.152 +SharedSSLState::NotePrivateBrowsingStatus()
   1.153 +{
   1.154 +  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
   1.155 +  mObserver = new PrivateBrowsingObserver(this);
   1.156 +  nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
   1.157 +  obsSvc->AddObserver(mObserver, "last-pb-context-exited", false);
   1.158 +}
   1.159 +
   1.160 +void
   1.161 +SharedSSLState::ResetStoredData()
   1.162 +{
   1.163 +  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
   1.164 +  mClientAuthRemember->ClearRememberedDecisions();
   1.165 +  mIOLayerHelpers.clearStoredData();
   1.166 +}
   1.167 +
   1.168 +void
   1.169 +SharedSSLState::NoteSocketCreated()
   1.170 +{
   1.171 +  MutexAutoLock lock(mMutex);
   1.172 +  mSocketCreated = true;
   1.173 +}
   1.174 +
   1.175 +bool
   1.176 +SharedSSLState::SocketCreated()
   1.177 +{
   1.178 +  MutexAutoLock lock(mMutex);
   1.179 +  return mSocketCreated;
   1.180 +}
   1.181 +
   1.182 +/*static*/ void
   1.183 +SharedSSLState::GlobalInit()
   1.184 +{
   1.185 +  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
   1.186 +  gPublicState = new SharedSSLState();
   1.187 +  gPrivateState = new SharedSSLState();
   1.188 +  gPrivateState->NotePrivateBrowsingStatus();
   1.189 +}
   1.190 +
   1.191 +/*static*/ void
   1.192 +SharedSSLState::GlobalCleanup()
   1.193 +{
   1.194 +  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
   1.195 +
   1.196 +  if (gPrivateState) {
   1.197 +    gPrivateState->Cleanup();
   1.198 +    delete gPrivateState;
   1.199 +    gPrivateState = nullptr;
   1.200 +  }
   1.201 +
   1.202 +  if (gPublicState) {
   1.203 +    gPublicState->Cleanup();
   1.204 +    delete gPublicState;
   1.205 +    gPublicState = nullptr;
   1.206 +  }
   1.207 +}
   1.208 +
   1.209 +/*static*/ void
   1.210 +SharedSSLState::NoteCertOverrideServiceInstantiated()
   1.211 +{
   1.212 +  sCertOverrideSvcExists = true;
   1.213 +}
   1.214 +
   1.215 +/*static*/ void
   1.216 +SharedSSLState::NoteCertDBServiceInstantiated()
   1.217 +{
   1.218 +  sCertDBExists = true;
   1.219 +}
   1.220 +
   1.221 +void
   1.222 +SharedSSLState::Cleanup()
   1.223 +{
   1.224 +  mIOLayerHelpers.Cleanup();
   1.225 +}
   1.226 +
   1.227 +SharedSSLState*
   1.228 +PublicSSLState()
   1.229 +{
   1.230 +  return gPublicState;
   1.231 +}
   1.232 +
   1.233 +SharedSSLState*
   1.234 +PrivateSSLState()
   1.235 +{
   1.236 +  return gPrivateState;
   1.237 +}
   1.238 +
   1.239 +} // namespace psm
   1.240 +} // namespace mozilla

mercurial