Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/manager/ssl/SharedSSLState.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "SharedSSLState.h"
8
#include "nsClientAuthRemember.h"
9
#include "nsComponentManagerUtils.h"
10
#include "nsICertOverrideService.h"
11
#include "nsIObserverService.h"
12
#include "mozilla/Services.h"
13
#include "nsThreadUtils.h"
14
#include "nsCRT.h"
15
#include "nsServiceManagerUtils.h"
16
#include "PSMRunnable.h"
17
#include "PublicSSL.h"
18
#include "ssl.h"
19
#include "nsNetCID.h"
20
#include "mozilla/Atomics.h"
21
#include "mozilla/Unused.h"
22
23
using mozilla::psm::SyncRunnableBase;
24
using mozilla::Atomic;
25
using mozilla::Unused;
26
27
namespace {
28
29
static Atomic<bool> sCertOverrideSvcExists(false);
30
31
class MainThreadClearer : public SyncRunnableBase
32
{
33
public:
34
0
  MainThreadClearer() : mShouldClearSessionCache(false) {}
35
36
0
  void RunOnTargetThread() override {
37
0
    // In some cases it's possible to cause PSM/NSS to initialize while XPCOM shutdown
38
0
    // is in progress. We want to avoid this, since they do not handle the situation well,
39
0
    // hence the flags to avoid instantiating the services if they don't already exist.
40
0
41
0
    bool certOverrideSvcExists = sCertOverrideSvcExists.exchange(false);
42
0
    if (certOverrideSvcExists) {
43
0
      sCertOverrideSvcExists = true;
44
0
      nsCOMPtr<nsICertOverrideService> icos = do_GetService(NS_CERTOVERRIDE_CONTRACTID);
45
0
      if (icos) {
46
0
        icos->ClearValidityOverride(
47
0
          NS_LITERAL_CSTRING("all:temporary-certificates"),
48
0
          0);
49
0
      }
50
0
    }
51
0
52
0
    // This needs to be checked on the main thread to avoid racing with NSS
53
0
    // initialization.
54
0
    mShouldClearSessionCache = mozilla::psm::PrivateSSLState() &&
55
0
                               mozilla::psm::PrivateSSLState()->SocketCreated();
56
0
  }
57
  bool mShouldClearSessionCache;
58
};
59
60
} // namespace
61
62
namespace mozilla {
63
64
void ClearPrivateSSLState()
65
0
{
66
0
  // This only works if it is called on the socket transport
67
0
  // service thread immediately after closing all private SSL
68
0
  // connections.
69
#ifdef DEBUG
70
  nsresult rv;
71
  nsCOMPtr<nsIEventTarget> sts
72
    = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
73
  MOZ_ASSERT(NS_SUCCEEDED(rv));
74
  bool onSTSThread;
75
  rv = sts->IsOnCurrentThread(&onSTSThread);
76
  MOZ_ASSERT(NS_SUCCEEDED(rv) && onSTSThread);
77
#endif
78
79
0
  RefPtr<MainThreadClearer> runnable = new MainThreadClearer;
80
0
  runnable->DispatchToMainThreadAndWait();
81
0
82
0
  // If NSS isn't initialized, this throws an assertion. We guard it by checking if
83
0
  // the session cache might even have anything worth clearing.
84
0
  if (runnable->mShouldClearSessionCache) {
85
0
    SSL_ClearSessionCache();
86
0
  }
87
0
}
88
89
namespace psm {
90
91
namespace {
92
class PrivateBrowsingObserver : public nsIObserver {
93
public:
94
  NS_DECL_ISUPPORTS
95
  NS_DECL_NSIOBSERVER
96
0
  explicit PrivateBrowsingObserver(SharedSSLState* aOwner) : mOwner(aOwner) {}
97
protected:
98
0
  virtual ~PrivateBrowsingObserver() {}
99
private:
100
  SharedSSLState* mOwner;
101
};
102
103
SharedSSLState* gPublicState;
104
SharedSSLState* gPrivateState;
105
} // namespace
106
107
NS_IMPL_ISUPPORTS(PrivateBrowsingObserver, nsIObserver)
108
109
NS_IMETHODIMP
110
PrivateBrowsingObserver::Observe(nsISupports     *aSubject,
111
                                 const char      *aTopic,
112
                                 const char16_t *aData)
113
0
{
114
0
  if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) {
115
0
    mOwner->ResetStoredData();
116
0
  }
117
0
  return NS_OK;
118
0
}
119
120
SharedSSLState::SharedSSLState(uint32_t aTlsFlags)
121
: mIOLayerHelpers(aTlsFlags)
122
, mMutex("SharedSSLState::mMutex")
123
, mSocketCreated(false)
124
, mOCSPStaplingEnabled(false)
125
, mOCSPMustStapleEnabled(false)
126
, mSignedCertTimestampsEnabled(false)
127
0
{
128
0
  mIOLayerHelpers.Init();
129
0
  if (!aTlsFlags) { // the per socket flags don't need memory
130
0
    mClientAuthRemember = new nsClientAuthRememberService();
131
0
    mClientAuthRemember->Init();
132
0
  }
133
0
}
134
135
SharedSSLState::~SharedSSLState()
136
0
{
137
0
}
138
139
void
140
SharedSSLState::NotePrivateBrowsingStatus()
141
0
{
142
0
  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
143
0
  mObserver = new PrivateBrowsingObserver(this);
144
0
  nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
145
0
  obsSvc->AddObserver(mObserver, "last-pb-context-exited", false);
146
0
}
147
148
void
149
SharedSSLState::ResetStoredData()
150
0
{
151
0
  if (!mClientAuthRemember) {
152
0
    return;
153
0
  }
154
0
  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
155
0
  mClientAuthRemember->ClearRememberedDecisions();
156
0
  mIOLayerHelpers.clearStoredData();
157
0
}
158
159
void
160
SharedSSLState::NoteSocketCreated()
161
0
{
162
0
  MutexAutoLock lock(mMutex);
163
0
  mSocketCreated = true;
164
0
}
165
166
bool
167
SharedSSLState::SocketCreated()
168
0
{
169
0
  MutexAutoLock lock(mMutex);
170
0
  return mSocketCreated;
171
0
}
172
173
/*static*/ void
174
SharedSSLState::GlobalInit()
175
0
{
176
0
  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
177
0
  gPublicState = new SharedSSLState();
178
0
  gPrivateState = new SharedSSLState();
179
0
  gPrivateState->NotePrivateBrowsingStatus();
180
0
}
181
182
/*static*/ void
183
SharedSSLState::GlobalCleanup()
184
0
{
185
0
  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
186
0
187
0
  if (gPrivateState) {
188
0
    gPrivateState->Cleanup();
189
0
    delete gPrivateState;
190
0
    gPrivateState = nullptr;
191
0
  }
192
0
193
0
  if (gPublicState) {
194
0
    gPublicState->Cleanup();
195
0
    delete gPublicState;
196
0
    gPublicState = nullptr;
197
0
  }
198
0
}
199
200
/*static*/ void
201
SharedSSLState::NoteCertOverrideServiceInstantiated()
202
0
{
203
0
  sCertOverrideSvcExists = true;
204
0
}
205
206
void
207
SharedSSLState::Cleanup()
208
0
{
209
0
  mIOLayerHelpers.Cleanup();
210
0
}
211
212
SharedSSLState*
213
PublicSSLState()
214
0
{
215
0
  return gPublicState;
216
0
}
217
218
SharedSSLState*
219
PrivateSSLState()
220
0
{
221
0
  return gPrivateState;
222
0
}
223
224
} // namespace psm
225
} // namespace mozilla