LCOV - code coverage report
Current view: directory - security/manager/ssl/src - nsNSSComponent.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1521 719 47.3 %
Date: 2012-06-02 Functions: 144 77 53.5 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Hubbie Shaw
      25                 :  *   Doug Turner <dougt@netscape.com>
      26                 :  *   Mitch Stoltz <mstoltz@netscape.com>
      27                 :  *   Brian Ryner <bryner@brianryner.com>
      28                 :  *   Kai Engert <kaie@netscape.com>
      29                 :  *   Vipul Gupta <vipul.gupta@sun.com>
      30                 :  *   Douglas Stebila <douglas@stebila.ca>
      31                 :  *   Kai Engert <kengert@redhat.com>
      32                 :  *
      33                 :  * Alternatively, the contents of this file may be used under the terms of
      34                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      35                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      36                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      37                 :  * of those above. If you wish to allow use of your version of this file only
      38                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      39                 :  * use your version of this file under the terms of the MPL, indicate your
      40                 :  * decision by deleting the provisions above and replace them with the notice
      41                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      42                 :  * the provisions above, a recipient may use your version of this file under
      43                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      44                 :  *
      45                 :  * ***** END LICENSE BLOCK ***** */
      46                 : 
      47                 : #include "nsNSSComponent.h"
      48                 : #include "nsNSSCallbacks.h"
      49                 : #include "nsNSSIOLayer.h"
      50                 : #include "nsCertVerificationThread.h"
      51                 : 
      52                 : #include "nsNetUtil.h"
      53                 : #include "nsAppDirectoryServiceDefs.h"
      54                 : #include "nsDirectoryService.h"
      55                 : #include "nsIStreamListener.h"
      56                 : #include "nsIStringBundle.h"
      57                 : #include "nsIDirectoryService.h"
      58                 : #include "nsIDOMNode.h"
      59                 : #include "nsCURILoader.h"
      60                 : #include "nsDirectoryServiceDefs.h"
      61                 : #include "nsIX509Cert.h"
      62                 : #include "nsIX509CertDB.h"
      63                 : #include "nsIProfileChangeStatus.h"
      64                 : #include "nsNSSCertificate.h"
      65                 : #include "nsNSSHelper.h"
      66                 : #include "nsSmartCardMonitor.h"
      67                 : #include "prlog.h"
      68                 : #include "nsIPrefService.h"
      69                 : #include "nsIPrefBranch.h"
      70                 : #include "nsIDateTimeFormat.h"
      71                 : #include "nsDateTimeFormatCID.h"
      72                 : #include "nsIDOMEvent.h"
      73                 : #include "nsIDOMDocument.h"
      74                 : #include "nsIDOMWindow.h"
      75                 : #include "nsIDOMWindowCollection.h"
      76                 : #include "nsIDOMSmartCardEvent.h"
      77                 : #include "nsIDOMCrypto.h"
      78                 : #include "nsThreadUtils.h"
      79                 : #include "nsAutoPtr.h"
      80                 : #include "nsCRT.h"
      81                 : #include "nsCRLInfo.h"
      82                 : #include "nsCertOverrideService.h"
      83                 : 
      84                 : #include "nsIWindowWatcher.h"
      85                 : #include "nsIPrompt.h"
      86                 : #include "nsIPrincipal.h"
      87                 : #include "nsReadableUtils.h"
      88                 : #include "nsIDateTimeFormat.h"
      89                 : #include "prtypes.h"
      90                 : #include "nsIEntropyCollector.h"
      91                 : #include "nsIBufEntropyCollector.h"
      92                 : #include "nsIServiceManager.h"
      93                 : #include "nsILocalFile.h"
      94                 : #include "nsITokenPasswordDialogs.h"
      95                 : #include "nsICRLManager.h"
      96                 : #include "nsNSSShutDown.h"
      97                 : #include "nsSmartCardEvent.h"
      98                 : #include "nsIKeyModule.h"
      99                 : 
     100                 : #include "nss.h"
     101                 : #include "pk11func.h"
     102                 : #include "ssl.h"
     103                 : #include "sslproto.h"
     104                 : #include "secmod.h"
     105                 : #include "sechash.h"
     106                 : #include "secmime.h"
     107                 : #include "ocsp.h"
     108                 : #include "cms.h"
     109                 : #include "nssckbi.h"
     110                 : #include "base64.h"
     111                 : #include "secerr.h"
     112                 : #include "sslerr.h"
     113                 : #include "cert.h"
     114                 : 
     115                 : #include "nsXULAppAPI.h"
     116                 : 
     117                 : #ifdef XP_WIN
     118                 : #include "nsILocalFileWin.h"
     119                 : #endif
     120                 : 
     121                 : extern "C" {
     122                 : #include "pkcs12.h"
     123                 : #include "p12plcy.h"
     124                 : }
     125                 : 
     126                 : using namespace mozilla;
     127                 : 
     128                 : #ifdef PR_LOGGING
     129                 : PRLogModuleInfo* gPIPNSSLog = nsnull;
     130                 : #endif
     131                 : 
     132                 : #define NS_CRYPTO_HASH_BUFFER_SIZE 4096
     133                 : 
     134                 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
     135                 : int nsNSSComponent::mInstanceCount = 0;
     136                 : bool nsNSSComponent::globalConstFlagUsePKIXVerification = false;
     137                 : 
     138                 : // XXX tmp callback for slot password
     139                 : extern char * PR_CALLBACK 
     140                 : pk11PasswordPrompt(PK11SlotInfo *slot, PRBool retry, void *arg);
     141                 : 
     142                 : #define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties"
     143                 : #define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties"
     144                 : 
     145               0 : static PLHashNumber PR_CALLBACK certHashtable_keyHash(const void *key)
     146                 : {
     147               0 :   if (!key)
     148               0 :     return 0;
     149                 :   
     150               0 :   SECItem *certKey = (SECItem*)key;
     151                 :   
     152                 :   // lazy hash function, sum up all char values of SECItem
     153                 :   
     154               0 :   PLHashNumber hash = 0;
     155               0 :   unsigned int i = 0;
     156               0 :   unsigned char *c = certKey->data;
     157                 :   
     158               0 :   for (i = 0; i < certKey->len; ++i, ++c) {
     159               0 :     hash += *c;
     160                 :   }
     161                 :   
     162               0 :   return hash;
     163                 : }
     164                 : 
     165               0 : static PRIntn PR_CALLBACK certHashtable_keyCompare(const void *k1, const void *k2)
     166                 : {
     167                 :   // return type is a bool, answering the question "are the keys equal?"
     168                 : 
     169               0 :   if (!k1 || !k2)
     170               0 :     return false;
     171                 :   
     172               0 :   SECItem *certKey1 = (SECItem*)k1;
     173               0 :   SECItem *certKey2 = (SECItem*)k2;
     174                 :   
     175               0 :   if (certKey1->len != certKey2->len) {
     176               0 :     return false;
     177                 :   }
     178                 :   
     179               0 :   unsigned int i = 0;
     180               0 :   unsigned char *c1 = certKey1->data;
     181               0 :   unsigned char *c2 = certKey2->data;
     182                 :   
     183               0 :   for (i = 0; i < certKey1->len; ++i, ++c1, ++c2) {
     184               0 :     if (*c1 != *c2) {
     185               0 :       return false;
     186                 :     }
     187                 :   }
     188                 :   
     189               0 :   return true;
     190                 : }
     191                 : 
     192               0 : static PRIntn PR_CALLBACK certHashtable_valueCompare(const void *v1, const void *v2)
     193                 : {
     194                 :   // two values are identical if their keys are identical
     195                 :   
     196               0 :   if (!v1 || !v2)
     197               0 :     return false;
     198                 :   
     199               0 :   CERTCertificate *cert1 = (CERTCertificate*)v1;
     200               0 :   CERTCertificate *cert2 = (CERTCertificate*)v2;
     201                 :   
     202               0 :   return certHashtable_keyCompare(&cert1->certKey, &cert2->certKey);
     203                 : }
     204                 : 
     205               0 : static PRIntn PR_CALLBACK certHashtable_clearEntry(PLHashEntry *he, PRIntn /*index*/, void * /*userdata*/)
     206                 : {
     207               0 :   if (he && he->value) {
     208               0 :     CERT_DestroyCertificate((CERTCertificate*)he->value);
     209                 :   }
     210                 :   
     211               0 :   return HT_ENUMERATE_NEXT;
     212                 : }
     213                 : 
     214               0 : class CRLDownloadEvent : public nsRunnable {
     215                 : public:
     216               0 :   CRLDownloadEvent(const nsCSubstring &urlString, nsIStreamListener *listener)
     217                 :     : mURLString(urlString)
     218               0 :     , mListener(listener)
     219               0 :   {}
     220                 : 
     221                 :   // Note that nsNSSComponent is a singleton object across all threads, 
     222                 :   // and automatic downloads are always scheduled sequentially - that is, 
     223                 :   // once one crl download is complete, the next one is scheduled
     224               0 :   NS_IMETHOD Run()
     225                 :   {
     226               0 :     if (!mListener || mURLString.IsEmpty())
     227               0 :       return NS_OK;
     228                 : 
     229               0 :     nsCOMPtr<nsIURI> uri;
     230               0 :     nsresult rv = NS_NewURI(getter_AddRefs(uri), mURLString);
     231               0 :     if (NS_SUCCEEDED(rv)){
     232               0 :       NS_OpenURI(mListener, nsnull, uri);
     233                 :     }
     234                 : 
     235               0 :     return NS_OK;
     236                 :   }
     237                 : 
     238                 : private:
     239                 :   nsCString mURLString;
     240                 :   nsCOMPtr<nsIStreamListener> mListener;
     241                 : };
     242                 : 
     243                 : //This class is used to run the callback code
     244                 : //passed to the event handlers for smart card notification
     245                 : class nsTokenEventRunnable : public nsIRunnable {
     246                 : public:
     247                 :   nsTokenEventRunnable(const nsAString &aType, const nsAString &aTokenName);
     248                 :   virtual ~nsTokenEventRunnable();
     249                 : 
     250                 :   NS_IMETHOD Run ();
     251                 :   NS_DECL_ISUPPORTS
     252                 : private:
     253                 :   nsString mType;
     254                 :   nsString mTokenName;
     255                 : };
     256                 : 
     257                 : // ISuuports implementation for nsTokenEventRunnable
     258               0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsTokenEventRunnable, nsIRunnable)
     259                 : 
     260               0 : nsTokenEventRunnable::nsTokenEventRunnable(const nsAString &aType, 
     261               0 :    const nsAString &aTokenName): mType(aType), mTokenName(aTokenName) { }
     262                 : 
     263               0 : nsTokenEventRunnable::~nsTokenEventRunnable() { }
     264                 : 
     265                 : //Implementation that runs the callback passed to 
     266                 : //crypto.generateCRMFRequest as an event.
     267                 : NS_IMETHODIMP
     268               0 : nsTokenEventRunnable::Run()
     269                 : { 
     270                 :   nsresult rv;
     271               0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
     272               0 :   if (NS_FAILED(rv))
     273               0 :     return rv;
     274                 : 
     275               0 :   return nssComponent->DispatchEvent(mType, mTokenName);
     276                 : }
     277                 : 
     278                 : bool nsPSMInitPanic::isPanic = false;
     279                 : 
     280                 : // We must ensure that the nsNSSComponent has been loaded before
     281                 : // creating any other components.
     282            9864 : bool EnsureNSSInitialized(EnsureNSSOperator op)
     283                 : {
     284            9864 :   if (nsPSMInitPanic::GetPanic())
     285               0 :     return false;
     286                 : 
     287            9864 :   if (GeckoProcessType_Default != XRE_GetProcessType())
     288                 :   {
     289               0 :     if (op == nssEnsureOnChromeOnly)
     290                 :     {
     291                 :       // If the component needs PSM/NSS initialized only on the chrome process,
     292                 :       // pretend we successfully initiated it but in reality we bypass it.
     293                 :       // It's up to the programmer to check for process type in such components
     294                 :       // and take care not to call anything that needs NSS/PSM initiated.
     295               0 :       return true;
     296                 :     }
     297                 : 
     298               0 :     NS_ERROR("Trying to initialize PSM/NSS in a non-chrome process!");
     299               0 :     return false;
     300                 :   }
     301                 : 
     302                 :   static bool loading = false;
     303                 :   static PRInt32 haveLoaded = 0;
     304                 : 
     305            9864 :   switch (op)
     306                 :   {
     307                 :     // In following 4 cases we are protected by monitor of XPCOM component
     308                 :     // manager - we are inside of do_GetService call for nss component, so it is
     309                 :     // safe to move with the flags here.
     310                 :   case nssLoadingComponent:
     311             328 :     if (loading)
     312               0 :       return false; // We are reentered during nss component creation
     313             328 :     loading = true;
     314             328 :     return true;
     315                 : 
     316                 :   case nssInitSucceeded:
     317             328 :     NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitSucceeded)");
     318             328 :     loading = false;
     319             328 :     PR_AtomicSet(&haveLoaded, 1);
     320             328 :     return true;
     321                 : 
     322                 :   case nssInitFailed:
     323               0 :     NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitFailed)");
     324               0 :     loading = false;
     325                 :     // no break
     326                 : 
     327                 :   case nssShutdown:
     328             656 :     PR_AtomicSet(&haveLoaded, 0);
     329             656 :     return false;
     330                 : 
     331                 :     // In this case we are called from a component to ensure nss initilization.
     332                 :     // If the component has not yet been loaded and is not currently loading
     333                 :     // call do_GetService for nss component to ensure it.
     334                 :   case nssEnsure:
     335                 :   case nssEnsureOnChromeOnly:
     336                 :     // We are reentered during nss component creation or nss component is already up
     337            8552 :     if (PR_AtomicAdd(&haveLoaded, 0) || loading)
     338            8273 :       return true;
     339                 : 
     340                 :     {
     341                 :     nsCOMPtr<nsINSSComponent> nssComponent
     342             558 :       = do_GetService(PSM_COMPONENT_CONTRACTID);
     343                 : 
     344                 :     // Nss component failed to initialize, inform the caller of that fact.
     345                 :     // Flags are appropriately set by component constructor itself.
     346             279 :     if (!nssComponent)
     347               0 :       return false;
     348                 : 
     349                 :     bool isInitialized;
     350             279 :     nsresult rv = nssComponent->IsNSSInitialized(&isInitialized);
     351             279 :     return NS_SUCCEEDED(rv) && isInitialized;
     352                 :     }
     353                 : 
     354                 :   default:
     355               0 :     NS_ASSERTION(false, "Bad operator to EnsureNSSInitialized");
     356               0 :     return false;
     357                 :   }
     358                 : }
     359                 : 
     360             328 : nsNSSComponent::nsNSSComponent()
     361                 :   :mutex("nsNSSComponent.mutex"),
     362                 :    mNSSInitialized(false),
     363                 :    mCrlTimerLock("nsNSSComponent.mCrlTimerLock"),
     364                 :    mThreadList(nsnull),
     365             328 :    mCertVerificationThread(NULL)
     366                 : {
     367                 : #ifdef PR_LOGGING
     368             328 :   if (!gPIPNSSLog)
     369             328 :     gPIPNSSLog = PR_NewLogModule("pipnss");
     370                 : #endif
     371             328 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ctor\n"));
     372             328 :   mUpdateTimerInitialized = false;
     373             328 :   crlDownloadTimerOn = false;
     374             328 :   crlsScheduledForDownload = nsnull;
     375             328 :   mTimer = nsnull;
     376             328 :   mObserversRegistered = false;
     377                 : 
     378                 :   // In order to keep startup time lower, we delay loading and 
     379                 :   // registering all identity data until first needed.
     380             328 :   memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
     381                 : 
     382             328 :   NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
     383             328 :   ++mInstanceCount;
     384             328 :   hashTableCerts = nsnull;
     385             328 :   mShutdownObjectList = nsNSSShutDownList::construct();
     386             328 :   mIsNetworkDown = false;
     387             328 : }
     388                 : 
     389                 : void 
     390             328 : nsNSSComponent::deleteBackgroundThreads()
     391                 : {
     392             328 :   if (mCertVerificationThread)
     393                 :   {
     394             328 :     mCertVerificationThread->requestExit();
     395             328 :     delete mCertVerificationThread;
     396             328 :     mCertVerificationThread = nsnull;
     397                 :   }
     398             328 : }
     399                 : 
     400                 : void
     401             328 : nsNSSComponent::createBackgroundThreads()
     402                 : {
     403             328 :   NS_ASSERTION(mCertVerificationThread == nsnull,
     404                 :                "Cert verification thread already created.");
     405                 : 
     406             328 :   mCertVerificationThread = new nsCertVerificationThread;
     407             328 :   nsresult rv = mCertVerificationThread->startThread();
     408             328 :   if (NS_FAILED(rv)) {
     409               0 :     delete mCertVerificationThread;
     410               0 :     mCertVerificationThread = nsnull;
     411                 :   }
     412             328 : }
     413                 : 
     414             984 : nsNSSComponent::~nsNSSComponent()
     415                 : {
     416             328 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor\n"));
     417                 : 
     418             328 :   deleteBackgroundThreads();
     419                 : 
     420             328 :   if (mUpdateTimerInitialized) {
     421                 :     {
     422              34 :       MutexAutoLock lock(mCrlTimerLock);
     423              17 :       if (crlDownloadTimerOn) {
     424               0 :         mTimer->Cancel();
     425                 :       }
     426              17 :       crlDownloadTimerOn = false;
     427                 :     }
     428              17 :     if(crlsScheduledForDownload != nsnull){
     429              17 :       crlsScheduledForDownload->Reset();
     430              17 :       delete crlsScheduledForDownload;
     431                 :     }
     432                 : 
     433              17 :     mUpdateTimerInitialized = false;
     434                 :   }
     435                 : 
     436                 :   // All cleanup code requiring services needs to happen in xpcom_shutdown
     437                 : 
     438             328 :   ShutdownNSS();
     439             328 :   nsSSLIOLayerHelpers::Cleanup();
     440             328 :   --mInstanceCount;
     441             328 :   delete mShutdownObjectList;
     442                 : 
     443                 :   // We are being freed, drop the haveLoaded flag to re-enable
     444                 :   // potential nss initialization later.
     445             328 :   EnsureNSSInitialized(nssShutdown);
     446                 : 
     447             328 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n"));
     448            1312 : }
     449                 : 
     450                 : NS_IMETHODIMP
     451               0 : nsNSSComponent::PostEvent(const nsAString &eventType, 
     452                 :                                                   const nsAString &tokenName)
     453                 : {
     454                 :   nsCOMPtr<nsIRunnable> runnable = 
     455               0 :                                new nsTokenEventRunnable(eventType, tokenName);
     456               0 :   if (!runnable) {
     457               0 :     return NS_ERROR_OUT_OF_MEMORY;
     458                 :   }
     459                 : 
     460               0 :   return NS_DispatchToMainThread(runnable);
     461                 : }
     462                 : 
     463                 : 
     464                 : NS_IMETHODIMP
     465               0 : nsNSSComponent::DispatchEvent(const nsAString &eventType,
     466                 :                                                  const nsAString &tokenName)
     467                 : {
     468                 :   // 'Dispatch' the event to all the windows. 'DispatchEventToWindow()' will
     469                 :   // first check to see if a given window has requested crypto events.
     470                 :   nsresult rv;
     471                 :   nsCOMPtr<nsIWindowWatcher> windowWatcher =
     472               0 :                             do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
     473                 : 
     474               0 :   if (NS_FAILED(rv)) {
     475               0 :     return rv;
     476                 :   }
     477                 : 
     478               0 :   nsCOMPtr<nsISimpleEnumerator> enumerator;
     479               0 :   rv = windowWatcher->GetWindowEnumerator(getter_AddRefs(enumerator));
     480               0 :   if (NS_FAILED(rv)) {
     481               0 :     return rv;
     482                 :   }
     483                 : 
     484                 :   bool hasMoreWindows;
     485                 : 
     486               0 :   while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreWindows))
     487                 :          && hasMoreWindows) {
     488               0 :     nsCOMPtr<nsISupports> supports;
     489               0 :     enumerator->GetNext(getter_AddRefs(supports));
     490               0 :     nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(supports));
     491               0 :     if (domWin) {
     492               0 :       nsresult rv2 = DispatchEventToWindow(domWin, eventType, tokenName);
     493               0 :       if (NS_FAILED(rv2)) {
     494                 :         // return the last failure, don't let a single failure prevent
     495                 :         // continued delivery of events.
     496               0 :         rv = rv2;
     497                 :       }
     498                 :     }
     499                 :   }
     500               0 :   return rv;
     501                 : }
     502                 : 
     503                 : nsresult
     504               0 : nsNSSComponent::DispatchEventToWindow(nsIDOMWindow *domWin,
     505                 :                       const nsAString &eventType, const nsAString &tokenName)
     506                 : {
     507                 :   // first walk the children and dispatch their events 
     508                 :   {
     509                 :     nsresult rv;
     510               0 :     nsCOMPtr<nsIDOMWindowCollection> frames;
     511               0 :     rv = domWin->GetFrames(getter_AddRefs(frames));
     512               0 :     if (NS_FAILED(rv)) {
     513               0 :       return rv;
     514                 :     }
     515                 : 
     516                 :     PRUint32 length;
     517               0 :     frames->GetLength(&length);
     518                 :     PRUint32 i;
     519               0 :     for (i = 0; i < length; i++) {
     520               0 :       nsCOMPtr<nsIDOMWindow> childWin;
     521               0 :       frames->Item(i, getter_AddRefs(childWin));
     522               0 :       DispatchEventToWindow(childWin, eventType, tokenName);
     523                 :     }
     524                 :   }
     525                 : 
     526                 :   // check if we've enabled smart card events on this window
     527                 :   // NOTE: it's not an error to say that we aren't going to dispatch
     528                 :   // the event.
     529                 :   {
     530               0 :     nsCOMPtr<nsIDOMWindow> domWindow = domWin;
     531               0 :     if (!domWindow) {
     532               0 :       return NS_OK; // nope, it's not an internal window
     533                 :     }
     534                 : 
     535               0 :     nsCOMPtr<nsIDOMCrypto> crypto;
     536               0 :     domWindow->GetCrypto(getter_AddRefs(crypto));
     537               0 :     if (!crypto) {
     538               0 :       return NS_OK; // nope, it doesn't have a crypto property
     539                 :     }
     540                 : 
     541                 :     bool boolrv;
     542               0 :     crypto->GetEnableSmartCardEvents(&boolrv);
     543               0 :     if (!boolrv) {
     544               0 :       return NS_OK; // nope, it's not enabled.
     545                 :     }
     546                 :   }
     547                 : 
     548                 :   // dispatch the event ...
     549                 : 
     550                 :   nsresult rv;
     551                 :   // find the document
     552               0 :   nsCOMPtr<nsIDOMDocument> doc;
     553               0 :   rv = domWin->GetDocument(getter_AddRefs(doc));
     554               0 :   if (doc == nsnull) {
     555               0 :     return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
     556                 :   }
     557                 : 
     558                 :   // create the event
     559               0 :   nsCOMPtr<nsIDOMEvent> event;
     560               0 :   rv = doc->CreateEvent(NS_LITERAL_STRING("Events"), 
     561               0 :                         getter_AddRefs(event));
     562               0 :   if (NS_FAILED(rv)) {
     563               0 :     return rv;
     564                 :   }
     565                 : 
     566               0 :   event->InitEvent(eventType, false, true);
     567                 : 
     568                 :   // create the Smart Card Event;
     569                 :   nsCOMPtr<nsIDOMSmartCardEvent> smartCardEvent = 
     570               0 :                                           new nsSmartCardEvent(tokenName);
     571                 :   // init the smart card event, fail here if we can't complete the 
     572                 :   // initialization.
     573               0 :   if (!smartCardEvent) {
     574               0 :     return NS_ERROR_OUT_OF_MEMORY;
     575                 :   }
     576                 : 
     577               0 :   rv = smartCardEvent->Init(event);
     578               0 :   if (NS_FAILED(rv)) {
     579               0 :     return rv;
     580                 :   }
     581                 : 
     582                 :   // Send it 
     583               0 :   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(doc, &rv);
     584               0 :   if (NS_FAILED(rv)) {
     585               0 :     return rv;
     586                 :   }
     587                 : 
     588                 :   bool boolrv;
     589               0 :   rv = target->DispatchEvent(smartCardEvent, &boolrv);
     590               0 :   return rv;
     591                 : }
     592                 : 
     593                 : 
     594                 : NS_IMETHODIMP
     595               4 : nsNSSComponent::PIPBundleFormatStringFromName(const char *name,
     596                 :                                               const PRUnichar **params,
     597                 :                                               PRUint32 numParams,
     598                 :                                               nsAString &outString)
     599                 : {
     600               4 :   nsresult rv = NS_ERROR_FAILURE;
     601                 : 
     602               4 :   if (mPIPNSSBundle && name) {
     603               8 :     nsXPIDLString result;
     604               8 :     rv = mPIPNSSBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
     605                 :                                              params, numParams,
     606               8 :                                              getter_Copies(result));
     607               4 :     if (NS_SUCCEEDED(rv)) {
     608               4 :       outString = result;
     609                 :     }
     610                 :   }
     611               4 :   return rv;
     612                 : }
     613                 : 
     614                 : NS_IMETHODIMP
     615            3280 : nsNSSComponent::GetPIPNSSBundleString(const char *name,
     616                 :                                       nsAString &outString)
     617                 : {
     618            3280 :   nsresult rv = NS_ERROR_FAILURE;
     619                 : 
     620            3280 :   outString.SetLength(0);
     621            3280 :   if (mPIPNSSBundle && name) {
     622            6560 :     nsXPIDLString result;
     623            6560 :     rv = mPIPNSSBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
     624            6560 :                                           getter_Copies(result));
     625            3280 :     if (NS_SUCCEEDED(rv)) {
     626            3280 :       outString = result;
     627            3280 :       rv = NS_OK;
     628                 :     }
     629                 :   }
     630                 : 
     631            3280 :   return rv;
     632                 : }
     633                 : 
     634                 : NS_IMETHODIMP
     635               0 : nsNSSComponent::NSSBundleFormatStringFromName(const char *name,
     636                 :                                               const PRUnichar **params,
     637                 :                                               PRUint32 numParams,
     638                 :                                               nsAString &outString)
     639                 : {
     640               0 :   nsresult rv = NS_ERROR_FAILURE;
     641                 : 
     642               0 :   if (mNSSErrorsBundle && name) {
     643               0 :     nsXPIDLString result;
     644               0 :     rv = mNSSErrorsBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
     645                 :                                                 params, numParams,
     646               0 :                                                 getter_Copies(result));
     647               0 :     if (NS_SUCCEEDED(rv)) {
     648               0 :       outString = result;
     649                 :     }
     650                 :   }
     651               0 :   return rv;
     652                 : }
     653                 : 
     654                 : NS_IMETHODIMP
     655               0 : nsNSSComponent::GetNSSBundleString(const char *name,
     656                 :                                    nsAString &outString)
     657                 : {
     658               0 :   nsresult rv = NS_ERROR_FAILURE;
     659                 : 
     660               0 :   outString.SetLength(0);
     661               0 :   if (mNSSErrorsBundle && name) {
     662               0 :     nsXPIDLString result;
     663               0 :     rv = mNSSErrorsBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
     664               0 :                                              getter_Copies(result));
     665               0 :     if (NS_SUCCEEDED(rv)) {
     666               0 :       outString = result;
     667               0 :       rv = NS_OK;
     668                 :     }
     669                 :   }
     670                 : 
     671               0 :   return rv;
     672                 : }
     673                 : 
     674                 : void
     675             328 : nsNSSComponent::LaunchSmartCardThreads()
     676                 : {
     677             656 :   nsNSSShutDownPreventionLock locker;
     678                 :   {
     679                 :     SECMODModuleList *list;
     680             328 :     SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
     681             328 :     if (!lock) {
     682               0 :         PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
     683                 :                ("Couldn't get the module list lock, can't launch smart card threads\n"));
     684                 :         return;
     685                 :     }
     686             328 :     SECMOD_GetReadLock(lock);
     687             328 :     list = SECMOD_GetDefaultModuleList();
     688                 : 
     689            1312 :     while (list) {
     690             656 :       SECMODModule *module = list->module;
     691             656 :       LaunchSmartCardThread(module);
     692             656 :       list = list->next;
     693                 :     }
     694             328 :     SECMOD_ReleaseReadLock(lock);
     695                 :   }
     696                 : }
     697                 : 
     698                 : NS_IMETHODIMP
     699             656 : nsNSSComponent::LaunchSmartCardThread(SECMODModule *module)
     700                 : {
     701                 :   SmartCardMonitoringThread *newThread;
     702             656 :   if (SECMOD_HasRemovableSlots(module)) {
     703               0 :     if (mThreadList == nsnull) {
     704               0 :       mThreadList = new SmartCardThreadList();
     705               0 :       if (!mThreadList) {
     706               0 :         return NS_ERROR_OUT_OF_MEMORY;
     707                 :       }
     708                 :     }
     709               0 :     newThread = new SmartCardMonitoringThread(module);
     710               0 :     if (!newThread) {
     711               0 :         return NS_ERROR_OUT_OF_MEMORY;
     712                 :     }
     713                 :     // newThread is adopted by the add.
     714               0 :     return mThreadList->Add(newThread);
     715                 :   }
     716             656 :   return NS_OK;
     717                 : }
     718                 : 
     719                 : NS_IMETHODIMP
     720               0 : nsNSSComponent::ShutdownSmartCardThread(SECMODModule *module)
     721                 : {
     722               0 :   if (!mThreadList) {
     723               0 :     return NS_OK;
     724                 :   }
     725               0 :   mThreadList->Remove(module);
     726               0 :   return NS_OK;
     727                 : }
     728                 : 
     729                 : void
     730             328 : nsNSSComponent::ShutdownSmartCardThreads()
     731                 : {
     732             328 :   delete mThreadList;
     733             328 :   mThreadList = nsnull;
     734             328 : }
     735                 : 
     736                 : static char *
     737             328 : nss_addEscape(const char *string, char quote)
     738                 : {
     739             328 :     char *newString = 0;
     740             328 :     int escapes = 0, size = 0;
     741                 :     const char *src;
     742                 :     char *dest;
     743                 : 
     744           24272 :     for (src=string; *src ; src++) {
     745           23944 :         if ((*src == quote) || (*src == '\\')) {
     746               0 :           escapes++;
     747                 :         }
     748           23944 :         size++;
     749                 :     }
     750                 : 
     751             328 :     newString = (char*)PORT_ZAlloc(escapes+size+1);
     752             328 :     if (newString == NULL) {
     753               0 :         return NULL;
     754                 :     }
     755                 : 
     756           24272 :     for (src=string, dest=newString; *src; src++,dest++) {
     757           23944 :         if ((*src == quote) || (*src == '\\')) {
     758               0 :             *dest++ = '\\';
     759                 :         }
     760           23944 :         *dest = *src;
     761                 :     }
     762                 : 
     763             328 :     return newString;
     764                 : }
     765                 : 
     766                 : void
     767             328 : nsNSSComponent::InstallLoadableRoots()
     768                 : {
     769             656 :   nsNSSShutDownPreventionLock locker;
     770             328 :   SECMODModule *RootsModule = nsnull;
     771                 : 
     772                 :   // In the past we used SECMOD_AddNewModule to load our module containing
     773                 :   // root CA certificates. This caused problems, refer to bug 176501.
     774                 :   // On startup, we fix our database and clean any stored module reference,
     775                 :   // and will use SECMOD_LoadUserModule to temporarily load it
     776                 :   // for the session. (This approach requires to clean up 
     777                 :   // using SECMOD_UnloadUserModule at the end of the session.)
     778                 : 
     779                 :   {
     780                 :     // Find module containing root certs
     781                 : 
     782                 :     SECMODModuleList *list;
     783             328 :     SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
     784             328 :     if (!lock) {
     785               0 :         PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
     786                 :                ("Couldn't get the module list lock, can't install loadable roots\n"));
     787                 :         return;
     788                 :     }
     789             328 :     SECMOD_GetReadLock(lock);
     790             328 :     list = SECMOD_GetDefaultModuleList();
     791                 : 
     792             984 :     while (!RootsModule && list) {
     793             328 :       SECMODModule *module = list->module;
     794                 : 
     795             984 :       for (int i=0; i < module->slotCount; i++) {
     796             656 :         PK11SlotInfo *slot = module->slots[i];
     797             656 :         if (PK11_IsPresent(slot)) {
     798             656 :           if (PK11_HasRootCerts(slot)) {
     799               0 :             RootsModule = SECMOD_ReferenceModule(module);
     800               0 :             break;
     801                 :           }
     802                 :         }
     803                 :       }
     804                 : 
     805             328 :       list = list->next;
     806                 :     }
     807             328 :     SECMOD_ReleaseReadLock(lock);
     808                 :   }
     809                 : 
     810             328 :   if (RootsModule) {
     811                 :     PRInt32 modType;
     812               0 :     SECMOD_DeleteModule(RootsModule->commonName, &modType);
     813               0 :     SECMOD_DestroyModule(RootsModule);
     814               0 :     RootsModule = nsnull;
     815                 :   }
     816                 : 
     817                 :   // Find the best Roots module for our purposes.
     818                 :   // Prefer the application's installation directory,
     819                 :   // but also ensure the library is at least the version we expect.
     820                 : 
     821                 :   nsresult rv;
     822             656 :   nsAutoString modName;
     823             328 :   rv = GetPIPNSSBundleString("RootCertModuleName", modName);
     824             328 :   if (NS_FAILED(rv)) return;
     825                 : 
     826             656 :   nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
     827             328 :   if (!directoryService)
     828                 :     return;
     829                 : 
     830                 :   static const char nss_lib[] = "nss3";
     831                 :   const char *possible_ckbi_locations[] = {
     832                 :     nss_lib, // This special value means: search for ckbi in the directory
     833                 :              // where nss3 is.
     834                 :     NS_XPCOM_CURRENT_PROCESS_DIR,
     835                 :     NS_GRE_DIR,
     836                 :     0 // This special value means: 
     837                 :       //   search for ckbi in the directories on the shared
     838                 :       //   library/DLL search path
     839             328 :   };
     840                 : 
     841             328 :   for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
     842             656 :     nsCOMPtr<nsILocalFile> mozFile;
     843             328 :     char *fullLibraryPath = nsnull;
     844                 : 
     845             328 :     if (!possible_ckbi_locations[il])
     846                 :     {
     847               0 :       fullLibraryPath = PR_GetLibraryName(nsnull, "nssckbi");
     848                 :     }
     849                 :     else
     850                 :     {
     851             328 :       if (possible_ckbi_locations[il] == nss_lib) {
     852                 :         // Get the location of the nss3 library.
     853                 :         char *nss_path = PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
     854             328 :                                                    (PRFuncPtr) NSS_Initialize);
     855             328 :         if (!nss_path) {
     856               0 :           continue;
     857                 :         }
     858                 :         // Get the directory containing the nss3 library.
     859             656 :         nsCOMPtr<nsILocalFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
     860             328 :         if (NS_SUCCEEDED(rv)) {
     861             328 :           rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
     862                 :         }
     863             328 :         PR_Free(nss_path);
     864             328 :         if (NS_SUCCEEDED(rv)) {
     865             656 :           nsCOMPtr<nsIFile> file;
     866             328 :           if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
     867             328 :             mozFile = do_QueryInterface(file);
     868                 :           }
     869                 :         }
     870                 :       } else {
     871               0 :         directoryService->Get( possible_ckbi_locations[il],
     872                 :                                NS_GET_IID(nsILocalFile), 
     873               0 :                                getter_AddRefs(mozFile));
     874                 :       }
     875                 :   
     876             328 :       if (!mozFile) {
     877               0 :         continue;
     878                 :       }
     879                 : 
     880             656 :       nsCAutoString processDir;
     881             328 :       mozFile->GetNativePath(processDir);
     882             328 :       fullLibraryPath = PR_GetLibraryName(processDir.get(), "nssckbi");
     883                 :     }
     884                 : 
     885             328 :     if (!fullLibraryPath) {
     886               0 :       continue;
     887                 :     }
     888                 : 
     889             328 :     char *escaped_fullLibraryPath = nss_addEscape(fullLibraryPath, '\"');
     890             328 :     if (!escaped_fullLibraryPath) {
     891               0 :       PR_FreeLibraryName(fullLibraryPath); // allocated by NSPR
     892               0 :       continue;
     893                 :     }
     894                 : 
     895                 :     /* If a module exists with the same name, delete it. */
     896             656 :     NS_ConvertUTF16toUTF8 modNameUTF8(modName);
     897                 :     int modType;
     898             328 :     SECMOD_DeleteModule(const_cast<char*>(modNameUTF8.get()), &modType);
     899                 : 
     900             656 :     nsCString pkcs11moduleSpec;
     901             328 :     pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("name=\""));
     902             328 :     pkcs11moduleSpec.Append(modNameUTF8.get());
     903             328 :     pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("\" library=\""));
     904             328 :     pkcs11moduleSpec.Append(escaped_fullLibraryPath);
     905             328 :     pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("\""));
     906                 : 
     907             328 :     PR_FreeLibraryName(fullLibraryPath); // allocated by NSPR
     908             328 :     PORT_Free(escaped_fullLibraryPath);
     909                 : 
     910                 :     RootsModule =
     911             328 :       SECMOD_LoadUserModule(const_cast<char*>(pkcs11moduleSpec.get()), 
     912                 :                             nsnull, // no parent 
     913             328 :                             false); // do not recurse
     914                 : 
     915             328 :     if (RootsModule) {
     916             328 :       bool found = (RootsModule->loaded);
     917                 : 
     918             328 :       SECMOD_DestroyModule(RootsModule);
     919             328 :       RootsModule = nsnull;
     920                 : 
     921             328 :       if (found) {
     922                 :         break;
     923                 :       }
     924                 :     }
     925                 :   }
     926                 : }
     927                 : 
     928                 : void 
     929             328 : nsNSSComponent::UnloadLoadableRoots()
     930                 : {
     931                 :   nsresult rv;
     932             656 :   nsAutoString modName;
     933             328 :   rv = GetPIPNSSBundleString("RootCertModuleName", modName);
     934             328 :   if (NS_FAILED(rv)) return;
     935                 : 
     936             656 :   NS_ConvertUTF16toUTF8 modNameUTF8(modName);
     937             328 :   SECMODModule *RootsModule = SECMOD_FindModule(modNameUTF8.get());
     938                 : 
     939             328 :   if (RootsModule) {
     940             328 :     SECMOD_UnloadUserModule(RootsModule);
     941             328 :     SECMOD_DestroyModule(RootsModule);
     942                 :   }
     943                 : }
     944                 : 
     945                 : nsresult
     946             328 : nsNSSComponent::ConfigureInternalPKCS11Token()
     947                 : {
     948             656 :   nsNSSShutDownPreventionLock locker;
     949             656 :   nsAutoString manufacturerID;
     950             656 :   nsAutoString libraryDescription;
     951             656 :   nsAutoString tokenDescription;
     952             656 :   nsAutoString privateTokenDescription;
     953             656 :   nsAutoString slotDescription;
     954             656 :   nsAutoString privateSlotDescription;
     955             656 :   nsAutoString fips140TokenDescription;
     956             656 :   nsAutoString fips140SlotDescription;
     957                 : 
     958                 :   nsresult rv;
     959             328 :   rv = GetPIPNSSBundleString("ManufacturerID", manufacturerID);
     960             328 :   if (NS_FAILED(rv)) return rv;
     961                 : 
     962             328 :   rv = GetPIPNSSBundleString("LibraryDescription", libraryDescription);
     963             328 :   if (NS_FAILED(rv)) return rv;
     964                 : 
     965             328 :   rv = GetPIPNSSBundleString("TokenDescription", tokenDescription);
     966             328 :   if (NS_FAILED(rv)) return rv;
     967                 : 
     968             328 :   rv = GetPIPNSSBundleString("PrivateTokenDescription", privateTokenDescription);
     969             328 :   if (NS_FAILED(rv)) return rv;
     970                 : 
     971             328 :   rv = GetPIPNSSBundleString("SlotDescription", slotDescription);
     972             328 :   if (NS_FAILED(rv)) return rv;
     973                 : 
     974             328 :   rv = GetPIPNSSBundleString("PrivateSlotDescription", privateSlotDescription);
     975             328 :   if (NS_FAILED(rv)) return rv;
     976                 : 
     977             328 :   rv = GetPIPNSSBundleString("Fips140TokenDescription", fips140TokenDescription);
     978             328 :   if (NS_FAILED(rv)) return rv;
     979                 : 
     980             328 :   rv = GetPIPNSSBundleString("Fips140SlotDescription", fips140SlotDescription);
     981             328 :   if (NS_FAILED(rv)) return rv;
     982                 : 
     983             328 :   PK11_ConfigurePKCS11(NS_ConvertUTF16toUTF8(manufacturerID).get(),
     984             328 :                        NS_ConvertUTF16toUTF8(libraryDescription).get(),
     985             328 :                        NS_ConvertUTF16toUTF8(tokenDescription).get(),
     986             328 :                        NS_ConvertUTF16toUTF8(privateTokenDescription).get(),
     987             328 :                        NS_ConvertUTF16toUTF8(slotDescription).get(),
     988             328 :                        NS_ConvertUTF16toUTF8(privateSlotDescription).get(),
     989             328 :                        NS_ConvertUTF16toUTF8(fips140TokenDescription).get(),
     990             328 :                        NS_ConvertUTF16toUTF8(fips140SlotDescription).get(),
     991             328 :                        0, 0);
     992             328 :   return NS_OK;
     993                 : }
     994                 : 
     995                 : nsresult
     996             328 : nsNSSComponent::InitializePIPNSSBundle()
     997                 : {
     998                 :   // Called during init only, no mutex required.
     999                 : 
    1000                 :   nsresult rv;
    1001             656 :   nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
    1002             328 :   if (NS_FAILED(rv) || !bundleService) 
    1003               0 :     return NS_ERROR_FAILURE;
    1004                 :   
    1005             328 :   bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL,
    1006             328 :                               getter_AddRefs(mPIPNSSBundle));
    1007             328 :   if (!mPIPNSSBundle)
    1008               0 :     rv = NS_ERROR_FAILURE;
    1009                 : 
    1010             328 :   bundleService->CreateBundle(NSSERR_STRBUNDLE_URL,
    1011             328 :                               getter_AddRefs(mNSSErrorsBundle));
    1012             328 :   if (!mNSSErrorsBundle)
    1013               0 :     rv = NS_ERROR_FAILURE;
    1014                 : 
    1015             328 :   return rv;
    1016                 : }
    1017                 : 
    1018                 : nsresult
    1019             328 : nsNSSComponent::RegisterPSMContentListener()
    1020                 : {
    1021                 :   // Called during init only, no mutex required.
    1022                 : 
    1023             328 :   nsresult rv = NS_OK;
    1024             328 :   if (!mPSMContentListener) {
    1025             656 :     nsCOMPtr<nsIURILoader> dispatcher(do_GetService(NS_URI_LOADER_CONTRACTID));
    1026             328 :     if (dispatcher) {
    1027             328 :       mPSMContentListener = do_CreateInstance(NS_PSMCONTENTLISTEN_CONTRACTID);
    1028             328 :       rv = dispatcher->RegisterContentListener(mPSMContentListener);
    1029                 :     }
    1030                 :   }
    1031             328 :   return rv;
    1032                 : }
    1033                 : 
    1034                 : /* Table of pref names and SSL cipher ID */
    1035                 : typedef struct {
    1036                 :   const char* pref;
    1037                 :   long id;
    1038                 : } CipherPref;
    1039                 : 
    1040                 : static CipherPref CipherPrefs[] = {
    1041                 :  /* SSL3/TLS cipher suites*/
    1042                 :  {"security.ssl3.rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5}, // 128-bit RC4 encryption with RSA and an MD5 MAC
    1043                 :  {"security.ssl3.rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with RSA and a SHA1 MAC
    1044                 :  {"security.ssl3.rsa_fips_des_ede3_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with RSA and a SHA1 MAC (FIPS)
    1045                 :  {"security.ssl3.rsa_des_ede3_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with RSA and a SHA1 MAC
    1046                 :  {"security.ssl3.rsa_fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA and a SHA1 MAC (FIPS)
    1047                 :  {"security.ssl3.rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA and a SHA1 MAC
    1048                 :  {"security.ssl3.rsa_1024_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, // 56-bit RC4 encryption with RSA and a SHA1 MAC (export)
    1049                 :  {"security.ssl3.rsa_1024_des_cbc_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA and a SHA1 MAC (export)
    1050                 :  {"security.ssl3.rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5}, // 40-bit RC4 encryption with RSA and an MD5 MAC (export)
    1051                 :  {"security.ssl3.rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5}, // 40-bit RC2 encryption with RSA and an MD5 MAC (export)
    1052                 :  /* Extra SSL3/TLS cipher suites */
    1053                 :  {"security.ssl3.dhe_rsa_camellia_256_sha", TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA}, // 256-bit Camellia encryption with RSA, DHE, and a SHA1 MAC
    1054                 :  {"security.ssl3.dhe_dss_camellia_256_sha", TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA}, // 256-bit Camellia encryption with DSA, DHE, and a SHA1 MAC
    1055                 :  {"security.ssl3.rsa_camellia_256_sha", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA}, // 256-bit Camellia encryption with RSA and a SHA1 MAC
    1056                 :  {"security.ssl3.dhe_rsa_aes_256_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with RSA, DHE, and a SHA1 MAC
    1057                 :  {"security.ssl3.dhe_dss_aes_256_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with DSA, DHE, and a SHA1 MAC
    1058                 :  {"security.ssl3.rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with RSA and a SHA1 MAC
    1059                 :    /* TLS_DHE_DSS_WITH_RC4_128_SHA // 128-bit RC4 encryption with DSA, DHE, and a SHA1 MAC
    1060                 :       If this cipher gets included at a later time, it should get added at this position */
    1061                 :  {"security.ssl3.ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with ECDHE-ECDSA and a SHA1 MAC
    1062                 :  {"security.ssl3.ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with ECDHE-ECDSA and a SHA1 MAC
    1063                 :  {"security.ssl3.ecdhe_ecdsa_des_ede3_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with ECDHE-ECDSA and a SHA1 MAC
    1064                 :  {"security.ssl3.ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with ECDHE-ECDSA and a SHA1 MAC
    1065                 :  {"security.ssl3.ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA}, // No encryption with ECDHE-ECDSA and a SHA1 MAC
    1066                 :  {"security.ssl3.ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with ECDHE-RSA and a SHA1 MAC
    1067                 :  {"security.ssl3.ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with ECDHE-RSA and a SHA1 MAC
    1068                 :  {"security.ssl3.ecdhe_rsa_des_ede3_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with ECDHE-RSA and a SHA1 MAC
    1069                 :  {"security.ssl3.ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with ECDHE-RSA and a SHA1 MAC
    1070                 :  {"security.ssl3.ecdhe_rsa_null_sha", TLS_ECDHE_RSA_WITH_NULL_SHA}, // No encryption with ECDHE-RSA and a SHA1 MAC
    1071                 :  {"security.ssl3.ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with ECDH-ECDSA and a SHA1 MAC
    1072                 :  {"security.ssl3.ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with ECDH-ECDSA and a SHA1 MAC
    1073                 :  {"security.ssl3.ecdh_ecdsa_des_ede3_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with ECDH-ECDSA and a SHA1 MAC
    1074                 :  {"security.ssl3.ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with ECDH-ECDSA and a SHA1 MAC
    1075                 :  {"security.ssl3.ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA}, // No encryption with ECDH-ECDSA and a SHA1 MAC
    1076                 :  {"security.ssl3.ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with ECDH-RSA and a SHA1 MAC
    1077                 :  {"security.ssl3.ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with ECDH-RSA and a SHA1 MAC
    1078                 :  {"security.ssl3.ecdh_rsa_des_ede3_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with ECDH-RSA and a SHA1 MAC
    1079                 :  {"security.ssl3.ecdh_rsa_rc4_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with ECDH-RSA and a SHA1 MAC
    1080                 :  {"security.ssl3.ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA}, // No encryption with ECDH-RSA and a SHA1 MAC
    1081                 :  {"security.ssl3.dhe_rsa_camellia_128_sha", TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA}, // 128-bit Camellia encryption with RSA, DHE, and a SHA1 MAC
    1082                 :  {"security.ssl3.dhe_dss_camellia_128_sha", TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA}, // 128-bit Camellia encryption with DSA, DHE, and a SHA1 MAC
    1083                 :  {"security.ssl3.rsa_camellia_128_sha", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA}, // 128-bit Camellia encryption with RSA and a SHA1 MAC
    1084                 :  {"security.ssl3.dhe_rsa_aes_128_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with RSA, DHE, and a SHA1 MAC
    1085                 :  {"security.ssl3.dhe_dss_aes_128_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with DSA, DHE, and a SHA1 MAC
    1086                 :  {"security.ssl3.rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with RSA and a SHA1 MAC
    1087                 :  {"security.ssl3.dhe_rsa_des_ede3_sha", SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with RSA, DHE, and a SHA1 MAC
    1088                 :  {"security.ssl3.dhe_dss_des_ede3_sha", SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with DSA, DHE, and a SHA1 MAC
    1089                 :  {"security.ssl3.dhe_rsa_des_sha", SSL_DHE_RSA_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA, DHE, and a SHA1 MAC
    1090                 :  {"security.ssl3.dhe_dss_des_sha", SSL_DHE_DSS_WITH_DES_CBC_SHA}, // 56-bit DES encryption with DSA, DHE, and a SHA1 MAC
    1091                 :  {"security.ssl3.rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, // No encryption with RSA authentication and a SHA1 MAC
    1092                 :  {"security.ssl3.rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, // No encryption with RSA authentication and an MD5 MAC
    1093                 :  {"security.ssl3.rsa_seed_sha", TLS_RSA_WITH_SEED_CBC_SHA}, // SEED encryption with RSA and a SHA1 MAC
    1094                 :  {NULL, 0} /* end marker */
    1095                 : };
    1096                 : 
    1097                 : static void
    1098             328 : setNonPkixOcspEnabled(PRInt32 ocspEnabled, nsIPrefBranch * pref)
    1099                 : {
    1100             328 :   switch (ocspEnabled) {
    1101                 :   case 0:
    1102               0 :     CERT_DisableOCSPChecking(CERT_GetDefaultCertDB());
    1103               0 :     CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
    1104               0 :     break;
    1105                 :   case 1:
    1106             328 :     CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
    1107             328 :     CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
    1108             328 :     break;
    1109                 :   case 2:
    1110                 :     {
    1111               0 :       char *signingCA = nsnull;
    1112               0 :       char *url = nsnull;
    1113                 : 
    1114                 :       // Get the signing CA and service url //
    1115               0 :       pref->GetCharPref("security.OCSP.signingCA", &signingCA);
    1116               0 :       pref->GetCharPref("security.OCSP.URL", &url);
    1117                 : 
    1118                 :       // Set OCSP up
    1119               0 :       CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
    1120               0 :       CERT_SetOCSPDefaultResponder(CERT_GetDefaultCertDB(), url, signingCA);
    1121               0 :       CERT_EnableOCSPDefaultResponder(CERT_GetDefaultCertDB());
    1122                 : 
    1123               0 :       nsMemory::Free(signingCA);
    1124               0 :       nsMemory::Free(url);
    1125                 :     }
    1126               0 :     break;
    1127                 :   }
    1128             328 : }
    1129                 : 
    1130                 : #define CRL_DOWNLOAD_DEFAULT false
    1131                 : #define OCSP_ENABLED_DEFAULT 1
    1132                 : #define OCSP_REQUIRED_DEFAULT 0
    1133                 : #define FRESH_REVOCATION_REQUIRED_DEFAULT false
    1134                 : #define MISSING_CERT_DOWNLOAD_DEFAULT false
    1135                 : #define FIRST_REVO_METHOD_DEFAULT "ocsp"
    1136                 : #define USE_NSS_LIBPKIX_DEFAULT false
    1137                 : 
    1138                 : // Caller must hold a lock on nsNSSComponent::mutex when calling this function
    1139             328 : void nsNSSComponent::setValidationOptions(nsIPrefBranch * pref)
    1140                 : {
    1141             656 :   nsNSSShutDownPreventionLock locker;
    1142                 :   nsresult rv;
    1143                 : 
    1144                 :   bool crlDownloading;
    1145             328 :   rv = pref->GetBoolPref("security.CRL_download.enabled", &crlDownloading);
    1146             328 :   if (NS_FAILED(rv))
    1147             328 :     crlDownloading = CRL_DOWNLOAD_DEFAULT;
    1148                 :   
    1149                 :   PRInt32 ocspEnabled;
    1150             328 :   rv = pref->GetIntPref("security.OCSP.enabled", &ocspEnabled);
    1151                 :   // 0 = disabled, 1 = enabled, 
    1152                 :   // 2 = enabled with given default responder
    1153             328 :   if (NS_FAILED(rv))
    1154               0 :     ocspEnabled = OCSP_ENABLED_DEFAULT;
    1155                 : 
    1156                 :   bool ocspRequired;
    1157             328 :   rv = pref->GetBoolPref("security.OCSP.require", &ocspRequired);
    1158             328 :   if (NS_FAILED(rv))
    1159               0 :     ocspRequired = OCSP_REQUIRED_DEFAULT;
    1160                 : 
    1161                 :   bool anyFreshRequired;
    1162             328 :   rv = pref->GetBoolPref("security.fresh_revocation_info.require", &anyFreshRequired);
    1163             328 :   if (NS_FAILED(rv))
    1164             328 :     anyFreshRequired = FRESH_REVOCATION_REQUIRED_DEFAULT;
    1165                 :   
    1166                 :   bool aiaDownloadEnabled;
    1167             328 :   rv = pref->GetBoolPref("security.missing_cert_download.enabled", &aiaDownloadEnabled);
    1168             328 :   if (NS_FAILED(rv))
    1169             328 :     aiaDownloadEnabled = MISSING_CERT_DOWNLOAD_DEFAULT;
    1170                 : 
    1171             656 :   nsCString firstNetworkRevo;
    1172             328 :   rv = pref->GetCharPref("security.first_network_revocation_method", getter_Copies(firstNetworkRevo));
    1173             328 :   if (NS_FAILED(rv))
    1174             328 :     firstNetworkRevo = FIRST_REVO_METHOD_DEFAULT;
    1175                 :   
    1176             328 :   setNonPkixOcspEnabled(ocspEnabled, pref);
    1177                 :   
    1178                 :   CERT_SetOCSPFailureMode( ocspRequired ?
    1179                 :                            ocspMode_FailureIsVerificationFailure
    1180             328 :                            : ocspMode_FailureIsNotAVerificationFailure);
    1181                 : 
    1182             656 :   nsRefPtr<nsCERTValInParamWrapper> newCVIN = new nsCERTValInParamWrapper;
    1183             328 :   if (NS_SUCCEEDED(newCVIN->Construct(
    1184                 :       aiaDownloadEnabled ? 
    1185                 :         nsCERTValInParamWrapper::missing_cert_download_on : nsCERTValInParamWrapper::missing_cert_download_off,
    1186                 :       crlDownloading ?
    1187                 :         nsCERTValInParamWrapper::crl_download_allowed : nsCERTValInParamWrapper::crl_local_only,
    1188                 :       ocspEnabled ? 
    1189                 :         nsCERTValInParamWrapper::ocsp_on : nsCERTValInParamWrapper::ocsp_off,
    1190                 :       ocspRequired ? 
    1191                 :         nsCERTValInParamWrapper::ocsp_strict : nsCERTValInParamWrapper::ocsp_relaxed,
    1192                 :       anyFreshRequired ?
    1193                 :         nsCERTValInParamWrapper::any_revo_strict : nsCERTValInParamWrapper::any_revo_relaxed,
    1194                 :       firstNetworkRevo.get()))) {
    1195                 :     // Swap to new defaults, and will cause the old defaults to be released,
    1196                 :     // as soon as any concurrent use of the old default objects has finished.
    1197             328 :     mDefaultCERTValInParam = newCVIN;
    1198                 :   }
    1199                 : 
    1200                 :   /*
    1201                 :     * The new defaults might change the validity of already established SSL sessions,
    1202                 :     * let's not reuse them.
    1203                 :     */
    1204             328 :   SSL_ClearSessionCache();
    1205             328 : }
    1206                 : 
    1207                 : NS_IMETHODIMP
    1208               0 : nsNSSComponent::SkipOcsp()
    1209                 : {
    1210               0 :   nsNSSShutDownPreventionLock locker;
    1211               0 :   CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
    1212                 : 
    1213               0 :   SECStatus rv = CERT_DisableOCSPChecking(certdb);
    1214               0 :   return (rv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
    1215                 : }
    1216                 : 
    1217                 : NS_IMETHODIMP
    1218               0 : nsNSSComponent::SkipOcspOff()
    1219                 : {
    1220               0 :   nsNSSShutDownPreventionLock locker;
    1221                 :   PRInt32 ocspEnabled;
    1222               0 :   if (NS_FAILED(mPrefBranch->GetIntPref("security.OCSP.enabled", &ocspEnabled)))
    1223               0 :     ocspEnabled = OCSP_ENABLED_DEFAULT;
    1224                 :   // 0 = disabled, 1 = enabled, 
    1225                 :   // 2 = enabled with given default responder
    1226                 :   
    1227               0 :   setNonPkixOcspEnabled(ocspEnabled, mPrefBranch);
    1228                 : 
    1229               0 :   if (ocspEnabled)
    1230               0 :     SSL_ClearSessionCache();
    1231                 : 
    1232               0 :   return NS_OK;
    1233                 : }
    1234                 : 
    1235                 : nsresult
    1236               0 : nsNSSComponent::PostCRLImportEvent(const nsCSubstring &urlString,
    1237                 :                                    nsIStreamListener *listener)
    1238                 : {
    1239                 :   //Create the event
    1240               0 :   nsCOMPtr<nsIRunnable> event = new CRLDownloadEvent(urlString, listener);
    1241               0 :   if (!event)
    1242               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1243                 : 
    1244                 :   //Get a handle to the ui thread
    1245               0 :   return NS_DispatchToMainThread(event);
    1246                 : }
    1247                 : 
    1248                 : nsresult
    1249               0 : nsNSSComponent::DownloadCRLDirectly(nsAutoString url, nsAutoString key)
    1250                 : {
    1251                 :   //This api is meant to support direct interactive update of crl from the crl manager
    1252                 :   //or other such ui.
    1253                 :   nsCOMPtr<nsIStreamListener> listener =
    1254               0 :       new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL);
    1255                 :   
    1256               0 :   NS_ConvertUTF16toUTF8 url8(url);
    1257               0 :   return PostCRLImportEvent(url8, listener);
    1258                 : }
    1259                 : 
    1260               0 : nsresult nsNSSComponent::DownloadCrlSilently()
    1261                 : {
    1262                 :   //Add this attempt to the hashtable
    1263               0 :   nsStringKey hashKey(mCrlUpdateKey.get());
    1264               0 :   crlsScheduledForDownload->Put(&hashKey,(void *)nsnull);
    1265                 :     
    1266                 :   //Set up the download handler
    1267                 :   nsRefPtr<PSMContentDownloader> psmDownloader =
    1268               0 :       new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL);
    1269               0 :   psmDownloader->setSilentDownload(true);
    1270               0 :   psmDownloader->setCrlAutodownloadKey(mCrlUpdateKey);
    1271                 :   
    1272                 :   //Now get the url string
    1273               0 :   NS_ConvertUTF16toUTF8 url8(mDownloadURL);
    1274               0 :   return PostCRLImportEvent(url8, psmDownloader);
    1275                 : }
    1276                 : 
    1277             328 : nsresult nsNSSComponent::getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key)
    1278                 : {
    1279             328 :   const char *updateEnabledPref = CRL_AUTOUPDATE_ENABLED_PREF;
    1280             328 :   const char *updateTimePref = CRL_AUTOUPDATE_TIME_PREF;
    1281             328 :   const char *updateURLPref = CRL_AUTOUPDATE_URL_PREF;
    1282                 :   char **allCrlsToBeUpdated;
    1283                 :   PRUint32 noOfCrls;
    1284             328 :   PRTime nearestUpdateTime = 0;
    1285             656 :   nsAutoString crlKey;
    1286                 :   char *tempUrl;
    1287                 :   nsresult rv;
    1288                 :   
    1289             656 :   nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID,&rv);
    1290             328 :   if(NS_FAILED(rv)){
    1291               0 :     return rv;
    1292                 :   }
    1293                 : 
    1294             328 :   rv = pref->GetChildList(updateEnabledPref, &noOfCrls, &allCrlsToBeUpdated);
    1295             328 :   if ( (NS_FAILED(rv)) || (noOfCrls==0) ){
    1296             328 :     return NS_ERROR_FAILURE;
    1297                 :   }
    1298                 : 
    1299               0 :   for(PRUint32 i=0;i<noOfCrls;i++) {
    1300                 :     //First check if update pref is enabled for this crl
    1301               0 :     bool autoUpdateEnabled = false;
    1302               0 :     rv = pref->GetBoolPref(*(allCrlsToBeUpdated+i), &autoUpdateEnabled);
    1303               0 :     if (NS_FAILED(rv) || !autoUpdateEnabled) {
    1304               0 :       continue;
    1305                 :     }
    1306                 : 
    1307               0 :     nsAutoString tempCrlKey;
    1308                 : 
    1309                 :     //Now, generate the crl key. Same key would be used as hashkey as well
    1310               0 :     nsCAutoString enabledPrefCString(*(allCrlsToBeUpdated+i));
    1311               0 :     enabledPrefCString.ReplaceSubstring(updateEnabledPref,".");
    1312               0 :     tempCrlKey.AssignWithConversion(enabledPrefCString.get());
    1313                 :       
    1314                 :     //Check if this crl has already been scheduled. Its presence in the hashtable
    1315                 :     //implies that it has been scheduled already this client session, and
    1316                 :     //is either in the process of being downloaded, or its download failed
    1317                 :     //for some reason. In the second case, we will not retry in the current client session
    1318               0 :     nsStringKey hashKey(tempCrlKey.get());
    1319               0 :     if(crlsScheduledForDownload->Exists(&hashKey)){
    1320               0 :       continue;
    1321                 :     }
    1322                 : 
    1323                 :     char *tempTimeString;
    1324                 :     PRTime tempTime;
    1325               0 :     nsCAutoString timingPrefCString(updateTimePref);
    1326               0 :     timingPrefCString.AppendWithConversion(tempCrlKey);
    1327               0 :     rv = pref->GetCharPref(timingPrefCString.get(), &tempTimeString);
    1328               0 :     if (NS_FAILED(rv)){
    1329               0 :       continue;
    1330                 :     }
    1331               0 :     rv = PR_ParseTimeString(tempTimeString,true, &tempTime);
    1332               0 :     nsMemory::Free(tempTimeString);
    1333               0 :     if (NS_FAILED(rv)){
    1334               0 :       continue;
    1335                 :     }
    1336                 : 
    1337               0 :     if(nearestUpdateTime == 0 || tempTime < nearestUpdateTime){
    1338               0 :       nsCAutoString urlPrefCString(updateURLPref);
    1339               0 :       urlPrefCString.AppendWithConversion(tempCrlKey);
    1340               0 :       rv = pref->GetCharPref(urlPrefCString.get(), &tempUrl);
    1341               0 :       if (NS_FAILED(rv) || (!tempUrl)){
    1342               0 :         continue;
    1343                 :       }
    1344               0 :       nearestUpdateTime = tempTime;
    1345               0 :       crlKey = tempCrlKey;
    1346                 :     }
    1347                 :   }
    1348                 : 
    1349               0 :   if(noOfCrls > 0)
    1350               0 :     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(noOfCrls, allCrlsToBeUpdated);
    1351                 : 
    1352               0 :   if(nearestUpdateTime > 0){
    1353               0 :     *time = nearestUpdateTime;
    1354               0 :     url->AssignWithConversion((const char *)tempUrl);
    1355               0 :     nsMemory::Free(tempUrl);
    1356               0 :     *key = crlKey;
    1357               0 :     rv = NS_OK;
    1358                 :   } else{
    1359               0 :     rv = NS_ERROR_FAILURE;
    1360                 :   }
    1361                 : 
    1362               0 :   return rv;
    1363                 : }
    1364                 : 
    1365                 : NS_IMETHODIMP
    1366               0 : nsNSSComponent::Notify(nsITimer *timer)
    1367                 : {
    1368                 :   //Timer has fired. So set the flag accordingly
    1369                 :   {
    1370               0 :     MutexAutoLock lock(mCrlTimerLock);
    1371               0 :     crlDownloadTimerOn = false;
    1372                 :   }
    1373                 : 
    1374                 :   //First, handle this download
    1375               0 :   DownloadCrlSilently();
    1376                 : 
    1377                 :   //Dont Worry if successful or not
    1378                 :   //Set the next timer
    1379               0 :   DefineNextTimer();
    1380               0 :   return NS_OK;
    1381                 : }
    1382                 : 
    1383                 : nsresult
    1384               0 : nsNSSComponent::RemoveCrlFromList(nsAutoString key)
    1385                 : {
    1386               0 :   nsStringKey hashKey(key.get());
    1387               0 :   if(crlsScheduledForDownload->Exists(&hashKey)){
    1388               0 :     crlsScheduledForDownload->Remove(&hashKey);
    1389                 :   }
    1390               0 :   return NS_OK;
    1391                 : }
    1392                 : 
    1393                 : nsresult
    1394             328 : nsNSSComponent::DefineNextTimer()
    1395                 : {
    1396                 :   PRTime nextFiring;
    1397             328 :   PRTime now = PR_Now();
    1398                 :   PRUint64 diff;
    1399                 :   PRUint32 interval;
    1400             328 :   PRUint32 primaryDelay = CRL_AUTOUPDATE_DEFAULT_DELAY;
    1401                 :   nsresult rv;
    1402                 : 
    1403             328 :   if(!mTimer){
    1404               0 :     mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
    1405               0 :     if(NS_FAILED(rv))
    1406               0 :       return rv;
    1407                 :   }
    1408                 : 
    1409                 :   //If some timer is already running, cancel it. Thus, the request that came last,
    1410                 :   //wins. This would ensure that in no way we end up setting two different timers
    1411                 :   //This part should be synchronized because this function might be called from separate
    1412                 :   //threads
    1413                 : 
    1414             656 :   MutexAutoLock lock(mCrlTimerLock);
    1415                 : 
    1416             328 :   if (crlDownloadTimerOn) {
    1417               0 :     mTimer->Cancel();
    1418                 :   }
    1419                 : 
    1420             328 :   rv = getParamsForNextCrlToDownload(&mDownloadURL, &nextFiring, &mCrlUpdateKey);
    1421                 :   //If there are no more crls to be updated any time in future
    1422             328 :   if(NS_FAILED(rv)){
    1423                 :     // Return - no error - just implies nothing to schedule
    1424             328 :     return NS_OK;
    1425                 :   }
    1426                 :      
    1427                 :   //Define the firing interval, from NOW
    1428               0 :   if ( now < nextFiring) {
    1429               0 :     LL_SUB(diff,nextFiring,now);
    1430               0 :     LL_L2UI(interval, diff);
    1431                 :     //Now, we are doing 32 operations - so, don't need LL_ functions...
    1432               0 :     interval = interval/PR_USEC_PER_MSEC;
    1433                 :   }else {
    1434               0 :     interval = primaryDelay;
    1435                 :   }
    1436                 :   
    1437               0 :   mTimer->InitWithCallback(static_cast<nsITimerCallback*>(this), 
    1438                 :                            interval,
    1439               0 :                            nsITimer::TYPE_ONE_SHOT);
    1440               0 :   crlDownloadTimerOn = true;
    1441                 : 
    1442               0 :   return NS_OK;
    1443                 : }
    1444                 : 
    1445                 : //Note that the StopCRLUpdateTimer and InitializeCRLUpdateTimer functions should never be called
    1446                 : //simultaneously from diff threads - they are NOT threadsafe. But, since there is no chance of 
    1447                 : //that happening, there is not much benefit it trying to make it so at this point
    1448                 : nsresult
    1449             315 : nsNSSComponent::StopCRLUpdateTimer()
    1450                 : {
    1451                 :   
    1452                 :   //If it is at all running. 
    1453             315 :   if (mUpdateTimerInitialized) {
    1454             311 :     if(crlsScheduledForDownload != nsnull){
    1455             311 :       crlsScheduledForDownload->Reset();
    1456             311 :       delete crlsScheduledForDownload;
    1457             311 :       crlsScheduledForDownload = nsnull;
    1458                 :     }
    1459                 :     {
    1460             622 :       MutexAutoLock lock(mCrlTimerLock);
    1461             311 :       if (crlDownloadTimerOn) {
    1462               0 :         mTimer->Cancel();
    1463                 :       }
    1464             311 :       crlDownloadTimerOn = false;
    1465                 :     }
    1466             311 :     mUpdateTimerInitialized = false;
    1467                 :   }
    1468                 : 
    1469             315 :   return NS_OK;
    1470                 : }
    1471                 : 
    1472                 : nsresult
    1473             328 : nsNSSComponent::InitializeCRLUpdateTimer()
    1474                 : {
    1475                 :   nsresult rv;
    1476                 :     
    1477                 :   //First check if this is already initialized. Then we stop it.
    1478             328 :   if (!mUpdateTimerInitialized) {
    1479             328 :     mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
    1480             328 :     if(NS_FAILED(rv)){
    1481               0 :       return rv;
    1482                 :     }
    1483             328 :     crlsScheduledForDownload = new nsHashtable(16, true);
    1484             328 :     DefineNextTimer();
    1485             328 :     mUpdateTimerInitialized = true;  
    1486                 :   } 
    1487                 : 
    1488             328 :   return NS_OK;
    1489                 : }
    1490                 : 
    1491                 : #ifdef XP_MACOSX
    1492                 : void
    1493                 : nsNSSComponent::TryCFM2MachOMigration(nsIFile *cfmPath, nsIFile *machoPath)
    1494                 : {
    1495                 :   // We will modify the parameters.
    1496                 :   //
    1497                 :   // If neither cert7.db, cert8.db, key3.db, are available, 
    1498                 :   // copy from filenames that were used in the old days
    1499                 :   // test for key3.db first, since a new profile might only contain cert8.db, 
    1500                 :   // but not cert7.db - this optimizes number of tests
    1501                 : 
    1502                 :   NS_NAMED_LITERAL_CSTRING(cstr_key3db, "key3.db");
    1503                 :   NS_NAMED_LITERAL_CSTRING(cstr_cert7db, "cert7.db");
    1504                 :   NS_NAMED_LITERAL_CSTRING(cstr_cert8db, "cert8.db");
    1505                 :   NS_NAMED_LITERAL_CSTRING(cstr_keydatabase3, "Key Database3");
    1506                 :   NS_NAMED_LITERAL_CSTRING(cstr_certificate7, "Certificates7");
    1507                 :   NS_NAMED_LITERAL_CSTRING(cstr_certificate8, "Certificates8");
    1508                 : 
    1509                 :   bool bExists;
    1510                 :   nsresult rv;
    1511                 : 
    1512                 :   nsCOMPtr<nsIFile> macho_key3db;
    1513                 :   rv = machoPath->Clone(getter_AddRefs(macho_key3db));
    1514                 :   if (NS_FAILED(rv)) {
    1515                 :     return;
    1516                 :   }
    1517                 : 
    1518                 :   macho_key3db->AppendNative(cstr_key3db);
    1519                 :   rv = macho_key3db->Exists(&bExists);
    1520                 :   if (NS_FAILED(rv) || bExists) {
    1521                 :     return;
    1522                 :   }
    1523                 : 
    1524                 :   nsCOMPtr<nsIFile> macho_cert7db;
    1525                 :   rv = machoPath->Clone(getter_AddRefs(macho_cert7db));
    1526                 :   if (NS_FAILED(rv)) {
    1527                 :     return;
    1528                 :   }
    1529                 : 
    1530                 :   macho_cert7db->AppendNative(cstr_cert7db);
    1531                 :   rv = macho_cert7db->Exists(&bExists);
    1532                 :   if (NS_FAILED(rv) || bExists) {
    1533                 :     return;
    1534                 :   }
    1535                 : 
    1536                 :   nsCOMPtr<nsIFile> macho_cert8db;
    1537                 :   rv = machoPath->Clone(getter_AddRefs(macho_cert8db));
    1538                 :   if (NS_FAILED(rv)) {
    1539                 :     return;
    1540                 :   }
    1541                 : 
    1542                 :   macho_cert8db->AppendNative(cstr_cert8db);
    1543                 :   rv = macho_cert7db->Exists(&bExists);
    1544                 :   if (NS_FAILED(rv) || bExists) {
    1545                 :     return;
    1546                 :   }
    1547                 : 
    1548                 :   // None of the new files exist. Try to copy any available old files.
    1549                 : 
    1550                 :   nsCOMPtr<nsIFile> cfm_key3;
    1551                 :   rv = cfmPath->Clone(getter_AddRefs(cfm_key3));
    1552                 :   if (NS_FAILED(rv)) {
    1553                 :     return;
    1554                 :   }
    1555                 : 
    1556                 :   cfm_key3->AppendNative(cstr_keydatabase3);
    1557                 :   rv = cfm_key3->Exists(&bExists);
    1558                 :   if (NS_FAILED(rv)) {
    1559                 :     return;
    1560                 :   }
    1561                 : 
    1562                 :   if (bExists) {
    1563                 :     cfm_key3->CopyToFollowingLinksNative(machoPath, cstr_key3db);
    1564                 :   }
    1565                 : 
    1566                 :   nsCOMPtr<nsIFile> cfm_cert7;
    1567                 :   rv = cfmPath->Clone(getter_AddRefs(cfm_cert7));
    1568                 :   if (NS_FAILED(rv)) {
    1569                 :     return;
    1570                 :   }
    1571                 : 
    1572                 :   cfm_cert7->AppendNative(cstr_certificate7);
    1573                 :   rv = cfm_cert7->Exists(&bExists);
    1574                 :   if (NS_FAILED(rv)) {
    1575                 :     return;
    1576                 :   }
    1577                 : 
    1578                 :   if (bExists) {
    1579                 :     cfm_cert7->CopyToFollowingLinksNative(machoPath, cstr_cert7db);
    1580                 :   }
    1581                 : 
    1582                 :   nsCOMPtr<nsIFile> cfm_cert8;
    1583                 :   rv = cfmPath->Clone(getter_AddRefs(cfm_cert8));
    1584                 :   if (NS_FAILED(rv)) {
    1585                 :     return;
    1586                 :   }
    1587                 : 
    1588                 :   cfm_cert8->AppendNative(cstr_certificate8);
    1589                 :   rv = cfm_cert8->Exists(&bExists);
    1590                 :   if (NS_FAILED(rv)) {
    1591                 :     return;
    1592                 :   }
    1593                 : 
    1594                 :   if (bExists) {
    1595                 :     cfm_cert8->CopyToFollowingLinksNative(machoPath, cstr_cert8db);
    1596                 :   }
    1597                 : }
    1598                 : #endif
    1599                 : 
    1600             328 : static void configureMD5(bool enabled)
    1601                 : {
    1602             328 :   if (enabled) { // set flags
    1603                 :     NSS_SetAlgorithmPolicy(SEC_OID_MD5, 
    1604             328 :         NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
    1605                 :     NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
    1606             328 :         NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
    1607                 :     NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
    1608             328 :         NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
    1609                 :   }
    1610                 :   else { // clear flags
    1611                 :     NSS_SetAlgorithmPolicy(SEC_OID_MD5,
    1612               0 :         0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
    1613                 :     NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
    1614               0 :         0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
    1615                 :     NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
    1616               0 :         0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
    1617                 :   }
    1618             328 : }
    1619                 : 
    1620                 : nsresult
    1621             328 : nsNSSComponent::InitializeNSS(bool showWarningBox)
    1622                 : {
    1623                 :   // Can be called both during init and profile change.
    1624                 :   // Needs mutex protection.
    1625                 : 
    1626             328 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::InitializeNSS\n"));
    1627                 : 
    1628                 :   // If we ever run into this assertion, we must update the values
    1629                 :   // in nsINSSErrorsService.idl
    1630                 :   PR_STATIC_ASSERT(nsINSSErrorsService::NSS_SEC_ERROR_BASE == SEC_ERROR_BASE
    1631                 :                    && nsINSSErrorsService::NSS_SEC_ERROR_LIMIT == SEC_ERROR_LIMIT
    1632                 :                    && nsINSSErrorsService::NSS_SSL_ERROR_BASE == SSL_ERROR_BASE
    1633                 :                    && nsINSSErrorsService::NSS_SSL_ERROR_LIMIT == SSL_ERROR_LIMIT);
    1634                 : 
    1635                 :   // variables used for flow control within this function
    1636                 : 
    1637                 :   enum { problem_none, problem_no_rw, problem_no_security_at_all }
    1638             328 :     which_nss_problem = problem_none;
    1639                 : 
    1640                 :   {
    1641             656 :     MutexAutoLock lock(mutex);
    1642                 : 
    1643                 :     // Init phase 1, prepare own variables used for NSS
    1644                 : 
    1645             328 :     if (mNSSInitialized) {
    1646               0 :       PR_ASSERT(!"Trying to initialize NSS twice"); // We should never try to 
    1647                 :                                                     // initialize NSS more than
    1648                 :                                                     // once in a process.
    1649               0 :       return NS_ERROR_FAILURE;
    1650                 :     }
    1651                 :     
    1652                 :     nsresult rv;
    1653             656 :     nsCAutoString profileStr;
    1654             656 :     nsCOMPtr<nsIFile> profilePath;
    1655                 : 
    1656                 :     rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
    1657             328 :                                 getter_AddRefs(profilePath));
    1658             328 :     if (NS_FAILED(rv)) {
    1659              15 :       PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to get profile directory\n"));
    1660              15 :       ConfigureInternalPKCS11Token();
    1661              15 :       SECStatus init_rv = NSS_NoDB_Init(NULL);
    1662              15 :       if (init_rv != SECSuccess) {
    1663               0 :         nsPSMInitPanic::SetPanic();
    1664               0 :         return NS_ERROR_NOT_AVAILABLE;
    1665                 :       }
    1666                 :     }
    1667                 :     else
    1668                 :     {
    1669                 : 
    1670                 :   // XP_MAC == CFM
    1671                 :   // XP_MACOSX == MachO
    1672                 : 
    1673                 :   #if defined(XP_MAC) && defined(XP_MACOSX)
    1674                 :   #error "This code assumes XP_MAC and XP_MACOSX will never be defined at the same time"
    1675                 :   #endif
    1676                 : 
    1677                 :   #if defined(XP_MAC) || defined(XP_MACOSX)
    1678                 :     // On Mac CFM we place all NSS DBs in the Security
    1679                 :     // Folder in the profile directory.
    1680                 :     nsCOMPtr<nsIFile> cfmSecurityPath;
    1681                 :     cfmSecurityPath = profilePath; // alias for easier code reading
    1682                 :     cfmSecurityPath->AppendNative(NS_LITERAL_CSTRING("Security"));
    1683                 :   #endif
    1684                 : 
    1685                 :   #if defined(XP_MAC)
    1686                 :     // on CFM, cfmSecurityPath and profilePath point to the same oject
    1687                 :     profilePath->Create(nsIFile::DIRECTORY_TYPE, 0); //This is for Mac, don't worry about
    1688                 :                                                      //permissions.
    1689                 :   #elif defined(XP_MACOSX)
    1690                 :     // On MachO, we need to access both directories,
    1691                 :     // and therefore need separate nsIFile instances.
    1692                 :     // Keep cfmSecurityPath instance, obtain new instance for MachO profilePath.
    1693                 :     rv = cfmSecurityPath->GetParent(getter_AddRefs(profilePath));
    1694                 :     if (NS_FAILED(rv)) {
    1695                 :       nsPSMInitPanic::SetPanic();
    1696                 :       return rv;
    1697                 :     }
    1698                 :   #endif
    1699                 : 
    1700             313 :     const char *dbdir_override = getenv("MOZPSM_NSSDBDIR_OVERRIDE");
    1701             313 :     if (dbdir_override && strlen(dbdir_override)) {
    1702               0 :       profileStr = dbdir_override;
    1703                 :     }
    1704                 :     else {
    1705                 :   #if defined(XP_WIN)
    1706                 :       // Native path will drop Unicode characters that cannot be mapped to system's
    1707                 :       // codepage, using short (canonical) path as workaround.
    1708                 :       nsCOMPtr<nsILocalFileWin> profilePathWin(do_QueryInterface(profilePath, &rv));
    1709                 :       if (profilePathWin)
    1710                 :         rv = profilePathWin->GetNativeCanonicalPath(profileStr);
    1711                 :   #else
    1712             313 :       rv = profilePath->GetNativePath(profileStr);
    1713                 :   #endif
    1714             313 :       if (NS_FAILED(rv)) {
    1715               0 :         nsPSMInitPanic::SetPanic();
    1716               0 :         return rv;
    1717                 :       }
    1718                 :     }
    1719                 : 
    1720                 :     hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare,
    1721             313 :       certHashtable_valueCompare, 0, 0 );
    1722                 : 
    1723                 :   #if defined(XP_MACOSX)
    1724                 :     // function may modify the parameters
    1725                 :     // ignore return code from conversion, we continue anyway
    1726                 :     TryCFM2MachOMigration(cfmSecurityPath, profilePath);
    1727                 :   #endif
    1728                 : 
    1729             313 :     rv = mPrefBranch->GetBoolPref("security.use_libpkix_verification", &globalConstFlagUsePKIXVerification);
    1730             313 :     if (NS_FAILED(rv))
    1731             313 :       globalConstFlagUsePKIXVerification = USE_NSS_LIBPKIX_DEFAULT;
    1732                 : 
    1733             313 :     bool supress_warning_preference = false;
    1734             313 :     rv = mPrefBranch->GetBoolPref("security.suppress_nss_rw_impossible_warning", &supress_warning_preference);
    1735                 : 
    1736             313 :     if (NS_FAILED(rv)) {
    1737             313 :       supress_warning_preference = false;
    1738                 :     }
    1739                 : 
    1740                 :     // init phase 2, init calls to NSS library
    1741                 : 
    1742             313 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization beginning\n"));
    1743                 : 
    1744                 :     // The call to ConfigureInternalPKCS11Token needs to be done before NSS is initialized, 
    1745                 :     // but affects only static data.
    1746                 :     // If we could assume i18n will not change between profiles, one call per application
    1747                 :     // run were sufficient. As I can't predict what happens in the future, let's repeat
    1748                 :     // this call for every re-init of NSS.
    1749                 : 
    1750             313 :     ConfigureInternalPKCS11Token();
    1751                 : 
    1752                 :     // The NSS_INIT_NOROOTINIT flag turns off the loading of the root certs
    1753                 :     // module by NSS_Initialize because we will load it in InstallLoadableRoots
    1754                 :     // later.  It also allows us to work around a bug in the system NSS in
    1755                 :     // Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as
    1756                 :     // "/usr/lib/nss/libnssckbi.so".
    1757             313 :     PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
    1758                 :     SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
    1759             313 :                                          SECMOD_DB, init_flags);
    1760                 : 
    1761             313 :     if (init_rv != SECSuccess) {
    1762               0 :       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init NSS r/w in %s\n", profileStr.get()));
    1763                 : 
    1764               0 :       if (supress_warning_preference) {
    1765               0 :         which_nss_problem = problem_none;
    1766                 :       }
    1767                 :       else {
    1768               0 :         which_nss_problem = problem_no_rw;
    1769                 :       }
    1770                 : 
    1771                 :       // try to init r/o
    1772               0 :       init_flags |= NSS_INIT_READONLY;
    1773                 :       init_rv = ::NSS_Initialize(profileStr.get(), "", "",
    1774               0 :                                  SECMOD_DB, init_flags);
    1775                 : 
    1776               0 :       if (init_rv != SECSuccess) {
    1777               0 :         PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init in r/o either\n"));
    1778               0 :         which_nss_problem = problem_no_security_at_all;
    1779                 : 
    1780               0 :         init_rv = NSS_NoDB_Init(profileStr.get());
    1781               0 :         if (init_rv != SECSuccess) {
    1782               0 :           nsPSMInitPanic::SetPanic();
    1783               0 :           return NS_ERROR_NOT_AVAILABLE;
    1784                 :         }
    1785                 :       }
    1786                 :     } // have profile dir
    1787                 :     } // lock
    1788                 : 
    1789                 :     // init phase 3, only if phase 2 was successful
    1790                 : 
    1791             328 :     if (problem_no_security_at_all != which_nss_problem) {
    1792                 : 
    1793             328 :       mNSSInitialized = true;
    1794                 : 
    1795             328 :       ::NSS_SetDomesticPolicy();
    1796                 :       //  SSL_EnableCipher(SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED);
    1797                 :       //  SSL_EnableCipher(SSL_RSA_WITH_NULL_SHA, SSL_ALLOWED);
    1798                 : 
    1799             328 :       PK11_SetPasswordFunc(PK11PasswordPrompt);
    1800                 : 
    1801                 :       // Register an observer so we can inform NSS when these prefs change
    1802             328 :       mPrefBranch->AddObserver("security.", this, false);
    1803                 : 
    1804             328 :       SSL_OptionSetDefault(SSL_ENABLE_SSL2, false);
    1805             328 :       SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, false);
    1806                 :       bool enabled;
    1807             328 :       mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
    1808             328 :       SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
    1809             328 :       mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
    1810             328 :       SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
    1811             328 :       mPrefBranch->GetBoolPref("security.enable_md5_signatures", &enabled);
    1812             328 :       configureMD5(enabled);
    1813                 : 
    1814                 :       // Configure TLS session tickets
    1815             328 :       mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
    1816             328 :       SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
    1817                 : 
    1818             328 :       mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
    1819             328 :       SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
    1820                 : 
    1821             328 :       mPrefBranch->GetBoolPref(
    1822                 :         "security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", 
    1823             328 :         &enabled);
    1824                 :       SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, 
    1825             328 :         enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
    1826                 : 
    1827                 : #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
    1828             328 :       mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
    1829             328 :       SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
    1830                 : #endif
    1831                 : 
    1832                 :       // Disable any ciphers that NSS might have enabled by default
    1833           18696 :       for (PRUint16 i = 0; i < SSL_NumImplementedCiphers; ++i)
    1834                 :       {
    1835           18368 :         PRUint16 cipher_id = SSL_ImplementedCiphers[i];
    1836           18368 :         SSL_CipherPrefSetDefault(cipher_id, false);
    1837                 :       }
    1838                 : 
    1839                 :       // Now only set SSL/TLS ciphers we knew about at compile time
    1840           16400 :       for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
    1841           16072 :         rv = mPrefBranch->GetBoolPref(cp->pref, &enabled);
    1842           16072 :         if (NS_FAILED(rv))
    1843               0 :           enabled = false;
    1844                 : 
    1845           16072 :         SSL_CipherPrefSetDefault(cp->id, enabled);
    1846                 :       }
    1847                 : 
    1848                 :       // Enable ciphers for PKCS#12
    1849             328 :       SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
    1850             328 :       SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
    1851             328 :       SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
    1852             328 :       SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
    1853             328 :       SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
    1854             328 :       SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
    1855             328 :       SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
    1856             328 :       PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
    1857                 : 
    1858                 :       // dynamic options from prefs
    1859             328 :       setValidationOptions(mPrefBranch);
    1860                 : 
    1861                 :       // static validation options for usagesarray - do not hit the network
    1862             328 :       mDefaultCERTValInParamLocalOnly = new nsCERTValInParamWrapper;
    1863                 :       rv = mDefaultCERTValInParamLocalOnly->Construct(
    1864                 :           nsCERTValInParamWrapper::missing_cert_download_off,
    1865                 :           nsCERTValInParamWrapper::crl_local_only,
    1866                 :           nsCERTValInParamWrapper::ocsp_off,
    1867                 :           nsCERTValInParamWrapper::ocsp_relaxed,
    1868                 :           nsCERTValInParamWrapper::any_revo_relaxed,
    1869             328 :           FIRST_REVO_METHOD_DEFAULT);
    1870             328 :       if (NS_FAILED(rv)) {
    1871               0 :         nsPSMInitPanic::SetPanic();
    1872               0 :         return rv;
    1873                 :       }
    1874                 :       
    1875             328 :       RegisterMyOCSPAIAInfoCallback();
    1876                 : 
    1877             328 :       mHttpForNSS.initTable();
    1878             328 :       mHttpForNSS.registerHttpClient();
    1879                 : 
    1880             328 :       InstallLoadableRoots();
    1881                 : 
    1882             328 :       LaunchSmartCardThreads();
    1883                 : 
    1884             328 :       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization done\n"));
    1885                 :     }
    1886                 :   }
    1887                 : 
    1888             328 :   if (problem_none != which_nss_problem) {
    1889               0 :     nsPSMInitPanic::SetPanic();
    1890                 : 
    1891               0 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS problem, trying to bring up GUI error message\n"));
    1892                 : 
    1893                 :     // We might want to use different messages, depending on what failed.
    1894                 :     // For now, let's use the same message.
    1895               0 :     if (showWarningBox) {
    1896               0 :       ShowAlertFromStringBundle("NSSInitProblemX");
    1897                 :     }
    1898                 :   }
    1899                 : 
    1900             328 :   return NS_OK;
    1901                 : }
    1902                 : 
    1903                 : nsresult
    1904             639 : nsNSSComponent::ShutdownNSS()
    1905                 : {
    1906                 :   // Can be called both during init and profile change,
    1907                 :   // needs mutex protection.
    1908                 :   
    1909             639 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ShutdownNSS\n"));
    1910                 : 
    1911            1278 :   MutexAutoLock lock(mutex);
    1912             639 :   nsresult rv = NS_OK;
    1913                 : 
    1914             639 :   if (hashTableCerts) {
    1915             313 :     PL_HashTableEnumerateEntries(hashTableCerts, certHashtable_clearEntry, 0);
    1916             313 :     PL_HashTableDestroy(hashTableCerts);
    1917             313 :     hashTableCerts = nsnull;
    1918                 :   }
    1919                 : 
    1920             639 :   if (mNSSInitialized) {
    1921             328 :     mNSSInitialized = false;
    1922                 : 
    1923             328 :     PK11_SetPasswordFunc((PK11PasswordFunc)nsnull);
    1924             328 :     mHttpForNSS.unregisterHttpClient();
    1925             328 :     UnregisterMyOCSPAIAInfoCallback();
    1926                 : 
    1927             328 :     if (mPrefBranch) {
    1928             328 :       mPrefBranch->RemoveObserver("security.", this);
    1929                 :     }
    1930                 : 
    1931             328 :     ShutdownSmartCardThreads();
    1932             328 :     SSL_ClearSessionCache();
    1933             328 :     if (mClientAuthRememberService) {
    1934             328 :       mClientAuthRememberService->ClearRememberedDecisions();
    1935                 :     }
    1936             328 :     UnloadLoadableRoots();
    1937             328 :     CleanupIdentityInfo();
    1938             328 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("evaporating psm resources\n"));
    1939             328 :     mShutdownObjectList->evaporateAllNSSResources();
    1940             328 :     EnsureNSSInitialized(nssShutdown);
    1941             328 :     if (SECSuccess != ::NSS_Shutdown()) {
    1942              36 :       PR_LOG(gPIPNSSLog, PR_LOG_ALWAYS, ("NSS SHUTDOWN FAILURE\n"));
    1943              36 :       rv = NS_ERROR_FAILURE;
    1944                 :     }
    1945                 :     else {
    1946             292 :       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS shutdown =====>> OK <<=====\n"));
    1947                 :     }
    1948                 :   }
    1949                 : 
    1950             639 :   return rv;
    1951                 : }
    1952                 :  
    1953                 : NS_IMETHODIMP
    1954             328 : nsNSSComponent::Init()
    1955                 : {
    1956                 :   // No mutex protection.
    1957                 :   // Assume Init happens before any concurrency on "this" can start.
    1958                 : 
    1959             328 :   nsresult rv = NS_OK;
    1960                 : 
    1961             328 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n"));
    1962                 : 
    1963             328 :   if (!mShutdownObjectList)
    1964                 :   {
    1965               0 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, out of memory in constructor\n"));
    1966               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1967                 :   }
    1968                 : 
    1969             328 :   rv = InitializePIPNSSBundle();
    1970             328 :   if (NS_FAILED(rv)) {
    1971               0 :     PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to create pipnss bundle.\n"));
    1972               0 :     return rv;
    1973                 :   }      
    1974                 : 
    1975                 :   // Access our string bundles now, this prevents assertions from I/O
    1976                 :   // - nsStandardURL not thread-safe
    1977                 :   // - wrong thread: 'NS_IsMainThread()' in nsIOService.cpp
    1978                 :   // when loading error strings on the SSL threads.
    1979                 :   {
    1980             656 :     NS_NAMED_LITERAL_STRING(dummy_name, "dummy");
    1981             656 :     nsXPIDLString result;
    1982             328 :     mPIPNSSBundle->GetStringFromName(dummy_name.get(),
    1983             328 :                                      getter_Copies(result));
    1984             328 :     mNSSErrorsBundle->GetStringFromName(dummy_name.get(),
    1985             328 :                                         getter_Copies(result));
    1986                 :   }
    1987                 : 
    1988             328 :   if (!mPrefBranch) {
    1989             328 :     mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
    1990             328 :     NS_ASSERTION(mPrefBranch, "Unable to get pref service");
    1991                 :   }
    1992                 : 
    1993                 :   // Do that before NSS init, to make sure we won't get unloaded.
    1994             328 :   RegisterObservers();
    1995                 : 
    1996             328 :   rv = InitializeNSS(true); // ok to show a warning box on failure
    1997             328 :   if (NS_FAILED(rv)) {
    1998               0 :     PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n"));
    1999                 : 
    2000               0 :     DeregisterObservers();
    2001               0 :     mPIPNSSBundle = nsnull;
    2002               0 :     return rv;
    2003                 :   }
    2004                 : 
    2005             328 :   nsSSLIOLayerHelpers::Init();
    2006             328 :   char *unrestricted_hosts=nsnull;
    2007             328 :   mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
    2008             328 :   if (unrestricted_hosts) {
    2009             328 :     nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
    2010             328 :     nsMemory::Free(unrestricted_hosts);
    2011             328 :     unrestricted_hosts=nsnull;
    2012                 :   }
    2013                 : 
    2014             328 :   bool enabled = false;
    2015             328 :   mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
    2016             328 :   nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
    2017                 : 
    2018             328 :   PRInt32 warnLevel = 1;
    2019             328 :   mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
    2020             328 :   nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
    2021                 :   
    2022             328 :   mClientAuthRememberService = new nsClientAuthRememberService;
    2023             328 :   if (mClientAuthRememberService)
    2024             328 :     mClientAuthRememberService->Init();
    2025                 : 
    2026             328 :   createBackgroundThreads();
    2027             328 :   if (!mCertVerificationThread)
    2028                 :   {
    2029               0 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, could not create threads\n"));
    2030                 : 
    2031               0 :     DeregisterObservers();
    2032               0 :     mPIPNSSBundle = nsnull;
    2033               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2034                 :   }
    2035                 : 
    2036             328 :   InitializeCRLUpdateTimer();
    2037             328 :   RegisterPSMContentListener();
    2038                 : 
    2039                 :   nsCOMPtr<nsIEntropyCollector> ec
    2040             656 :       = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
    2041                 : 
    2042             656 :   nsCOMPtr<nsIBufEntropyCollector> bec;
    2043                 : 
    2044             328 :   if (ec) {
    2045             328 :     bec = do_QueryInterface(ec);
    2046                 :   }
    2047                 : 
    2048             328 :   NS_ASSERTION(bec, "No buffering entropy collector.  "
    2049                 :                     "This means no entropy will be collected.");
    2050             328 :   if (bec) {
    2051             328 :     bec->ForwardTo(this);
    2052                 :   }
    2053                 : 
    2054             328 :   return rv;
    2055                 : }
    2056                 : 
    2057                 : /* nsISupports Implementation for the class */
    2058           22242 : NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSComponent,
    2059                 :                               nsISignatureVerifier,
    2060                 :                               nsIEntropyCollector,
    2061                 :                               nsINSSComponent,
    2062                 :                               nsIObserver,
    2063                 :                               nsISupportsWeakReference,
    2064                 :                               nsITimerCallback)
    2065                 : 
    2066                 : 
    2067                 : /* Callback functions for decoder. For now, use empty/default functions. */
    2068               0 : static void ContentCallback(void *arg, 
    2069                 :                                            const char *buf,
    2070                 :                                            unsigned long len)
    2071                 : {
    2072               0 : }
    2073                 : 
    2074               0 : static PK11SymKey * GetDecryptKeyCallback(void *arg, 
    2075                 :                                                  SECAlgorithmID *algid)
    2076                 : {
    2077               0 :   return nsnull;
    2078                 : }
    2079                 : 
    2080               0 : static PRBool DecryptionAllowedCallback(SECAlgorithmID *algid,  
    2081                 :                                                PK11SymKey *bulkkey)
    2082                 : {
    2083               0 :   return SECMIME_DecryptionAllowed(algid, bulkkey);
    2084                 : }
    2085                 : 
    2086               0 : static void * GetPasswordKeyCallback(void *arg, void *handle)
    2087                 : {
    2088               0 :   return NULL;
    2089                 : }
    2090                 : 
    2091                 : NS_IMETHODIMP
    2092               0 : nsNSSComponent::VerifySignature(const char* aRSABuf, PRUint32 aRSABufLen,
    2093                 :                                 const char* aPlaintext, PRUint32 aPlaintextLen,
    2094                 :                                 PRInt32* aErrorCode,
    2095                 :                                 nsIPrincipal** aPrincipal)
    2096                 : {
    2097               0 :   if (!aPrincipal || !aErrorCode) {
    2098               0 :     return NS_ERROR_NULL_POINTER;
    2099                 :   }
    2100                 : 
    2101               0 :   *aErrorCode = 0;
    2102               0 :   *aPrincipal = nsnull;
    2103                 : 
    2104               0 :   nsNSSShutDownPreventionLock locker;
    2105               0 :   SEC_PKCS7ContentInfo * p7_info = nsnull; 
    2106                 :   unsigned char hash[SHA1_LENGTH]; 
    2107                 : 
    2108                 :   SECItem item;
    2109               0 :   item.type = siEncodedCertBuffer;
    2110               0 :   item.data = (unsigned char*)aRSABuf;
    2111               0 :   item.len = aRSABufLen;
    2112                 :   p7_info = SEC_PKCS7DecodeItem(&item,
    2113                 :                                 ContentCallback, nsnull,
    2114                 :                                 GetPasswordKeyCallback, nsnull,
    2115                 :                                 GetDecryptKeyCallback, nsnull,
    2116               0 :                                 DecryptionAllowedCallback);
    2117                 : 
    2118               0 :   if (!p7_info) {
    2119               0 :     return NS_ERROR_FAILURE;
    2120                 :   }
    2121                 : 
    2122                 :   // Make sure we call SEC_PKCS7DestroyContentInfo after this point;
    2123                 :   // otherwise we leak data in p7_info
    2124                 :   
    2125                 :   //-- If a plaintext was provided, hash it.
    2126                 :   SECItem digest;
    2127               0 :   digest.data = nsnull;
    2128               0 :   digest.len = 0;
    2129                 : 
    2130               0 :   if (aPlaintext) {
    2131                 :     HASHContext* hash_ctxt;
    2132               0 :     PRUint32 hashLen = 0;
    2133                 : 
    2134               0 :     hash_ctxt = HASH_Create(HASH_AlgSHA1);
    2135               0 :     HASH_Begin(hash_ctxt);
    2136               0 :     HASH_Update(hash_ctxt,(const unsigned char*)aPlaintext, aPlaintextLen);
    2137               0 :     HASH_End(hash_ctxt, hash, &hashLen, SHA1_LENGTH); 
    2138               0 :     HASH_Destroy(hash_ctxt);
    2139                 : 
    2140               0 :     digest.data = hash;
    2141               0 :     digest.len = SHA1_LENGTH;
    2142                 :   }
    2143                 : 
    2144                 :   //-- Verify signature
    2145                 :   bool rv = SEC_PKCS7VerifyDetachedSignature(p7_info, certUsageObjectSigner,
    2146               0 :                                                &digest, HASH_AlgSHA1, false);
    2147               0 :   if (!rv) {
    2148               0 :     *aErrorCode = PR_GetError();
    2149                 :   }
    2150                 : 
    2151                 :   // Get the signing cert //
    2152               0 :   CERTCertificate *cert = p7_info->content.signedData->signerInfos[0]->cert;
    2153               0 :   nsresult rv2 = NS_OK;
    2154               0 :   if (cert) {
    2155                 :     // Use |do { } while (0);| as a "more C++-ish" thing than goto;
    2156                 :     // this way we don't have to worry about goto across variable
    2157                 :     // declarations.  We have no loops in this code, so it's OK.
    2158                 :     do {
    2159               0 :       nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert);
    2160               0 :       if (!pCert) {
    2161               0 :         rv2 = NS_ERROR_OUT_OF_MEMORY;
    2162                 :         break;
    2163                 :       }
    2164                 : 
    2165               0 :       if (!mScriptSecurityManager) {
    2166               0 :         MutexAutoLock lock(mutex);
    2167                 :         // re-test the condition to prevent double initialization
    2168               0 :         if (!mScriptSecurityManager) {
    2169                 :           mScriptSecurityManager = 
    2170               0 :             do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv2);
    2171               0 :           if (NS_FAILED(rv2)) {
    2172                 :             break;
    2173                 :           }
    2174                 :         }
    2175                 :       }
    2176                 : 
    2177                 :       //-- Create a certificate principal with id and organization data
    2178               0 :       nsAutoString fingerprint;
    2179               0 :       rv2 = pCert->GetSha1Fingerprint(fingerprint);
    2180               0 :       if (NS_FAILED(rv2)) {
    2181                 :         break;
    2182                 :       }
    2183               0 :       nsAutoString orgName;
    2184               0 :       rv2 = pCert->GetOrganization(orgName);
    2185               0 :       if (NS_FAILED(rv2)) {
    2186                 :         break;
    2187                 :       }
    2188               0 :       nsAutoString subjectName;
    2189               0 :       rv2 = pCert->GetSubjectName(subjectName);
    2190               0 :       if (NS_FAILED(rv2)) {
    2191                 :         break;
    2192                 :       }
    2193                 :     
    2194               0 :       nsCOMPtr<nsIPrincipal> certPrincipal;
    2195               0 :       rv2 = mScriptSecurityManager->
    2196               0 :         GetCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
    2197               0 :                                 NS_ConvertUTF16toUTF8(subjectName),
    2198               0 :                                 NS_ConvertUTF16toUTF8(orgName),
    2199               0 :                                 pCert, nsnull, getter_AddRefs(certPrincipal));
    2200               0 :       if (NS_FAILED(rv2) || !certPrincipal) {
    2201                 :         break;
    2202                 :       }
    2203                 :       
    2204               0 :       certPrincipal.swap(*aPrincipal);
    2205                 :     } while (0);
    2206                 :   }
    2207                 : 
    2208               0 :   SEC_PKCS7DestroyContentInfo(p7_info);
    2209                 : 
    2210               0 :   return rv2;
    2211                 : }
    2212                 : 
    2213                 : NS_IMETHODIMP
    2214             328 : nsNSSComponent::RandomUpdate(void *entropy, PRInt32 bufLen)
    2215                 : {
    2216             656 :   nsNSSShutDownPreventionLock locker;
    2217                 : 
    2218                 :   // Asynchronous event happening often,
    2219                 :   // must not interfere with initialization or profile switch.
    2220                 :   
    2221             656 :   MutexAutoLock lock(mutex);
    2222                 : 
    2223             328 :   if (!mNSSInitialized)
    2224               0 :       return NS_ERROR_NOT_INITIALIZED;
    2225                 : 
    2226             328 :   PK11_RandomUpdate(entropy, bufLen);
    2227             328 :   return NS_OK;
    2228                 : }
    2229                 : 
    2230                 : #define PROFILE_CHANGE_NET_TEARDOWN_TOPIC "profile-change-net-teardown"
    2231                 : #define PROFILE_CHANGE_NET_RESTORE_TOPIC "profile-change-net-restore"
    2232                 : #define PROFILE_APPROVE_CHANGE_TOPIC "profile-approve-change"
    2233                 : #define PROFILE_CHANGE_TEARDOWN_TOPIC "profile-change-teardown"
    2234                 : #define PROFILE_CHANGE_TEARDOWN_VETO_TOPIC "profile-change-teardown-veto"
    2235                 : #define PROFILE_BEFORE_CHANGE_TOPIC "profile-before-change"
    2236                 : #define PROFILE_DO_CHANGE_TOPIC "profile-do-change"
    2237                 : 
    2238                 : NS_IMETHODIMP
    2239            1273 : nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic, 
    2240                 :                         const PRUnichar *someData)
    2241                 : {
    2242            1273 :   if (nsCRT::strcmp(aTopic, PROFILE_APPROVE_CHANGE_TOPIC) == 0) {
    2243               0 :     DoProfileApproveChange(aSubject);
    2244                 :   }
    2245            1273 :   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_TOPIC) == 0) {
    2246             315 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("in PSM code, receiving change-teardown\n"));
    2247             315 :     DoProfileChangeTeardown(aSubject);
    2248                 :   }
    2249             958 :   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC) == 0) {
    2250               0 :     mShutdownObjectList->allowUI();
    2251                 :   }
    2252             958 :   else if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) {
    2253             315 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving profile change topic\n"));
    2254             315 :     DoProfileBeforeChange(aSubject);
    2255                 :   }
    2256             643 :   else if (nsCRT::strcmp(aTopic, PROFILE_DO_CHANGE_TOPIC) == 0) {
    2257               0 :     if (someData && NS_LITERAL_STRING("startup").Equals(someData)) {
    2258                 :       // The application is initializing against a known profile directory for
    2259                 :       // the first time during process execution.
    2260                 :       // However, earlier code execution might have already triggered NSS init.
    2261                 :       // We must ensure that NSS gets shut down prior to any attempt to init
    2262                 :       // it again. We use the same cleanup functionality used when switching
    2263                 :       // profiles. The order of function calls must correspond to the order
    2264                 :       // of notifications sent by Profile Manager (nsProfile).
    2265               0 :       DoProfileApproveChange(aSubject);
    2266               0 :       DoProfileChangeNetTeardown();
    2267               0 :       DoProfileChangeTeardown(aSubject);
    2268               0 :       DoProfileBeforeChange(aSubject);
    2269               0 :       DoProfileChangeNetRestore();
    2270                 :     }
    2271                 :   
    2272               0 :     bool needsInit = true;
    2273                 : 
    2274                 :     {
    2275               0 :       MutexAutoLock lock(mutex);
    2276                 : 
    2277               0 :       if (mNSSInitialized) {
    2278                 :         // We have already initialized NSS before the profile came up,
    2279                 :         // no need to do it again
    2280               0 :         needsInit = false;
    2281                 :       }
    2282                 :     }
    2283                 :     
    2284               0 :     if (needsInit) {
    2285               0 :       if (NS_FAILED(InitializeNSS(false))) { // do not show a warning box on failure
    2286               0 :         PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS after profile switch.\n"));
    2287               0 :         nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
    2288               0 :         if (status) {
    2289               0 :           status->ChangeFailed();
    2290                 :         }
    2291                 :       }
    2292                 :     }
    2293                 : 
    2294               0 :     InitializeCRLUpdateTimer();
    2295                 :   }
    2296             643 :   else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
    2297                 : 
    2298             328 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: XPCom shutdown observed\n"));
    2299                 : 
    2300                 :     // Cleanup code that requires services, it's too late in destructor.
    2301                 : 
    2302             328 :     if (mPSMContentListener) {
    2303             656 :       nsCOMPtr<nsIURILoader> dispatcher(do_GetService(NS_URI_LOADER_CONTRACTID));
    2304             328 :       if (dispatcher) {
    2305             328 :         dispatcher->UnRegisterContentListener(mPSMContentListener);
    2306                 :       }
    2307             328 :       mPSMContentListener = nsnull;
    2308                 :     }
    2309                 : 
    2310                 :     nsCOMPtr<nsIEntropyCollector> ec
    2311             656 :         = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
    2312                 : 
    2313             328 :     if (ec) {
    2314                 :       nsCOMPtr<nsIBufEntropyCollector> bec
    2315             656 :         = do_QueryInterface(ec);
    2316             328 :       if (bec) {
    2317             328 :         bec->DontForward();
    2318                 :       }
    2319                 :     }
    2320                 :   }
    2321             315 :   else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) { 
    2322               0 :     nsNSSShutDownPreventionLock locker;
    2323               0 :     bool clearSessionCache = false;
    2324                 :     bool enabled;
    2325               0 :     NS_ConvertUTF16toUTF8  prefName(someData);
    2326                 : 
    2327               0 :     if (prefName.Equals("security.enable_ssl3")) {
    2328               0 :       mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
    2329               0 :       SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
    2330               0 :       clearSessionCache = true;
    2331               0 :     } else if (prefName.Equals("security.enable_tls")) {
    2332               0 :       mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
    2333               0 :       SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
    2334               0 :       clearSessionCache = true;
    2335               0 :     } else if (prefName.Equals("security.enable_md5_signatures")) {
    2336               0 :       mPrefBranch->GetBoolPref("security.enable_md5_signatures", &enabled);
    2337               0 :       configureMD5(enabled);
    2338               0 :       clearSessionCache = true;
    2339               0 :     } else if (prefName.Equals("security.enable_tls_session_tickets")) {
    2340               0 :       mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
    2341               0 :       SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
    2342               0 :     } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
    2343               0 :       mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
    2344               0 :       SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
    2345               0 :     } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
    2346               0 :       mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
    2347                 :       SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, 
    2348               0 :         enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
    2349               0 :     } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
    2350               0 :       char *unrestricted_hosts=nsnull;
    2351               0 :       mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
    2352               0 :       if (unrestricted_hosts) {
    2353               0 :         nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
    2354               0 :         nsMemory::Free(unrestricted_hosts);
    2355                 :       }
    2356               0 :     } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
    2357               0 :       mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
    2358               0 :       nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
    2359               0 :     } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
    2360               0 :       PRInt32 warnLevel = 1;
    2361               0 :       mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
    2362               0 :       nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
    2363                 : #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
    2364               0 :     } else if (prefName.Equals("security.ssl.enable_false_start")) {
    2365               0 :       mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
    2366               0 :       SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
    2367                 : #endif
    2368               0 :     } else if (prefName.Equals("security.OCSP.enabled")
    2369               0 :                || prefName.Equals("security.CRL_download.enabled")
    2370               0 :                || prefName.Equals("security.fresh_revocation_info.require")
    2371               0 :                || prefName.Equals("security.missing_cert_download.enabled")
    2372               0 :                || prefName.Equals("security.first_network_revocation_method")
    2373               0 :                || prefName.Equals("security.OCSP.require")) {
    2374               0 :       MutexAutoLock lock(mutex);
    2375               0 :       setValidationOptions(mPrefBranch);
    2376                 :     } else {
    2377                 :       /* Look through the cipher table and set according to pref setting */
    2378               0 :       for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
    2379               0 :         if (prefName.Equals(cp->pref)) {
    2380               0 :           mPrefBranch->GetBoolPref(cp->pref, &enabled);
    2381               0 :           SSL_CipherPrefSetDefault(cp->id, enabled);
    2382               0 :           clearSessionCache = true;
    2383               0 :           break;
    2384                 :         }
    2385                 :       }
    2386                 :     }
    2387               0 :     if (clearSessionCache)
    2388               0 :       SSL_ClearSessionCache();
    2389                 :   }
    2390             315 :   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
    2391             315 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
    2392             315 :     DoProfileChangeNetTeardown();
    2393                 :   }
    2394               0 :   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_RESTORE_TOPIC) == 0) {
    2395               0 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network restore topic\n"));
    2396               0 :     DoProfileChangeNetRestore();
    2397                 :   }
    2398                 : 
    2399            1273 :   return NS_OK;
    2400                 : }
    2401                 : 
    2402                 : /*static*/ nsresult
    2403               0 : nsNSSComponent::GetNewPrompter(nsIPrompt ** result)
    2404                 : {
    2405               0 :   NS_ENSURE_ARG_POINTER(result);
    2406               0 :   *result = nsnull;
    2407                 : 
    2408               0 :   if (!NS_IsMainThread()) {
    2409               0 :     NS_ERROR("nsSDRContext::GetNewPrompter called off the main thread");
    2410               0 :     return NS_ERROR_NOT_SAME_THREAD;
    2411                 :   }
    2412                 : 
    2413                 :   nsresult rv;
    2414               0 :   nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
    2415               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2416                 : 
    2417               0 :   rv = wwatch->GetNewPrompter(0, result);
    2418               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2419                 : 
    2420               0 :   return rv;
    2421                 : }
    2422                 : 
    2423                 : /*static*/ nsresult
    2424               0 : nsNSSComponent::ShowAlertWithConstructedString(const nsString & message)
    2425                 : {
    2426               0 :   nsCOMPtr<nsIPrompt> prompter;
    2427               0 :   nsresult rv = GetNewPrompter(getter_AddRefs(prompter));
    2428               0 :   if (prompter) {
    2429               0 :     nsPSMUITracker tracker;
    2430               0 :     if (tracker.isUIForbidden()) {
    2431               0 :       NS_WARNING("Suppressing alert because PSM UI is forbidden");
    2432               0 :       rv = NS_ERROR_UNEXPECTED;
    2433                 :     } else {
    2434               0 :       rv = prompter->Alert(nsnull, message.get());
    2435                 :     }
    2436                 :   }
    2437               0 :   return rv;
    2438                 : }
    2439                 : 
    2440                 : NS_IMETHODIMP
    2441               0 : nsNSSComponent::ShowAlertFromStringBundle(const char * messageID)
    2442                 : {
    2443               0 :   nsString message;
    2444                 :   nsresult rv;
    2445                 : 
    2446               0 :   rv = GetPIPNSSBundleString(messageID, message);
    2447               0 :   if (NS_FAILED(rv)) {
    2448               0 :     NS_ERROR("GetPIPNSSBundleString failed");
    2449               0 :     return rv;
    2450                 :   }
    2451                 : 
    2452               0 :   return ShowAlertWithConstructedString(message);
    2453                 : }
    2454                 : 
    2455             142 : nsresult nsNSSComponent::LogoutAuthenticatedPK11()
    2456                 : {
    2457                 :   nsCOMPtr<nsICertOverrideService> icos =
    2458             284 :     do_GetService("@mozilla.org/security/certoverride;1");
    2459             142 :   if (icos) {
    2460             142 :     icos->ClearValidityOverride(
    2461             142 :             NS_LITERAL_CSTRING("all:temporary-certificates"),
    2462             142 :             0);
    2463                 :   }
    2464                 : 
    2465             142 :   if (mClientAuthRememberService) {
    2466             142 :     mClientAuthRememberService->ClearRememberedDecisions();
    2467                 :   }
    2468                 : 
    2469             142 :   return mShutdownObjectList->doPK11Logout();
    2470                 : }
    2471                 : 
    2472                 : nsresult
    2473             328 : nsNSSComponent::RegisterObservers()
    2474                 : {
    2475                 :   // Happens once during init only, no mutex protection.
    2476                 : 
    2477             656 :   nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
    2478             328 :   NS_ASSERTION(observerService, "could not get observer service");
    2479             328 :   if (observerService) {
    2480             328 :     mObserversRegistered = true;
    2481             328 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: adding observers\n"));
    2482                 : 
    2483                 :     // We are a service.
    2484                 :     // Once we are loaded, don't allow being removed from memory.
    2485                 :     // This makes sense, as initializing NSS is expensive.
    2486                 : 
    2487                 :     // By using false for parameter ownsWeak in AddObserver,
    2488                 :     // we make sure that we won't get unloaded until the application shuts down.
    2489                 : 
    2490             328 :     observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
    2491                 : 
    2492             328 :     observerService->AddObserver(this, PROFILE_APPROVE_CHANGE_TOPIC, false);
    2493             328 :     observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC, false);
    2494             328 :     observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC, false);
    2495             328 :     observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
    2496             328 :     observerService->AddObserver(this, PROFILE_DO_CHANGE_TOPIC, false);
    2497             328 :     observerService->AddObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC, false);
    2498             328 :     observerService->AddObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC, false);
    2499                 :   }
    2500             328 :   return NS_OK;
    2501                 : }
    2502                 : 
    2503                 : nsresult
    2504               0 : nsNSSComponent::DeregisterObservers()
    2505                 : {
    2506               0 :   if (!mObserversRegistered)
    2507               0 :     return NS_OK;
    2508                 : 
    2509               0 :   nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
    2510               0 :   NS_ASSERTION(observerService, "could not get observer service");
    2511               0 :   if (observerService) {
    2512               0 :     mObserversRegistered = false;
    2513               0 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: removing observers\n"));
    2514                 : 
    2515               0 :     observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
    2516                 : 
    2517               0 :     observerService->RemoveObserver(this, PROFILE_APPROVE_CHANGE_TOPIC);
    2518               0 :     observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC);
    2519               0 :     observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC);
    2520               0 :     observerService->RemoveObserver(this, PROFILE_BEFORE_CHANGE_TOPIC);
    2521               0 :     observerService->RemoveObserver(this, PROFILE_DO_CHANGE_TOPIC);
    2522               0 :     observerService->RemoveObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC);
    2523               0 :     observerService->RemoveObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC);
    2524                 :   }
    2525               0 :   return NS_OK;
    2526                 : }
    2527                 : 
    2528                 : NS_IMETHODIMP
    2529               0 : nsNSSComponent::RememberCert(CERTCertificate *cert)
    2530                 : {
    2531               0 :   nsNSSShutDownPreventionLock locker;
    2532                 : 
    2533                 :   // Must not interfere with init / shutdown / profile switch.
    2534                 : 
    2535               0 :   MutexAutoLock lock(mutex);
    2536                 : 
    2537               0 :   if (!hashTableCerts || !cert)
    2538               0 :     return NS_OK;
    2539                 :   
    2540               0 :   void *found = PL_HashTableLookup(hashTableCerts, (void*)&cert->certKey);
    2541                 :   
    2542               0 :   if (found) {
    2543                 :     // we remember that cert already
    2544               0 :     return NS_OK;
    2545                 :   }
    2546                 :   
    2547               0 :   CERTCertificate *myDupCert = CERT_DupCertificate(cert);
    2548                 :   
    2549               0 :   if (!myDupCert)
    2550               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2551                 :   
    2552               0 :   if (!PL_HashTableAdd(hashTableCerts, (void*)&myDupCert->certKey, myDupCert)) {
    2553               0 :     CERT_DestroyCertificate(myDupCert);
    2554                 :   }
    2555                 :   
    2556               0 :   return NS_OK;
    2557                 : }
    2558                 : 
    2559                 : static const char PROFILE_SWITCH_CRYPTO_UI_ACTIVE[] =
    2560                 :                         "ProfileSwitchCryptoUIActive";
    2561                 : static const char PROFILE_SWITCH_SOCKETS_STILL_ACTIVE[] =
    2562                 :                         "ProfileSwitchSocketsStillActive";
    2563                 : 
    2564                 : void
    2565               0 : nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
    2566                 : {
    2567               0 :   if (mShutdownObjectList->isUIActive()) {
    2568               0 :     ShowAlertFromStringBundle(PROFILE_SWITCH_CRYPTO_UI_ACTIVE);
    2569               0 :     nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
    2570               0 :     if (status) {
    2571               0 :       status->VetoChange();
    2572                 :     }
    2573                 :   }
    2574               0 : }
    2575                 : 
    2576                 : void
    2577             315 : nsNSSComponent::DoProfileChangeNetTeardown()
    2578                 : {
    2579             315 :   if (mCertVerificationThread)
    2580             315 :     mCertVerificationThread->requestExit();
    2581             315 :   mIsNetworkDown = true;
    2582             315 : }
    2583                 : 
    2584                 : void
    2585             315 : nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
    2586                 : {
    2587             315 :   bool callVeto = false;
    2588                 : 
    2589             315 :   if (!mShutdownObjectList->ifPossibleDisallowUI()) {
    2590               0 :     callVeto = true;
    2591               0 :     ShowAlertFromStringBundle(PROFILE_SWITCH_CRYPTO_UI_ACTIVE);
    2592                 :   }
    2593             315 :   else if (mShutdownObjectList->areSSLSocketsActive()) {
    2594               0 :     callVeto = true;
    2595               0 :     ShowAlertFromStringBundle(PROFILE_SWITCH_SOCKETS_STILL_ACTIVE);
    2596                 :   }
    2597                 : 
    2598             315 :   if (callVeto) {
    2599               0 :     nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
    2600               0 :     if (status) {
    2601               0 :       status->VetoChange();
    2602                 :     }
    2603                 :   }
    2604             315 : }
    2605                 : 
    2606                 : void
    2607             315 : nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
    2608                 : {
    2609             315 :   NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
    2610                 : 
    2611             315 :   bool needsCleanup = true;
    2612                 : 
    2613                 :   {
    2614             630 :     MutexAutoLock lock(mutex);
    2615                 : 
    2616             315 :     if (!mNSSInitialized) {
    2617                 :       // Make sure we don't try to cleanup if we have already done so.
    2618                 :       // This makes sure we behave safely, in case we are notified
    2619                 :       // multiple times.
    2620               4 :       needsCleanup = false;
    2621                 :     }
    2622                 :   }
    2623                 :     
    2624             315 :   StopCRLUpdateTimer();
    2625                 : 
    2626             315 :   if (needsCleanup) {
    2627             311 :     if (NS_FAILED(ShutdownNSS())) {
    2628              66 :       nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
    2629              33 :       if (status) {
    2630               0 :         status->ChangeFailed();
    2631                 :       }
    2632                 :     }
    2633                 :   }
    2634             315 :   mShutdownObjectList->allowUI();
    2635             315 : }
    2636                 : 
    2637                 : void
    2638               0 : nsNSSComponent::DoProfileChangeNetRestore()
    2639                 : {
    2640                 :   /* XXX this doesn't work well, since nothing expects null pointers */
    2641               0 :   deleteBackgroundThreads();
    2642               0 :   createBackgroundThreads();
    2643               0 :   mIsNetworkDown = false;
    2644               0 : }
    2645                 : 
    2646                 : NS_IMETHODIMP
    2647               0 : nsNSSComponent::GetClientAuthRememberService(nsClientAuthRememberService **cars)
    2648                 : {
    2649               0 :   NS_ENSURE_ARG_POINTER(cars);
    2650               0 :   NS_IF_ADDREF(*cars = mClientAuthRememberService);
    2651               0 :   return NS_OK;
    2652                 : }
    2653                 : 
    2654                 : NS_IMETHODIMP
    2655             279 : nsNSSComponent::IsNSSInitialized(bool *initialized)
    2656                 : {
    2657             558 :   MutexAutoLock lock(mutex);
    2658             279 :   *initialized = mNSSInitialized;
    2659             279 :   return NS_OK;
    2660                 : }
    2661                 : 
    2662                 : NS_IMETHODIMP
    2663               0 : nsNSSComponent::GetDefaultCERTValInParam(nsRefPtr<nsCERTValInParamWrapper> &out)
    2664                 : {
    2665               0 :   MutexAutoLock lock(mutex);
    2666               0 :   if (!mNSSInitialized)
    2667               0 :       return NS_ERROR_NOT_INITIALIZED;
    2668               0 :   out = mDefaultCERTValInParam;
    2669               0 :   return NS_OK;
    2670                 : }
    2671                 : 
    2672                 : NS_IMETHODIMP
    2673               0 : nsNSSComponent::GetDefaultCERTValInParamLocalOnly(nsRefPtr<nsCERTValInParamWrapper> &out)
    2674                 : {
    2675               0 :   MutexAutoLock lock(mutex);
    2676               0 :   if (!mNSSInitialized)
    2677               0 :       return NS_ERROR_NOT_INITIALIZED;
    2678               0 :   out = mDefaultCERTValInParamLocalOnly;
    2679               0 :   return NS_OK;
    2680                 : }
    2681                 : 
    2682                 : //---------------------------------------------
    2683                 : // Implementing nsICryptoHash
    2684                 : //---------------------------------------------
    2685                 : 
    2686            1466 : nsCryptoHash::nsCryptoHash()
    2687                 :   : mHashContext(nsnull)
    2688            1466 :   , mInitialized(false)
    2689                 : {
    2690            1466 : }
    2691                 : 
    2692            4398 : nsCryptoHash::~nsCryptoHash()
    2693                 : {
    2694            2932 :   nsNSSShutDownPreventionLock locker;
    2695                 : 
    2696            1466 :   if (isAlreadyShutDown())
    2697                 :     return;
    2698                 : 
    2699             951 :   destructorSafeDestroyNSSReference();
    2700            2417 :   shutdown(calledFromObject);
    2701            5864 : }
    2702                 : 
    2703             515 : void nsCryptoHash::virtualDestroyNSSReference()
    2704                 : {
    2705             515 :   destructorSafeDestroyNSSReference();
    2706             515 : }
    2707                 : 
    2708            1466 : void nsCryptoHash::destructorSafeDestroyNSSReference()
    2709                 : {
    2710            1466 :   if (isAlreadyShutDown())
    2711               0 :     return;
    2712                 : 
    2713            1466 :   if (mHashContext)
    2714            1450 :     HASH_Destroy(mHashContext);
    2715            1466 :   mHashContext = nsnull;
    2716                 : }
    2717                 : 
    2718           23427 : NS_IMPL_ISUPPORTS1(nsCryptoHash, nsICryptoHash)
    2719                 : 
    2720                 : NS_IMETHODIMP 
    2721            2252 : nsCryptoHash::Init(PRUint32 algorithm)
    2722                 : {
    2723            4504 :   nsNSSShutDownPreventionLock locker;
    2724                 : 
    2725            2252 :   HASH_HashType hashType = (HASH_HashType)algorithm;
    2726            2252 :   if (mHashContext)
    2727                 :   {
    2728             802 :     if ((!mInitialized) && (HASH_GetType(mHashContext) == hashType))
    2729                 :     {
    2730             802 :       mInitialized = true;
    2731             802 :       HASH_Begin(mHashContext);
    2732             802 :       return NS_OK;
    2733                 :     }
    2734                 : 
    2735                 :     // Destroy current hash context if the type was different
    2736                 :     // or Finish method wasn't called.
    2737               0 :     HASH_Destroy(mHashContext);
    2738               0 :     mInitialized = false;
    2739                 :   }
    2740                 : 
    2741            1450 :   mHashContext = HASH_Create(hashType);
    2742            1450 :   if (!mHashContext)
    2743               0 :     return NS_ERROR_INVALID_ARG;
    2744                 : 
    2745            1450 :   HASH_Begin(mHashContext);
    2746            1450 :   mInitialized = true;
    2747            1450 :   return NS_OK; 
    2748                 : }
    2749                 : 
    2750                 : NS_IMETHODIMP
    2751             290 : nsCryptoHash::InitWithString(const nsACString & aAlgorithm)
    2752                 : {
    2753             290 :   if (aAlgorithm.LowerCaseEqualsLiteral("md2"))
    2754               5 :     return Init(nsICryptoHash::MD2);
    2755                 : 
    2756             285 :   if (aAlgorithm.LowerCaseEqualsLiteral("md5"))
    2757               5 :     return Init(nsICryptoHash::MD5);
    2758                 : 
    2759             280 :   if (aAlgorithm.LowerCaseEqualsLiteral("sha1"))
    2760             265 :     return Init(nsICryptoHash::SHA1);
    2761                 : 
    2762              15 :   if (aAlgorithm.LowerCaseEqualsLiteral("sha256"))
    2763               5 :     return Init(nsICryptoHash::SHA256);
    2764                 : 
    2765              10 :   if (aAlgorithm.LowerCaseEqualsLiteral("sha384"))
    2766               5 :     return Init(nsICryptoHash::SHA384);
    2767                 : 
    2768               5 :   if (aAlgorithm.LowerCaseEqualsLiteral("sha512"))
    2769               5 :     return Init(nsICryptoHash::SHA512);
    2770                 : 
    2771               0 :   return NS_ERROR_INVALID_ARG;
    2772                 : }
    2773                 : 
    2774                 : NS_IMETHODIMP
    2775            2252 : nsCryptoHash::Update(const PRUint8 *data, PRUint32 len)
    2776                 : {
    2777            4504 :   nsNSSShutDownPreventionLock locker;
    2778                 :   
    2779            2252 :   if (!mInitialized)
    2780               0 :     return NS_ERROR_NOT_INITIALIZED;
    2781                 : 
    2782            2252 :   HASH_Update(mHashContext, data, len);
    2783            2252 :   return NS_OK; 
    2784                 : }
    2785                 : 
    2786                 : NS_IMETHODIMP
    2787            1109 : nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 len)
    2788                 : {
    2789            1109 :   if (!mInitialized)
    2790               0 :     return NS_ERROR_NOT_INITIALIZED;
    2791                 : 
    2792            1109 :   if (!data)
    2793               0 :     return NS_ERROR_INVALID_ARG;
    2794                 : 
    2795                 :   PRUint32 n;
    2796            1109 :   nsresult rv = data->Available(&n);
    2797            1109 :   if (NS_FAILED(rv))
    2798               0 :     return rv;
    2799                 : 
    2800                 :   // if the user has passed PR_UINT32_MAX, then read
    2801                 :   // everything in the stream
    2802                 : 
    2803            1109 :   if (len == PR_UINT32_MAX)
    2804             843 :     len = n;
    2805                 : 
    2806                 :   // So, if the stream has NO data available for the hash,
    2807                 :   // or if the data available is less then what the caller
    2808                 :   // requested, we can not fulfill the hash update.  In this
    2809                 :   // case, just return NS_ERROR_NOT_AVAILABLE indicating
    2810                 :   // that there is not enough data in the stream to satisify
    2811                 :   // the request.
    2812                 : 
    2813            1109 :   if (n == 0 || n < len)
    2814               0 :     return NS_ERROR_NOT_AVAILABLE;
    2815                 :   
    2816                 :   char buffer[NS_CRYPTO_HASH_BUFFER_SIZE];
    2817                 :   PRUint32 read, readLimit;
    2818                 :   
    2819            3327 :   while(NS_SUCCEEDED(rv) && len>0)
    2820                 :   {
    2821            1109 :     readLimit = NS_MIN(PRUint32(NS_CRYPTO_HASH_BUFFER_SIZE), len);
    2822                 :     
    2823            1109 :     rv = data->Read(buffer, readLimit, &read);
    2824                 :     
    2825            1109 :     if (NS_SUCCEEDED(rv))
    2826            1109 :       rv = Update((const PRUint8*)buffer, read);
    2827                 :     
    2828            1109 :     len -= read;
    2829                 :   }
    2830                 :   
    2831            1109 :   return rv;
    2832                 : }
    2833                 : 
    2834                 : NS_IMETHODIMP
    2835            2233 : nsCryptoHash::Finish(bool ascii, nsACString & _retval)
    2836                 : {
    2837            4466 :   nsNSSShutDownPreventionLock locker;
    2838                 :   
    2839            2233 :   if (!mInitialized)
    2840               0 :     return NS_ERROR_NOT_INITIALIZED;
    2841                 :   
    2842            2233 :   PRUint32 hashLen = 0;
    2843                 :   unsigned char buffer[HASH_LENGTH_MAX];
    2844            2233 :   unsigned char* pbuffer = buffer;
    2845                 : 
    2846            2233 :   HASH_End(mHashContext, pbuffer, &hashLen, HASH_LENGTH_MAX);
    2847                 : 
    2848            2233 :   mInitialized = false;
    2849                 : 
    2850            2233 :   if (ascii)
    2851                 :   {
    2852              24 :     char *asciiData = BTOA_DataToAscii(buffer, hashLen);
    2853              24 :     NS_ENSURE_TRUE(asciiData, NS_ERROR_OUT_OF_MEMORY);
    2854                 : 
    2855              24 :     _retval.Assign(asciiData);
    2856              24 :     PORT_Free(asciiData);
    2857                 :   }
    2858                 :   else
    2859                 :   {
    2860            2209 :     _retval.Assign((const char*)buffer, hashLen);
    2861                 :   }
    2862                 : 
    2863            2233 :   return NS_OK;
    2864                 : }
    2865                 : 
    2866                 : //---------------------------------------------
    2867                 : // Implementing nsICryptoHMAC
    2868                 : //---------------------------------------------
    2869                 : 
    2870           27280 : NS_IMPL_ISUPPORTS1(nsCryptoHMAC, nsICryptoHMAC)
    2871                 : 
    2872            1558 : nsCryptoHMAC::nsCryptoHMAC()
    2873                 : {
    2874            1558 :   mHMACContext = nsnull;
    2875            1558 : }
    2876                 : 
    2877            4674 : nsCryptoHMAC::~nsCryptoHMAC()
    2878                 : {
    2879            3116 :   nsNSSShutDownPreventionLock locker;
    2880                 : 
    2881            1558 :   if (isAlreadyShutDown())
    2882                 :     return;
    2883                 : 
    2884             458 :   destructorSafeDestroyNSSReference();
    2885            2016 :   shutdown(calledFromObject);
    2886            6232 : }
    2887                 : 
    2888            1100 : void nsCryptoHMAC::virtualDestroyNSSReference()
    2889                 : {
    2890            1100 :   destructorSafeDestroyNSSReference();
    2891            1100 : }
    2892                 : 
    2893            1558 : void nsCryptoHMAC::destructorSafeDestroyNSSReference()
    2894                 : {
    2895            1558 :   if (isAlreadyShutDown())
    2896               0 :     return;
    2897                 : 
    2898            1558 :   if (mHMACContext)
    2899            1558 :     PK11_DestroyContext(mHMACContext, true);
    2900            1558 :   mHMACContext = nsnull;
    2901                 : }
    2902                 : 
    2903                 : /* void init (in unsigned long aAlgorithm, in nsIKeyObject aKeyObject); */
    2904            1558 : NS_IMETHODIMP nsCryptoHMAC::Init(PRUint32 aAlgorithm, nsIKeyObject *aKeyObject)
    2905                 : {
    2906            3116 :   nsNSSShutDownPreventionLock locker;
    2907                 : 
    2908            1558 :   if (mHMACContext)
    2909                 :   {
    2910               0 :     PK11_DestroyContext(mHMACContext, true);
    2911               0 :     mHMACContext = nsnull;
    2912                 :   }
    2913                 : 
    2914                 :   CK_MECHANISM_TYPE HMACMechType;
    2915            1558 :   switch (aAlgorithm)
    2916                 :   {
    2917                 :   case nsCryptoHMAC::MD2:
    2918               0 :     HMACMechType = CKM_MD2_HMAC; break;
    2919                 :   case nsCryptoHMAC::MD5:
    2920               5 :     HMACMechType = CKM_MD5_HMAC; break;
    2921                 :   case nsCryptoHMAC::SHA1:
    2922              27 :     HMACMechType = CKM_SHA_1_HMAC; break;
    2923                 :   case nsCryptoHMAC::SHA256:
    2924            1519 :     HMACMechType = CKM_SHA256_HMAC; break;
    2925                 :   case nsCryptoHMAC::SHA384:
    2926               1 :     HMACMechType = CKM_SHA384_HMAC; break;
    2927                 :   case nsCryptoHMAC::SHA512:
    2928               6 :     HMACMechType = CKM_SHA512_HMAC; break;
    2929                 :   default:
    2930               0 :     return NS_ERROR_INVALID_ARG;
    2931                 :   }
    2932                 : 
    2933            1558 :   NS_ENSURE_ARG_POINTER(aKeyObject);
    2934                 : 
    2935                 :   nsresult rv;
    2936                 : 
    2937                 :   PRInt16 keyType;
    2938            1558 :   rv = aKeyObject->GetType(&keyType);
    2939            1558 :   NS_ENSURE_SUCCESS(rv, rv);
    2940                 : 
    2941            1558 :   NS_ENSURE_TRUE(keyType == nsIKeyObject::SYM_KEY, NS_ERROR_INVALID_ARG);
    2942                 : 
    2943                 :   PK11SymKey* key;
    2944                 :   // GetKeyObj doesn't addref the key
    2945            1558 :   rv = aKeyObject->GetKeyObj((void**)&key);
    2946            1558 :   NS_ENSURE_SUCCESS(rv, rv);
    2947                 : 
    2948                 :   SECItem rawData;
    2949            1558 :   rawData.data = 0;
    2950            1558 :   rawData.len = 0;
    2951                 :   mHMACContext = PK11_CreateContextBySymKey(
    2952            1558 :       HMACMechType, CKA_SIGN, key, &rawData);
    2953            1558 :   NS_ENSURE_TRUE(mHMACContext, NS_ERROR_FAILURE);
    2954                 : 
    2955            1558 :   SECStatus ss = PK11_DigestBegin(mHMACContext);
    2956            1558 :   NS_ENSURE_TRUE(ss == SECSuccess, NS_ERROR_FAILURE);
    2957                 : 
    2958            1558 :   return NS_OK;
    2959                 : }
    2960                 : 
    2961                 : /* void update ([array, size_is (aLen), const] in octet aData, in unsigned long aLen); */
    2962           22078 : NS_IMETHODIMP nsCryptoHMAC::Update(const PRUint8 *aData, PRUint32 aLen)
    2963                 : {
    2964           44156 :   nsNSSShutDownPreventionLock locker;
    2965                 : 
    2966           22078 :   if (!mHMACContext)
    2967               0 :     return NS_ERROR_NOT_INITIALIZED;
    2968                 : 
    2969           22078 :   if (!aData)
    2970               0 :     return NS_ERROR_INVALID_ARG;
    2971                 : 
    2972           22078 :   SECStatus ss = PK11_DigestOp(mHMACContext, aData, aLen);
    2973           22078 :   NS_ENSURE_TRUE(ss == SECSuccess, NS_ERROR_FAILURE);
    2974                 :   
    2975           22078 :   return NS_OK;
    2976                 : }
    2977                 : 
    2978                 : /* void updateFromStream (in nsIInputStream aStream, in unsigned long aLen); */
    2979               0 : NS_IMETHODIMP nsCryptoHMAC::UpdateFromStream(nsIInputStream *aStream, PRUint32 aLen)
    2980                 : {
    2981               0 :   if (!mHMACContext)
    2982               0 :     return NS_ERROR_NOT_INITIALIZED;
    2983                 : 
    2984               0 :   if (!aStream)
    2985               0 :     return NS_ERROR_INVALID_ARG;
    2986                 : 
    2987                 :   PRUint32 n;
    2988               0 :   nsresult rv = aStream->Available(&n);
    2989               0 :   if (NS_FAILED(rv))
    2990               0 :     return rv;
    2991                 : 
    2992                 :   // if the user has passed PR_UINT32_MAX, then read
    2993                 :   // everything in the stream
    2994                 : 
    2995               0 :   if (aLen == PR_UINT32_MAX)
    2996               0 :     aLen = n;
    2997                 : 
    2998                 :   // So, if the stream has NO data available for the hash,
    2999                 :   // or if the data available is less then what the caller
    3000                 :   // requested, we can not fulfill the HMAC update.  In this
    3001                 :   // case, just return NS_ERROR_NOT_AVAILABLE indicating
    3002                 :   // that there is not enough data in the stream to satisify
    3003                 :   // the request.
    3004                 : 
    3005               0 :   if (n == 0 || n < aLen)
    3006               0 :     return NS_ERROR_NOT_AVAILABLE;
    3007                 :   
    3008                 :   char buffer[NS_CRYPTO_HASH_BUFFER_SIZE];
    3009                 :   PRUint32 read, readLimit;
    3010                 :   
    3011               0 :   while(NS_SUCCEEDED(rv) && aLen > 0)
    3012                 :   {
    3013               0 :     readLimit = NS_MIN(PRUint32(NS_CRYPTO_HASH_BUFFER_SIZE), aLen);
    3014                 :     
    3015               0 :     rv = aStream->Read(buffer, readLimit, &read);
    3016               0 :     if (read == 0)
    3017               0 :       return NS_BASE_STREAM_CLOSED;
    3018                 :     
    3019               0 :     if (NS_SUCCEEDED(rv))
    3020               0 :       rv = Update((const PRUint8*)buffer, read);
    3021                 :     
    3022               0 :     aLen -= read;
    3023                 :   }
    3024                 :   
    3025               0 :   return rv;
    3026                 : }
    3027                 : 
    3028                 : /* ACString finish (in bool aASCII); */
    3029           22078 : NS_IMETHODIMP nsCryptoHMAC::Finish(bool aASCII, nsACString & _retval)
    3030                 : {
    3031           44156 :   nsNSSShutDownPreventionLock locker;
    3032                 : 
    3033           22078 :   if (!mHMACContext)
    3034               0 :     return NS_ERROR_NOT_INITIALIZED;
    3035                 :   
    3036           22078 :   PRUint32 hashLen = 0;
    3037                 :   unsigned char buffer[HASH_LENGTH_MAX];
    3038           22078 :   unsigned char* pbuffer = buffer;
    3039                 : 
    3040           22078 :   PK11_DigestFinal(mHMACContext, pbuffer, &hashLen, HASH_LENGTH_MAX);
    3041           22078 :   if (aASCII)
    3042                 :   {
    3043              12 :     char *asciiData = BTOA_DataToAscii(buffer, hashLen);
    3044              12 :     NS_ENSURE_TRUE(asciiData, NS_ERROR_OUT_OF_MEMORY);
    3045                 : 
    3046              12 :     _retval.Assign(asciiData);
    3047              12 :     PORT_Free(asciiData);
    3048                 :   }
    3049                 :   else
    3050                 :   {
    3051           22066 :     _retval.Assign((const char*)buffer, hashLen);
    3052                 :   }
    3053                 : 
    3054           22078 :   return NS_OK;
    3055                 : }
    3056                 : 
    3057                 : /* void reset (); */
    3058           22048 : NS_IMETHODIMP nsCryptoHMAC::Reset()
    3059                 : {
    3060           44096 :   nsNSSShutDownPreventionLock locker;
    3061                 : 
    3062           22048 :   SECStatus ss = PK11_DigestBegin(mHMACContext);
    3063           22048 :   NS_ENSURE_TRUE(ss == SECSuccess, NS_ERROR_FAILURE);
    3064                 : 
    3065           22048 :   return NS_OK;
    3066                 : }
    3067                 : 
    3068           17265 : NS_IMPL_THREADSAFE_ISUPPORTS1(PipUIContext, nsIInterfaceRequestor)
    3069                 : 
    3070            3453 : PipUIContext::PipUIContext()
    3071                 : {
    3072            3453 : }
    3073                 : 
    3074            6906 : PipUIContext::~PipUIContext()
    3075                 : {
    3076           13812 : }
    3077                 : 
    3078                 : /* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
    3079               0 : NS_IMETHODIMP PipUIContext::GetInterface(const nsIID & uuid, void * *result)
    3080                 : {
    3081               0 :   NS_ENSURE_ARG_POINTER(result);
    3082               0 :   *result = nsnull;
    3083                 : 
    3084               0 :   if (!NS_IsMainThread()) {
    3085               0 :     NS_ERROR("PipUIContext::GetInterface called off the main thread");
    3086               0 :     return NS_ERROR_NOT_SAME_THREAD;
    3087                 :   }
    3088                 : 
    3089               0 :   if (!uuid.Equals(NS_GET_IID(nsIPrompt)))
    3090               0 :     return NS_ERROR_NO_INTERFACE;
    3091                 : 
    3092               0 :   nsIPrompt * prompt = nsnull;
    3093               0 :   nsresult rv = nsNSSComponent::GetNewPrompter(&prompt);
    3094               0 :   *result = prompt;
    3095               0 :   return rv;
    3096                 : }
    3097                 : 
    3098                 : nsresult 
    3099               0 : getNSSDialogs(void **_result, REFNSIID aIID, const char *contract)
    3100                 : {
    3101               0 :   if (!NS_IsMainThread()) {
    3102               0 :     NS_ERROR("getNSSDialogs called off the main thread");
    3103               0 :     return NS_ERROR_NOT_SAME_THREAD;
    3104                 :   }
    3105                 : 
    3106                 :   nsresult rv;
    3107                 : 
    3108               0 :   nsCOMPtr<nsISupports> svc = do_GetService(contract, &rv);
    3109               0 :   if (NS_FAILED(rv)) 
    3110               0 :     return rv;
    3111                 : 
    3112               0 :   rv = svc->QueryInterface(aIID, _result);
    3113                 : 
    3114               0 :   return rv;
    3115                 : }
    3116                 : 
    3117                 : nsresult
    3118             339 : setPassword(PK11SlotInfo *slot, nsIInterfaceRequestor *ctx)
    3119                 : {
    3120             678 :   nsNSSShutDownPreventionLock locker;
    3121             339 :   nsresult rv = NS_OK;
    3122                 :   
    3123             339 :   if (PK11_NeedUserInit(slot)) {
    3124                 :     nsITokenPasswordDialogs *dialogs;
    3125                 :     bool canceled;
    3126               0 :     NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(slot));
    3127                 : 
    3128                 :     rv = getNSSDialogs((void**)&dialogs,
    3129                 :                        NS_GET_IID(nsITokenPasswordDialogs),
    3130               0 :                        NS_TOKENPASSWORDSDIALOG_CONTRACTID);
    3131                 : 
    3132               0 :     if (NS_FAILED(rv)) goto loser;
    3133                 : 
    3134                 :     {
    3135               0 :       nsPSMUITracker tracker;
    3136               0 :       if (tracker.isUIForbidden()) {
    3137               0 :         rv = NS_ERROR_NOT_AVAILABLE;
    3138                 :       }
    3139                 :       else {
    3140                 :         rv = dialogs->SetPassword(ctx,
    3141                 :                                   tokenName.get(),
    3142               0 :                                   &canceled);
    3143                 :       }
    3144                 :     }
    3145               0 :     NS_RELEASE(dialogs);
    3146               0 :     if (NS_FAILED(rv)) goto loser;
    3147                 : 
    3148               0 :     if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
    3149                 :   }
    3150                 :  loser:
    3151             339 :   return rv;
    3152                 : }
    3153                 : 
    3154                 : 
    3155               0 : PSMContentDownloader::PSMContentDownloader(PRUint32 type)
    3156                 :   : mByteData(nsnull),
    3157                 :     mType(type),
    3158               0 :     mDoSilentDownload(false)
    3159                 : {
    3160               0 : }
    3161                 : 
    3162               0 : PSMContentDownloader::~PSMContentDownloader()
    3163                 : {
    3164               0 :   if (mByteData)
    3165               0 :     nsMemory::Free(mByteData);
    3166               0 : }
    3167                 : 
    3168               0 : NS_IMPL_ISUPPORTS2(PSMContentDownloader, nsIStreamListener, nsIRequestObserver)
    3169                 : 
    3170                 : const PRInt32 kDefaultCertAllocLength = 2048;
    3171                 : 
    3172                 : NS_IMETHODIMP
    3173               0 : PSMContentDownloader::OnStartRequest(nsIRequest* request, nsISupports* context)
    3174                 : {
    3175                 :   nsresult rv;
    3176               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnStartRequest\n"));
    3177               0 :   nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
    3178               0 :   if (!channel) return NS_ERROR_FAILURE;
    3179                 : 
    3180                 :   // Get the URI //
    3181               0 :   channel->GetURI(getter_AddRefs(mURI));
    3182                 : 
    3183                 :   PRInt32 contentLength;
    3184               0 :   rv = channel->GetContentLength(&contentLength);
    3185               0 :   if (NS_FAILED(rv) || contentLength <= 0)
    3186               0 :     contentLength = kDefaultCertAllocLength;
    3187                 :   
    3188               0 :   mBufferOffset = 0;
    3189               0 :   mBufferSize = 0;
    3190               0 :   mByteData = (char*) nsMemory::Alloc(contentLength);
    3191               0 :   if (!mByteData)
    3192               0 :     return NS_ERROR_OUT_OF_MEMORY;
    3193                 :   
    3194               0 :   mBufferSize = contentLength;
    3195               0 :   return NS_OK;
    3196                 : }
    3197                 : 
    3198                 : NS_IMETHODIMP
    3199               0 : PSMContentDownloader::OnDataAvailable(nsIRequest* request,
    3200                 :                                 nsISupports* context,
    3201                 :                                 nsIInputStream *aIStream,
    3202                 :                                 PRUint32 aSourceOffset,
    3203                 :                                 PRUint32 aLength)
    3204                 : {
    3205               0 :   if (!mByteData)
    3206               0 :     return NS_ERROR_OUT_OF_MEMORY;
    3207                 :   
    3208                 :   PRUint32 amt;
    3209                 :   nsresult err;
    3210                 :   //Do a check to see if we need to allocate more memory.
    3211               0 :   if ((mBufferOffset + (PRInt32)aLength) > mBufferSize) {
    3212               0 :       size_t newSize = (mBufferOffset + aLength) *2; // grow some more than needed
    3213                 :       char *newBuffer;
    3214               0 :       newBuffer = (char*)nsMemory::Realloc(mByteData, newSize);
    3215               0 :       if (newBuffer == nsnull) {
    3216               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3217                 :       }
    3218               0 :       mByteData = newBuffer;
    3219               0 :       mBufferSize = newSize;
    3220                 :   }
    3221                 :   
    3222               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnDataAvailable\n"));
    3223               0 :   do {
    3224                 :     err = aIStream->Read(mByteData+mBufferOffset,
    3225               0 :                          aLength, &amt);
    3226               0 :     if (NS_FAILED(err)) return err;
    3227               0 :     if (amt == 0) break;
    3228                 :     
    3229               0 :     aLength -= amt;
    3230               0 :     mBufferOffset += amt;
    3231                 :     
    3232                 :   } while (aLength > 0);
    3233                 :   
    3234               0 :   return NS_OK;
    3235                 : }
    3236                 : 
    3237                 : NS_IMETHODIMP
    3238               0 : PSMContentDownloader::OnStopRequest(nsIRequest* request,
    3239                 :                               nsISupports* context,
    3240                 :                               nsresult aStatus)
    3241                 : {
    3242               0 :   nsNSSShutDownPreventionLock locker;
    3243                 :   //Check if the download succeeded - it might have failed due to
    3244                 :   //network issues, etc.
    3245               0 :   if (NS_FAILED(aStatus)){
    3246               0 :     handleContentDownloadError(aStatus);
    3247               0 :     return aStatus;
    3248                 :   }
    3249                 : 
    3250               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnStopRequest\n"));
    3251                 : 
    3252               0 :   nsCOMPtr<nsIX509CertDB> certdb;
    3253               0 :   nsCOMPtr<nsICRLManager> crlManager;
    3254                 : 
    3255                 :   nsresult rv;
    3256               0 :   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
    3257                 : 
    3258               0 :   switch (mType) {
    3259                 :   case PSMContentDownloader::X509_CA_CERT:
    3260                 :   case PSMContentDownloader::X509_USER_CERT:
    3261                 :   case PSMContentDownloader::X509_EMAIL_CERT:
    3262               0 :     certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
    3263               0 :     break;
    3264                 : 
    3265                 :   case PSMContentDownloader::PKCS7_CRL:
    3266               0 :     crlManager = do_GetService(NS_CRLMANAGER_CONTRACTID);
    3267                 : 
    3268                 :   default:
    3269               0 :     break;
    3270                 :   }
    3271                 : 
    3272               0 :   switch (mType) {
    3273                 :   case PSMContentDownloader::X509_CA_CERT:
    3274               0 :     return certdb->ImportCertificates((PRUint8*)mByteData, mBufferOffset, mType, ctx); 
    3275                 :   case PSMContentDownloader::X509_USER_CERT:
    3276               0 :     return certdb->ImportUserCertificate((PRUint8*)mByteData, mBufferOffset, ctx);
    3277                 :   case PSMContentDownloader::X509_EMAIL_CERT:
    3278               0 :     return certdb->ImportEmailCertificate((PRUint8*)mByteData, mBufferOffset, ctx); 
    3279                 :   case PSMContentDownloader::PKCS7_CRL:
    3280               0 :     return crlManager->ImportCrl((PRUint8*)mByteData, mBufferOffset, mURI, SEC_CRL_TYPE, mDoSilentDownload, mCrlAutoDownloadKey.get());
    3281                 :   default:
    3282               0 :     rv = NS_ERROR_FAILURE;
    3283                 :     break;
    3284                 :   }
    3285                 :   
    3286               0 :   return rv;
    3287                 : }
    3288                 : 
    3289                 : 
    3290                 : nsresult
    3291               0 : PSMContentDownloader::handleContentDownloadError(nsresult errCode)
    3292                 : {
    3293               0 :   nsString tmpMessage;
    3294                 :   nsresult rv;
    3295               0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
    3296               0 :   if(NS_FAILED(rv)){
    3297               0 :     return rv;
    3298                 :   }
    3299                 :       
    3300                 :   //Handling errors for crl download only, for now.
    3301               0 :   switch (mType){
    3302                 :   case PSMContentDownloader::PKCS7_CRL:
    3303                 : 
    3304                 :     //TO DO: Handle network errors in details
    3305                 :     //XXXXXXXXXXXXXXXXXX
    3306               0 :     nssComponent->GetPIPNSSBundleString("CrlImportFailureNetworkProblem", tmpMessage);
    3307                 :       
    3308               0 :     if (mDoSilentDownload) {
    3309                 :       //This is the case for automatic download. Update failure history
    3310               0 :       nsCAutoString updateErrCntPrefStr(CRL_AUTOUPDATE_ERRCNT_PREF);
    3311               0 :       nsCAutoString updateErrDetailPrefStr(CRL_AUTOUPDATE_ERRDETAIL_PREF);
    3312                 :       PRUnichar *nameInDb;
    3313               0 :       nsCString errMsg;
    3314                 :       PRInt32 errCnt;
    3315                 : 
    3316               0 :       nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID,&rv);
    3317               0 :       if(NS_FAILED(rv)){
    3318               0 :         return rv;
    3319                 :       }
    3320                 :       
    3321               0 :       nameInDb = (PRUnichar *)mCrlAutoDownloadKey.get();
    3322               0 :       updateErrCntPrefStr.AppendWithConversion(nameInDb);
    3323               0 :       updateErrDetailPrefStr.AppendWithConversion(nameInDb);  
    3324               0 :       errMsg.AssignWithConversion(tmpMessage.get());
    3325                 :       
    3326               0 :       rv = pref->GetIntPref(updateErrCntPrefStr.get(),&errCnt);
    3327               0 :       if( (NS_FAILED(rv)) || (errCnt == 0) ){
    3328               0 :         pref->SetIntPref(updateErrCntPrefStr.get(),1);
    3329                 :       }else{
    3330               0 :         pref->SetIntPref(updateErrCntPrefStr.get(),errCnt+1);
    3331                 :       }
    3332               0 :       pref->SetCharPref(updateErrDetailPrefStr.get(),errMsg.get());
    3333               0 :       nsCOMPtr<nsIPrefService> prefSvc(do_QueryInterface(pref));
    3334               0 :       prefSvc->SavePrefFile(nsnull);
    3335                 :     }else{
    3336               0 :       nsString message;
    3337               0 :       nssComponent->GetPIPNSSBundleString("CrlImportFailure1x", message);
    3338               0 :       message.Append(NS_LITERAL_STRING("\n").get());
    3339               0 :       message.Append(tmpMessage);
    3340               0 :       nssComponent->GetPIPNSSBundleString("CrlImportFailure2", tmpMessage);
    3341               0 :       message.Append(NS_LITERAL_STRING("\n").get());
    3342               0 :       message.Append(tmpMessage);
    3343               0 :       nsNSSComponent::ShowAlertWithConstructedString(message);
    3344                 :     }
    3345               0 :     break;
    3346                 :   default:
    3347               0 :     break;
    3348                 :   }
    3349                 : 
    3350               0 :   return NS_OK;
    3351                 : 
    3352                 : }
    3353                 : 
    3354                 : void 
    3355               0 : PSMContentDownloader::setSilentDownload(bool flag)
    3356                 : {
    3357               0 :   mDoSilentDownload = flag;
    3358               0 : }
    3359                 : 
    3360                 : void
    3361               0 : PSMContentDownloader::setCrlAutodownloadKey(nsAutoString key)
    3362                 : {
    3363               0 :   mCrlAutoDownloadKey = key;
    3364               0 : }
    3365                 : 
    3366                 : 
    3367                 : /* other mime types that we should handle sometime:
    3368                 :    
    3369                 :    application/x-pkcs7-crl
    3370                 :    application/x-pkcs7-mime
    3371                 :    application/pkcs7-signature
    3372                 :    application/pre-encrypted
    3373                 :    
    3374                 : */
    3375                 : 
    3376                 : PRUint32
    3377               0 : getPSMContentType(const char * aContentType)
    3378                 : { 
    3379                 :   // Don't forget to update RegisterPSMContentListeners in nsNSSModule.cpp 
    3380                 :   // for every supported content type.
    3381                 :   
    3382               0 :   if (!nsCRT::strcasecmp(aContentType, "application/x-x509-ca-cert"))
    3383               0 :     return PSMContentDownloader::X509_CA_CERT;
    3384               0 :   else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-server-cert"))
    3385               0 :     return PSMContentDownloader::X509_SERVER_CERT;
    3386               0 :   else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-user-cert"))
    3387               0 :     return PSMContentDownloader::X509_USER_CERT;
    3388               0 :   else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-email-cert"))
    3389               0 :     return PSMContentDownloader::X509_EMAIL_CERT;
    3390               0 :   else if (!nsCRT::strcasecmp(aContentType, "application/x-pkcs7-crl"))
    3391               0 :     return PSMContentDownloader::PKCS7_CRL;
    3392               0 :   else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-crl"))
    3393               0 :     return PSMContentDownloader::PKCS7_CRL;
    3394               0 :   else if (!nsCRT::strcasecmp(aContentType, "application/pkix-crl"))
    3395               0 :     return PSMContentDownloader::PKCS7_CRL;
    3396               0 :   return PSMContentDownloader::UNKNOWN_TYPE;
    3397                 : }
    3398                 : 
    3399                 : 
    3400            4592 : NS_IMPL_ISUPPORTS2(PSMContentListener,
    3401                 :                    nsIURIContentListener,
    3402                 :                    nsISupportsWeakReference) 
    3403                 : 
    3404             328 : PSMContentListener::PSMContentListener()
    3405                 : {
    3406             328 :   mLoadCookie = nsnull;
    3407             328 :   mParentContentListener = nsnull;
    3408             328 : }
    3409                 : 
    3410             656 : PSMContentListener::~PSMContentListener()
    3411                 : {
    3412            1312 : }
    3413                 : 
    3414                 : nsresult
    3415             328 : PSMContentListener::init()
    3416                 : {
    3417             328 :   return NS_OK;
    3418                 : }
    3419                 : 
    3420                 : NS_IMETHODIMP
    3421               0 : PSMContentListener::OnStartURIOpen(nsIURI *aURI, bool *aAbortOpen)
    3422                 : {
    3423                 :   //if we don't want to handle the URI, return true in
    3424                 :   //*aAbortOpen
    3425               0 :   return NS_OK;
    3426                 : }
    3427                 : 
    3428                 : NS_IMETHODIMP
    3429               0 : PSMContentListener::IsPreferred(const char * aContentType,
    3430                 :                                  char ** aDesiredContentType,
    3431                 :                                  bool * aCanHandleContent)
    3432                 : {
    3433                 :   return CanHandleContent(aContentType, true,
    3434               0 :                           aDesiredContentType, aCanHandleContent);
    3435                 : }
    3436                 : 
    3437                 : NS_IMETHODIMP
    3438               0 : PSMContentListener::CanHandleContent(const char * aContentType,
    3439                 :                                       bool aIsContentPreferred,
    3440                 :                                       char ** aDesiredContentType,
    3441                 :                                       bool * aCanHandleContent)
    3442                 : {
    3443                 :   PRUint32 type;
    3444               0 :   type = getPSMContentType(aContentType);
    3445               0 :   if (type == PSMContentDownloader::UNKNOWN_TYPE) {
    3446               0 :     *aCanHandleContent = false;
    3447                 :   } else {
    3448               0 :     *aCanHandleContent = true;
    3449                 :   }
    3450               0 :   return NS_OK;
    3451                 : }
    3452                 : 
    3453                 : NS_IMETHODIMP
    3454               0 : PSMContentListener::DoContent(const char * aContentType,
    3455                 :                                bool aIsContentPreferred,
    3456                 :                                nsIRequest * aRequest,
    3457                 :                                nsIStreamListener ** aContentHandler,
    3458                 :                                bool * aAbortProcess)
    3459                 : {
    3460                 :   PSMContentDownloader *downLoader;
    3461                 :   PRUint32 type;
    3462               0 :   type = getPSMContentType(aContentType);
    3463               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("PSMContentListener::DoContent\n"));
    3464               0 :   if (type != PSMContentDownloader::UNKNOWN_TYPE) {
    3465               0 :     downLoader = new PSMContentDownloader(type);
    3466               0 :     if (downLoader) {
    3467                 :       downLoader->QueryInterface(NS_GET_IID(nsIStreamListener), 
    3468               0 :                                             (void **)aContentHandler);
    3469               0 :       return NS_OK;
    3470                 :     }
    3471                 :   }
    3472               0 :   return NS_ERROR_FAILURE;
    3473                 : }
    3474                 : 
    3475                 : NS_IMETHODIMP
    3476               0 : PSMContentListener::GetLoadCookie(nsISupports * *aLoadCookie)
    3477                 : {
    3478               0 :   *aLoadCookie = mLoadCookie;
    3479               0 :   NS_IF_ADDREF(*aLoadCookie);
    3480               0 :   return NS_OK;
    3481                 : }
    3482                 : 
    3483                 : NS_IMETHODIMP
    3484               0 : PSMContentListener::SetLoadCookie(nsISupports * aLoadCookie)
    3485                 : {
    3486               0 :   mLoadCookie = aLoadCookie;
    3487               0 :   return NS_OK;
    3488                 : }
    3489                 : 
    3490                 : NS_IMETHODIMP
    3491               0 : PSMContentListener::GetParentContentListener(nsIURIContentListener ** aContentListener)
    3492                 : {
    3493               0 :   *aContentListener = mParentContentListener;
    3494               0 :   NS_IF_ADDREF(*aContentListener);
    3495               0 :   return NS_OK;
    3496                 : }
    3497                 : 
    3498                 : NS_IMETHODIMP
    3499               0 : PSMContentListener::SetParentContentListener(nsIURIContentListener * aContentListener)
    3500                 : {
    3501               0 :   mParentContentListener = aContentListener;
    3502               0 :   return NS_OK;
    3503                 : }

Generated by: LCOV version 1.7