|
|
1b6f66 |
diff --git a/lib/pk11wrap/pk11util.c b/lib/pk11wrap/pk11util.c
|
|
|
1b6f66 |
--- a/lib/pk11wrap/pk11util.c
|
|
|
1b6f66 |
+++ b/lib/pk11wrap/pk11util.c
|
|
|
1b6f66 |
@@ -1258,53 +1258,62 @@ SECMOD_HasRemovableSlots(SECMODModule *m
|
|
|
1b6f66 |
return ret;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
|
|
|
1b6f66 |
/*
|
|
|
1b6f66 |
* helper function to actually create and destroy user defined slots
|
|
|
1b6f66 |
*/
|
|
|
1b6f66 |
static SECStatus
|
|
|
1b6f66 |
secmod_UserDBOp(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass,
|
|
|
1b6f66 |
- const char *sendSpec)
|
|
|
1b6f66 |
+ const char *sendSpec, PRBool needlock)
|
|
|
1b6f66 |
{
|
|
|
1b6f66 |
CK_OBJECT_HANDLE dummy;
|
|
|
1b6f66 |
CK_ATTRIBUTE template[2] ;
|
|
|
1b6f66 |
CK_ATTRIBUTE *attrs = template;
|
|
|
1b6f66 |
CK_RV crv;
|
|
|
1b6f66 |
|
|
|
1b6f66 |
PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++;
|
|
|
1b6f66 |
PK11_SETATTRS(attrs, CKA_NETSCAPE_MODULE_SPEC , (unsigned char *)sendSpec,
|
|
|
1b6f66 |
strlen(sendSpec)+1); attrs++;
|
|
|
1b6f66 |
|
|
|
1b6f66 |
PORT_Assert(attrs-template <= 2);
|
|
|
1b6f66 |
|
|
|
1b6f66 |
|
|
|
1b6f66 |
- PK11_EnterSlotMonitor(slot);
|
|
|
1b6f66 |
+ if (needlock) PK11_EnterSlotMonitor(slot);
|
|
|
1b6f66 |
crv = PK11_CreateNewObject(slot, slot->session,
|
|
|
1b6f66 |
template, attrs-template, PR_FALSE, &dummy);
|
|
|
1b6f66 |
- PK11_ExitSlotMonitor(slot);
|
|
|
1b6f66 |
+ if (needlock) PK11_ExitSlotMonitor(slot);
|
|
|
1b6f66 |
|
|
|
1b6f66 |
if (crv != CKR_OK) {
|
|
|
1b6f66 |
PORT_SetError(PK11_MapError(crv));
|
|
|
1b6f66 |
return SECFailure;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
- return SECMOD_UpdateSlotList(slot->module);
|
|
|
1b6f66 |
+ return SECSuccess;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
|
|
|
1b6f66 |
/*
|
|
|
1b6f66 |
* return true if the selected slot ID is not present or doesn't exist
|
|
|
1b6f66 |
*/
|
|
|
1b6f66 |
static PRBool
|
|
|
1b6f66 |
secmod_SlotIsEmpty(SECMODModule *mod, CK_SLOT_ID slotID)
|
|
|
1b6f66 |
{
|
|
|
1b6f66 |
- PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, slotID);
|
|
|
1b6f66 |
+ PK11SlotInfo *slot = SECMOD_FindSlotByID(mod, slotID);
|
|
|
1b6f66 |
if (slot) {
|
|
|
1b6f66 |
- PRBool present = PK11_IsPresent(slot);
|
|
|
1b6f66 |
+ CK_SLOT_INFO slotInfo;
|
|
|
1b6f66 |
+ CK_RV crv;
|
|
|
1b6f66 |
+ /* check if the slot is present, skip any slot reinit stuff,
|
|
|
1b6f66 |
+ * or cached present values, or locking. (we don't need to lock
|
|
|
1b6f66 |
+ * even if the module is not thread safe because we are already
|
|
|
1b6f66 |
+ * holding the module refLock, which is the same as the slot
|
|
|
1b6f66 |
+ * sessionLock if the module isn't thread safe. */
|
|
|
1b6f66 |
+ crv = PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID,&slotInfo);
|
|
|
1b6f66 |
PK11_FreeSlot(slot);
|
|
|
1b6f66 |
- if (present) {
|
|
|
1b6f66 |
+ if ((crv == CKR_OK) &&
|
|
|
1b6f66 |
+ ((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT)) {
|
|
|
1b6f66 |
+ /* slot is present, so it's not empty */
|
|
|
1b6f66 |
return PR_FALSE;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
/* it doesn't exist or isn't present, it's available */
|
|
|
1b6f66 |
return PR_TRUE;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
|
|
|
1b6f66 |
/*
|
|
|
1b6f66 |
@@ -1350,52 +1359,67 @@ PK11SlotInfo *
|
|
|
1b6f66 |
SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec)
|
|
|
1b6f66 |
{
|
|
|
1b6f66 |
CK_SLOT_ID slotID = 0;
|
|
|
1b6f66 |
PK11SlotInfo *slot;
|
|
|
1b6f66 |
char *escSpec;
|
|
|
1b6f66 |
char *sendSpec;
|
|
|
1b6f66 |
SECStatus rv;
|
|
|
1b6f66 |
|
|
|
1b6f66 |
+ PZ_Lock(mod->refLock); /* don't reuse a slot on the fly */
|
|
|
1b6f66 |
slotID = secmod_FindFreeSlot(mod);
|
|
|
1b6f66 |
if (slotID == (CK_SLOT_ID) -1) {
|
|
|
1b6f66 |
+ PZ_Unlock(mod->refLock);
|
|
|
1b6f66 |
return NULL;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
|
|
|
1b6f66 |
if (mod->slotCount == 0) {
|
|
|
1b6f66 |
+ PZ_Unlock(mod->refLock);
|
|
|
1b6f66 |
return NULL;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
|
|
|
1b6f66 |
/* just grab the first slot in the module, any present slot should work */
|
|
|
1b6f66 |
slot = PK11_ReferenceSlot(mod->slots[0]);
|
|
|
1b6f66 |
if (slot == NULL) {
|
|
|
1b6f66 |
+ PZ_Unlock(mod->refLock);
|
|
|
1b6f66 |
return NULL;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
|
|
|
1b6f66 |
/* we've found the slot, now build the moduleSpec */
|
|
|
1b6f66 |
escSpec = NSSUTIL_DoubleEscape(moduleSpec, '>', ']');
|
|
|
1b6f66 |
if (escSpec == NULL) {
|
|
|
1b6f66 |
+ PZ_Unlock(mod->refLock);
|
|
|
1b6f66 |
PK11_FreeSlot(slot);
|
|
|
1b6f66 |
return NULL;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec);
|
|
|
1b6f66 |
PORT_Free(escSpec);
|
|
|
1b6f66 |
|
|
|
1b6f66 |
if (sendSpec == NULL) {
|
|
|
1b6f66 |
/* PR_smprintf does not set SEC_ERROR_NO_MEMORY on failure. */
|
|
|
1b6f66 |
+ PZ_Unlock(mod->refLock);
|
|
|
1b6f66 |
PK11_FreeSlot(slot);
|
|
|
1b6f66 |
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
|
1b6f66 |
return NULL;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
- rv = secmod_UserDBOp(slot, CKO_NETSCAPE_NEWSLOT, sendSpec);
|
|
|
1b6f66 |
+ rv = secmod_UserDBOp(slot, CKO_NETSCAPE_NEWSLOT, sendSpec,
|
|
|
1b6f66 |
+ /* If the module isn't thread safe, the slot sessionLock == mod->refLock
|
|
|
1b6f66 |
+ * since we already hold the refLock we don't need to lock the sessionLock
|
|
|
1b6f66 |
+ */
|
|
|
1b6f66 |
+ mod->isThreadSafe);
|
|
|
1b6f66 |
+ PZ_Unlock(mod->refLock);
|
|
|
1b6f66 |
PR_smprintf_free(sendSpec);
|
|
|
1b6f66 |
PK11_FreeSlot(slot);
|
|
|
1b6f66 |
if (rv != SECSuccess) {
|
|
|
1b6f66 |
return NULL;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
+ rv = SECMOD_UpdateSlotList(mod); /* don't call holding the mod->reflock */
|
|
|
1b6f66 |
+ if (rv != SECSuccess) {
|
|
|
1b6f66 |
+ return NULL;
|
|
|
1b6f66 |
+ }
|
|
|
1b6f66 |
|
|
|
1b6f66 |
slot = SECMOD_FindSlotByID(mod, slotID);
|
|
|
1b6f66 |
if (slot) {
|
|
|
1b6f66 |
/* if we are in the delay period for the "isPresent" call, reset
|
|
|
1b6f66 |
* the delay since we know things have probably changed... */
|
|
|
1b6f66 |
if (slot->nssToken && slot->nssToken->slot) {
|
|
|
1b6f66 |
nssSlot_ResetDelay(slot->nssToken->slot);
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
@@ -1488,17 +1512,17 @@ SECMOD_CloseUserDB(PK11SlotInfo *slot)
|
|
|
1b6f66 |
char *sendSpec;
|
|
|
1b6f66 |
|
|
|
1b6f66 |
sendSpec = PR_smprintf("tokens=[0x%x=<>]", slot->slotID);
|
|
|
1b6f66 |
if (sendSpec == NULL) {
|
|
|
1b6f66 |
/* PR_smprintf does not set no memory error */
|
|
|
1b6f66 |
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
|
1b6f66 |
return SECFailure;
|
|
|
1b6f66 |
}
|
|
|
1b6f66 |
- rv = secmod_UserDBOp(slot, CKO_NETSCAPE_DELSLOT, sendSpec);
|
|
|
1b6f66 |
+ rv = secmod_UserDBOp(slot, CKO_NETSCAPE_DELSLOT, sendSpec, PR_TRUE);
|
|
|
1b6f66 |
PR_smprintf_free(sendSpec);
|
|
|
1b6f66 |
/* if we are in the delay period for the "isPresent" call, reset
|
|
|
1b6f66 |
* the delay since we know things have probably changed... */
|
|
|
1b6f66 |
if (slot->nssToken && slot->nssToken->slot) {
|
|
|
1b6f66 |
nssSlot_ResetDelay(slot->nssToken->slot);
|
|
|
1b6f66 |
/* force the slot info structures to properly reset */
|
|
|
1b6f66 |
(void)PK11_IsPresent(slot);
|
|
|
1b6f66 |
}
|