/* * find a module by name and delete it off the module list */ SECStatus SECMOD_DeleteInternalModule(const char *name) { SECMODModuleList *mlp; SECMODModuleList **mlpp; SECStatus rv = SECFailure; if (pendingModule) { PORT_SetError(SEC_ERROR_MODULE_STUCK); return rv; } if (!moduleLock) { PORT_SetError(SEC_ERROR_NOT_INITIALIZED); return rv; } SECMOD_GetWriteLock(moduleLock); for(mlpp = &modules,mlp = modules; mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) { if (PORT_Strcmp(name,mlp->module->commonName) == 0) { /* don't delete the internal module */ if (mlp->module->internal) { SECMOD_RemoveList(mlpp,mlp); rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module); } break; } } SECMOD_ReleaseWriteLock(moduleLock); if (rv == SECSuccess) { SECMODModule *newModule,*oldModule; if (mlp->module->isFIPS) { newModule = SECMOD_CreateModule(NULL, SECMOD_INT_NAME, NULL, SECMOD_INT_FLAGS); } else { newModule = SECMOD_CreateModule(NULL, SECMOD_FIPS_NAME, NULL, SECMOD_FIPS_FLAGS); } if (newModule) { PK11SlotInfo *slot; newModule->libraryParams = PORT_ArenaStrdup(newModule->arena,mlp->module->libraryParams); /* if an explicit internal key slot has been set, reset it */ slot = pk11_SwapInternalKeySlot(NULL); if (slot) { secmod_SetInternalKeySlotFlag(newModule, PR_TRUE); } rv = SECMOD_AddModule(newModule); if (rv != SECSuccess) { /* load failed, restore the internal key slot */ pk11_SetInternalKeySlot(slot); SECMOD_DestroyModule(newModule); newModule = NULL; } /* free the old explicit internal key slot, we now have a new one */ if (slot) { PK11_FreeSlot(slot); } } if (newModule == NULL) { SECMODModuleList *last = NULL,*mlp2; /* we're in pretty deep trouble if this happens...Security * not going to work well... try to put the old module back on * the list */ SECMOD_GetWriteLock(moduleLock); for(mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) { last = mlp2; } if (last == NULL) { modules = mlp; } else { SECMOD_AddList(last,mlp,NULL); } SECMOD_ReleaseWriteLock(moduleLock); return SECFailure; } pendingModule = oldModule = internalModule; internalModule = NULL; SECMOD_DestroyModule(oldModule); SECMOD_DeletePermDB(mlp->module); SECMOD_DestroyModuleListElement(mlp); internalModule = newModule; /* adopt the module */ } return rv; }
/* * 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_SetInternalKeySlot(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; }