| Index: mozilla/security/nss/lib/pk11wrap/pk11load.c
|
| ===================================================================
|
| --- mozilla/security/nss/lib/pk11wrap/pk11load.c (revision 191424)
|
| +++ mozilla/security/nss/lib/pk11wrap/pk11load.c (working copy)
|
| @@ -1,639 +0,0 @@
|
| -/* This Source Code Form is subject to the terms of the Mozilla Public
|
| - * License, v. 2.0. If a copy of the MPL was not distributed with this
|
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
| -/*
|
| - * The following handles the loading, unloading and management of
|
| - * various PCKS #11 modules
|
| - */
|
| -#define FORCE_PR_LOG 1
|
| -#include "seccomon.h"
|
| -#include "pkcs11.h"
|
| -#include "secmod.h"
|
| -#include "prlink.h"
|
| -#include "pk11func.h"
|
| -#include "secmodi.h"
|
| -#include "secmodti.h"
|
| -#include "nssilock.h"
|
| -#include "secerr.h"
|
| -#include "prenv.h"
|
| -#include "utilparst.h"
|
| -
|
| -#define DEBUG_MODULE 1
|
| -
|
| -#ifdef DEBUG_MODULE
|
| -static char *modToDBG = NULL;
|
| -
|
| -#include "debug_module.c"
|
| -#endif
|
| -
|
| -/* build the PKCS #11 2.01 lock files */
|
| -CK_RV PR_CALLBACK secmodCreateMutext(CK_VOID_PTR_PTR pmutex) {
|
| - *pmutex = (CK_VOID_PTR) PZ_NewLock(nssILockOther);
|
| - if ( *pmutex ) return CKR_OK;
|
| - return CKR_HOST_MEMORY;
|
| -}
|
| -
|
| -CK_RV PR_CALLBACK secmodDestroyMutext(CK_VOID_PTR mutext) {
|
| - PZ_DestroyLock((PZLock *)mutext);
|
| - return CKR_OK;
|
| -}
|
| -
|
| -CK_RV PR_CALLBACK secmodLockMutext(CK_VOID_PTR mutext) {
|
| - PZ_Lock((PZLock *)mutext);
|
| - return CKR_OK;
|
| -}
|
| -
|
| -CK_RV PR_CALLBACK secmodUnlockMutext(CK_VOID_PTR mutext) {
|
| - PZ_Unlock((PZLock *)mutext);
|
| - return CKR_OK;
|
| -}
|
| -
|
| -static SECMODModuleID nextModuleID = 1;
|
| -static const CK_C_INITIALIZE_ARGS secmodLockFunctions = {
|
| - secmodCreateMutext, secmodDestroyMutext, secmodLockMutext,
|
| - secmodUnlockMutext, CKF_LIBRARY_CANT_CREATE_OS_THREADS|
|
| - CKF_OS_LOCKING_OK
|
| - ,NULL
|
| -};
|
| -
|
| -static PRBool loadSingleThreadedModules = PR_TRUE;
|
| -static PRBool enforceAlreadyInitializedError = PR_TRUE;
|
| -static PRBool finalizeModules = PR_TRUE;
|
| -
|
| -/* set global options for NSS PKCS#11 module loader */
|
| -SECStatus pk11_setGlobalOptions(PRBool noSingleThreadedModules,
|
| - PRBool allowAlreadyInitializedModules,
|
| - PRBool dontFinalizeModules)
|
| -{
|
| - if (noSingleThreadedModules) {
|
| - loadSingleThreadedModules = PR_FALSE;
|
| - } else {
|
| - loadSingleThreadedModules = PR_TRUE;
|
| - }
|
| - if (allowAlreadyInitializedModules) {
|
| - enforceAlreadyInitializedError = PR_FALSE;
|
| - } else {
|
| - enforceAlreadyInitializedError = PR_TRUE;
|
| - }
|
| - if (dontFinalizeModules) {
|
| - finalizeModules = PR_FALSE;
|
| - } else {
|
| - finalizeModules = PR_TRUE;
|
| - }
|
| - return SECSuccess;
|
| -}
|
| -
|
| -PRBool pk11_getFinalizeModulesOption(void)
|
| -{
|
| - return finalizeModules;
|
| -}
|
| -
|
| -/*
|
| - * Allow specification loading the same module more than once at init time.
|
| - * This enables 2 things.
|
| - *
|
| - * 1) we can load additional databases by manipulating secmod.db/pkcs11.txt.
|
| - * 2) we can handle the case where some library has already initialized NSS
|
| - * before the main application.
|
| - *
|
| - * oldModule is the module we have already initialized.
|
| - * char *modulespec is the full module spec for the library we want to
|
| - * initialize.
|
| - */
|
| -static SECStatus
|
| -secmod_handleReload(SECMODModule *oldModule, SECMODModule *newModule)
|
| -{
|
| - PK11SlotInfo *slot;
|
| - char *modulespec;
|
| - char *newModuleSpec;
|
| - char **children;
|
| - CK_SLOT_ID *ids;
|
| - SECMODConfigList *conflist = NULL;
|
| - SECStatus rv = SECFailure;
|
| - int count = 0;
|
| -
|
| - /* first look for tokens= key words from the module spec */
|
| - modulespec = newModule->libraryParams;
|
| - newModuleSpec = secmod_ParseModuleSpecForTokens(PR_TRUE,
|
| - newModule->isFIPS, modulespec, &children, &ids);
|
| - if (!newModuleSpec) {
|
| - return SECFailure;
|
| - }
|
| -
|
| - /*
|
| - * We are now trying to open a new slot on an already loaded module.
|
| - * If that slot represents a cert/key database, we don't want to open
|
| - * multiple copies of that same database. Unfortunately we understand
|
| - * the softoken flags well enough to be able to do this, so we can only get
|
| - * the list of already loaded databases if we are trying to open another
|
| - * internal module.
|
| - */
|
| - if (oldModule->internal) {
|
| - conflist = secmod_GetConfigList(oldModule->isFIPS,
|
| - oldModule->libraryParams, &count);
|
| - }
|
| -
|
| -
|
| - /* don't open multiple of the same db */
|
| - if (conflist && secmod_MatchConfigList(newModuleSpec, conflist, count)) {
|
| - rv = SECSuccess;
|
| - goto loser;
|
| - }
|
| - slot = SECMOD_OpenNewSlot(oldModule, newModuleSpec);
|
| - if (slot) {
|
| - int newID;
|
| - char **thisChild;
|
| - CK_SLOT_ID *thisID;
|
| - char *oldModuleSpec;
|
| -
|
| - if (secmod_IsInternalKeySlot(newModule)) {
|
| - pk11_SetInternalKeySlotIfFirst(slot);
|
| - }
|
| - newID = slot->slotID;
|
| - PK11_FreeSlot(slot);
|
| - for (thisChild=children, thisID=ids; thisChild && *thisChild;
|
| - thisChild++,thisID++) {
|
| - if (conflist &&
|
| - secmod_MatchConfigList(*thisChild, conflist, count)) {
|
| - *thisID = (CK_SLOT_ID) -1;
|
| - continue;
|
| - }
|
| - slot = SECMOD_OpenNewSlot(oldModule, *thisChild);
|
| - if (slot) {
|
| - *thisID = slot->slotID;
|
| - PK11_FreeSlot(slot);
|
| - } else {
|
| - *thisID = (CK_SLOT_ID) -1;
|
| - }
|
| - }
|
| -
|
| - /* update the old module initialization string in case we need to
|
| - * shutdown and reinit the whole mess (this is rare, but can happen
|
| - * when trying to stop smart card insertion/removal threads)... */
|
| - oldModuleSpec = secmod_MkAppendTokensList(oldModule->arena,
|
| - oldModule->libraryParams, newModuleSpec, newID,
|
| - children, ids);
|
| - if (oldModuleSpec) {
|
| - oldModule->libraryParams = oldModuleSpec;
|
| - }
|
| -
|
| - rv = SECSuccess;
|
| - }
|
| -
|
| -loser:
|
| - secmod_FreeChildren(children, ids);
|
| - PORT_Free(newModuleSpec);
|
| - if (conflist) {
|
| - secmod_FreeConfigList(conflist, count);
|
| - }
|
| - return rv;
|
| -}
|
| -
|
| -/*
|
| - * collect the steps we need to initialize a module in a single function
|
| - */
|
| -SECStatus
|
| -secmod_ModuleInit(SECMODModule *mod, SECMODModule **reload,
|
| - PRBool* alreadyLoaded)
|
| -{
|
| - CK_C_INITIALIZE_ARGS moduleArgs;
|
| - CK_VOID_PTR pInitArgs;
|
| - CK_RV crv;
|
| -
|
| - if (reload) {
|
| - *reload = NULL;
|
| - }
|
| -
|
| - if (!mod || !alreadyLoaded) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return SECFailure;
|
| - }
|
| -
|
| - if (mod->isThreadSafe == PR_FALSE) {
|
| - pInitArgs = NULL;
|
| - } else if (mod->libraryParams == NULL) {
|
| - pInitArgs = (void *) &secmodLockFunctions;
|
| - } else {
|
| - moduleArgs = secmodLockFunctions;
|
| - moduleArgs.LibraryParameters = (void *) mod->libraryParams;
|
| - pInitArgs = &moduleArgs;
|
| - }
|
| - crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
|
| - if (CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) {
|
| - SECMODModule *oldModule = NULL;
|
| -
|
| - /* Library has already been loaded once, if caller expects it, and it
|
| - * has additional configuration, try reloading it as well. */
|
| - if (reload != NULL && mod->libraryParams) {
|
| - oldModule = secmod_FindModuleByFuncPtr(mod->functionList);
|
| - }
|
| - /* Library has been loaded by NSS. It means it may be capable of
|
| - * reloading */
|
| - if (oldModule) {
|
| - SECStatus rv;
|
| - rv = secmod_handleReload(oldModule, mod);
|
| - if (rv == SECSuccess) {
|
| - /* This module should go away soon, since we've
|
| - * simply expanded the slots on the old module.
|
| - * When it goes away, it should not Finalize since
|
| - * that will close our old module as well. Setting
|
| - * the function list to NULL will prevent that close */
|
| - mod->functionList = NULL;
|
| - *reload = oldModule;
|
| - return SECSuccess;
|
| - }
|
| - SECMOD_DestroyModule(oldModule);
|
| - }
|
| - /* reload not possible, fall back to old semantics */
|
| - if (!enforceAlreadyInitializedError) {
|
| - *alreadyLoaded = PR_TRUE;
|
| - return SECSuccess;
|
| - }
|
| - }
|
| - if (crv != CKR_OK) {
|
| - if (pInitArgs == NULL ||
|
| - crv == CKR_NETSCAPE_CERTDB_FAILED ||
|
| - crv == CKR_NETSCAPE_KEYDB_FAILED) {
|
| - PORT_SetError(PK11_MapError(crv));
|
| - return SECFailure;
|
| - }
|
| - if (!loadSingleThreadedModules) {
|
| - PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
|
| - return SECFailure;
|
| - }
|
| - mod->isThreadSafe = PR_FALSE;
|
| - crv = PK11_GETTAB(mod)->C_Initialize(NULL);
|
| - if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) &&
|
| - (!enforceAlreadyInitializedError)) {
|
| - *alreadyLoaded = PR_TRUE;
|
| - return SECSuccess;
|
| - }
|
| - if (crv != CKR_OK) {
|
| - PORT_SetError(PK11_MapError(crv));
|
| - return SECFailure;
|
| - }
|
| - }
|
| - return SECSuccess;
|
| -}
|
| -
|
| -/*
|
| - * set the hasRootCerts flags in the module so it can be stored back
|
| - * into the database.
|
| - */
|
| -void
|
| -SECMOD_SetRootCerts(PK11SlotInfo *slot, SECMODModule *mod) {
|
| - PK11PreSlotInfo *psi = NULL;
|
| - int i;
|
| -
|
| - if (slot->hasRootCerts) {
|
| - for (i=0; i < mod->slotInfoCount; i++) {
|
| - if (slot->slotID == mod->slotInfo[i].slotID) {
|
| - psi = &mod->slotInfo[i];
|
| - break;
|
| - }
|
| - }
|
| - if (psi == NULL) {
|
| - /* allocate more slots */
|
| - PK11PreSlotInfo *psi_list = (PK11PreSlotInfo *)
|
| - PORT_ArenaAlloc(mod->arena,
|
| - (mod->slotInfoCount+1)* sizeof(PK11PreSlotInfo));
|
| - /* copy the old ones */
|
| - if (mod->slotInfoCount > 0) {
|
| - PORT_Memcpy(psi_list,mod->slotInfo,
|
| - (mod->slotInfoCount)*sizeof(PK11PreSlotInfo));
|
| - }
|
| - /* assign psi to the last new slot */
|
| - psi = &psi_list[mod->slotInfoCount];
|
| - psi->slotID = slot->slotID;
|
| - psi->askpw = 0;
|
| - psi->timeout = 0;
|
| - psi ->defaultFlags = 0;
|
| -
|
| - /* increment module count & store new list */
|
| - mod->slotInfo = psi_list;
|
| - mod->slotInfoCount++;
|
| -
|
| - }
|
| - psi->hasRootCerts = 1;
|
| - }
|
| -}
|
| -
|
| -#ifdef NSS_STATIC
|
| -extern CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList);
|
| -extern CK_RV FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList);
|
| -extern char **NSC_ModuleDBFunc(unsigned long function,char *parameters, void *args);
|
| -extern CK_RV builtinsC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList);
|
| -#else
|
| -static const char* my_shlib_name =
|
| - SHLIB_PREFIX"nss"SHLIB_VERSION"."SHLIB_SUFFIX;
|
| -static const char* softoken_shlib_name =
|
| - SHLIB_PREFIX"softokn"SOFTOKEN_SHLIB_VERSION"."SHLIB_SUFFIX;
|
| -static const PRCallOnceType pristineCallOnce;
|
| -static PRCallOnceType loadSoftokenOnce;
|
| -static PRLibrary* softokenLib;
|
| -static PRInt32 softokenLoadCount;
|
| -#endif /* NSS_STATIC */
|
| -
|
| -#include "prio.h"
|
| -#include "prprf.h"
|
| -#include <stdio.h>
|
| -#include "prsystem.h"
|
| -
|
| -#ifndef NSS_STATIC
|
| -/* This function must be run only once. */
|
| -/* determine if hybrid platform, then actually load the DSO. */
|
| -static PRStatus
|
| -softoken_LoadDSO( void )
|
| -{
|
| - PRLibrary * handle;
|
| -
|
| - handle = PORT_LoadLibraryFromOrigin(my_shlib_name,
|
| - (PRFuncPtr) &softoken_LoadDSO,
|
| - softoken_shlib_name);
|
| - if (handle) {
|
| - softokenLib = handle;
|
| - return PR_SUCCESS;
|
| - }
|
| - return PR_FAILURE;
|
| -}
|
| -#endif /* !NSS_STATIC */
|
| -
|
| -/*
|
| - * load a new module into our address space and initialize it.
|
| - */
|
| -SECStatus
|
| -secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) {
|
| - PRLibrary *library = NULL;
|
| - CK_C_GetFunctionList entry = NULL;
|
| - CK_INFO info;
|
| - CK_ULONG slotCount = 0;
|
| - SECStatus rv;
|
| - PRBool alreadyLoaded = PR_FALSE;
|
| - char *disableUnload = NULL;
|
| -
|
| - if (mod->loaded) return SECSuccess;
|
| -
|
| - /* intenal modules get loaded from their internal list */
|
| - if (mod->internal && (mod->dllName == NULL)) {
|
| -#ifdef NSS_STATIC
|
| - if (mod->isFIPS) {
|
| - entry = FC_GetFunctionList;
|
| - } else {
|
| - entry = NSC_GetFunctionList;
|
| - }
|
| - if (mod->isModuleDB) {
|
| - mod->moduleDBFunc = NSC_ModuleDBFunc;
|
| - }
|
| -#else
|
| - /*
|
| - * Loads softoken as a dynamic library,
|
| - * even though the rest of NSS assumes this as the "internal" module.
|
| - */
|
| - if (!softokenLib &&
|
| - PR_SUCCESS != PR_CallOnce(&loadSoftokenOnce, &softoken_LoadDSO))
|
| - return SECFailure;
|
| -
|
| - PR_ATOMIC_INCREMENT(&softokenLoadCount);
|
| -
|
| - if (mod->isFIPS) {
|
| - entry = (CK_C_GetFunctionList)
|
| - PR_FindSymbol(softokenLib, "FC_GetFunctionList");
|
| - } else {
|
| - entry = (CK_C_GetFunctionList)
|
| - PR_FindSymbol(softokenLib, "NSC_GetFunctionList");
|
| - }
|
| -
|
| - if (!entry)
|
| - return SECFailure;
|
| -
|
| - if (mod->isModuleDB) {
|
| - mod->moduleDBFunc = (CK_C_GetFunctionList)
|
| - PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc");
|
| - }
|
| -#endif
|
| -
|
| - if (mod->moduleDBOnly) {
|
| - mod->loaded = PR_TRUE;
|
| - return SECSuccess;
|
| - }
|
| - } else {
|
| - /* Not internal, load the DLL and look up C_GetFunctionList */
|
| - if (mod->dllName == NULL) {
|
| - return SECFailure;
|
| - }
|
| -#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS)
|
| - if (strstr(mod->dllName, "nssckbi") != NULL) {
|
| - mod->library = NULL;
|
| - PORT_Assert(!mod->moduleDBOnly);
|
| - entry = builtinsC_GetFunctionList;
|
| - PORT_Assert(!mod->isModuleDB);
|
| - goto library_loaded;
|
| - }
|
| -#endif
|
| -
|
| - /* load the library. If this succeeds, then we have to remember to
|
| - * unload the library if anything goes wrong from here on out...
|
| - */
|
| - library = PR_LoadLibrary(mod->dllName);
|
| - mod->library = (void *)library;
|
| -
|
| - if (library == NULL) {
|
| - return SECFailure;
|
| - }
|
| -
|
| - /*
|
| - * now we need to get the entry point to find the function pointers
|
| - */
|
| - if (!mod->moduleDBOnly) {
|
| - entry = (CK_C_GetFunctionList)
|
| - PR_FindSymbol(library, "C_GetFunctionList");
|
| - }
|
| - if (mod->isModuleDB) {
|
| - mod->moduleDBFunc = (void *)
|
| - PR_FindSymbol(library, "NSS_ReturnModuleSpecData");
|
| - }
|
| -#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS)
|
| -library_loaded:
|
| -#endif
|
| - if (mod->moduleDBFunc == NULL) mod->isModuleDB = PR_FALSE;
|
| - if (entry == NULL) {
|
| - if (mod->isModuleDB) {
|
| - mod->loaded = PR_TRUE;
|
| - mod->moduleDBOnly = PR_TRUE;
|
| - return SECSuccess;
|
| - }
|
| - PR_UnloadLibrary(library);
|
| - return SECFailure;
|
| - }
|
| - }
|
| -
|
| - /*
|
| - * We need to get the function list
|
| - */
|
| - if ((*entry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK)
|
| - goto fail;
|
| -
|
| -#ifdef DEBUG_MODULE
|
| - if (PR_TRUE) {
|
| - modToDBG = PR_GetEnv("NSS_DEBUG_PKCS11_MODULE");
|
| - if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) {
|
| - mod->functionList = (void *)nss_InsertDeviceLog(
|
| - (CK_FUNCTION_LIST_PTR)mod->functionList);
|
| - }
|
| - }
|
| -#endif
|
| -
|
| - mod->isThreadSafe = PR_TRUE;
|
| -
|
| - /* Now we initialize the module */
|
| - rv = secmod_ModuleInit(mod, oldModule, &alreadyLoaded);
|
| - if (rv != SECSuccess) {
|
| - goto fail;
|
| - }
|
| -
|
| - /* module has been reloaded, this module itself is done,
|
| - * return to the caller */
|
| - if (mod->functionList == NULL) {
|
| - mod->loaded = PR_TRUE; /* technically the module is loaded.. */
|
| - return SECSuccess;
|
| - }
|
| -
|
| - /* check the version number */
|
| - if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK) goto fail2;
|
| - if (info.cryptokiVersion.major != 2) goto fail2;
|
| - /* all 2.0 are a priori *not* thread safe */
|
| - if (info.cryptokiVersion.minor < 1) {
|
| - if (!loadSingleThreadedModules) {
|
| - PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
|
| - goto fail2;
|
| - } else {
|
| - mod->isThreadSafe = PR_FALSE;
|
| - }
|
| - }
|
| - mod->cryptokiVersion = info.cryptokiVersion;
|
| -
|
| - /* If we don't have a common name, get it from the PKCS 11 module */
|
| - if ((mod->commonName == NULL) || (mod->commonName[0] == 0)) {
|
| - mod->commonName = PK11_MakeString(mod->arena,NULL,
|
| - (char *)info.libraryDescription, sizeof(info.libraryDescription));
|
| - if (mod->commonName == NULL) goto fail2;
|
| - }
|
| -
|
| -
|
| - /* initialize the Slots */
|
| - if (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &slotCount) == CKR_OK) {
|
| - CK_SLOT_ID *slotIDs;
|
| - int i;
|
| - CK_RV crv;
|
| -
|
| - mod->slots = (PK11SlotInfo **)PORT_ArenaAlloc(mod->arena,
|
| - sizeof(PK11SlotInfo *) * slotCount);
|
| - if (mod->slots == NULL) goto fail2;
|
| -
|
| - slotIDs = (CK_SLOT_ID *) PORT_Alloc(sizeof(CK_SLOT_ID)*slotCount);
|
| - if (slotIDs == NULL) {
|
| - goto fail2;
|
| - }
|
| - crv = PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, slotIDs, &slotCount);
|
| - if (crv != CKR_OK) {
|
| - PORT_Free(slotIDs);
|
| - goto fail2;
|
| - }
|
| -
|
| - /* Initialize each slot */
|
| - for (i=0; i < (int)slotCount; i++) {
|
| - mod->slots[i] = PK11_NewSlotInfo(mod);
|
| - PK11_InitSlot(mod,slotIDs[i],mod->slots[i]);
|
| - /* look down the slot info table */
|
| - PK11_LoadSlotList(mod->slots[i],mod->slotInfo,mod->slotInfoCount);
|
| - SECMOD_SetRootCerts(mod->slots[i],mod);
|
| - /* explicitly mark the internal slot as such if IsInternalKeySlot()
|
| - * is set */
|
| - if (secmod_IsInternalKeySlot(mod) && (i == (mod->isFIPS ? 0 : 1))) {
|
| - pk11_SetInternalKeySlotIfFirst(mod->slots[i]);
|
| - }
|
| - }
|
| - mod->slotCount = slotCount;
|
| - mod->slotInfoCount = 0;
|
| - PORT_Free(slotIDs);
|
| - }
|
| -
|
| - mod->loaded = PR_TRUE;
|
| - mod->moduleID = nextModuleID++;
|
| - return SECSuccess;
|
| -fail2:
|
| - if (enforceAlreadyInitializedError || (!alreadyLoaded)) {
|
| - PK11_GETTAB(mod)->C_Finalize(NULL);
|
| - }
|
| -fail:
|
| - mod->functionList = NULL;
|
| - disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
|
| - if (library && !disableUnload) {
|
| - PR_UnloadLibrary(library);
|
| - }
|
| - return SECFailure;
|
| -}
|
| -
|
| -SECStatus
|
| -SECMOD_UnloadModule(SECMODModule *mod) {
|
| - PRLibrary *library;
|
| - char *disableUnload = NULL;
|
| -
|
| - if (!mod->loaded) {
|
| - return SECFailure;
|
| - }
|
| - if (finalizeModules) {
|
| - if (mod->functionList &&!mod->moduleDBOnly) {
|
| - PK11_GETTAB(mod)->C_Finalize(NULL);
|
| - }
|
| - }
|
| - mod->moduleID = 0;
|
| - mod->loaded = PR_FALSE;
|
| -
|
| - /* do we want the semantics to allow unloading the internal library?
|
| - * if not, we should change this to SECFailure and move it above the
|
| - * mod->loaded = PR_FALSE; */
|
| - if (mod->internal && (mod->dllName == NULL)) {
|
| -#ifndef NSS_STATIC
|
| - if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) {
|
| - if (softokenLib) {
|
| - disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
|
| - if (!disableUnload) {
|
| - PRStatus status = PR_UnloadLibrary(softokenLib);
|
| - PORT_Assert(PR_SUCCESS == status);
|
| - }
|
| - softokenLib = NULL;
|
| - }
|
| - loadSoftokenOnce = pristineCallOnce;
|
| - }
|
| -#endif
|
| - return SECSuccess;
|
| - }
|
| -
|
| - library = (PRLibrary *)mod->library;
|
| - /* paranoia */
|
| - if (library == NULL) {
|
| -#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS)
|
| - if (strstr(mod->dllName, "nssckbi") != NULL) {
|
| - return SECSuccess;
|
| - }
|
| -#endif
|
| - return SECFailure;
|
| - }
|
| -
|
| - disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
|
| - if (!disableUnload) {
|
| - PR_UnloadLibrary(library);
|
| - }
|
| - return SECSuccess;
|
| -}
|
| -
|
| -void
|
| -nss_DumpModuleLog(void)
|
| -{
|
| -#ifdef DEBUG_MODULE
|
| - if (modToDBG) {
|
| - print_final_statistics();
|
| - }
|
| -#endif
|
| -}
|
|
|