Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : *
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 "nsClientAuthRemember.h"
8 :
9 : #include "nsIX509Cert.h"
10 : #include "mozilla/BasePrincipal.h"
11 : #include "mozilla/RefPtr.h"
12 : #include "nsCRT.h"
13 : #include "nsNSSCertHelper.h"
14 : #include "nsIObserverService.h"
15 : #include "nsNetUtil.h"
16 : #include "nsISupportsPrimitives.h"
17 : #include "nsPromiseFlatString.h"
18 : #include "nsThreadUtils.h"
19 : #include "nsStringBuffer.h"
20 : #include "cert.h"
21 : #include "nspr.h"
22 : #include "pk11pub.h"
23 : #include "certdb.h"
24 : #include "sechash.h"
25 : #include "SharedSSLState.h"
26 :
27 : using namespace mozilla;
28 : using namespace mozilla::psm;
29 :
30 8 : NS_IMPL_ISUPPORTS(nsClientAuthRememberService,
31 : nsIObserver,
32 : nsISupportsWeakReference)
33 :
34 2 : nsClientAuthRememberService::nsClientAuthRememberService()
35 2 : : monitor("nsClientAuthRememberService.monitor")
36 : {
37 2 : }
38 :
39 0 : nsClientAuthRememberService::~nsClientAuthRememberService()
40 : {
41 0 : RemoveAllFromMemory();
42 0 : }
43 :
44 : nsresult
45 2 : nsClientAuthRememberService::Init()
46 : {
47 2 : if (!NS_IsMainThread()) {
48 0 : NS_ERROR("nsClientAuthRememberService::Init called off the main thread");
49 0 : return NS_ERROR_NOT_SAME_THREAD;
50 : }
51 :
52 : nsCOMPtr<nsIObserverService> observerService =
53 4 : mozilla::services::GetObserverService();
54 2 : if (observerService) {
55 2 : observerService->AddObserver(this, "profile-before-change", true);
56 : }
57 :
58 2 : return NS_OK;
59 : }
60 :
61 : NS_IMETHODIMP
62 0 : nsClientAuthRememberService::Observe(nsISupports* aSubject,
63 : const char* aTopic,
64 : const char16_t* aData)
65 : {
66 : // check the topic
67 0 : if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
68 : // The profile is about to change,
69 : // or is going away because the application is shutting down.
70 :
71 0 : ReentrantMonitorAutoEnter lock(monitor);
72 0 : RemoveAllFromMemory();
73 : }
74 :
75 0 : return NS_OK;
76 : }
77 :
78 0 : void nsClientAuthRememberService::ClearRememberedDecisions()
79 : {
80 0 : ReentrantMonitorAutoEnter lock(monitor);
81 0 : RemoveAllFromMemory();
82 0 : }
83 :
84 0 : void nsClientAuthRememberService::ClearAllRememberedDecisions()
85 : {
86 : RefPtr<nsClientAuthRememberService> svc =
87 0 : PublicSSLState()->GetClientAuthRememberService();
88 0 : svc->ClearRememberedDecisions();
89 :
90 0 : svc = PrivateSSLState()->GetClientAuthRememberService();
91 0 : svc->ClearRememberedDecisions();
92 0 : }
93 :
94 : void
95 0 : nsClientAuthRememberService::RemoveAllFromMemory()
96 : {
97 0 : mSettingsTable.Clear();
98 0 : }
99 :
100 : nsresult
101 0 : nsClientAuthRememberService::RememberDecision(
102 : const nsACString& aHostName, const OriginAttributes& aOriginAttributes,
103 : CERTCertificate* aServerCert, CERTCertificate* aClientCert)
104 : {
105 : // aClientCert == nullptr means: remember that user does not want to use a cert
106 0 : NS_ENSURE_ARG_POINTER(aServerCert);
107 0 : if (aHostName.IsEmpty()) {
108 0 : return NS_ERROR_INVALID_ARG;
109 : }
110 :
111 0 : nsAutoCString fpStr;
112 0 : nsresult rv = GetCertFingerprintByOidTag(aServerCert, SEC_OID_SHA256, fpStr);
113 0 : if (NS_FAILED(rv)) {
114 0 : return rv;
115 : }
116 :
117 : {
118 0 : ReentrantMonitorAutoEnter lock(monitor);
119 0 : if (aClientCert) {
120 0 : RefPtr<nsNSSCertificate> pipCert(new nsNSSCertificate(aClientCert));
121 0 : nsAutoCString dbkey;
122 0 : rv = pipCert->GetDbKey(dbkey);
123 0 : if (NS_SUCCEEDED(rv)) {
124 0 : AddEntryToList(aHostName, aOriginAttributes, fpStr, dbkey);
125 : }
126 : } else {
127 0 : nsCString empty;
128 0 : AddEntryToList(aHostName, aOriginAttributes, fpStr, empty);
129 : }
130 : }
131 :
132 0 : return NS_OK;
133 : }
134 :
135 : nsresult
136 0 : nsClientAuthRememberService::HasRememberedDecision(
137 : const nsACString& aHostName, const OriginAttributes& aOriginAttributes,
138 : CERTCertificate* aCert, nsACString& aCertDBKey, bool* aRetVal)
139 : {
140 0 : if (aHostName.IsEmpty())
141 0 : return NS_ERROR_INVALID_ARG;
142 :
143 0 : NS_ENSURE_ARG_POINTER(aCert);
144 0 : NS_ENSURE_ARG_POINTER(aRetVal);
145 0 : *aRetVal = false;
146 :
147 : nsresult rv;
148 0 : nsAutoCString fpStr;
149 0 : rv = GetCertFingerprintByOidTag(aCert, SEC_OID_SHA256, fpStr);
150 0 : if (NS_FAILED(rv))
151 0 : return rv;
152 :
153 0 : nsAutoCString entryKey;
154 0 : GetEntryKey(aHostName, aOriginAttributes, fpStr, entryKey);
155 0 : nsClientAuthRemember settings;
156 :
157 : {
158 0 : ReentrantMonitorAutoEnter lock(monitor);
159 0 : nsClientAuthRememberEntry* entry = mSettingsTable.GetEntry(entryKey.get());
160 0 : if (!entry)
161 0 : return NS_OK;
162 0 : settings = entry->mSettings; // copy
163 : }
164 :
165 0 : aCertDBKey = settings.mDBKey;
166 0 : *aRetVal = true;
167 0 : return NS_OK;
168 : }
169 :
170 : nsresult
171 0 : nsClientAuthRememberService::AddEntryToList(
172 : const nsACString& aHostName, const OriginAttributes& aOriginAttributes,
173 : const nsACString& aFingerprint, const nsACString& aDBKey)
174 : {
175 0 : nsAutoCString entryKey;
176 0 : GetEntryKey(aHostName, aOriginAttributes, aFingerprint, entryKey);
177 :
178 : {
179 0 : ReentrantMonitorAutoEnter lock(monitor);
180 0 : nsClientAuthRememberEntry* entry = mSettingsTable.PutEntry(entryKey.get());
181 :
182 0 : if (!entry) {
183 0 : NS_ERROR("can't insert a null entry!");
184 0 : return NS_ERROR_OUT_OF_MEMORY;
185 : }
186 :
187 0 : entry->mEntryKey = entryKey;
188 :
189 0 : nsClientAuthRemember& settings = entry->mSettings;
190 0 : settings.mAsciiHost = aHostName;
191 0 : settings.mFingerprint = aFingerprint;
192 0 : settings.mDBKey = aDBKey;
193 : }
194 :
195 0 : return NS_OK;
196 : }
197 :
198 : void
199 0 : nsClientAuthRememberService::GetEntryKey(
200 : const nsACString& aHostName,
201 : const OriginAttributes& aOriginAttributes,
202 : const nsACString& aFingerprint,
203 : nsACString& aEntryKey)
204 : {
205 0 : nsAutoCString hostCert(aHostName);
206 0 : nsAutoCString suffix;
207 0 : aOriginAttributes.CreateSuffix(suffix);
208 0 : hostCert.Append(suffix);
209 0 : hostCert.Append(':');
210 0 : hostCert.Append(aFingerprint);
211 :
212 0 : aEntryKey.Assign(hostCert);
213 0 : }
|