security/manager/ssl/src/nsClientAuthRemember.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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/. */
     7 #include "nsClientAuthRemember.h"
     9 #include "nsIX509Cert.h"
    10 #include "mozilla/RefPtr.h"
    11 #include "nsCRT.h"
    12 #include "nsNetUtil.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"
    27 using namespace mozilla;
    28 using namespace mozilla::psm;
    30 NS_IMPL_ISUPPORTS(nsClientAuthRememberService,
    31                   nsIObserver,
    32                   nsISupportsWeakReference)
    34 nsClientAuthRememberService::nsClientAuthRememberService()
    35   : monitor("nsClientAuthRememberService.monitor")
    36 {
    37 }
    39 nsClientAuthRememberService::~nsClientAuthRememberService()
    40 {
    41   RemoveAllFromMemory();
    42 }
    44 nsresult
    45 nsClientAuthRememberService::Init()
    46 {
    47   if (!NS_IsMainThread()) {
    48     NS_ERROR("nsClientAuthRememberService::Init called off the main thread");
    49     return NS_ERROR_NOT_SAME_THREAD;
    50   }
    52   nsCOMPtr<nsIObserverService> observerService =
    53       mozilla::services::GetObserverService();
    54   if (observerService) {
    55     observerService->AddObserver(this, "profile-before-change", true);
    56   }
    58   return NS_OK;
    59 }
    61 NS_IMETHODIMP
    62 nsClientAuthRememberService::Observe(nsISupports     *aSubject,
    63                                const char      *aTopic,
    64                                const char16_t *aData)
    65 {
    66   // check the topic
    67   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.
    71     ReentrantMonitorAutoEnter lock(monitor);
    72     RemoveAllFromMemory();
    73   }
    75   return NS_OK;
    76 }
    78 void nsClientAuthRememberService::ClearRememberedDecisions()
    79 {
    80   ReentrantMonitorAutoEnter lock(monitor);
    81   RemoveAllFromMemory();
    82 }
    84 void nsClientAuthRememberService::ClearAllRememberedDecisions()
    85 {
    86   RefPtr<nsClientAuthRememberService> svc =
    87     PublicSSLState()->GetClientAuthRememberService();
    88   svc->ClearRememberedDecisions();
    90   svc = PrivateSSLState()->GetClientAuthRememberService();
    91   svc->ClearRememberedDecisions();
    92 }
    94 void
    95 nsClientAuthRememberService::RemoveAllFromMemory()
    96 {
    97   mSettingsTable.Clear();
    98 }
   100 nsresult
   101 nsClientAuthRememberService::RememberDecision(const nsACString & aHostName, 
   102                                               CERTCertificate *aServerCert, CERTCertificate *aClientCert)
   103 {
   104   // aClientCert == nullptr means: remember that user does not want to use a cert
   105   NS_ENSURE_ARG_POINTER(aServerCert);
   106   if (aHostName.IsEmpty())
   107     return NS_ERROR_INVALID_ARG;
   109   nsAutoCString fpStr;
   110   nsresult rv = GetCertFingerprintByOidTag(aServerCert, SEC_OID_SHA256, fpStr);
   111   if (NS_FAILED(rv))
   112     return rv;
   114   {
   115     ReentrantMonitorAutoEnter lock(monitor);
   116     if (aClientCert) {
   117       nsNSSCertificate pipCert(aClientCert);
   118       char *dbkey = nullptr;
   119       rv = pipCert.GetDbKey(&dbkey);
   120       if (NS_SUCCEEDED(rv) && dbkey) {
   121         AddEntryToList(aHostName, fpStr, 
   122                        nsDependentCString(dbkey));
   123       }
   124       if (dbkey) {
   125         PORT_Free(dbkey);
   126       }
   127     }
   128     else {
   129       nsCString empty;
   130       AddEntryToList(aHostName, fpStr, empty);
   131     }
   132   }
   134   return NS_OK;
   135 }
   137 nsresult
   138 nsClientAuthRememberService::HasRememberedDecision(const nsACString & aHostName, 
   139                                                    CERTCertificate *aCert, 
   140                                                    nsACString & aCertDBKey,
   141                                                    bool *_retval)
   142 {
   143   if (aHostName.IsEmpty())
   144     return NS_ERROR_INVALID_ARG;
   146   NS_ENSURE_ARG_POINTER(aCert);
   147   NS_ENSURE_ARG_POINTER(_retval);
   148   *_retval = false;
   150   nsresult rv;
   151   nsAutoCString fpStr;
   152   rv = GetCertFingerprintByOidTag(aCert, SEC_OID_SHA256, fpStr);
   153   if (NS_FAILED(rv))
   154     return rv;
   156   nsAutoCString hostCert;
   157   GetHostWithCert(aHostName, fpStr, hostCert);
   158   nsClientAuthRemember settings;
   160   {
   161     ReentrantMonitorAutoEnter lock(monitor);
   162     nsClientAuthRememberEntry *entry = mSettingsTable.GetEntry(hostCert.get());
   163     if (!entry)
   164       return NS_OK;
   165     settings = entry->mSettings; // copy
   166   }
   168   aCertDBKey = settings.mDBKey;
   169   *_retval = true;
   170   return NS_OK;
   171 }
   173 nsresult
   174 nsClientAuthRememberService::AddEntryToList(const nsACString &aHostName, 
   175                                       const nsACString &fingerprint,
   176                                       const nsACString &db_key)
   178 {
   179   nsAutoCString hostCert;
   180   GetHostWithCert(aHostName, fingerprint, hostCert);
   182   {
   183     ReentrantMonitorAutoEnter lock(monitor);
   184     nsClientAuthRememberEntry *entry = mSettingsTable.PutEntry(hostCert.get());
   186     if (!entry) {
   187       NS_ERROR("can't insert a null entry!");
   188       return NS_ERROR_OUT_OF_MEMORY;
   189     }
   191     entry->mHostWithCert = hostCert;
   193     nsClientAuthRemember &settings = entry->mSettings;
   194     settings.mAsciiHost = aHostName;
   195     settings.mFingerprint = fingerprint;
   196     settings.mDBKey = db_key;
   197   }
   199   return NS_OK;
   200 }
   202 void
   203 nsClientAuthRememberService::GetHostWithCert(const nsACString & aHostName, 
   204                                              const nsACString & fingerprint, 
   205                                              nsACString& _retval)
   206 {
   207   nsAutoCString hostCert(aHostName);
   208   hostCert.AppendLiteral(":");
   209   hostCert.Append(fingerprint);
   211   _retval.Assign(hostCert);
   212 }

mercurial