nsClientAuthRemember.cpp 5.5 KB

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