/security/manager/ssl/src/nsNSSComponent.cpp
http://github.com/zpao/v8monkey · C++ · 3481 lines · 2587 code · 585 blank · 309 comment · 455 complexity · 66116bc7232cc97e1ff3ed29287b7653 MD5 · raw file
Large files are truncated click here to view the full file
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Hubbie Shaw
- * Doug Turner <dougt@netscape.com>
- * Mitch Stoltz <mstoltz@netscape.com>
- * Brian Ryner <bryner@brianryner.com>
- * Kai Engert <kaie@netscape.com>
- * Vipul Gupta <vipul.gupta@sun.com>
- * Douglas Stebila <douglas@stebila.ca>
- * Kai Engert <kengert@redhat.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
- #include "nsNSSComponent.h"
- #include "nsNSSCallbacks.h"
- #include "nsNSSIOLayer.h"
- #include "nsCertVerificationThread.h"
- #include "nsNetUtil.h"
- #include "nsAppDirectoryServiceDefs.h"
- #include "nsDirectoryService.h"
- #include "nsIStreamListener.h"
- #include "nsIStringBundle.h"
- #include "nsIDirectoryService.h"
- #include "nsIDOMNode.h"
- #include "nsCURILoader.h"
- #include "nsDirectoryServiceDefs.h"
- #include "nsIX509Cert.h"
- #include "nsIX509CertDB.h"
- #include "nsIProfileChangeStatus.h"
- #include "nsNSSCertificate.h"
- #include "nsNSSHelper.h"
- #include "nsSmartCardMonitor.h"
- #include "prlog.h"
- #include "nsIPrefService.h"
- #include "nsIPrefBranch.h"
- #include "nsIDateTimeFormat.h"
- #include "nsDateTimeFormatCID.h"
- #include "nsIDOMEvent.h"
- #include "nsIDOMDocument.h"
- #include "nsIDOMWindow.h"
- #include "nsIDOMWindowCollection.h"
- #include "nsIDOMSmartCardEvent.h"
- #include "nsIDOMCrypto.h"
- #include "nsThreadUtils.h"
- #include "nsAutoPtr.h"
- #include "nsCRT.h"
- #include "nsCRLInfo.h"
- #include "nsCertOverrideService.h"
- #include "nsIWindowWatcher.h"
- #include "nsIPrompt.h"
- #include "nsIPrincipal.h"
- #include "nsReadableUtils.h"
- #include "nsIDateTimeFormat.h"
- #include "prtypes.h"
- #include "nsIEntropyCollector.h"
- #include "nsIBufEntropyCollector.h"
- #include "nsIServiceManager.h"
- #include "nsILocalFile.h"
- #include "nsITokenPasswordDialogs.h"
- #include "nsICRLManager.h"
- #include "nsNSSShutDown.h"
- #include "nsSmartCardEvent.h"
- #include "nsIKeyModule.h"
- #include "nss.h"
- #include "pk11func.h"
- #include "ssl.h"
- #include "sslproto.h"
- #include "secmod.h"
- #include "sechash.h"
- #include "secmime.h"
- #include "ocsp.h"
- #include "cms.h"
- #include "nssckbi.h"
- #include "base64.h"
- #include "secerr.h"
- #include "sslerr.h"
- #include "cert.h"
- #include "nsXULAppAPI.h"
- #ifdef XP_WIN
- #include "nsILocalFileWin.h"
- #endif
- extern "C" {
- #include "pkcs12.h"
- #include "p12plcy.h"
- }
- using namespace mozilla;
- #ifdef PR_LOGGING
- PRLogModuleInfo* gPIPNSSLog = nsnull;
- #endif
- #define NS_CRYPTO_HASH_BUFFER_SIZE 4096
- static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
- int nsNSSComponent::mInstanceCount = 0;
- bool nsNSSComponent::globalConstFlagUsePKIXVerification = false;
- // XXX tmp callback for slot password
- extern char * PR_CALLBACK
- pk11PasswordPrompt(PK11SlotInfo *slot, PRBool retry, void *arg);
- #define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties"
- #define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties"
- static PLHashNumber PR_CALLBACK certHashtable_keyHash(const void *key)
- {
- if (!key)
- return 0;
-
- SECItem *certKey = (SECItem*)key;
-
- // lazy hash function, sum up all char values of SECItem
-
- PLHashNumber hash = 0;
- unsigned int i = 0;
- unsigned char *c = certKey->data;
-
- for (i = 0; i < certKey->len; ++i, ++c) {
- hash += *c;
- }
-
- return hash;
- }
- static PRIntn PR_CALLBACK certHashtable_keyCompare(const void *k1, const void *k2)
- {
- // return type is a bool, answering the question "are the keys equal?"
- if (!k1 || !k2)
- return false;
-
- SECItem *certKey1 = (SECItem*)k1;
- SECItem *certKey2 = (SECItem*)k2;
-
- if (certKey1->len != certKey2->len) {
- return false;
- }
-
- unsigned int i = 0;
- unsigned char *c1 = certKey1->data;
- unsigned char *c2 = certKey2->data;
-
- for (i = 0; i < certKey1->len; ++i, ++c1, ++c2) {
- if (*c1 != *c2) {
- return false;
- }
- }
-
- return true;
- }
- static PRIntn PR_CALLBACK certHashtable_valueCompare(const void *v1, const void *v2)
- {
- // two values are identical if their keys are identical
-
- if (!v1 || !v2)
- return false;
-
- CERTCertificate *cert1 = (CERTCertificate*)v1;
- CERTCertificate *cert2 = (CERTCertificate*)v2;
-
- return certHashtable_keyCompare(&cert1->certKey, &cert2->certKey);
- }
- static PRIntn PR_CALLBACK certHashtable_clearEntry(PLHashEntry *he, PRIntn /*index*/, void * /*userdata*/)
- {
- if (he && he->value) {
- CERT_DestroyCertificate((CERTCertificate*)he->value);
- }
-
- return HT_ENUMERATE_NEXT;
- }
- class CRLDownloadEvent : public nsRunnable {
- public:
- CRLDownloadEvent(const nsCSubstring &urlString, nsIStreamListener *listener)
- : mURLString(urlString)
- , mListener(listener)
- {}
- // Note that nsNSSComponent is a singleton object across all threads,
- // and automatic downloads are always scheduled sequentially - that is,
- // once one crl download is complete, the next one is scheduled
- NS_IMETHOD Run()
- {
- if (!mListener || mURLString.IsEmpty())
- return NS_OK;
- nsCOMPtr<nsIURI> uri;
- nsresult rv = NS_NewURI(getter_AddRefs(uri), mURLString);
- if (NS_SUCCEEDED(rv)){
- NS_OpenURI(mListener, nsnull, uri);
- }
- return NS_OK;
- }
- private:
- nsCString mURLString;
- nsCOMPtr<nsIStreamListener> mListener;
- };
- //This class is used to run the callback code
- //passed to the event handlers for smart card notification
- class nsTokenEventRunnable : public nsIRunnable {
- public:
- nsTokenEventRunnable(const nsAString &aType, const nsAString &aTokenName);
- virtual ~nsTokenEventRunnable();
- NS_IMETHOD Run ();
- NS_DECL_ISUPPORTS
- private:
- nsString mType;
- nsString mTokenName;
- };
- // ISuuports implementation for nsTokenEventRunnable
- NS_IMPL_THREADSAFE_ISUPPORTS1(nsTokenEventRunnable, nsIRunnable)
- nsTokenEventRunnable::nsTokenEventRunnable(const nsAString &aType,
- const nsAString &aTokenName): mType(aType), mTokenName(aTokenName) { }
- nsTokenEventRunnable::~nsTokenEventRunnable() { }
- //Implementation that runs the callback passed to
- //crypto.generateCRMFRequest as an event.
- NS_IMETHODIMP
- nsTokenEventRunnable::Run()
- {
- nsresult rv;
- nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
- if (NS_FAILED(rv))
- return rv;
- return nssComponent->DispatchEvent(mType, mTokenName);
- }
- bool nsPSMInitPanic::isPanic = false;
- // We must ensure that the nsNSSComponent has been loaded before
- // creating any other components.
- bool EnsureNSSInitialized(EnsureNSSOperator op)
- {
- if (nsPSMInitPanic::GetPanic())
- return false;
- if (GeckoProcessType_Default != XRE_GetProcessType())
- {
- if (op == nssEnsureOnChromeOnly)
- {
- // If the component needs PSM/NSS initialized only on the chrome process,
- // pretend we successfully initiated it but in reality we bypass it.
- // It's up to the programmer to check for process type in such components
- // and take care not to call anything that needs NSS/PSM initiated.
- return true;
- }
- NS_ERROR("Trying to initialize PSM/NSS in a non-chrome process!");
- return false;
- }
- static bool loading = false;
- static PRInt32 haveLoaded = 0;
- switch (op)
- {
- // In following 4 cases we are protected by monitor of XPCOM component
- // manager - we are inside of do_GetService call for nss component, so it is
- // safe to move with the flags here.
- case nssLoadingComponent:
- if (loading)
- return false; // We are reentered during nss component creation
- loading = true;
- return true;
- case nssInitSucceeded:
- NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitSucceeded)");
- loading = false;
- PR_AtomicSet(&haveLoaded, 1);
- return true;
- case nssInitFailed:
- NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitFailed)");
- loading = false;
- // no break
- case nssShutdown:
- PR_AtomicSet(&haveLoaded, 0);
- return false;
- // In this case we are called from a component to ensure nss initilization.
- // If the component has not yet been loaded and is not currently loading
- // call do_GetService for nss component to ensure it.
- case nssEnsure:
- case nssEnsureOnChromeOnly:
- // We are reentered during nss component creation or nss component is already up
- if (PR_AtomicAdd(&haveLoaded, 0) || loading)
- return true;
- {
- nsCOMPtr<nsINSSComponent> nssComponent
- = do_GetService(PSM_COMPONENT_CONTRACTID);
- // Nss component failed to initialize, inform the caller of that fact.
- // Flags are appropriately set by component constructor itself.
- if (!nssComponent)
- return false;
- bool isInitialized;
- nsresult rv = nssComponent->IsNSSInitialized(&isInitialized);
- return NS_SUCCEEDED(rv) && isInitialized;
- }
- default:
- NS_ASSERTION(false, "Bad operator to EnsureNSSInitialized");
- return false;
- }
- }
- nsNSSComponent::nsNSSComponent()
- :mutex("nsNSSComponent.mutex"),
- mNSSInitialized(false),
- mCrlTimerLock("nsNSSComponent.mCrlTimerLock"),
- mThreadList(nsnull),
- mCertVerificationThread(NULL)
- {
- #ifdef PR_LOGGING
- if (!gPIPNSSLog)
- gPIPNSSLog = PR_NewLogModule("pipnss");
- #endif
- PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ctor\n"));
- mUpdateTimerInitialized = false;
- crlDownloadTimerOn = false;
- crlsScheduledForDownload = nsnull;
- mTimer = nsnull;
- mObserversRegistered = false;
- // In order to keep startup time lower, we delay loading and
- // registering all identity data until first needed.
- memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
- NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
- ++mInstanceCount;
- hashTableCerts = nsnull;
- mShutdownObjectList = nsNSSShutDownList::construct();
- mIsNetworkDown = false;
- }
- void
- nsNSSComponent::deleteBackgroundThreads()
- {
- if (mCertVerificationThread)
- {
- mCertVerificationThread->requestExit();
- delete mCertVerificationThread;
- mCertVerificationThread = nsnull;
- }
- }
- void
- nsNSSComponent::createBackgroundThreads()
- {
- NS_ASSERTION(mCertVerificationThread == nsnull,
- "Cert verification thread already created.");
- mCertVerificationThread = new nsCertVerificationThread;
- nsresult rv = mCertVerificationThread->startThread();
- if (NS_FAILED(rv)) {
- delete mCertVerificationThread;
- mCertVerificationThread = nsnull;
- }
- }
- nsNSSComponent::~nsNSSComponent()
- {
- PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor\n"));
- deleteBackgroundThreads();
- if (mUpdateTimerInitialized) {
- {
- MutexAutoLock lock(mCrlTimerLock);
- if (crlDownloadTimerOn) {
- mTimer->Cancel();
- }
- crlDownloadTimerOn = false;
- }
- if(crlsScheduledForDownload != nsnull){
- crlsScheduledForDownload->Reset();
- delete crlsScheduledForDownload;
- }
- mUpdateTimerInitialized = false;
- }
- // All cleanup code requiring services needs to happen in xpcom_shutdown
- ShutdownNSS();
- nsSSLIOLayerHelpers::Cleanup();
- --mInstanceCount;
- delete mShutdownObjectList;
- // We are being freed, drop the haveLoaded flag to re-enable
- // potential nss initialization later.
- EnsureNSSInitialized(nssShutdown);
- PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n"));
- }
- NS_IMETHODIMP
- nsNSSComponent::PostEvent(const nsAString &eventType,
- const nsAString &tokenName)
- {
- nsCOMPtr<nsIRunnable> runnable =
- new nsTokenEventRunnable(eventType, tokenName);
- if (!runnable) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- return NS_DispatchToMainThread(runnable);
- }
- NS_IMETHODIMP
- nsNSSComponent::DispatchEvent(const nsAString &eventType,
- const nsAString &tokenName)
- {
- // 'Dispatch' the event to all the windows. 'DispatchEventToWindow()' will
- // first check to see if a given window has requested crypto events.
- nsresult rv;
- nsCOMPtr<nsIWindowWatcher> windowWatcher =
- do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
- if (NS_FAILED(rv)) {
- return rv;
- }
- nsCOMPtr<nsISimpleEnumerator> enumerator;
- rv = windowWatcher->GetWindowEnumerator(getter_AddRefs(enumerator));
- if (NS_FAILED(rv)) {
- return rv;
- }
- bool hasMoreWindows;
- while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreWindows))
- && hasMoreWindows) {
- nsCOMPtr<nsISupports> supports;
- enumerator->GetNext(getter_AddRefs(supports));
- nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(supports));
- if (domWin) {
- nsresult rv2 = DispatchEventToWindow(domWin, eventType, tokenName);
- if (NS_FAILED(rv2)) {
- // return the last failure, don't let a single failure prevent
- // continued delivery of events.
- rv = rv2;
- }
- }
- }
- return rv;
- }
- nsresult
- nsNSSComponent::DispatchEventToWindow(nsIDOMWindow *domWin,
- const nsAString &eventType, const nsAString &tokenName)
- {
- // first walk the children and dispatch their events
- {
- nsresult rv;
- nsCOMPtr<nsIDOMWindowCollection> frames;
- rv = domWin->GetFrames(getter_AddRefs(frames));
- if (NS_FAILED(rv)) {
- return rv;
- }
- PRUint32 length;
- frames->GetLength(&length);
- PRUint32 i;
- for (i = 0; i < length; i++) {
- nsCOMPtr<nsIDOMWindow> childWin;
- frames->Item(i, getter_AddRefs(childWin));
- DispatchEventToWindow(childWin, eventType, tokenName);
- }
- }
- // check if we've enabled smart card events on this window
- // NOTE: it's not an error to say that we aren't going to dispatch
- // the event.
- {
- nsCOMPtr<nsIDOMWindow> domWindow = domWin;
- if (!domWindow) {
- return NS_OK; // nope, it's not an internal window
- }
- nsCOMPtr<nsIDOMCrypto> crypto;
- domWindow->GetCrypto(getter_AddRefs(crypto));
- if (!crypto) {
- return NS_OK; // nope, it doesn't have a crypto property
- }
- bool boolrv;
- crypto->GetEnableSmartCardEvents(&boolrv);
- if (!boolrv) {
- return NS_OK; // nope, it's not enabled.
- }
- }
- // dispatch the event ...
- nsresult rv;
- // find the document
- nsCOMPtr<nsIDOMDocument> doc;
- rv = domWin->GetDocument(getter_AddRefs(doc));
- if (doc == nsnull) {
- return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
- }
- // create the event
- nsCOMPtr<nsIDOMEvent> event;
- rv = doc->CreateEvent(NS_LITERAL_STRING("Events"),
- getter_AddRefs(event));
- if (NS_FAILED(rv)) {
- return rv;
- }
- event->InitEvent(eventType, false, true);
- // create the Smart Card Event;
- nsCOMPtr<nsIDOMSmartCardEvent> smartCardEvent =
- new nsSmartCardEvent(tokenName);
- // init the smart card event, fail here if we can't complete the
- // initialization.
- if (!smartCardEvent) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- rv = smartCardEvent->Init(event);
- if (NS_FAILED(rv)) {
- return rv;
- }
- // Send it
- nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(doc, &rv);
- if (NS_FAILED(rv)) {
- return rv;
- }
- bool boolrv;
- rv = target->DispatchEvent(smartCardEvent, &boolrv);
- return rv;
- }
- NS_IMETHODIMP
- nsNSSComponent::PIPBundleFormatStringFromName(const char *name,
- const PRUnichar **params,
- PRUint32 numParams,
- nsAString &outString)
- {
- nsresult rv = NS_ERROR_FAILURE;
- if (mPIPNSSBundle && name) {
- nsXPIDLString result;
- rv = mPIPNSSBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
- params, numParams,
- getter_Copies(result));
- if (NS_SUCCEEDED(rv)) {
- outString = result;
- }
- }
- return rv;
- }
- NS_IMETHODIMP
- nsNSSComponent::GetPIPNSSBundleString(const char *name,
- nsAString &outString)
- {
- nsresult rv = NS_ERROR_FAILURE;
- outString.SetLength(0);
- if (mPIPNSSBundle && name) {
- nsXPIDLString result;
- rv = mPIPNSSBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
- getter_Copies(result));
- if (NS_SUCCEEDED(rv)) {
- outString = result;
- rv = NS_OK;
- }
- }
- return rv;
- }
- NS_IMETHODIMP
- nsNSSComponent::NSSBundleFormatStringFromName(const char *name,
- const PRUnichar **params,
- PRUint32 numParams,
- nsAString &outString)
- {
- nsresult rv = NS_ERROR_FAILURE;
- if (mNSSErrorsBundle && name) {
- nsXPIDLString result;
- rv = mNSSErrorsBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
- params, numParams,
- getter_Copies(result));
- if (NS_SUCCEEDED(rv)) {
- outString = result;
- }
- }
- return rv;
- }
- NS_IMETHODIMP
- nsNSSComponent::GetNSSBundleString(const char *name,
- nsAString &outString)
- {
- nsresult rv = NS_ERROR_FAILURE;
- outString.SetLength(0);
- if (mNSSErrorsBundle && name) {
- nsXPIDLString result;
- rv = mNSSErrorsBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
- getter_Copies(result));
- if (NS_SUCCEEDED(rv)) {
- outString = result;
- rv = NS_OK;
- }
- }
- return rv;
- }
- void
- nsNSSComponent::LaunchSmartCardThreads()
- {
- nsNSSShutDownPreventionLock locker;
- {
- SECMODModuleList *list;
- SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
- if (!lock) {
- PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
- ("Couldn't get the module list lock, can't launch smart card threads\n"));
- return;
- }
- SECMOD_GetReadLock(lock);
- list = SECMOD_GetDefaultModuleList();
- while (list) {
- SECMODModule *module = list->module;
- LaunchSmartCardThread(module);
- list = list->next;
- }
- SECMOD_ReleaseReadLock(lock);
- }
- }
- NS_IMETHODIMP
- nsNSSComponent::LaunchSmartCardThread(SECMODModule *module)
- {
- SmartCardMonitoringThread *newThread;
- if (SECMOD_HasRemovableSlots(module)) {
- if (mThreadList == nsnull) {
- mThreadList = new SmartCardThreadList();
- if (!mThreadList) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- }
- newThread = new SmartCardMonitoringThread(module);
- if (!newThread) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- // newThread is adopted by the add.
- return mThreadList->Add(newThread);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsNSSComponent::ShutdownSmartCardThread(SECMODModule *module)
- {
- if (!mThreadList) {
- return NS_OK;
- }
- mThreadList->Remove(module);
- return NS_OK;
- }
- void
- nsNSSComponent::ShutdownSmartCardThreads()
- {
- delete mThreadList;
- mThreadList = nsnull;
- }
- static char *
- nss_addEscape(const char *string, char quote)
- {
- char *newString = 0;
- int escapes = 0, size = 0;
- const char *src;
- char *dest;
- for (src=string; *src ; src++) {
- if ((*src == quote) || (*src == '\\')) {
- escapes++;
- }
- size++;
- }
- newString = (char*)PORT_ZAlloc(escapes+size+1);
- if (newString == NULL) {
- return NULL;
- }
- for (src=string, dest=newString; *src; src++,dest++) {
- if ((*src == quote) || (*src == '\\')) {
- *dest++ = '\\';
- }
- *dest = *src;
- }
- return newString;
- }
- void
- nsNSSComponent::InstallLoadableRoots()
- {
- nsNSSShutDownPreventionLock locker;
- SECMODModule *RootsModule = nsnull;
- // In the past we used SECMOD_AddNewModule to load our module containing
- // root CA certificates. This caused problems, refer to bug 176501.
- // On startup, we fix our database and clean any stored module reference,
- // and will use SECMOD_LoadUserModule to temporarily load it
- // for the session. (This approach requires to clean up
- // using SECMOD_UnloadUserModule at the end of the session.)
- {
- // Find module containing root certs
- SECMODModuleList *list;
- SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
- if (!lock) {
- PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
- ("Couldn't get the module list lock, can't install loadable roots\n"));
- return;
- }
- SECMOD_GetReadLock(lock);
- list = SECMOD_GetDefaultModuleList();
- while (!RootsModule && list) {
- SECMODModule *module = list->module;
- for (int i=0; i < module->slotCount; i++) {
- PK11SlotInfo *slot = module->slots[i];
- if (PK11_IsPresent(slot)) {
- if (PK11_HasRootCerts(slot)) {
- RootsModule = SECMOD_ReferenceModule(module);
- break;
- }
- }
- }
- list = list->next;
- }
- SECMOD_ReleaseReadLock(lock);
- }
- if (RootsModule) {
- PRInt32 modType;
- SECMOD_DeleteModule(RootsModule->commonName, &modType);
- SECMOD_DestroyModule(RootsModule);
- RootsModule = nsnull;
- }
- // Find the best Roots module for our purposes.
- // Prefer the application's installation directory,
- // but also ensure the library is at least the version we expect.
- nsresult rv;
- nsAutoString modName;
- rv = GetPIPNSSBundleString("RootCertModuleName", modName);
- if (NS_FAILED(rv)) return;
- nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
- if (!directoryService)
- return;
- static const char nss_lib[] = "nss3";
- const char *possible_ckbi_locations[] = {
- nss_lib, // This special value means: search for ckbi in the directory
- // where nss3 is.
- NS_XPCOM_CURRENT_PROCESS_DIR,
- NS_GRE_DIR,
- 0 // This special value means:
- // search for ckbi in the directories on the shared
- // library/DLL search path
- };
- for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
- nsCOMPtr<nsILocalFile> mozFile;
- char *fullLibraryPath = nsnull;
- if (!possible_ckbi_locations[il])
- {
- fullLibraryPath = PR_GetLibraryName(nsnull, "nssckbi");
- }
- else
- {
- if (possible_ckbi_locations[il] == nss_lib) {
- // Get the location of the nss3 library.
- char *nss_path = PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
- (PRFuncPtr) NSS_Initialize);
- if (!nss_path) {
- continue;
- }
- // Get the directory containing the nss3 library.
- nsCOMPtr<nsILocalFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
- if (NS_SUCCEEDED(rv)) {
- rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
- }
- PR_Free(nss_path);
- if (NS_SUCCEEDED(rv)) {
- nsCOMPtr<nsIFile> file;
- if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
- mozFile = do_QueryInterface(file);
- }
- }
- } else {
- directoryService->Get( possible_ckbi_locations[il],
- NS_GET_IID(nsILocalFile),
- getter_AddRefs(mozFile));
- }
-
- if (!mozFile) {
- continue;
- }
- nsCAutoString processDir;
- mozFile->GetNativePath(processDir);
- fullLibraryPath = PR_GetLibraryName(processDir.get(), "nssckbi");
- }
- if (!fullLibraryPath) {
- continue;
- }
- char *escaped_fullLibraryPath = nss_addEscape(fullLibraryPath, '\"');
- if (!escaped_fullLibraryPath) {
- PR_FreeLibraryName(fullLibraryPath); // allocated by NSPR
- continue;
- }
- /* If a module exists with the same name, delete it. */
- NS_ConvertUTF16toUTF8 modNameUTF8(modName);
- int modType;
- SECMOD_DeleteModule(const_cast<char*>(modNameUTF8.get()), &modType);
- nsCString pkcs11moduleSpec;
- pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("name=\""));
- pkcs11moduleSpec.Append(modNameUTF8.get());
- pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("\" library=\""));
- pkcs11moduleSpec.Append(escaped_fullLibraryPath);
- pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("\""));
- PR_FreeLibraryName(fullLibraryPath); // allocated by NSPR
- PORT_Free(escaped_fullLibraryPath);
- RootsModule =
- SECMOD_LoadUserModule(const_cast<char*>(pkcs11moduleSpec.get()),
- nsnull, // no parent
- false); // do not recurse
- if (RootsModule) {
- bool found = (RootsModule->loaded);
- SECMOD_DestroyModule(RootsModule);
- RootsModule = nsnull;
- if (found) {
- break;
- }
- }
- }
- }
- void
- nsNSSComponent::UnloadLoadableRoots()
- {
- nsresult rv;
- nsAutoString modName;
- rv = GetPIPNSSBundleString("RootCertModuleName", modName);
- if (NS_FAILED(rv)) return;
- NS_ConvertUTF16toUTF8 modNameUTF8(modName);
- SECMODModule *RootsModule = SECMOD_FindModule(modNameUTF8.get());
- if (RootsModule) {
- SECMOD_UnloadUserModule(RootsModule);
- SECMOD_DestroyModule(RootsModule);
- }
- }
- nsresult
- nsNSSComponent::ConfigureInternalPKCS11Token()
- {
- nsNSSShutDownPreventionLock locker;
- nsAutoString manufacturerID;
- nsAutoString libraryDescription;
- nsAutoString tokenDescription;
- nsAutoString privateTokenDescription;
- nsAutoString slotDescription;
- nsAutoString privateSlotDescription;
- nsAutoString fips140TokenDescription;
- nsAutoString fips140SlotDescription;
- nsresult rv;
- rv = GetPIPNSSBundleString("ManufacturerID", manufacturerID);
- if (NS_FAILED(rv)) return rv;
- rv = GetPIPNSSBundleString("LibraryDescription", libraryDescription);
- if (NS_FAILED(rv)) return rv;
- rv = GetPIPNSSBundleString("TokenDescription", tokenDescription);
- if (NS_FAILED(rv)) return rv;
- rv = GetPIPNSSBundleString("PrivateTokenDescription", privateTokenDescription);
- if (NS_FAILED(rv)) return rv;
- rv = GetPIPNSSBundleString("SlotDescription", slotDescription);
- if (NS_FAILED(rv)) return rv;
- rv = GetPIPNSSBundleString("PrivateSlotDescription", privateSlotDescription);
- if (NS_FAILED(rv)) return rv;
- rv = GetPIPNSSBundleString("Fips140TokenDescription", fips140TokenDescription);
- if (NS_FAILED(rv)) return rv;
- rv = GetPIPNSSBundleString("Fips140SlotDescription", fips140SlotDescription);
- if (NS_FAILED(rv)) return rv;
- PK11_ConfigurePKCS11(NS_ConvertUTF16toUTF8(manufacturerID).get(),
- NS_ConvertUTF16toUTF8(libraryDescription).get(),
- NS_ConvertUTF16toUTF8(tokenDescription).get(),
- NS_ConvertUTF16toUTF8(privateTokenDescription).get(),
- NS_ConvertUTF16toUTF8(slotDescription).get(),
- NS_ConvertUTF16toUTF8(privateSlotDescription).get(),
- NS_ConvertUTF16toUTF8(fips140TokenDescription).get(),
- NS_ConvertUTF16toUTF8(fips140SlotDescription).get(),
- 0, 0);
- return NS_OK;
- }
- nsresult
- nsNSSComponent::InitializePIPNSSBundle()
- {
- // Called during init only, no mutex required.
- nsresult rv;
- nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
- if (NS_FAILED(rv) || !bundleService)
- return NS_ERROR_FAILURE;
-
- bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL,
- getter_AddRefs(mPIPNSSBundle));
- if (!mPIPNSSBundle)
- rv = NS_ERROR_FAILURE;
- bundleService->CreateBundle(NSSERR_STRBUNDLE_URL,
- getter_AddRefs(mNSSErrorsBundle));
- if (!mNSSErrorsBundle)
- rv = NS_ERROR_FAILURE;
- return rv;
- }
- nsresult
- nsNSSComponent::RegisterPSMContentListener()
- {
- // Called during init only, no mutex required.
- nsresult rv = NS_OK;
- if (!mPSMContentListener) {
- nsCOMPtr<nsIURILoader> dispatcher(do_GetService(NS_URI_LOADER_CONTRACTID));
- if (dispatcher) {
- mPSMContentListener = do_CreateInstance(NS_PSMCONTENTLISTEN_CONTRACTID);
- rv = dispatcher->RegisterContentListener(mPSMContentListener);
- }
- }
- return rv;
- }
- /* Table of pref names and SSL cipher ID */
- typedef struct {
- const char* pref;
- long id;
- } CipherPref;
- static CipherPref CipherPrefs[] = {
- /* SSL3/TLS cipher suites*/
- {"security.ssl3.rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5}, // 128-bit RC4 encryption with RSA and an MD5 MAC
- {"security.ssl3.rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with RSA and a SHA1 MAC
- {"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)
- {"security.ssl3.rsa_des_ede3_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with RSA and a SHA1 MAC
- {"security.ssl3.rsa_fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA and a SHA1 MAC (FIPS)
- {"security.ssl3.rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA and a SHA1 MAC
- {"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)
- {"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)
- {"security.ssl3.rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5}, // 40-bit RC4 encryption with RSA and an MD5 MAC (export)
- {"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)
- /* Extra SSL3/TLS cipher suites */
- {"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
- {"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
- {"security.ssl3.rsa_camellia_256_sha", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA}, // 256-bit Camellia encryption with RSA and a SHA1 MAC
- {"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
- {"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
- {"security.ssl3.rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with RSA and a SHA1 MAC
- /* TLS_DHE_DSS_WITH_RC4_128_SHA // 128-bit RC4 encryption with DSA, DHE, and a SHA1 MAC
- If this cipher gets included at a later time, it should get added at this position */
- {"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
- {"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
- {"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
- {"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
- {"security.ssl3.ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA}, // No encryption with ECDHE-ECDSA and a SHA1 MAC
- {"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
- {"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
- {"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
- {"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
- {"security.ssl3.ecdhe_rsa_null_sha", TLS_ECDHE_RSA_WITH_NULL_SHA}, // No encryption with ECDHE-RSA and a SHA1 MAC
- {"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
- {"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
- {"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
- {"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
- {"security.ssl3.ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA}, // No encryption with ECDH-ECDSA and a SHA1 MAC
- {"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
- {"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
- {"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
- {"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
- {"security.ssl3.ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA}, // No encryption with ECDH-RSA and a SHA1 MAC
- {"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
- {"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
- {"security.ssl3.rsa_camellia_128_sha", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA}, // 128-bit Camellia encryption with RSA and a SHA1 MAC
- {"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
- {"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
- {"security.ssl3.rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with RSA and a SHA1 MAC
- {"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
- {"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
- {"security.ssl3.dhe_rsa_des_sha", SSL_DHE_RSA_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA, DHE, and a SHA1 MAC
- {"security.ssl3.dhe_dss_des_sha", SSL_DHE_DSS_WITH_DES_CBC_SHA}, // 56-bit DES encryption with DSA, DHE, and a SHA1 MAC
- {"security.ssl3.rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, // No encryption with RSA authentication and a SHA1 MAC
- {"security.ssl3.rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, // No encryption with RSA authentication and an MD5 MAC
- {"security.ssl3.rsa_seed_sha", TLS_RSA_WITH_SEED_CBC_SHA}, // SEED encryption with RSA and a SHA1 MAC
- {NULL, 0} /* end marker */
- };
- static void
- setNonPkixOcspEnabled(PRInt32 ocspEnabled, nsIPrefBranch * pref)
- {
- switch (ocspEnabled) {
- case 0:
- CERT_DisableOCSPChecking(CERT_GetDefaultCertDB());
- CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
- break;
- case 1:
- CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
- CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
- break;
- case 2:
- {
- char *signingCA = nsnull;
- char *url = nsnull;
- // Get the signing CA and service url //
- pref->GetCharPref("security.OCSP.signingCA", &signingCA);
- pref->GetCharPref("security.OCSP.URL", &url);
- // Set OCSP up
- CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
- CERT_SetOCSPDefaultResponder(CERT_GetDefaultCertDB(), url, signingCA);
- CERT_EnableOCSPDefaultResponder(CERT_GetDefaultCertDB());
- nsMemory::Free(signingCA);
- nsMemory::Free(url);
- }
- break;
- }
- }
- #define CRL_DOWNLOAD_DEFAULT false
- #define OCSP_ENABLED_DEFAULT 1
- #define OCSP_REQUIRED_DEFAULT 0
- #define FRESH_REVOCATION_REQUIRED_DEFAULT false
- #define MISSING_CERT_DOWNLOAD_DEFAULT false
- #define FIRST_REVO_METHOD_DEFAULT "ocsp"
- #define USE_NSS_LIBPKIX_DEFAULT false
- // Caller must hold a lock on nsNSSComponent::mutex when calling this function
- void nsNSSComponent::setValidationOptions(nsIPrefBranch * pref)
- {
- nsNSSShutDownPreventionLock locker;
- nsresult rv;
- bool crlDownloading;
- rv = pref->GetBoolPref("security.CRL_download.enabled", &crlDownloading);
- if (NS_FAILED(rv))
- crlDownloading = CRL_DOWNLOAD_DEFAULT;
-
- PRInt32 ocspEnabled;
- rv = pref->GetIntPref("security.OCSP.enabled", &ocspEnabled);
- // 0 = disabled, 1 = enabled,
- // 2 = enabled with given default responder
- if (NS_FAILED(rv))
- ocspEnabled = OCSP_ENABLED_DEFAULT;
- bool ocspRequired;
- rv = pref->GetBoolPref("security.OCSP.require", &ocspRequired);
- if (NS_FAILED(rv))
- ocspRequired = OCSP_REQUIRED_DEFAULT;
- bool anyFreshRequired;
- rv = pref->GetBoolPref("security.fresh_revocation_info.require", &anyFreshRequired);
- if (NS_FAILED(rv))
- anyFreshRequired = FRESH_REVOCATION_REQUIRED_DEFAULT;
-
- bool aiaDownloadEnabled;
- rv = pref->GetBoolPref("security.missing_cert_download.enabled", &aiaDownloadEnabled);
- if (NS_FAILED(rv))
- aiaDownloadEnabled = MISSING_CERT_DOWNLOAD_DEFAULT;
- nsCString firstNetworkRevo;
- rv = pref->GetCharPref("security.first_network_revocation_method", getter_Copies(firstNetworkRevo));
- if (NS_FAILED(rv))
- firstNetworkRevo = FIRST_REVO_METHOD_DEFAULT;
-
- setNonPkixOcspEnabled(ocspEnabled, pref);
-
- CERT_SetOCSPFailureMode( ocspRequired ?
- ocspMode_FailureIsVerificationFailure
- : ocspMode_FailureIsNotAVerificationFailure);
- nsRefPtr<nsCERTValInParamWrapper> newCVIN = new nsCERTValInParamWrapper;
- if (NS_SUCCEEDED(newCVIN->Construct(
- aiaDownloadEnabled ?
- nsCERTValInParamWrapper::missing_cert_download_on : nsCERTValInParamWrapper::missing_cert_download_off,
- crlDownloading ?
- nsCERTValInParamWrapper::crl_download_allowed : nsCERTValInParamWrapper::crl_local_only,
- ocspEnabled ?
- nsCERTValInParamWrapper::ocsp_on : nsCERTValInParamWrapper::ocsp_off,
- ocspRequired ?
- nsCERTValInParamWrapper::ocsp_strict : nsCERTValInParamWrapper::ocsp_relaxed,
- anyFreshRequired ?
- nsCERTValInParamWrapper::any_revo_strict : nsCERTValInParamWrapper::any_revo_relaxed,
- firstNetworkRevo.get()))) {
- // Swap to new defaults, and will cause the old defaults to be released,
- // as soon as any concurrent use of the old default objects has finished.
- mDefaultCERTValInParam = newCVIN;
- }
- /*
- * The new defaults might change the validity of already established SSL sessions,
- * let's not reuse them.
- */
- SSL_ClearSessionCache();
- }
- NS_IMETHODIMP
- nsNSSComponent::SkipOcsp()
- {
- nsNSSShutDownPreventionLock locker;
- CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
- SECStatus rv = CERT_DisableOCSPChecking(certdb);
- return (rv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsNSSComponent::SkipOcspOff()
- {
- nsNSSShutDownPreventionLock locker;
- PRInt32 ocspEnabled;
- if (NS_FAILED(mPrefBranch->GetIntPref("security.OCSP.enabled", &ocspEnabled)))
- ocspEnabled = OCSP_ENABLED_DEFAULT;
- // 0 = disabled, 1 = enabled,
- // 2 = enabled with given default responder
-
- setNonPkixOcspEnabled(ocspEnabled, mPrefBranch);
- if (ocspEnabled)
- SSL_ClearSessionCache();
- return NS_OK;
- }
- nsresult
- nsNSSComponent::PostCRLImportEvent(const nsCSubstring &urlString,
- nsIStreamListener *listener)
- {
- //Create the event
- nsCOMPtr<nsIRunnable> event = new CRLDownloadEvent(urlString, listener);
- if (!event)
- return NS_ERROR_OUT_OF_MEMORY;
- //Get a handle to the ui thread
- return NS_DispatchToMainThread(event);
- }
- nsresult
- nsNSSComponent::DownloadCRLDirectly(nsAutoString url, nsAutoString key)
- {
- //This api is meant to support direct interactive update of crl from the crl manager
- //or other such ui.
- nsCOMPtr<nsIStreamListener> listener =
- new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL);
-
- NS_ConvertUTF16toUTF8 url8(url);
- return PostCRLImportEvent(url8, listener);
- }
- nsresult nsNSSComponent::DownloadCrlSilently()
- {
- //Add this attempt to the hashtable
- nsStringKey hashKey(mCrlUpdateKey.get());
- crlsScheduledForDownload->Put(&hashKey,(void *)nsnull);
-
- //Set up the download handler
- nsRefPtr<PSMContentDownloader> psmDownloader =
- new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL);
- psmDownloader->setSilentDownload(true);
- psmDownloader->setCrlAutodownloadKey(mCrlUpdateKey);
-
- //Now get the url string
- NS_ConvertUTF16toUTF8 url8(mDownloadURL);
- return PostCRLImportEvent(url8, psmDownloader);
- }
- nsresult nsNSSComponent::getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key)
- {
- const char *updateEnabledPref = CRL_AUTOUPDATE_ENABLED_PREF;
- const char *updateTimePref = CRL_AUTOUPDATE_TIME_PREF;
- const char *updateURLPref = CRL_AUTOUPDATE_URL_PREF;
- char **allCrlsToBeUpdated;
- PRUint32 noOfCrls;
- PRTime nearestUpdateTime = 0;
- nsAutoString crlKey;
- char *tempUrl;
- nsresult rv;
-
- nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID,&rv);
- if(NS_FAILED(rv)){
- return rv;
- }
- rv = pref->GetChildList(updateEnabledPref, &noOfCrls, &allCrlsToBeUpdated);
- if ( (NS_FAILED(rv)) || (noOfCrls==0) ){
- return NS_ERROR_FAILURE;
- }
- for(PRUint32 i=0;i<noOfCrls;i++) {
- //First check if update pref is enabled for this crl
- bool autoUpdateEnabled = false;
- rv = pref->GetBoolPref(*(allCrlsToBeUpdated+i), &autoUpdateEnabled);
- if (NS_FAILED(rv) || !autoUpdateEnabled) {
- continue;
- }
- nsAutoString tempCrlKey;
- //Now, generate the crl key. Same key would be used as hashkey as well
- nsCAutoString enabledPrefCString(*(allCrlsToBeUpdated+i));
- enabledPrefCString.ReplaceSubstring(updateEnabledPref,".");
- tempCrlKey.AssignWithConversion(enabledPrefCString.get());
-
- //Check if this crl has already been scheduled. Its presence in the hashtable
- //implies that it has been scheduled already this client session, and
- //is either in the process of being downloaded, or its download failed
- //for some reason. In the second case, we will not retry in the current client session
- nsStringKey hashKey(tempCrlKey.get());
- if(crlsScheduledForDownload->Exists(&hashKey)){
- continue;
- }
- char *tempTimeString;
- PRTime tempTime;
- nsCAutoString timingPrefCString(updateTimePref);
- timingPrefCString.AppendWithConversion(tempCrlKey);
- rv = pref->GetCharPref(timingPrefCString.get(), &tempTimeString);
- if (NS_FAILED(rv)){
- continue;
- }
- rv = PR_ParseTimeString(tempTimeString,true, &tempTime);
- nsMemory::Free(tempTimeString);
- if (NS_FAILED(rv)){
- continue;
- }
- if(nearestUpdateTime == 0 || tempTime < nearestUpdateTime){
- nsCAutoString urlPrefCString(updateURLPref);
- urlPrefCString.AppendWithConversion(tempCrlKey);
- rv = pref->GetCharPref(urlPrefCString.get(), &tempUrl);
- if (NS_FAILED(rv) || (!tempUrl)){
- continue;
- }
- nearestUpdateTime = tempTime;
- crlKey = tempCrlKey;
- }
- }
- if(noOfCrls > 0)
- NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(noOfCrls, allCrlsToBeUpdated);
- if(nearestUpdateTime > 0){
- *time = nearestUpdateTime;
- url->AssignWithConversion((const char *)tempUrl);
- nsMemory::Free(tempUrl);
- *key = crlKey;
- rv = NS_OK;
- } else{
- rv = NS_ERROR_FAILURE;
- }
- return rv;
- }
- NS_IMETHODIMP
- nsNSSComponent::Notify(nsITimer *timer)
- {
- nsresult rv;
- //Timer has fired. So set the flag accordingly
- {
- MutexAutoLock lock(mCrlTimerLock);
- crlDownloadTimerOn = false;
- }
- //First, handle this download
- rv = DownloadCrlSilently();
- //Dont Worry if successful or not
- //Set the next timer
- DefineNextTimer();
- return NS_OK;
- }
- nsresult
- nsNSSComponent::RemoveCrlFromList(nsAutoString key)
- {
- nsStringKey hashKey(key.get());
- if(crlsScheduledForDownload->Exists(&hashKey)){
- crlsScheduledForDownload->Remove(&hashKey);
- }
- return NS_OK;
- }
- nsresult
- nsNSSComponent::DefineNextTimer()
- {
- PRTime nextFiring;
- PRTime now = PR_Now();
- PRUint64 diff;
- PRUint32 interval;
- PRUint32 primaryDelay = CRL_AUTOUPDATE_DEFAULT_DELAY;
- nsresult rv;
- if(!mTimer){
- mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
- if(NS_FAILED(rv))
- return rv;
- }
- //If some timer is already running, cancel it. Thus, the request that came last,
- //wins. This would ensure that in no way we end up setting two different timers
- //This part should be synchronized because this function might be called from separate
- //threads
- MutexAutoLock lock(mCrlTimerLock);
- if (crlDownloadTimerOn) {
- mTimer->Cancel();
- }
- rv = getParamsForNextCrlToDownload(&mDownloadURL, &nextFiring, &mCrlUpdateKey);
- //If there are no more crls to be updated any time in future
- if(NS_FAILED(rv)){
- // Return - no error - just implies nothing to schedule
- return NS_OK;
- }
-
- //Define the firing interval, from NOW
- if ( now < nextFiring) {
- LL_SUB(diff,nextFiring,now);
- LL_L2UI(interval, diff);
- //Now, we are doing 32 operations - so, don't need LL_ functions...
- interval = interval/PR_USEC_PER_MSEC;
- }else {
- interval = primaryDelay;
- }
-
- mTimer->InitWithCallback(static_cast<nsITimerCallback*>(this),
- interval,
- nsITimer::TYPE_ONE_SHOT);
- crlDownloadTimerOn = true;
- return NS_OK;
- }
- //Note that the StopCRLUpdateTimer and InitializeCRLUpdateTimer functions should never be called
- //simultaneously from diff threads - they are NOT threadsafe. But, since there is no chance of
- //that happening, there is not much benefit it trying to make it so at this point
- nsresult
- nsNSSComponent::StopCRLUpdateTimer()
- {
-
- //If it is at all running.
- if (mUpdateTimerInitialized) {
- if(crlsScheduledForDownload != nsnull){
- crlsScheduledForDownload->Reset();
- delete crlsScheduledForDownload;
- crlsScheduledForDownload = nsnull;
- }
- {
- MutexAutoLock lock(mCrlTimerLock);
- if (crlDownloadTimerOn) {
- mTimer->Cancel();
- }
- crlDownloadTimerOn = false;
- }
- mUpdateTimerInitialized = false;
- }
- return NS_OK;
- }
- nsresult
- nsNSSComponent::InitializeCRLUpdateTimer()
- {
- nsresult rv;
-
- //First check if this is already initialized. Then we stop it.
- if (!mUpdateTimerInitialized) {
- mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
- if(NS_FAILED(rv)){
- return rv;
- }
- crlsScheduledForDownload = new nsHashtable(16, true);
- DefineNextTimer();
- mUpdateTimerInitialized = true;
- }
- return NS_OK;
- }
- #ifdef XP_MACOSX
- void
- nsNSSComponent::TryCFM2MachOMigration(nsIFile *cfmPath, nsIFile *machoPath)
- {
- // We will modify the parameters.
- //
- // If neither cert7.db, cert8.db, key3.db, are available,
- // copy from filenames that were used in the old days
- // test for key3.db first, since a new profile might only contain cert8.db,
- // but not cert7.db - this optimizes number of tests
- NS_NAMED_LITERAL_CSTRING(cstr_key3db, "key3.db");
- NS_NAMED_LITERAL_CSTRING(cstr_cert7db, "cert7.db");
- NS_NAMED_LITERAL_CSTRING(cstr_cert8db, "cert8.db");
- NS_NAMED_LITERAL_CSTRING(cstr_keydatabase3, "Key Database3");
- NS_NAMED_LITERAL_CSTRING(cstr_certificate7, "Certificates7");
- NS_NAMED_LITERAL_CSTRING(cstr_certificate8, "Certificates8");
- bool bExists;
- nsresult rv;
- nsCOMPtr<nsIFile> macho_key3db;
- rv = machoPath->Clone(getter_AddRefs(macho_key3db));
- if (NS_FAILED(rv)) {
- return;
- }
- macho_key3db->AppendNative(cstr_key3db);
- rv = macho_key3db->Exists(&bExists);
- if (NS_FAILED(rv) || bExists) {
- return;
- }
- nsCOMPtr<nsIFile> macho_cert7db;
- rv = machoPath->Clone(getter_AddRefs(macho_cert7db));
- if (NS_FAILED(rv)) {
- return;
- }
- macho_cert7db->AppendNative(cstr_cert7db);
- rv = macho_cert7db->Exists(&bExists);
- if (NS_FAILED(rv) || bExists) {
- return;
- }
- nsCOMPtr<nsIFile> macho_cert8db;
- rv = machoPath->Clone(getter_AddRefs(macho_cert8db));
- if (NS_FAILED(rv)) {
- return;
- }
- macho_cert8db->AppendNative(cstr_cert8db);
- rv = macho_cert7db->Exists(&bExists);
- if (NS_FAILED(rv) || bExists) {
- return;
- }
- // None of the new files exist. Try to copy any available old files.
- nsCOMPtr<nsIFile> cfm_key3;
- rv = cfmPath->Clone(getter_AddRefs(cfm_key3));
- if (NS_FAILED(rv)) {
- return;
- }
- cfm_key3->AppendNative(cstr_keydatabase3);
- rv = cfm_key3->Exists(&bExists);
- if (NS_FAILED(rv)) {
- return;
- }
- if (bExists) {
- cfm_key3->CopyToFollowingLinksNative(machoPath, cstr_key3db);
- }
- nsCOMPtr<nsIFile> cfm_cert7;
- rv = cfmPath->Clone(getter_Ad…