Line data Source code
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 0 : class MainThreadClearer : public SyncRunnableBase
32 : {
33 : public:
34 0 : MainThreadClearer() : mShouldClearSessionCache(false) {}
35 :
36 0 : void RunOnTargetThread() {
37 : // In some cases it's possible to cause PSM/NSS to initialize while XPCOM shutdown
38 : // is in progress. We want to avoid this, since they do not handle the situation well,
39 : // hence the flags to avoid instantiating the services if they don't already exist.
40 :
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 : }
50 : }
51 :
52 : // This needs to be checked on the main thread to avoid racing with NSS
53 : // 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 0 : void ClearPrivateSSLState()
65 : {
66 : // This only works if it is called on the socket transport
67 : // service thread immediately after closing all private SSL
68 : // connections.
69 : #ifdef DEBUG
70 : nsresult rv;
71 : nsCOMPtr<nsIEventTarget> sts
72 0 : = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
73 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
74 : bool onSTSThread;
75 0 : rv = sts->IsOnCurrentThread(&onSTSThread);
76 0 : MOZ_ASSERT(NS_SUCCEEDED(rv) && onSTSThread);
77 : #endif
78 :
79 0 : RefPtr<MainThreadClearer> runnable = new MainThreadClearer;
80 0 : runnable->DispatchToMainThreadAndWait();
81 :
82 : // If NSS isn't initialized, this throws an assertion. We guard it by checking if
83 : // the session cache might even have anything worth clearing.
84 0 : if (runnable->mShouldClearSessionCache) {
85 0 : SSL_ClearSessionCache();
86 : }
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 1 : 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 5 : NS_IMPL_ISUPPORTS(PrivateBrowsingObserver, nsIObserver)
108 :
109 : NS_IMETHODIMP
110 0 : PrivateBrowsingObserver::Observe(nsISupports *aSubject,
111 : const char *aTopic,
112 : const char16_t *aData)
113 : {
114 0 : if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) {
115 0 : mOwner->ResetStoredData();
116 : }
117 0 : return NS_OK;
118 : }
119 :
120 2 : SharedSSLState::SharedSSLState()
121 2 : : mClientAuthRemember(new nsClientAuthRememberService)
122 : , mMutex("SharedSSLState::mMutex")
123 : , mSocketCreated(false)
124 : , mOCSPStaplingEnabled(false)
125 4 : , mOCSPMustStapleEnabled(false)
126 : {
127 2 : mIOLayerHelpers.Init();
128 2 : mClientAuthRemember->Init();
129 2 : }
130 :
131 0 : SharedSSLState::~SharedSSLState()
132 : {
133 0 : }
134 :
135 : void
136 1 : SharedSSLState::NotePrivateBrowsingStatus()
137 : {
138 1 : MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
139 1 : mObserver = new PrivateBrowsingObserver(this);
140 2 : nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
141 1 : obsSvc->AddObserver(mObserver, "last-pb-context-exited", false);
142 1 : }
143 :
144 : void
145 0 : SharedSSLState::ResetStoredData()
146 : {
147 0 : MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
148 0 : mClientAuthRemember->ClearRememberedDecisions();
149 0 : mIOLayerHelpers.clearStoredData();
150 0 : }
151 :
152 : void
153 0 : SharedSSLState::NoteSocketCreated()
154 : {
155 0 : MutexAutoLock lock(mMutex);
156 0 : mSocketCreated = true;
157 0 : }
158 :
159 : bool
160 0 : SharedSSLState::SocketCreated()
161 : {
162 0 : MutexAutoLock lock(mMutex);
163 0 : return mSocketCreated;
164 : }
165 :
166 : /*static*/ void
167 1 : SharedSSLState::GlobalInit()
168 : {
169 1 : MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
170 1 : gPublicState = new SharedSSLState();
171 1 : gPrivateState = new SharedSSLState();
172 1 : gPrivateState->NotePrivateBrowsingStatus();
173 1 : }
174 :
175 : /*static*/ void
176 0 : SharedSSLState::GlobalCleanup()
177 : {
178 0 : MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
179 :
180 0 : if (gPrivateState) {
181 0 : gPrivateState->Cleanup();
182 0 : delete gPrivateState;
183 0 : gPrivateState = nullptr;
184 : }
185 :
186 0 : if (gPublicState) {
187 0 : gPublicState->Cleanup();
188 0 : delete gPublicState;
189 0 : gPublicState = nullptr;
190 : }
191 0 : }
192 :
193 : /*static*/ void
194 0 : SharedSSLState::NoteCertOverrideServiceInstantiated()
195 : {
196 0 : sCertOverrideSvcExists = true;
197 0 : }
198 :
199 : void
200 0 : SharedSSLState::Cleanup()
201 : {
202 0 : mIOLayerHelpers.Cleanup();
203 0 : }
204 :
205 : SharedSSLState*
206 3 : PublicSSLState()
207 : {
208 3 : return gPublicState;
209 : }
210 :
211 : SharedSSLState*
212 3 : PrivateSSLState()
213 : {
214 3 : return gPrivateState;
215 : }
216 :
217 : } // namespace psm
218 : } // namespace mozilla
|