security/manager/ssl/src/nsClientAuthRemember.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial