Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/security/nss/lib/pk11wrap/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 23 kB image not shown  

Quelle  pk11load.c   Sprache: C

 
/* 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 "base.h"
#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 "utilpars.h"
#include "prio.h"
#include "prprf.h"
#include <stdio.h>
#include "prsystem.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 const CK_C_INITIALIZE_ARGS secmodNoLockArgs = {
    NULL, NULL, NULL, NULL,
    CKF_LIBRARY_CANT_CREATE_OS_THREADS, 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->libraryParams == NULL) {
        if (mod->isThreadSafe) {
            pInitArgs = (void *)&secmodLockFunctions;
        } else {
            pInitArgs = NULL;
        }
    } else {
        if (mod->isThreadSafe) {
            moduleArgs = secmodLockFunctions;
        } else {
            moduleArgs = secmodNoLockArgs;
        }
        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 (!mod->isThreadSafe ||
            crv == CKR_NSS_CERTDB_FAILED ||
            crv == CKR_NSS_KEYDB_FAILED) {
            PORT_SetError(PK11_MapError(crv));
            return SECFailure;
        }
        /* If we had attempted to init a single threaded module "with"
         * parameters and it failed, should we retry "without" parameters?
         * (currently we don't retry in this scenario) */


        if (!loadSingleThreadedModules) {
            PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
            return SECFailure;
        }
        /* If we arrive here, the module failed a ThreadSafe init. */
        mod->isThreadSafe = PR_FALSE;
        if (!mod->libraryParams) {
            pInitArgs = NULL;
        } else {
            moduleArgs = secmodNoLockArgs;
            moduleArgs.LibraryParameters = (void *)mod->libraryParams;
            pInitArgs = &moduleArgs;
        }
        crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
        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;
    }
}

#ifndef NSS_STATIC_SOFTOKEN
static const char *my_shlib_name =
    SHLIB_PREFIX "nss" 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;

/* 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;
}
#else
CK_RV NSC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName,
                       CK_VERSION_PTR pVersion,
                       CK_INTERFACE_PTR_PTR *ppInterface, CK_FLAGS flags);
char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args);
#endif

SECStatus
secmod_DetermineModuleFunctionList(SECMODModule *mod)
{
    PRLibrary *library = NULL;
    CK_C_GetInterface ientry = NULL;
    CK_C_GetFunctionList fentry = NULL;
    char *disableUnload = NULL;
#ifndef NSS_STATIC_SOFTOKEN
    const char *nss_interface;
    const char *nss_function;
#endif
    CK_INTERFACE_PTR interface;

    /* internal modules get loaded from their internal list */
    if (mod->internal && (mod->dllName == NULL)) {
#ifdef NSS_STATIC_SOFTOKEN
        ientry = (CK_C_GetInterface)NSC_GetInterface;
#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) {
            nss_interface = "FC_GetInterface";
            nss_function = "FC_GetFunctionList";
        } else {
            nss_interface = "NSC_GetInterface";
            nss_function = "NSC_GetFunctionList";
        }

        ientry = (CK_C_GetInterface)
            PR_FindSymbol(softokenLib, nss_interface);
        if (!ientry) {
            fentry = (CK_C_GetFunctionList)
                PR_FindSymbol(softokenLib, nss_function);
            if (!fentry) {
                return SECFailure;
            }
        }
#endif

        if (mod->isModuleDB) {
            mod->moduleDBFunc = (CK_C_GetFunctionList)
#ifdef NSS_STATIC_SOFTOKEN
                NSC_ModuleDBFunc;
#else
                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;
        }

/* load the library. If this succeeds, then we have to remember to
 * unload the library if anything goes wrong from here on out...
 */

#if defined(_WIN32)
        if (nssUTF8_Length(mod->dllName, NULL)) {
            wchar_t *dllNameWide = _NSSUTIL_UTF8ToWide(mod->dllName);
            if (dllNameWide) {
                PRLibSpec libSpec;
                libSpec.type = PR_LibSpec_PathnameU;
                libSpec.value.pathname_u = dllNameWide;
                library = PR_LoadLibraryWithFlags(libSpec, 0);
                PORT_Free(dllNameWide);
            }
        }
        if (library == NULL) {
            // fallback to system code page
            library = PR_LoadLibrary(mod->dllName);
        }
#else
        library = PR_LoadLibrary(mod->dllName);
#endif // defined(_WIN32)
        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) {
            ientry = (CK_C_GetInterface)
                PR_FindSymbol(library, "C_GetInterface");
            if (!ientry) {
                fentry = (CK_C_GetFunctionList)
                    PR_FindSymbol(library, "C_GetFunctionList");
            }
        }
        if (mod->isModuleDB) {
            mod->moduleDBFunc = (void *)
                PR_FindSymbol(library, "NSS_ReturnModuleSpecData");
        }
        if (mod->moduleDBFunc == NULL)
            mod->isModuleDB = PR_FALSE;
        if ((ientry == NULL) && (fentry == 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 (ientry) {
        /* we first try to get a FORK_SAFE interface */
        if ((*ientry)((CK_UTF8CHAR_PTR) "PKCS 11", NULL, &interface,
                      CKF_INTERFACE_FORK_SAFE) != CKR_OK) {
            /* one is not appearantly available, get a non-fork safe version */
            if ((*ientry)((CK_UTF8CHAR_PTR) "PKCS 11", NULL, &interface, 0) != CKR_OK) {
                goto fail;
            }
        }
        mod->functionList = interface->pFunctionList;
        mod->flags = interface->flags;
        /* if we have a fips indicator, grab it */
        if ((*ientry)((CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", NULL,
                      &interface, 0) == CKR_OK) {
            mod->fipsIndicator = ((CK_NSS_FIPS_FUNCTIONS *)(interface->pFunctionList))->NSC_NSSGetFIPSStatus;
        }
    } else {
        if ((*fentry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK)
            goto fail;
        mod->flags = 0;
    }

#ifdef DEBUG_MODULE
    modToDBG = PR_GetEnvSecure("NSS_DEBUG_PKCS11_MODULE");
    if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) {
        mod->functionList = (void *)nss_InsertDeviceLog(
            (CK_FUNCTION_LIST_3_0_PTR)mod->functionList);
    }
#endif

    return SECSuccess;

fail:
    mod->functionList = NULL;
    disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
    if (library && !disableUnload) {
        PR_UnloadLibrary(library);
    }
    return SECFailure;
}

SECStatus
secmod_InitializeModuleAndGetSlotInfo(SECMODModule *mod, SECMODModule **oldModule)
{
    CK_INFO info;
    CK_ULONG slotCount = 0;
    SECStatus rv;
    PRBool alreadyLoaded = PR_FALSE;

    /* This test operation makes sure our locking system is
     * consistent even if we are using non-thread safe tokens by
     * simulating unsafe tokens with safe ones. */

    mod->isThreadSafe = !PR_GetEnvSecure("NSS_FORCE_TOKEN_LOCK");

    /* 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.major == 2) && (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;
    return SECFailure;
}

/*
 * load a new module into our address space and initialize it.
 */

SECStatus
secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
{
    SECStatus rv = SECFailure;
    if (mod->loaded) {
        return SECSuccess;
    }

    mod->fipsIndicator = NULL;

    rv = secmod_DetermineModuleFunctionList(mod);
    if (rv != SECSuccess) { // The error code is set up by secmod_DetermineModuleFunctionList.
        return rv;
    }

    if (mod->loaded == PR_TRUE) {
        return SECSuccess;
    }

    rv = secmod_InitializeModuleAndGetSlotInfo(mod, oldModule);
    if (rv != SECSuccess) { // The error code is set up by secmod_InitializeModuleAndGetSlotInfo
        return rv;
    }

    return SECSuccess;
}

/*
 * load a new module using provided fentry function
 */

SECStatus
secmod_LoadPKCS11ModuleFromFunction(SECMODModule *mod, SECMODModule **oldModule,
                                    CK_C_GetFunctionList fentry)
{
    SECStatus rv = SECFailure;
    CK_RV crv;
    if (mod->loaded) {
        return SECSuccess;
    }

    mod->fipsIndicator = NULL;

    if (!fentry) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    crv = fentry((CK_FUNCTION_LIST_PTR *)&mod->functionList);
    if (crv != CKR_OK) {
        mod->functionList = NULL;
        PORT_SetError(PK11_MapError(crv));
        return SECFailure;
    }

    if (mod->functionList == NULL) {
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
        return SECFailure;
    }

    mod->flags = 0;
    rv = secmod_InitializeModuleAndGetSlotInfo(mod, oldModule);
    if (rv != SECSuccess) {
        return rv;
    }

    return SECSuccess;
}

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_SOFTOKEN
        if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) {
            if (softokenLib) {
                disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
                if (!disableUnload) {
#ifdef DEBUG
                    PRStatus status = PR_UnloadLibrary(softokenLib);
                    PORT_Assert(PR_SUCCESS == status);
#else
                    PR_UnloadLibrary(softokenLib);
#endif
                }
                softokenLib = NULL;
            }
            loadSoftokenOnce = pristineCallOnce;
        }
#endif
        return SECSuccess;
    }

    library = (PRLibrary *)mod->library;
    /* if no library, then we should not unload it */
    if (library == NULL) {
        return SECSuccess;
    }

    disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
    if (!disableUnload) {
        PR_UnloadLibrary(library);
    }
    return SECSuccess;
}

void
nss_DumpModuleLog(void)
{
#ifdef DEBUG_MODULE
    if (modToDBG) {
        print_final_statistics();
    }
#endif
}

Messung V0.5
C=94 H=88 G=90

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.