LCOV - app.info - security/manager/ssl/src/nsNSSComponent.cpp

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-04-21 | 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           10114 : bool EnsureNSSInitialized(EnsureNSSOperator op)
         283                 : {
         284           10114 :   if (nsPSMInitPanic::GetPanic())
         285               0 :     return false;
         286                 :
         287           10114 :   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           10114 :   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             327 :     if (loading)
         312               0 :       return false; // We are reentered during nss component creation
         313             327 :     loading = true;
         314             327 :     return true;
         315                 :
         316                 :   case nssInitSucceeded:
         317             327 :     NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitSucceeded)");
         318             327 :     loading = false;
         319             327 :     PR_AtomicSet(&haveLoaded, 1);
         320             327 :     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             654 :     PR_AtomicSet(&haveLoaded, 0);
         329             654 :     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            8806 :     if (PR_AtomicAdd(&haveLoaded, 0) || loading)
         338            8528 :       return true;
         339                 :
         340                 :     {
         341                 :     nsCOMPtr<nsINSSComponent> nssComponent
         342             556 :       = 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             278 :     if (!nssComponent)
         347               0 :       return false;
         348                 :
         349                 :     bool isInitialized;
         350             278 :     nsresult rv = nssComponent->IsNSSInitialized(&isInitialized);
         351             278 :     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             327 : nsNSSComponent::nsNSSComponent()
         361                 :   :mutex("nsNSSComponent.mutex"),
         362                 :    mNSSInitialized(false),
         363                 :    mCrlTimerLock("nsNSSComponent.mCrlTimerLock"),
         364                 :    mThreadList(nsnull),
         365             327 :    mCertVerificationThread(NULL)
         366                 : {
         367                 : #ifdef PR_LOGGING
         368             327 :   if (!gPIPNSSLog)
         369             327 :     gPIPNSSLog = PR_NewLogModule("pipnss");
         370                 : #endif
         371             327 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ctor\n"));
         372             327 :   mUpdateTimerInitialized = false;
         373             327 :   crlDownloadTimerOn = false;
         374             327 :   crlsScheduledForDownload = nsnull;
         375             327 :   mTimer = nsnull;
         376             327 :   mObserversRegistered = false;
         377                 :
         378                 :   // In order to keep startup time lower, we delay loading and
         379                 :   // registering all identity data until first needed.
         380             327 :   memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
         381                 :
         382             327 :   NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
         383             327 :   ++mInstanceCount;
         384             327 :   hashTableCerts = nsnull;
         385             327 :   mShutdownObjectList = nsNSSShutDownList::construct();
         386             327 :   mIsNetworkDown = false;
         387             327 : }
         388                 :
         389                 : void
         390             327 : nsNSSComponent::deleteBackgroundThreads()
         391                 : {
         392             327 :   if (mCertVerificationThread)
         393                 :   {
         394             327 :     mCertVerificationThread->requestExit();
         395             327 :     delete mCertVerificationThread;
         396             327 :     mCertVerificationThread = nsnull;
         397                 :   }
         398             327 : }
         399                 :
         400                 : void
         401             327 : nsNSSComponent::createBackgroundThreads()
         402                 : {
         403             327 :   NS_ASSERTION(mCertVerificationThread == nsnull,
         404                 :                "Cert verification thread already created.");
         405                 :
         406             327 :   mCertVerificationThread = new nsCertVerificationThread;
         407             327 :   nsresult rv = mCertVerificationThread->startThread();
         408             327 :   if (NS_FAILED(rv)) {
         409               0 :     delete mCertVerificationThread;
         410               0 :     mCertVerificationThread = nsnull;
         411                 :   }
         412             327 : }
         413                 :
         414             981 : nsNSSComponent::~nsNSSComponent()
         415                 : {
         416             327 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor\n"));
         417                 :
         418             327 :   deleteBackgroundThreads();
         419                 :
         420             327 :   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             327 :   ShutdownNSS();
         439             327 :   nsSSLIOLayerHelpers::Cleanup();
         440             327 :   --mInstanceCount;
         441             327 :   delete mShutdownObjectList;
         442                 :
         443                 :   // We are being freed, drop the haveLoaded flag to re-enable
         444                 :   // potential nss initialization later.
         445             327 :   EnsureNSSInitialized(nssShutdown);
         446                 :
         447             327 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n"));
         448            1308 : }
         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            3270 : nsNSSComponent::GetPIPNSSBundleString(const char *name,
         616                 :                                       nsAString &outString)
         617                 : {
         618            3270 :   nsresult rv = NS_ERROR_FAILURE;
         619                 :
         620            3270 :   outString.SetLength(0);
         621            3270 :   if (mPIPNSSBundle && name) {
         622            6540 :     nsXPIDLString result;
         623            6540 :     rv = mPIPNSSBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
         624            6540 :                                           getter_Copies(result));
         625            3270 :     if (NS_SUCCEEDED(rv)) {
         626            3270 :       outString = result;
         627            3270 :       rv = NS_OK;
         628                 :     }
         629                 :   }
         630                 :
         631            3270 :   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             327 : nsNSSComponent::LaunchSmartCardThreads()
         676                 : {
         677             654 :   nsNSSShutDownPreventionLock locker;
         678                 :   {
         679                 :     SECMODModuleList *list;
         680             327 :     SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
         681             327 :     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             327 :     SECMOD_GetReadLock(lock);
         687             327 :     list = SECMOD_GetDefaultModuleList();
         688                 :
         689            1308 :     while (list) {
         690             654 :       SECMODModule *module = list->module;
         691             654 :       LaunchSmartCardThread(module);
         692             654 :       list = list->next;
         693                 :     }
         694             327 :     SECMOD_ReleaseReadLock(lock);
         695                 :   }
         696                 : }
         697                 :
         698                 : NS_IMETHODIMP
         699             654 : nsNSSComponent::LaunchSmartCardThread(SECMODModule *module)
         700                 : {
         701                 :   SmartCardMonitoringThread *newThread;
         702             654 :   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             654 :   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             327 : nsNSSComponent::ShutdownSmartCardThreads()
         731                 : {
         732             327 :   delete mThreadList;
         733             327 :   mThreadList = nsnull;
         734             327 : }
         735                 :
         736                 : static char *
         737             327 : nss_addEscape(const char *string, char quote)
         738                 : {
         739             327 :     char *newString = 0;
         740             327 :     int escapes = 0, size = 0;
         741                 :     const char *src;
         742                 :     char *dest;
         743                 :
         744           24852 :     for (src=string; *src ; src++) {
         745           24525 :         if ((*src == quote) || (*src == '\\')) {
         746               0 :           escapes++;
         747                 :         }
         748           24525 :         size++;
         749                 :     }
         750                 :
         751             327 :     newString = (char*)PORT_ZAlloc(escapes+size+1);
         752             327 :     if (newString == NULL) {
         753               0 :         return NULL;
         754                 :     }
         755                 :
         756           24852 :     for (src=string, dest=newString; *src; src++,dest++) {
         757           24525 :         if ((*src == quote) || (*src == '\\')) {
         758               0 :             *dest++ = '\\';
         759                 :         }
         760           24525 :         *dest = *src;
         761                 :     }
         762                 :
         763             327 :     return newString;
         764                 : }
         765                 :
         766                 : void
         767             327 : nsNSSComponent::InstallLoadableRoots()
         768                 : {
         769             654 :   nsNSSShutDownPreventionLock locker;
         770             327 :   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             327 :     SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
         784             327 :     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             327 :     SECMOD_GetReadLock(lock);
         790             327 :     list = SECMOD_GetDefaultModuleList();
         791                 :
         792             981 :     while (!RootsModule && list) {
         793             327 :       SECMODModule *module = list->module;
         794                 :
         795             981 :       for (int i=0; i < module->slotCount; i++) {
         796             654 :         PK11SlotInfo *slot = module->slots[i];
         797             654 :         if (PK11_IsPresent(slot)) {
         798             654 :           if (PK11_HasRootCerts(slot)) {
         799               0 :             RootsModule = SECMOD_ReferenceModule(module);
         800               0 :             break;
         801                 :           }
         802                 :         }
         803                 :       }
         804                 :
         805             327 :       list = list->next;
         806                 :     }
         807             327 :     SECMOD_ReleaseReadLock(lock);
         808                 :   }
         809                 :
         810             327 :   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             654 :   nsAutoString modName;
         823             327 :   rv = GetPIPNSSBundleString("RootCertModuleName", modName);
         824             327 :   if (NS_FAILED(rv)) return;
         825                 :
         826             654 :   nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
         827             327 :   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             327 :   };
         840                 :
         841             327 :   for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
         842             654 :     nsCOMPtr<nsILocalFile> mozFile;
         843             327 :     char *fullLibraryPath = nsnull;
         844                 :
         845             327 :     if (!possible_ckbi_locations[il])
         846                 :     {
         847               0 :       fullLibraryPath = PR_GetLibraryName(nsnull, "nssckbi");
         848                 :     }
         849                 :     else
         850                 :     {
         851             327 :       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             327 :                                                    (PRFuncPtr) NSS_Initialize);
         855             327 :         if (!nss_path) {
         856               0 :           continue;
         857                 :         }
         858                 :         // Get the directory containing the nss3 library.
         859             654 :         nsCOMPtr<nsILocalFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
         860             327 :         if (NS_SUCCEEDED(rv)) {
         861             327 :           rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
         862                 :         }
         863             327 :         PR_Free(nss_path);
         864             327 :         if (NS_SUCCEEDED(rv)) {
         865             654 :           nsCOMPtr<nsIFile> file;
         866             327 :           if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
         867             327 :             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             327 :       if (!mozFile) {
         877               0 :         continue;
         878                 :       }
         879                 :
         880             654 :       nsCAutoString processDir;
         881             327 :       mozFile->GetNativePath(processDir);
         882             327 :       fullLibraryPath = PR_GetLibraryName(processDir.get(), "nssckbi");
         883                 :     }
         884                 :
         885             327 :     if (!fullLibraryPath) {
         886               0 :       continue;
         887                 :     }
         888                 :
         889             327 :     char *escaped_fullLibraryPath = nss_addEscape(fullLibraryPath, '\"');
         890             327 :     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             654 :     NS_ConvertUTF16toUTF8 modNameUTF8(modName);
         897                 :     int modType;
         898             327 :     SECMOD_DeleteModule(const_cast<char*>(modNameUTF8.get()), &modType);
         899                 :
         900             654 :     nsCString pkcs11moduleSpec;
         901             327 :     pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("name=\""));
         902             327 :     pkcs11moduleSpec.Append(modNameUTF8.get());
         903             327 :     pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("\" library=\""));
         904             327 :     pkcs11moduleSpec.Append(escaped_fullLibraryPath);
         905             327 :     pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("\""));
         906                 :
         907             327 :     PR_FreeLibraryName(fullLibraryPath); // allocated by NSPR
         908             327 :     PORT_Free(escaped_fullLibraryPath);
         909                 :
         910                 :     RootsModule =
         911             327 :       SECMOD_LoadUserModule(const_cast<char*>(pkcs11moduleSpec.get()),
         912                 :                             nsnull, // no parent
         913             327 :                             false); // do not recurse
         914                 :
         915             327 :     if (RootsModule) {
         916             327 :       bool found = (RootsModule->loaded);
         917                 :
         918             327 :       SECMOD_DestroyModule(RootsModule);
         919             327 :       RootsModule = nsnull;
         920                 :
         921             327 :       if (found) {
         922                 :         break;
         923                 :       }
         924                 :     }
         925                 :   }
         926                 : }
         927                 :
         928                 : void
         929             327 : nsNSSComponent::UnloadLoadableRoots()
         930                 : {
         931                 :   nsresult rv;
         932             654 :   nsAutoString modName;
         933             327 :   rv = GetPIPNSSBundleString("RootCertModuleName", modName);
         934             327 :   if (NS_FAILED(rv)) return;
         935                 :
         936             654 :   NS_ConvertUTF16toUTF8 modNameUTF8(modName);
         937             327 :   SECMODModule *RootsModule = SECMOD_FindModule(modNameUTF8.get());
         938                 :
         939             327 :   if (RootsModule) {
         940             327 :     SECMOD_UnloadUserModule(RootsModule);
         941             327 :     SECMOD_DestroyModule(RootsModule);
         942                 :   }
         943                 : }
         944                 :
         945                 : nsresult
         946             327 : nsNSSComponent::ConfigureInternalPKCS11Token()
         947                 : {
         948             654 :   nsNSSShutDownPreventionLock locker;
         949             654 :   nsAutoString manufacturerID;
         950             654 :   nsAutoString libraryDescription;
         951             654 :   nsAutoString tokenDescription;
         952             654 :   nsAutoString privateTokenDescription;
         953             654 :   nsAutoString slotDescription;
         954             654 :   nsAutoString privateSlotDescription;
         955             654 :   nsAutoString fips140TokenDescription;
         956             654 :   nsAutoString fips140SlotDescription;
         957                 :
         958                 :   nsresult rv;
         959             327 :   rv = GetPIPNSSBundleString("ManufacturerID", manufacturerID);
         960             327 :   if (NS_FAILED(rv)) return rv;
         961                 :
         962             327 :   rv = GetPIPNSSBundleString("LibraryDescription", libraryDescription);
         963             327 :   if (NS_FAILED(rv)) return rv;
         964                 :
         965             327 :   rv = GetPIPNSSBundleString("TokenDescription", tokenDescription);
         966             327 :   if (NS_FAILED(rv)) return rv;
         967                 :
         968             327 :   rv = GetPIPNSSBundleString("PrivateTokenDescription", privateTokenDescription);
         969             327 :   if (NS_FAILED(rv)) return rv;
         970                 :
         971             327 :   rv = GetPIPNSSBundleString("SlotDescription", slotDescription);
         972             327 :   if (NS_FAILED(rv)) return rv;
         973                 :
         974             327 :   rv = GetPIPNSSBundleString("PrivateSlotDescription", privateSlotDescription);
         975             327 :   if (NS_FAILED(rv)) return rv;
         976                 :
         977             327 :   rv = GetPIPNSSBundleString("Fips140TokenDescription", fips140TokenDescription);
         978             327 :   if (NS_FAILED(rv)) return rv;
         979                 :
         980             327 :   rv = GetPIPNSSBundleString("Fips140SlotDescription", fips140SlotDescription);
         981             327 :   if (NS_FAILED(rv)) return rv;
         982                 :
         983             327 :   PK11_ConfigurePKCS11(NS_ConvertUTF16toUTF8(manufacturerID).get(),
         984             327 :                        NS_ConvertUTF16toUTF8(libraryDescription).get(),
         985             327 :                        NS_ConvertUTF16toUTF8(tokenDescription).get(),
         986             327 :                        NS_ConvertUTF16toUTF8(privateTokenDescription).get(),
         987             327 :                        NS_ConvertUTF16toUTF8(slotDescription).get(),
         988             327 :                        NS_ConvertUTF16toUTF8(privateSlotDescription).get(),
         989             327 :                        NS_ConvertUTF16toUTF8(fips140TokenDescription).get(),
         990             327 :                        NS_ConvertUTF16toUTF8(fips140SlotDescription).get(),
         991             327 :                        0, 0);
         992             327 :   return NS_OK;
         993                 : }
         994                 :
         995                 : nsresult
         996             327 : nsNSSComponent::InitializePIPNSSBundle()
         997                 : {
         998                 :   // Called during init only, no mutex required.
         999                 :
        1000                 :   nsresult rv;
        1001             654 :   nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
        1002             327 :   if (NS_FAILED(rv) || !bundleService)
        1003               0 :     return NS_ERROR_FAILURE;
        1004                 :
        1005             327 :   bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL,
        1006             327 :                               getter_AddRefs(mPIPNSSBundle));
        1007             327 :   if (!mPIPNSSBundle)
        1008               0 :     rv = NS_ERROR_FAILURE;
        1009                 :
        1010             327 :   bundleService->CreateBundle(NSSERR_STRBUNDLE_URL,
        1011             327 :                               getter_AddRefs(mNSSErrorsBundle));
        1012             327 :   if (!mNSSErrorsBundle)
        1013               0 :     rv = NS_ERROR_FAILURE;
        1014                 :
        1015             327 :   return rv;
        1016                 : }
        1017                 :
        1018                 : nsresult
        1019             327 : nsNSSComponent::RegisterPSMContentListener()
        1020                 : {
        1021                 :   // Called during init only, no mutex required.
        1022                 :
        1023             327 :   nsresult rv = NS_OK;
        1024             327 :   if (!mPSMContentListener) {
        1025             654 :     nsCOMPtr<nsIURILoader> dispatcher(do_GetService(NS_URI_LOADER_CONTRACTID));
        1026             327 :     if (dispatcher) {
        1027             327 :       mPSMContentListener = do_CreateInstance(NS_PSMCONTENTLISTEN_CONTRACTID);
        1028             327 :       rv = dispatcher->RegisterContentListener(mPSMContentListener);
        1029                 :     }
        1030                 :   }
        1031             327 :   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             327 : setNonPkixOcspEnabled(PRInt32 ocspEnabled, nsIPrefBranch * pref)
        1099                 : {
        1100             327 :   switch (ocspEnabled) {
        1101                 :   case 0:
        1102               0 :     CERT_DisableOCSPChecking(CERT_GetDefaultCertDB());
        1103               0 :     CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
        1104               0 :     break;
        1105                 :   case 1:
        1106             327 :     CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
        1107             327 :     CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
        1108             327 :     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             327 : }
        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             327 : void nsNSSComponent::setValidationOptions(nsIPrefBranch * pref)
        1140                 : {
        1141             654 :   nsNSSShutDownPreventionLock locker;
        1142                 :   nsresult rv;
        1143                 :
        1144                 :   bool crlDownloading;
        1145             327 :   rv = pref->GetBoolPref("security.CRL_download.enabled", &crlDownloading);
        1146             327 :   if (NS_FAILED(rv))
        1147             327 :     crlDownloading = CRL_DOWNLOAD_DEFAULT;
        1148                 :
        1149                 :   PRInt32 ocspEnabled;
        1150             327 :   rv = pref->GetIntPref("security.OCSP.enabled", &ocspEnabled);
        1151                 :   // 0 = disabled, 1 = enabled,
        1152                 :   // 2 = enabled with given default responder
        1153             327 :   if (NS_FAILED(rv))
        1154               0 :     ocspEnabled = OCSP_ENABLED_DEFAULT;
        1155                 :
        1156                 :   bool ocspRequired;
        1157             327 :   rv = pref->GetBoolPref("security.OCSP.require", &ocspRequired);
        1158             327 :   if (NS_FAILED(rv))
        1159               0 :     ocspRequired = OCSP_REQUIRED_DEFAULT;
        1160                 :
        1161                 :   bool anyFreshRequired;
        1162             327 :   rv = pref->GetBoolPref("security.fresh_revocation_info.require", &anyFreshRequired);
        1163             327 :   if (NS_FAILED(rv))
        1164             327 :     anyFreshRequired = FRESH_REVOCATION_REQUIRED_DEFAULT;
        1165                 :
        1166                 :   bool aiaDownloadEnabled;
        1167             327 :   rv = pref->GetBoolPref("security.missing_cert_download.enabled", &aiaDownloadEnabled);
        1168             327 :   if (NS_FAILED(rv))
        1169             327 :     aiaDownloadEnabled = MISSING_CERT_DOWNLOAD_DEFAULT;
        1170                 :
        1171             654 :   nsCString firstNetworkRevo;
        1172             327 :   rv = pref->GetCharPref("security.first_network_revocation_method", getter_Copies(firstNetworkRevo));
        1173             327 :   if (NS_FAILED(rv))
        1174             327 :     firstNetworkRevo = FIRST_REVO_METHOD_DEFAULT;
        1175                 :
        1176             327 :   setNonPkixOcspEnabled(ocspEnabled, pref);
        1177                 :
        1178                 :   CERT_SetOCSPFailureMode( ocspRequired ?
        1179                 :                            ocspMode_FailureIsVerificationFailure
        1180             327 :                            : ocspMode_FailureIsNotAVerificationFailure);
        1181                 :
        1182             654 :   nsRefPtr<nsCERTValInParamWrapper> newCVIN = new nsCERTValInParamWrapper;
        1183             327 :   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             327 :     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             327 :   SSL_ClearSessionCache();
        1205             327 : }
        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             327 : nsresult nsNSSComponent::getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key)
        1278                 : {
        1279             327 :   const char *updateEnabledPref = CRL_AUTOUPDATE_ENABLED_PREF;
        1280             327 :   const char *updateTimePref = CRL_AUTOUPDATE_TIME_PREF;
        1281             327 :   const char *updateURLPref = CRL_AUTOUPDATE_URL_PREF;
        1282                 :   char **allCrlsToBeUpdated;
        1283                 :   PRUint32 noOfCrls;
        1284             327 :   PRTime nearestUpdateTime = 0;
        1285             654 :   nsAutoString crlKey;
        1286                 :   char *tempUrl;
        1287                 :   nsresult rv;
        1288                 :
        1289             654 :   nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID,&rv);
        1290             327 :   if(NS_FAILED(rv)){
        1291               0 :     return rv;
        1292                 :   }
        1293                 :
        1294             327 :   rv = pref->GetChildList(updateEnabledPref, &noOfCrls, &allCrlsToBeUpdated);
        1295             327 :   if ( (NS_FAILED(rv)) || (noOfCrls==0) ){
        1296             327 :     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             327 : nsNSSComponent::DefineNextTimer()
        1395                 : {
        1396                 :   PRTime nextFiring;
        1397             327 :   PRTime now = PR_Now();
        1398                 :   PRUint64 diff;
        1399                 :   PRUint32 interval;
        1400             327 :   PRUint32 primaryDelay = CRL_AUTOUPDATE_DEFAULT_DELAY;
        1401                 :   nsresult rv;
        1402                 :
        1403             327 :   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             654 :   MutexAutoLock lock(mCrlTimerLock);
        1415                 :
        1416             327 :   if (crlDownloadTimerOn) {
        1417               0 :     mTimer->Cancel();
        1418                 :   }
        1419                 :
        1420             327 :   rv = getParamsForNextCrlToDownload(&mDownloadURL, &nextFiring, &mCrlUpdateKey);
        1421                 :   //If there are no more crls to be updated any time in future
        1422             327 :   if(NS_FAILED(rv)){
        1423                 :     // Return - no error - just implies nothing to schedule
        1424             327 :     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             314 : nsNSSComponent::StopCRLUpdateTimer()
        1450                 : {
        1451                 :
        1452                 :   //If it is at all running.
        1453             314 :   if (mUpdateTimerInitialized) {
        1454             310 :     if(crlsScheduledForDownload != nsnull){
        1455             310 :       crlsScheduledForDownload->Reset();
        1456             310 :       delete crlsScheduledForDownload;
        1457             310 :       crlsScheduledForDownload = nsnull;
        1458                 :     }
        1459                 :     {
        1460             620 :       MutexAutoLock lock(mCrlTimerLock);
        1461             310 :       if (crlDownloadTimerOn) {
        1462               0 :         mTimer->Cancel();
        1463                 :       }
        1464             310 :       crlDownloadTimerOn = false;
        1465                 :     }
        1466             310 :     mUpdateTimerInitialized = false;
        1467                 :   }
        1468                 :
        1469             314 :   return NS_OK;
        1470                 : }
        1471                 :
        1472                 : nsresult
        1473             327 : nsNSSComponent::InitializeCRLUpdateTimer()
        1474                 : {
        1475                 :   nsresult rv;
        1476                 :
        1477                 :   //First check if this is already initialized. Then we stop it.
        1478             327 :   if (!mUpdateTimerInitialized) {
        1479             327 :     mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
        1480             327 :     if(NS_FAILED(rv)){
        1481               0 :       return rv;
        1482                 :     }
        1483             327 :     crlsScheduledForDownload = new nsHashtable(16, true);
        1484             327 :     DefineNextTimer();
        1485             327 :     mUpdateTimerInitialized = true;
        1486                 :   }
        1487                 :
        1488             327 :   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             327 : static void configureMD5(bool enabled)
        1601                 : {
        1602             327 :   if (enabled) { // set flags
        1603                 :     NSS_SetAlgorithmPolicy(SEC_OID_MD5,
        1604             327 :         NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
        1605                 :     NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
        1606             327 :         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             327 :         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             327 : }
        1619                 :
        1620                 : nsresult
        1621             327 : nsNSSComponent::InitializeNSS(bool showWarningBox)
        1622                 : {
        1623                 :   // Can be called both during init and profile change.
        1624                 :   // Needs mutex protection.
        1625                 :
        1626             327 :   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             327 :     which_nss_problem = problem_none;
        1639                 :
        1640                 :   {
        1641             654 :     MutexAutoLock lock(mutex);
        1642                 :
        1643                 :     // Init phase 1, prepare own variables used for NSS
        1644                 :
        1645             327 :     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             654 :     nsCAutoString profileStr;
        1654             654 :     nsCOMPtr<nsIFile> profilePath;
        1655                 :
        1656                 :     rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
        1657             327 :                                 getter_AddRefs(profilePath));
        1658             327 :     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             312 :     const char *dbdir_override = getenv("MOZPSM_NSSDBDIR_OVERRIDE");
        1701             312 :     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             312 :       rv = profilePath->GetNativePath(profileStr);
        1713                 :   #endif
        1714             312 :       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             312 :       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             312 :     rv = mPrefBranch->GetBoolPref("security.use_libpkix_verification", &globalConstFlagUsePKIXVerification);
        1730             312 :     if (NS_FAILED(rv))
        1731             312 :       globalConstFlagUsePKIXVerification = USE_NSS_LIBPKIX_DEFAULT;
        1732                 :
        1733             312 :     bool supress_warning_preference = false;
        1734             312 :     rv = mPrefBranch->GetBoolPref("security.suppress_nss_rw_impossible_warning", &supress_warning_preference);
        1735                 :
        1736             312 :     if (NS_FAILED(rv)) {
        1737             312 :       supress_warning_preference = false;
        1738                 :     }
        1739                 :
        1740                 :     // init phase 2, init calls to NSS library
        1741                 :
        1742             312 :     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             312 :     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             312 :     PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
        1758                 :     SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
        1759             312 :                                          SECMOD_DB, init_flags);
        1760                 :
        1761             312 :     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             327 :     if (problem_no_security_at_all != which_nss_problem) {
        1792                 :
        1793             327 :       mNSSInitialized = true;
        1794                 :
        1795             327 :       ::NSS_SetDomesticPolicy();
        1796                 :       //  SSL_EnableCipher(SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED);
        1797                 :       //  SSL_EnableCipher(SSL_RSA_WITH_NULL_SHA, SSL_ALLOWED);
        1798                 :
        1799             327 :       PK11_SetPasswordFunc(PK11PasswordPrompt);
        1800                 :
        1801                 :       // Register an observer so we can inform NSS when these prefs change
        1802             327 :       mPrefBranch->AddObserver("security.", this, false);
        1803                 :
        1804             327 :       SSL_OptionSetDefault(SSL_ENABLE_SSL2, false);
        1805             327 :       SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, false);
        1806                 :       bool enabled;
        1807             327 :       mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
        1808             327 :       SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
        1809             327 :       mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
        1810             327 :       SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
        1811             327 :       mPrefBranch->GetBoolPref("security.enable_md5_signatures", &enabled);
        1812             327 :       configureMD5(enabled);
        1813                 :
        1814                 :       // Configure TLS session tickets
        1815             327 :       mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
        1816             327 :       SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
        1817                 :
        1818             327 :       mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
        1819             327 :       SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
        1820                 :
        1821             327 :       mPrefBranch->GetBoolPref(
        1822                 :         "security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref",
        1823             327 :         &enabled);
        1824                 :       SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
        1825             327 :         enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
        1826                 :
        1827                 : #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
        1828             327 :       mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
        1829             327 :       SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
        1830                 : #endif
        1831                 :
        1832                 :       // Disable any ciphers that NSS might have enabled by default
        1833           18639 :       for (PRUint16 i = 0; i < SSL_NumImplementedCiphers; ++i)
        1834                 :       {
        1835           18312 :         PRUint16 cipher_id = SSL_ImplementedCiphers[i];
        1836           18312 :         SSL_CipherPrefSetDefault(cipher_id, false);
        1837                 :       }
        1838                 :
        1839                 :       // Now only set SSL/TLS ciphers we knew about at compile time
        1840           16350 :       for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
        1841           16023 :         rv = mPrefBranch->GetBoolPref(cp->pref, &enabled);
        1842           16023 :         if (NS_FAILED(rv))
        1843               0 :           enabled = false;
        1844                 :
        1845           16023 :         SSL_CipherPrefSetDefault(cp->id, enabled);
        1846                 :       }
        1847                 :
        1848                 :       // Enable ciphers for PKCS#12
        1849             327 :       SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
        1850             327 :       SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
        1851             327 :       SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
        1852             327 :       SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
        1853             327 :       SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
        1854             327 :       SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
        1855             327 :       SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
        1856             327 :       PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
        1857                 :
        1858                 :       // dynamic options from prefs
        1859             327 :       setValidationOptions(mPrefBranch);
        1860                 :
        1861                 :       // static validation options for usagesarray - do not hit the network
        1862             327 :       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             327 :           FIRST_REVO_METHOD_DEFAULT);
        1870             327 :       if (NS_FAILED(rv)) {
        1871               0 :         nsPSMInitPanic::SetPanic();
        1872               0 :         return rv;
        1873                 :       }
        1874                 :
        1875             327 :       RegisterMyOCSPAIAInfoCallback();
        1876                 :
        1877             327 :       mHttpForNSS.initTable();
        1878             327 :       mHttpForNSS.registerHttpClient();
        1879                 :
        1880             327 :       InstallLoadableRoots();
        1881                 :
        1882             327 :       LaunchSmartCardThreads();
        1883                 :
        1884             327 :       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization done\n"));
        1885                 :     }
        1886                 :   }
        1887                 :
        1888             327 :   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             327 :   return NS_OK;
        1901                 : }
        1902                 :
        1903                 : nsresult
        1904             637 : nsNSSComponent::ShutdownNSS()
        1905                 : {
        1906                 :   // Can be called both during init and profile change,
        1907                 :   // needs mutex protection.
        1908                 :
        1909             637 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ShutdownNSS\n"));
        1910                 :
        1911            1274 :   MutexAutoLock lock(mutex);
        1912             637 :   nsresult rv = NS_OK;
        1913                 :
        1914             637 :   if (hashTableCerts) {
        1915             312 :     PL_HashTableEnumerateEntries(hashTableCerts, certHashtable_clearEntry, 0);
        1916             312 :     PL_HashTableDestroy(hashTableCerts);
        1917             312 :     hashTableCerts = nsnull;
        1918                 :   }
        1919                 :
        1920             637 :   if (mNSSInitialized) {
        1921             327 :     mNSSInitialized = false;
        1922                 :
        1923             327 :     PK11_SetPasswordFunc((PK11PasswordFunc)nsnull);
        1924             327 :     mHttpForNSS.unregisterHttpClient();
        1925             327 :     UnregisterMyOCSPAIAInfoCallback();
        1926                 :
        1927             327 :     if (mPrefBranch) {
        1928             327 :       mPrefBranch->RemoveObserver("security.", this);
        1929                 :     }
        1930                 :
        1931             327 :     ShutdownSmartCardThreads();
        1932             327 :     SSL_ClearSessionCache();
        1933             327 :     if (mClientAuthRememberService) {
        1934             327 :       mClientAuthRememberService->ClearRememberedDecisions();
        1935                 :     }
        1936             327 :     UnloadLoadableRoots();
        1937             327 :     CleanupIdentityInfo();
        1938             327 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("evaporating psm resources\n"));
        1939             327 :     mShutdownObjectList->evaporateAllNSSResources();
        1940             327 :     EnsureNSSInitialized(nssShutdown);
        1941             327 :     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             291 :       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS shutdown =====>> OK <<=====\n"));
        1947                 :     }
        1948                 :   }
        1949                 :
        1950             637 :   return rv;
        1951                 : }
        1952                 :
        1953                 : NS_IMETHODIMP
        1954             327 : nsNSSComponent::Init()
        1955                 : {
        1956                 :   // No mutex protection.
        1957                 :   // Assume Init happens before any concurrency on "this" can start.
        1958                 :
        1959             327 :   nsresult rv = NS_OK;
        1960                 :
        1961             327 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n"));
        1962                 :
        1963             327 :   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             327 :   rv = InitializePIPNSSBundle();
        1970             327 :   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             654 :     NS_NAMED_LITERAL_STRING(dummy_name, "dummy");
        1981             654 :     nsXPIDLString result;
        1982             327 :     mPIPNSSBundle->GetStringFromName(dummy_name.get(),
        1983             327 :                                      getter_Copies(result));
        1984             327 :     mNSSErrorsBundle->GetStringFromName(dummy_name.get(),
        1985             327 :                                         getter_Copies(result));
        1986                 :   }
        1987                 :
        1988             327 :   if (!mPrefBranch) {
        1989             327 :     mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
        1990             327 :     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             327 :   RegisterObservers();
        1995                 :
        1996             327 :   rv = InitializeNSS(true); // ok to show a warning box on failure
        1997             327 :   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             327 :   nsSSLIOLayerHelpers::Init();
        2006             327 :   char *unrestricted_hosts=nsnull;
        2007             327 :   mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
        2008             327 :   if (unrestricted_hosts) {
        2009             327 :     nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
        2010             327 :     nsMemory::Free(unrestricted_hosts);
        2011             327 :     unrestricted_hosts=nsnull;
        2012                 :   }
        2013                 :
        2014             327 :   bool enabled = false;
        2015             327 :   mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
        2016             327 :   nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
        2017                 :
        2018             327 :   PRInt32 warnLevel = 1;
        2019             327 :   mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
        2020             327 :   nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
        2021                 :
        2022             327 :   mClientAuthRememberService = new nsClientAuthRememberService;
        2023             327 :   if (mClientAuthRememberService)
        2024             327 :     mClientAuthRememberService->Init();
        2025                 :
        2026             327 :   createBackgroundThreads();
        2027             327 :   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             327 :   InitializeCRLUpdateTimer();
        2037             327 :   RegisterPSMContentListener();
        2038                 :
        2039                 :   nsCOMPtr<nsIEntropyCollector> ec
        2040             654 :       = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
        2041                 :
        2042             654 :   nsCOMPtr<nsIBufEntropyCollector> bec;
        2043                 :
        2044             327 :   if (ec) {
        2045             327 :     bec = do_QueryInterface(ec);
        2046                 :   }
        2047                 :
        2048             327 :   NS_ASSERTION(bec, "No buffering entropy collector.  "
        2049                 :                     "This means no entropy will be collected.");
        2050             327 :   if (bec) {
        2051             327 :     bec->ForwardTo(this);
        2052                 :   }
        2053                 :
        2054             327 :   return rv;
        2055                 : }
        2056                 :
        2057                 : /* nsISupports Implementation for the class */
        2058           22178 : 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             327 : nsNSSComponent::RandomUpdate(void *entropy, PRInt32 bufLen)
        2215                 : {
        2216             654 :   nsNSSShutDownPreventionLock locker;
        2217                 :
        2218                 :   // Asynchronous event happening often,
        2219                 :   // must not interfere with initialization or profile switch.
        2220                 :
        2221             654 :   MutexAutoLock lock(mutex);
        2222                 :
        2223             327 :   if (!mNSSInitialized)
        2224               0 :       return NS_ERROR_NOT_INITIALIZED;
        2225                 :
        2226             327 :   PK11_RandomUpdate(entropy, bufLen);
        2227             327 :   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            1269 : nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
        2240                 :                         const PRUnichar *someData)
        2241                 : {
        2242            1269 :   if (nsCRT::strcmp(aTopic, PROFILE_APPROVE_CHANGE_TOPIC) == 0) {
        2243               0 :     DoProfileApproveChange(aSubject);
        2244                 :   }
        2245            1269 :   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_TOPIC) == 0) {
        2246             314 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("in PSM code, receiving change-teardown\n"));
        2247             314 :     DoProfileChangeTeardown(aSubject);
        2248                 :   }
        2249             955 :   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC) == 0) {
        2250               0 :     mShutdownObjectList->allowUI();
        2251                 :   }
        2252             955 :   else if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) {
        2253             314 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving profile change topic\n"));
        2254             314 :     DoProfileBeforeChange(aSubject);
        2255                 :   }
        2256             641 :   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             641 :   else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
        2297                 :
        2298             327 :     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             327 :     if (mPSMContentListener) {
        2303             654 :       nsCOMPtr<nsIURILoader> dispatcher(do_GetService(NS_URI_LOADER_CONTRACTID));
        2304             327 :       if (dispatcher) {
        2305             327 :         dispatcher->UnRegisterContentListener(mPSMContentListener);
        2306                 :       }
        2307             327 :       mPSMContentListener = nsnull;
        2308                 :     }
        2309                 :
        2310                 :     nsCOMPtr<nsIEntropyCollector> ec
        2311             654 :         = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
        2312                 :
        2313             327 :     if (ec) {
        2314                 :       nsCOMPtr<nsIBufEntropyCollector> bec
        2315             654 :         = do_QueryInterface(ec);
        2316             327 :       if (bec) {
        2317             327 :         bec->DontForward();
        2318                 :       }
        2319                 :     }
        2320                 :   }
        2321             314 :   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             314 :   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
        2391             314 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
        2392             314 :     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            1269 :   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             327 : nsNSSComponent::RegisterObservers()
        2474                 : {
        2475                 :   // Happens once during init only, no mutex protection.
        2476                 :
        2477             654 :   nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
        2478             327 :   NS_ASSERTION(observerService, "could not get observer service");
        2479             327 :   if (observerService) {
        2480             327 :     mObserversRegistered = true;
        2481             327 :     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             327 :     observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
        2491                 :
        2492             327 :     observerService->AddObserver(this, PROFILE_APPROVE_CHANGE_TOPIC, false);
        2493             327 :     observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC, false);
        2494             327 :     observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC, false);
        2495             327 :     observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
        2496             327 :     observerService->AddObserver(this, PROFILE_DO_CHANGE_TOPIC, false);
        2497             327 :     observerService->AddObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC, false);
        2498             327 :     observerService->AddObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC, false);
        2499                 :   }
        2500             327 :   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             314 : nsNSSComponent::DoProfileChangeNetTeardown()
        2578                 : {
        2579             314 :   if (mCertVerificationThread)
        2580             314 :     mCertVerificationThread->requestExit();
        2581             314 :   mIsNetworkDown = true;
        2582             314 : }
        2583                 :
        2584                 : void
        2585             314 : nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
        2586                 : {
        2587             314 :   bool callVeto = false;
        2588                 :
        2589             314 :   if (!mShutdownObjectList->ifPossibleDisallowUI()) {
        2590               0 :     callVeto = true;
        2591               0 :     ShowAlertFromStringBundle(PROFILE_SWITCH_CRYPTO_UI_ACTIVE);
        2592                 :   }
        2593             314 :   else if (mShutdownObjectList->areSSLSocketsActive()) {
        2594               0 :     callVeto = true;
        2595               0 :     ShowAlertFromStringBundle(PROFILE_SWITCH_SOCKETS_STILL_ACTIVE);
        2596                 :   }
        2597                 :
        2598             314 :   if (callVeto) {
        2599               0 :     nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
        2600               0 :     if (status) {
        2601               0 :       status->VetoChange();
        2602                 :     }
        2603                 :   }
        2604             314 : }
        2605                 :
        2606                 : void
        2607             314 : nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
        2608                 : {
        2609             314 :   NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
        2610                 :
        2611             314 :   bool needsCleanup = true;
        2612                 :
        2613                 :   {
        2614             628 :     MutexAutoLock lock(mutex);
        2615                 :
        2616             314 :     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             314 :   StopCRLUpdateTimer();
        2625                 :
        2626             314 :   if (needsCleanup) {
        2627             310 :     if (NS_FAILED(ShutdownNSS())) {
        2628              66 :       nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
        2629              33 :       if (status) {
        2630               0 :         status->ChangeFailed();
        2631                 :       }
        2632                 :     }
        2633                 :   }
        2634             314 :   mShutdownObjectList->allowUI();
        2635             314 : }
        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             278 : nsNSSComponent::IsNSSInitialized(bool *initialized)
        2656                 : {
        2657             556 :   MutexAutoLock lock(mutex);
        2658             278 :   *initialized = mNSSInitialized;
        2659             278 :   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            1715 : nsCryptoHash::nsCryptoHash()
        2687                 :   : mHashContext(nsnull)
        2688            1715 :   , mInitialized(false)
        2689                 : {
        2690            1715 : }
        2691                 :
        2692            5145 : nsCryptoHash::~nsCryptoHash()
        2693                 : {
        2694            3430 :   nsNSSShutDownPreventionLock locker;
        2695                 :
        2696            1715 :   if (isAlreadyShutDown())
        2697                 :     return;
        2698                 :
        2699            1219 :   destructorSafeDestroyNSSReference();
        2700            2934 :   shutdown(calledFromObject);
        2701            6860 : }
        2702                 :
        2703             496 : void nsCryptoHash::virtualDestroyNSSReference()
        2704                 : {
        2705             496 :   destructorSafeDestroyNSSReference();
        2706             496 : }
        2707                 :
        2708            1715 : void nsCryptoHash::destructorSafeDestroyNSSReference()
        2709                 : {
        2710            1715 :   if (isAlreadyShutDown())
        2711               0 :     return;
        2712                 :
        2713            1715 :   if (mHashContext)
        2714            1698 :     HASH_Destroy(mHashContext);
        2715            1715 :   mHashContext = nsnull;
        2716                 : }
        2717                 :
        2718           25819 : NS_IMPL_ISUPPORTS1(nsCryptoHash, nsICryptoHash)
        2719                 :
        2720                 : NS_IMETHODIMP
        2721            2464 : nsCryptoHash::Init(PRUint32 algorithm)
        2722                 : {
        2723            4928 :   nsNSSShutDownPreventionLock locker;
        2724                 :
        2725            2464 :   HASH_HashType hashType = (HASH_HashType)algorithm;
        2726            2464 :   if (mHashContext)
        2727                 :   {
        2728             766 :     if ((!mInitialized) && (HASH_GetType(mHashContext) == hashType))
        2729                 :     {
        2730             766 :       mInitialized = true;
        2731             766 :       HASH_Begin(mHashContext);
        2732             766 :       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            1698 :   mHashContext = HASH_Create(hashType);
        2742            1698 :   if (!mHashContext)
        2743               0 :     return NS_ERROR_INVALID_ARG;
        2744                 :
        2745            1698 :   HASH_Begin(mHashContext);
        2746            1698 :   mInitialized = true;
        2747            1698 :   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            5568 : nsCryptoHash::Update(const PRUint8 *data, PRUint32 len)
        2776                 : {
        2777           11136 :   nsNSSShutDownPreventionLock locker;
        2778                 :
        2779            5568 :   if (!mInitialized)
        2780               0 :     return NS_ERROR_NOT_INITIALIZED;
        2781                 :
        2782            5568 :   HASH_Update(mHashContext, data, len);
        2783            5568 :   return NS_OK;
        2784                 : }
        2785                 :
        2786                 : NS_IMETHODIMP
        2787            1308 : nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 len)
        2788                 : {
        2789            1308 :   if (!mInitialized)
        2790               0 :     return NS_ERROR_NOT_INITIALIZED;
        2791                 :
        2792            1308 :   if (!data)
        2793               0 :     return NS_ERROR_INVALID_ARG;
        2794                 :
        2795                 :   PRUint32 n;
        2796            1308 :   nsresult rv = data->Available(&n);
        2797            1308 :   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            1308 :   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            1308 :   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            3924 :   while(NS_SUCCEEDED(rv) && len>0)
        2820                 :   {
        2821            1308 :     readLimit = NS_MIN(PRUint32(NS_CRYPTO_HASH_BUFFER_SIZE), len);
        2822                 :
        2823            1308 :     rv = data->Read(buffer, readLimit, &read);
        2824                 :
        2825            1308 :     if (NS_SUCCEEDED(rv))
        2826            1308 :       rv = Update((const PRUint8*)buffer, read);
        2827                 :
        2828            1308 :     len -= read;
        2829                 :   }
        2830                 :
        2831            1308 :   return rv;
        2832                 : }
        2833                 :
        2834                 : NS_IMETHODIMP
        2835            2445 : nsCryptoHash::Finish(bool ascii, nsACString & _retval)
        2836                 : {
        2837            4890 :   nsNSSShutDownPreventionLock locker;
        2838                 :
        2839            2445 :   if (!mInitialized)
        2840               0 :     return NS_ERROR_NOT_INITIALIZED;
        2841                 :
        2842            2445 :   PRUint32 hashLen = 0;
        2843                 :   unsigned char buffer[HASH_LENGTH_MAX];
        2844            2445 :   unsigned char* pbuffer = buffer;
        2845                 :
        2846            2445 :   HASH_End(mHashContext, pbuffer, &hashLen, HASH_LENGTH_MAX);
        2847                 :
        2848            2445 :   mInitialized = false;
        2849                 :
        2850            2445 :   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            2421 :     _retval.Assign((const char*)buffer, hashLen);
        2861                 :   }
        2862                 :
        2863            2445 :   return NS_OK;
        2864                 : }
        2865                 :
        2866                 : //---------------------------------------------
        2867                 : // Implementing nsICryptoHMAC
        2868                 : //---------------------------------------------
        2869                 :
        2870           27328 : NS_IMPL_ISUPPORTS1(nsCryptoHMAC, nsICryptoHMAC)
        2871                 :
        2872            1564 : nsCryptoHMAC::nsCryptoHMAC()
        2873                 : {
        2874            1564 :   mHMACContext = nsnull;
        2875            1564 : }
        2876                 :
        2877            4692 : nsCryptoHMAC::~nsCryptoHMAC()
        2878                 : {
        2879            3128 :   nsNSSShutDownPreventionLock locker;
        2880                 :
        2881            1564 :   if (isAlreadyShutDown())
        2882                 :     return;
        2883                 :
        2884             464 :   destructorSafeDestroyNSSReference();
        2885            2028 :   shutdown(calledFromObject);
        2886            6256 : }
        2887                 :
        2888            1100 : void nsCryptoHMAC::virtualDestroyNSSReference()
        2889                 : {
        2890            1100 :   destructorSafeDestroyNSSReference();
        2891            1100 : }
        2892                 :
        2893            1564 : void nsCryptoHMAC::destructorSafeDestroyNSSReference()
        2894                 : {
        2895            1564 :   if (isAlreadyShutDown())
        2896               0 :     return;
        2897                 :
        2898            1564 :   if (mHMACContext)
        2899            1564 :     PK11_DestroyContext(mHMACContext, true);
        2900            1564 :   mHMACContext = nsnull;
        2901                 : }
        2902                 :
        2903                 : /* void init (in unsigned long aAlgorithm, in nsIKeyObject aKeyObject); */
        2904            1564 : NS_IMETHODIMP nsCryptoHMAC::Init(PRUint32 aAlgorithm, nsIKeyObject *aKeyObject)
        2905                 : {
        2906            3128 :   nsNSSShutDownPreventionLock locker;
        2907                 :
        2908            1564 :   if (mHMACContext)
        2909                 :   {
        2910               0 :     PK11_DestroyContext(mHMACContext, true);
        2911               0 :     mHMACContext = nsnull;
        2912                 :   }
        2913                 :
        2914                 :   CK_MECHANISM_TYPE HMACMechType;
        2915            1564 :   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              33 :     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            1564 :   NS_ENSURE_ARG_POINTER(aKeyObject);
        2934                 :
        2935                 :   nsresult rv;
        2936                 :
        2937                 :   PRInt16 keyType;
        2938            1564 :   rv = aKeyObject->GetType(&keyType);
        2939            1564 :   NS_ENSURE_SUCCESS(rv, rv);
        2940                 :
        2941            1564 :   NS_ENSURE_TRUE(keyType == nsIKeyObject::SYM_KEY, NS_ERROR_INVALID_ARG);
        2942                 :
        2943                 :   PK11SymKey* key;
        2944                 :   // GetKeyObj doesn't addref the key
        2945            1564 :   rv = aKeyObject->GetKeyObj((void**)&key);
        2946            1564 :   NS_ENSURE_SUCCESS(rv, rv);
        2947                 :
        2948                 :   SECItem rawData;
        2949            1564 :   rawData.data = 0;
        2950            1564 :   rawData.len = 0;
        2951                 :   mHMACContext = PK11_CreateContextBySymKey(
        2952            1564 :       HMACMechType, CKA_SIGN, key, &rawData);
        2953            1564 :   NS_ENSURE_TRUE(mHMACContext, NS_ERROR_FAILURE);
        2954                 :
        2955            1564 :   SECStatus ss = PK11_DigestBegin(mHMACContext);
        2956            1564 :   NS_ENSURE_TRUE(ss == SECSuccess, NS_ERROR_FAILURE);
        2957                 :
        2958            1564 :   return NS_OK;
        2959                 : }
        2960                 :
        2961                 : /* void update ([array, size_is (aLen), const] in octet aData, in unsigned long aLen); */
        2962           22082 : NS_IMETHODIMP nsCryptoHMAC::Update(const PRUint8 *aData, PRUint32 aLen)
        2963                 : {
        2964           44164 :   nsNSSShutDownPreventionLock locker;
        2965                 :
        2966           22082 :   if (!mHMACContext)
        2967               0 :     return NS_ERROR_NOT_INITIALIZED;
        2968                 :
        2969           22082 :   if (!aData)
        2970               0 :     return NS_ERROR_INVALID_ARG;
        2971                 :
        2972           22082 :   SECStatus ss = PK11_DigestOp(mHMACContext, aData, aLen);
        2973           22082 :   NS_ENSURE_TRUE(ss == SECSuccess, NS_ERROR_FAILURE);
        2974                 :
        2975           22082 :   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           22081 : NS_IMETHODIMP nsCryptoHMAC::Finish(bool aASCII, nsACString & _retval)
        3030                 : {
        3031           44162 :   nsNSSShutDownPreventionLock locker;
        3032                 :
        3033           22081 :   if (!mHMACContext)
        3034               0 :     return NS_ERROR_NOT_INITIALIZED;
        3035                 :
        3036           22081 :   PRUint32 hashLen = 0;
        3037                 :   unsigned char buffer[HASH_LENGTH_MAX];
        3038           22081 :   unsigned char* pbuffer = buffer;
        3039                 :
        3040           22081 :   PK11_DigestFinal(mHMACContext, pbuffer, &hashLen, HASH_LENGTH_MAX);
        3041           22081 :   if (aASCII)
        3042                 :   {
        3043              15 :     char *asciiData = BTOA_DataToAscii(buffer, hashLen);
        3044              15 :     NS_ENSURE_TRUE(asciiData, NS_ERROR_OUT_OF_MEMORY);
        3045                 :
        3046              15 :     _retval.Assign(asciiData);
        3047              15 :     PORT_Free(asciiData);
        3048                 :   }
        3049                 :   else
        3050                 :   {
        3051           22066 :     _retval.Assign((const char*)buffer, hashLen);
        3052                 :   }
        3053                 :
        3054           22081 :   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            4578 : NS_IMPL_ISUPPORTS2(PSMContentListener,
        3401                 :                    nsIURIContentListener,
        3402                 :                    nsISupportsWeakReference)
        3403                 :
        3404             327 : PSMContentListener::PSMContentListener()
        3405                 : {
        3406             327 :   mLoadCookie = nsnull;
        3407             327 :   mParentContentListener = nsnull;
        3408             327 : }
        3409                 :
        3410             654 : PSMContentListener::~PSMContentListener()
        3411                 : {
        3412            1308 : }
        3413                 :
        3414                 : nsresult
        3415             327 : PSMContentListener::init()
        3416                 : {
        3417             327 :   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