Bug 364684. Fix session object handle counter overflows. r=rrelyea,wtchang

This commit is contained in:
nelson%bolyard.com 2007-01-10 04:47:57 +00:00
Родитель c2a23523d9
Коммит 9b2b54fbda
3 изменённых файлов: 87 добавлений и 51 удалений

Просмотреть файл

@ -86,6 +86,7 @@ static char libraryDescription_space[33];
* failure so that there are at most 60 login attempts per minute.
*/
static PRIntervalTime loginWaitTime;
static PRUint32 minSessionObjectHandle = 1U;
#define __PASTE(x,y) x##y
@ -1432,7 +1433,7 @@ fail:
return CKR_OK;
}
/* forward delcare the DES formating function for handleSecretKey */
/* forward declare the DES formating function for handleSecretKey */
void sftk_FormatDESKey(unsigned char *key, int length);
static NSSLOWKEYPrivateKey *sftk_mkSecretKeyRep(SFTKObject *object);
@ -1817,9 +1818,11 @@ CK_RV
sftk_handleObject(SFTKObject *object, SFTKSession *session)
{
SFTKSlot *slot = session->slot;
SFTKAttribute *attribute;
SFTKObject *duplicateObject = NULL;
CK_OBJECT_HANDLE handle;
CK_BBOOL ckfalse = CK_FALSE;
CK_BBOOL cktrue = CK_TRUE;
SFTKAttribute *attribute;
CK_RV crv;
/* make sure all the base object types are defined. If not set the
@ -1845,11 +1848,37 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session)
return CKR_SESSION_READ_ONLY;
}
/* PKCS #11 object ID's are unique for all objects on a
* token */
PZ_Lock(slot->objectLock);
object->handle = slot->tokenIDCount++;
PZ_Unlock(slot->objectLock);
/* Assign a unique SESSION object handle to every new object,
* whether it is a session object or a token object.
* At this point, all new objects are structured as session objects.
* Objects with the CKA_TOKEN attribute true will be turned into
* token objects and will have a token object handle assigned to
* them by a call to sftk_mkHandle in the handler for each object
* class, invoked below.
*
* It may be helpful to note/remember that
* sftk_narrowToXxxObject uses sftk_isToken,
* sftk_isToken examines the sign bit of the object's handle, but
* sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute.
*/
do {
PRUint32 wrappedAround;
duplicateObject = NULL;
PZ_Lock(slot->objectLock);
wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK;
handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK;
if (!handle) /* don't allow zero handle */
handle = minSessionObjectHandle;
slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround;
/* Is there already a session object with this handle? */
if (wrappedAround) {
sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable, \
slot->sessObjHashSize);
}
PZ_Unlock(slot->objectLock);
} while (duplicateObject != NULL);
object->handle = handle;
/* get the object class */
attribute = sftk_FindAttribute(object,CKA_CLASS);
@ -1859,8 +1888,10 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session)
object->objclass = *(CK_OBJECT_CLASS *)attribute->attrib.pValue;
sftk_FreeAttribute(attribute);
/* now handle the specific. Get a session handle for these functions
* to use */
/* Now handle the specific object class.
* At this point, all objects are session objects, and the session
* number must be passed to the object class handlers.
*/
switch (object->objclass) {
case CKO_DATA:
crv = sftk_handleDataObject(session,object);
@ -1896,7 +1927,11 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session)
return crv;
}
/* now link the object into the slot and session structures */
/* Now link the object into the slot and session structures.
* If the object has a true CKA_TOKEN attribute, the above object
* class handlers will have set the sign bit in the object handle,
* causing the following test to be true.
*/
if (sftk_isToken(object->handle)) {
sftk_convertSessionToToken(object);
} else {
@ -2685,11 +2720,11 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex)
slot->optimizeSpace = params->optimizeSpace;
if (slot->optimizeSpace) {
slot->tokObjHashSize = SPACE_TOKEN_OBJECT_HASH_SIZE;
slot->sessObjHashSize = SPACE_SESSION_OBJECT_HASH_SIZE;
slot->sessHashSize = SPACE_SESSION_HASH_SIZE;
slot->numSessionLocks = 1;
} else {
slot->tokObjHashSize = TIME_TOKEN_OBJECT_HASH_SIZE;
slot->sessObjHashSize = TIME_SESSION_OBJECT_HASH_SIZE;
slot->sessHashSize = TIME_SESSION_HASH_SIZE;
slot->numSessionLocks = slot->sessHashSize/BUCKETS_PER_SESSION_LOCK;
}
@ -2715,16 +2750,16 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex)
slot->head = PORT_ZNewArray(SFTKSession *, slot->sessHashSize);
if (slot->head == NULL)
goto mem_loser;
slot->tokObjects = PORT_ZNewArray(SFTKObject *, slot->tokObjHashSize);
if (slot->tokObjects == NULL)
slot->sessObjHashTable = PORT_ZNewArray(SFTKObject *, slot->sessObjHashSize);
if (slot->sessObjHashTable == NULL)
goto mem_loser;
slot->tokenHashTable = PL_NewHashTable(64,sftk_HashNumber,PL_CompareValues,
slot->tokObjHashTable = PL_NewHashTable(64,sftk_HashNumber,PL_CompareValues,
SECITEM_HashCompare, NULL, 0);
if (slot->tokenHashTable == NULL)
if (slot->tokObjHashTable == NULL)
goto mem_loser;
slot->sessionIDCount = 0;
slot->tokenIDCount = 1;
slot->sessionObjectHandleCount = minSessionObjectHandle;
slot->slotID = slotID;
sftk_setStringName(params->slotdes ? params->slotdes :
sftk_getDefSlotName(slotID), slot->slotDescription,
@ -2843,9 +2878,9 @@ SFTK_ShutdownSlot(SFTKSlot *slot)
/* clear all objects.. session objects are cleared as a result of
* closing all the sessions. We just need to clear the token object
* cache. slot->tokenHashTable guarentees we have the token
* cache. slot->tokObjHashTable guarentees we have the token
* infrastructure set up. */
if (slot->tokenHashTable) {
if (slot->tokObjHashTable) {
SFTK_ClearTokenKeyHashTable(slot);
}
@ -2867,16 +2902,16 @@ SFTK_DestroySlotData(SFTKSlot *slot)
SFTK_ShutdownSlot(slot);
if (slot->tokenHashTable) {
PL_HashTableDestroy(slot->tokenHashTable);
slot->tokenHashTable = NULL;
if (slot->tokObjHashTable) {
PL_HashTableDestroy(slot->tokObjHashTable);
slot->tokObjHashTable = NULL;
}
if (slot->tokObjects) {
PORT_Free(slot->tokObjects);
slot->tokObjects = NULL;
if (slot->sessObjHashTable) {
PORT_Free(slot->sessObjHashTable);
slot->sessObjHashTable = NULL;
}
slot->tokObjHashSize = 0;
slot->sessObjHashSize = 0;
if (slot->head) {
PORT_Free(slot->head);
@ -3467,15 +3502,15 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
/* first, delete all our loaded key and cert objects from our
* internal list. */
PZ_Lock(slot->objectLock);
for (i=0; i < slot->tokObjHashSize; i++) {
for (i=0; i < slot->sessObjHashSize; i++) {
do {
object = slot->tokObjects[i];
object = slot->sessObjHashTable[i];
/* hand deque */
/* this duplicates function of NSC_close session functions, but
* because we know that we are freeing all the sessions, we can
* do more efficient processing */
if (object) {
slot->tokObjects[i] = object->next;
slot->sessObjHashTable[i] = object->next;
if (object->next) object->next->prev = NULL;
object->next = object->prev = NULL;
@ -5164,9 +5199,9 @@ CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession,
/* build list of found objects in the session */
if (!tokenOnly) {
crv = sftk_searchObjectList(search, slot->tokObjects,
slot->tokObjHashSize, slot->objectLock,
pTemplate, ulCount, isLoggedIn);
crv = sftk_searchObjectList(search, slot->sessObjHashTable,
slot->sessObjHashSize, slot->objectLock,
pTemplate, ulCount, isLoggedIn);
}
if (crv != CKR_OK) {
goto loser;

Просмотреть файл

@ -88,10 +88,10 @@
* NSS is a shared library.
*/
#define SPACE_ATTRIBUTE_HASH_SIZE 32
#define SPACE_TOKEN_OBJECT_HASH_SIZE 32
#define SPACE_SESSION_OBJECT_HASH_SIZE 32
#define SPACE_SESSION_HASH_SIZE 32
#define TIME_ATTRIBUTE_HASH_SIZE 32
#define TIME_TOKEN_OBJECT_HASH_SIZE 1024
#define TIME_SESSION_OBJECT_HASH_SIZE 1024
#define TIME_SESSION_HASH_SIZE 1024
#define MAX_OBJECT_LIST_SIZE 800
/* how many objects to keep on the free list
@ -319,8 +319,9 @@ struct SFTKSessionStr {
*
* The array of sessionLock's protect the session hash table (head[])
* as well as the reference count of session objects in that bucket
* (head[]->refCount), objectLock protects all elements of the token
* object hash table (tokObjects[], tokenIDCount, and tokenHashTable),
* (head[]->refCount), objectLock protects all elements of the slot's
* object hash tables (sessObjHashTable[] and tokObjHashTable), and
* sessionObjectHandleCount.
* slotLock protects the remaining protected elements:
* password, isLoggedIn, ssoLoggedIn, and sessionCount,
* and pwCheckLock serializes the key database password checks in
@ -366,11 +367,11 @@ struct SFTKSlotStr {
int sessionCount; /* variable - reset */
PRInt32 rwSessionCount; /* set by atomic operations */
/* (reset) */
int tokenIDCount; /* variable - perserved */
PRUint32 sessionObjectHandleCount; /* variable - preserved */
int index; /* invariant */
PLHashTable *tokenHashTable; /* invariant */
SFTKObject **tokObjects; /* variable - reset */
unsigned int tokObjHashSize; /* invariant */
PLHashTable *tokObjHashTable; /* invariant */
SFTKObject **sessObjHashTable; /* variable - reset */
unsigned int sessObjHashSize; /* invariant */
SFTKSession **head; /* variable -reset */
unsigned int sessHashSize; /* invariant */
char tokDescription[33]; /* per load */

Просмотреть файл

@ -2093,8 +2093,8 @@ sftk_deleteTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
SECItem *item;
PRBool rem;
item = (SECItem *)PL_HashTableLookup(slot->tokenHashTable, (void *)handle);
rem = PL_HashTableRemove(slot->tokenHashTable,(void *)handle) ;
item = (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle);
rem = PL_HashTableRemove(slot->tokObjHashTable,(void *)handle) ;
if (rem && item) {
SECITEM_FreeItem(item,PR_TRUE);
}
@ -2117,7 +2117,7 @@ sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
if (item == NULL) {
return SECFailure;
}
entry = PL_HashTableAdd(slot->tokenHashTable,(void *)handle,item);
entry = PL_HashTableAdd(slot->tokObjHashTable,(void *)handle,item);
if (entry == NULL) {
SECITEM_FreeItem(item,PR_TRUE);
return SECFailure;
@ -2129,7 +2129,7 @@ sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
static SECItem *
sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
{
return (SECItem *)PL_HashTableLookup(slot->tokenHashTable, (void *)handle);
return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle);
}
/*
@ -2161,7 +2161,7 @@ SFTK_ClearTokenKeyHashTable(SFTKSlot *slot)
{
sftk_tokenKeyLock(slot);
PORT_Assert(!slot->present);
PL_HashTableEnumerateEntries(slot->tokenHashTable, sftk_freeHashItem, NULL);
PL_HashTableEnumerateEntries(slot->tokObjHashTable, sftk_freeHashItem, NULL);
sftk_tokenKeyUnlock(slot);
return CKR_OK;
}
@ -2408,14 +2408,14 @@ static SFTKObject *
sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot)
{
SFTKObject *object;
PRUint32 index = sftk_hash(handle, slot->tokObjHashSize);
PRUint32 index = sftk_hash(handle, slot->sessObjHashSize);
if (sftk_isToken(handle)) {
return sftk_NewTokenObject(slot, NULL, handle);
}
PZ_Lock(slot->objectLock);
sftkqueue_find2(object, handle, index, slot->tokObjects);
sftkqueue_find2(object, handle, index, slot->sessObjHashTable);
if (object) {
sftk_ReferenceObject(object);
}
@ -2468,10 +2468,10 @@ sftk_FreeObject(SFTKObject *object)
void
sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object)
{
PRUint32 index = sftk_hash(object->handle, slot->tokObjHashSize);
PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize);
sftkqueue_init_element(object);
PZ_Lock(slot->objectLock);
sftkqueue_add2(object, object->handle, index, slot->tokObjects);
sftkqueue_add2(object, object->handle, index, slot->sessObjHashTable);
PZ_Unlock(slot->objectLock);
}
@ -2505,7 +2505,7 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
NSSLOWCERTCertificate *cert;
NSSLOWCERTCertTrust tmptrust;
PRBool isKrl;
PRUint32 index = sftk_hash(object->handle, slot->tokObjHashSize);
PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize);
/* Handle Token case */
if (so && so->session) {
@ -2514,7 +2514,7 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
sftkqueue_delete(&so->sessionList,0,session->objects,0);
PZ_Unlock(session->objectLock);
PZ_Lock(slot->objectLock);
sftkqueue_delete2(object, object->handle, index, slot->tokObjects);
sftkqueue_delete2(object, object->handle, index, slot->sessObjHashTable);
PZ_Unlock(slot->objectLock);
sftkqueue_clear_deleted_element(object);
sftk_FreeObject(object); /* reduce it's reference count */