Coverage Report

Created: 2018-09-25 14:53

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