security/manager/ssl/src/SharedSSLState.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:aa54d02d6c49
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 "nsRecentBadCerts.h"
17 #include "PSMRunnable.h"
18 #include "PublicSSL.h"
19 #include "ssl.h"
20 #include "nsNetCID.h"
21 #include "mozilla/Atomics.h"
22 #include "mozilla/unused.h"
23
24 using mozilla::psm::SyncRunnableBase;
25 using mozilla::Atomic;
26 using mozilla::unused;
27
28 namespace {
29
30 static Atomic<bool> sCertOverrideSvcExists(false);
31 static Atomic<bool> sCertDBExists(false);
32
33 class MainThreadClearer : public SyncRunnableBase
34 {
35 public:
36 MainThreadClearer() : mShouldClearSessionCache(false) {}
37
38 void RunOnTargetThread() {
39 // In some cases it's possible to cause PSM/NSS to initialize while XPCOM shutdown
40 // is in progress. We want to avoid this, since they do not handle the situation well,
41 // hence the flags to avoid instantiating the services if they don't already exist.
42
43 bool certOverrideSvcExists = sCertOverrideSvcExists.exchange(false);
44 if (certOverrideSvcExists) {
45 sCertOverrideSvcExists = true;
46 nsCOMPtr<nsICertOverrideService> icos = do_GetService(NS_CERTOVERRIDE_CONTRACTID);
47 if (icos) {
48 icos->ClearValidityOverride(
49 NS_LITERAL_CSTRING("all:temporary-certificates"),
50 0);
51 }
52 }
53
54 bool certDBExists = sCertDBExists.exchange(false);
55 if (certDBExists) {
56 sCertDBExists = true;
57 nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
58 if (certdb) {
59 nsCOMPtr<nsIRecentBadCerts> badCerts;
60 certdb->GetRecentBadCerts(true, getter_AddRefs(badCerts));
61 if (badCerts) {
62 badCerts->ResetStoredCerts();
63 }
64 }
65 }
66
67 // This needs to be checked on the main thread to avoid racing with NSS
68 // initialization.
69 mShouldClearSessionCache = mozilla::psm::PrivateSSLState() &&
70 mozilla::psm::PrivateSSLState()->SocketCreated();
71 }
72 bool mShouldClearSessionCache;
73 };
74
75 } // anonymous namespace
76
77 namespace mozilla {
78
79 void ClearPrivateSSLState()
80 {
81 // This only works if it is called on the socket transport
82 // service thread immediately after closing all private SSL
83 // connections.
84 #ifdef DEBUG
85 nsresult rv;
86 nsCOMPtr<nsIEventTarget> sts
87 = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
88 MOZ_ASSERT(NS_SUCCEEDED(rv));
89 bool onSTSThread;
90 rv = sts->IsOnCurrentThread(&onSTSThread);
91 MOZ_ASSERT(NS_SUCCEEDED(rv) && onSTSThread);
92 #endif
93
94 RefPtr<MainThreadClearer> runnable = new MainThreadClearer;
95 runnable->DispatchToMainThreadAndWait();
96
97 // If NSS isn't initialized, this throws an assertion. We guard it by checking if
98 // the session cache might even have anything worth clearing.
99 if (runnable->mShouldClearSessionCache) {
100 SSL_ClearSessionCache();
101 }
102 }
103
104 namespace psm {
105
106 namespace {
107 class PrivateBrowsingObserver : public nsIObserver {
108 public:
109 NS_DECL_ISUPPORTS
110 NS_DECL_NSIOBSERVER
111 PrivateBrowsingObserver(SharedSSLState* aOwner) : mOwner(aOwner) {}
112 virtual ~PrivateBrowsingObserver() {}
113 private:
114 SharedSSLState* mOwner;
115 };
116
117 SharedSSLState* gPublicState;
118 SharedSSLState* gPrivateState;
119 } // anonymous namespace
120
121 NS_IMPL_ISUPPORTS(PrivateBrowsingObserver, nsIObserver)
122
123 NS_IMETHODIMP
124 PrivateBrowsingObserver::Observe(nsISupports *aSubject,
125 const char *aTopic,
126 const char16_t *aData)
127 {
128 if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) {
129 mOwner->ResetStoredData();
130 }
131 return NS_OK;
132 }
133
134 SharedSSLState::SharedSSLState()
135 : mClientAuthRemember(new nsClientAuthRememberService)
136 , mMutex("SharedSSLState::mMutex")
137 , mSocketCreated(false)
138 , mOCSPStaplingEnabled(false)
139 {
140 mIOLayerHelpers.Init();
141 mClientAuthRemember->Init();
142 }
143
144 SharedSSLState::~SharedSSLState()
145 {
146 }
147
148 void
149 SharedSSLState::NotePrivateBrowsingStatus()
150 {
151 MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
152 mObserver = new PrivateBrowsingObserver(this);
153 nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
154 obsSvc->AddObserver(mObserver, "last-pb-context-exited", false);
155 }
156
157 void
158 SharedSSLState::ResetStoredData()
159 {
160 MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
161 mClientAuthRemember->ClearRememberedDecisions();
162 mIOLayerHelpers.clearStoredData();
163 }
164
165 void
166 SharedSSLState::NoteSocketCreated()
167 {
168 MutexAutoLock lock(mMutex);
169 mSocketCreated = true;
170 }
171
172 bool
173 SharedSSLState::SocketCreated()
174 {
175 MutexAutoLock lock(mMutex);
176 return mSocketCreated;
177 }
178
179 /*static*/ void
180 SharedSSLState::GlobalInit()
181 {
182 MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
183 gPublicState = new SharedSSLState();
184 gPrivateState = new SharedSSLState();
185 gPrivateState->NotePrivateBrowsingStatus();
186 }
187
188 /*static*/ void
189 SharedSSLState::GlobalCleanup()
190 {
191 MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
192
193 if (gPrivateState) {
194 gPrivateState->Cleanup();
195 delete gPrivateState;
196 gPrivateState = nullptr;
197 }
198
199 if (gPublicState) {
200 gPublicState->Cleanup();
201 delete gPublicState;
202 gPublicState = nullptr;
203 }
204 }
205
206 /*static*/ void
207 SharedSSLState::NoteCertOverrideServiceInstantiated()
208 {
209 sCertOverrideSvcExists = true;
210 }
211
212 /*static*/ void
213 SharedSSLState::NoteCertDBServiceInstantiated()
214 {
215 sCertDBExists = true;
216 }
217
218 void
219 SharedSSLState::Cleanup()
220 {
221 mIOLayerHelpers.Cleanup();
222 }
223
224 SharedSSLState*
225 PublicSSLState()
226 {
227 return gPublicState;
228 }
229
230 SharedSSLState*
231 PrivateSSLState()
232 {
233 return gPrivateState;
234 }
235
236 } // namespace psm
237 } // namespace mozilla

mercurial