зеркало из https://github.com/mozilla/gecko-dev.git
When doing cert traversals, create the certs in full as they are found. This avoids thrashing the softoken's object cache when the database has a large number of certs.
This commit is contained in:
Родитель
1378739a27
Коммит
cdae9ed5a1
|
@ -41,7 +41,7 @@
|
|||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.25 $ $Date: 2002/04/19 23:06:39 $ $Name: $";
|
||||
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.26 $ $Date: 2002/04/26 14:33:59 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef NSSCKT_H
|
||||
|
@ -952,6 +952,16 @@ nssToken_NofifyCertsNotVisible
|
|||
NSSToken *tok
|
||||
);
|
||||
|
||||
NSS_EXTERN PRStatus
|
||||
nssToken_TraverseCertificates
|
||||
(
|
||||
NSSToken *token,
|
||||
nssSession *sessionOpt,
|
||||
nssTokenSearchType searchType,
|
||||
PRStatus (* callback)(nssCryptokiObject *instance, void *arg),
|
||||
void *arg
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.20 $ $Date: 2002/04/25 20:49:49 $ $Name: $";
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.21 $ $Date: 2002/04/26 14:33:59 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef NSSCKEPV_H
|
||||
|
@ -1547,3 +1547,113 @@ nssToken_IsPresent
|
|||
return nssSlot_IsTokenPresent(token->slot);
|
||||
}
|
||||
|
||||
/* Sigh. The methods to find objects declared above cause problems with
|
||||
* the low-level object cache in the softoken -- the objects are found in
|
||||
* toto, then one wave of GetAttributes is done, then another. Having a
|
||||
* large number of objects causes the cache to be thrashed, as the objects
|
||||
* are gone before there's any chance to ask for their attributes.
|
||||
* So, for now, bringing back traversal methods for certs. This way all of
|
||||
* the cert's attributes can be grabbed immediately after finding it,
|
||||
* increasing the likelihood that the cache takes care of it.
|
||||
*/
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssToken_TraverseCertificates
|
||||
(
|
||||
NSSToken *token,
|
||||
nssSession *sessionOpt,
|
||||
nssTokenSearchType searchType,
|
||||
PRStatus (* callback)(nssCryptokiObject *instance, void *arg),
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
CK_RV ckrv;
|
||||
CK_ULONG count;
|
||||
CK_OBJECT_HANDLE *objectHandles;
|
||||
CK_ATTRIBUTE_PTR attr;
|
||||
CK_ATTRIBUTE cert_template[2];
|
||||
CK_ULONG ctsize;
|
||||
NSSArena *arena;
|
||||
PRStatus status;
|
||||
PRUint32 arraySize, numHandles;
|
||||
nssCryptokiObject **objects;
|
||||
void *epv = nssToken_GetCryptokiEPV(token);
|
||||
nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession;
|
||||
|
||||
/* template for all certs */
|
||||
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
|
||||
if (searchType == nssTokenSearchType_SessionOnly) {
|
||||
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
|
||||
} else if (searchType == nssTokenSearchType_TokenOnly ||
|
||||
searchType == nssTokenSearchType_TokenForced) {
|
||||
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
|
||||
}
|
||||
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
|
||||
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
|
||||
|
||||
/* the arena is only for the array of object handles */
|
||||
arena = nssArena_Create();
|
||||
if (!arena) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
arraySize = OBJECT_STACK_SIZE;
|
||||
numHandles = 0;
|
||||
objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize);
|
||||
if (!objectHandles) {
|
||||
goto loser;
|
||||
}
|
||||
nssSession_EnterMonitor(session); /* ==== session lock === */
|
||||
/* Initialize the find with the template */
|
||||
ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle,
|
||||
cert_template, ctsize);
|
||||
if (ckrv != CKR_OK) {
|
||||
nssSession_ExitMonitor(session);
|
||||
goto loser;
|
||||
}
|
||||
while (PR_TRUE) {
|
||||
/* Issue the find for up to arraySize - numHandles objects */
|
||||
ckrv = CKAPI(epv)->C_FindObjects(session->handle,
|
||||
objectHandles + numHandles,
|
||||
arraySize - numHandles,
|
||||
&count);
|
||||
if (ckrv != CKR_OK) {
|
||||
nssSession_ExitMonitor(session);
|
||||
goto loser;
|
||||
}
|
||||
/* bump the number of found objects */
|
||||
numHandles += count;
|
||||
if (numHandles < arraySize) {
|
||||
break;
|
||||
}
|
||||
/* the array is filled, double it and continue */
|
||||
arraySize *= 2;
|
||||
objectHandles = nss_ZREALLOCARRAY(objectHandles,
|
||||
CK_OBJECT_HANDLE,
|
||||
arraySize);
|
||||
if (!objectHandles) {
|
||||
nssSession_ExitMonitor(session);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
|
||||
nssSession_ExitMonitor(session); /* ==== end session lock === */
|
||||
if (ckrv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
if (numHandles > 0) {
|
||||
objects = create_objects_from_handles(token, session,
|
||||
objectHandles, numHandles);
|
||||
if (objects) {
|
||||
nssCryptokiObject **op;
|
||||
for (op = objects; *op; op++) {
|
||||
status = (*callback)(*op, arg);
|
||||
}
|
||||
nss_ZFreeIf(objects);
|
||||
}
|
||||
}
|
||||
nssArena_Destroy(arena);
|
||||
return PR_SUCCESS;
|
||||
loser:
|
||||
nssArena_Destroy(arena);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.4 $ $Date: 2002/04/18 19:26:17 $ $Name: $";
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.5 $ $Date: 2002/04/26 14:34:04 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef DEV_H
|
||||
|
@ -716,7 +716,7 @@ find_object_in_collection
|
|||
return (pkiObjectCollectionNode *)NULL;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
static pkiObjectCollectionNode *
|
||||
add_object_instance
|
||||
(
|
||||
nssPKIObjectCollection *collection,
|
||||
|
@ -740,7 +740,7 @@ add_object_instance
|
|||
* are not using it, it must be destroyed.
|
||||
*/
|
||||
nssCryptokiObject_Destroy(instance);
|
||||
return PR_SUCCESS;
|
||||
return node;
|
||||
}
|
||||
mark = nssArena_Mark(collection->arena);
|
||||
if (!mark) {
|
||||
|
@ -780,13 +780,13 @@ add_object_instance
|
|||
status = PR_SUCCESS;
|
||||
}
|
||||
nssArena_Unmark(collection->arena, mark);
|
||||
return status;
|
||||
return node;
|
||||
loser:
|
||||
if (mark) {
|
||||
nssArena_Release(collection->arena, mark);
|
||||
}
|
||||
nssCryptokiObject_Destroy(instance);
|
||||
return PR_FAILURE;
|
||||
return (pkiObjectCollectionNode *)NULL;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
|
@ -799,13 +799,14 @@ nssPKIObjectCollection_AddInstances
|
|||
{
|
||||
PRStatus status = PR_SUCCESS;
|
||||
PRUint32 i = 0;
|
||||
pkiObjectCollectionNode *node;
|
||||
if (instances) {
|
||||
for (; *instances; instances++, i++) {
|
||||
if (numInstances > 0 && i == numInstances) {
|
||||
break;
|
||||
}
|
||||
status = add_object_instance(collection, *instances);
|
||||
if (status != PR_SUCCESS) {
|
||||
node = add_object_instance(collection, *instances);
|
||||
if (node == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
@ -891,6 +892,35 @@ nssPKIObjectCollection_Traverse
|
|||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssPKIObjectCollection_AddInstanceAsObject
|
||||
(
|
||||
nssPKIObjectCollection *collection,
|
||||
nssCryptokiObject *instance
|
||||
)
|
||||
{
|
||||
pkiObjectCollectionNode *node;
|
||||
node = add_object_instance(collection, instance);
|
||||
if (node == NULL) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
if (!node->haveObject) {
|
||||
node->object = (*collection->createObject)(node->object);
|
||||
node->haveObject = PR_TRUE;
|
||||
}
|
||||
#ifdef NSS_3_4_CODE
|
||||
else {
|
||||
/* The instance was added to a pre-existing node. This
|
||||
* function is *only* being used for certificates, and having
|
||||
* multiple instances of certs in 3.X requires updating the
|
||||
* CERTCertificate.
|
||||
*/
|
||||
STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object);
|
||||
}
|
||||
#endif
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Certificate collections
|
||||
*/
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#define PKIM_H
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char PKIM_CVS_ID[] = "@(#) $RCSfile: pkim.h,v $ $Revision: 1.19 $ $Date: 2002/04/19 23:06:43 $ $Name: $";
|
||||
static const char PKIM_CVS_ID[] = "@(#) $RCSfile: pkim.h,v $ $Revision: 1.20 $ $Date: 2002/04/26 14:34:04 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef BASE_H
|
||||
|
@ -496,6 +496,18 @@ nssPKIObjectCollection_Traverse
|
|||
nssPKIObjectCallback *callback
|
||||
);
|
||||
|
||||
/* This function is being added for NSS 3.5. It corresponds to the function
|
||||
* nssToken_TraverseCertificates. The idea is to use the collection during
|
||||
* a traversal, creating certs each time a new instance is added for which
|
||||
* a cert does not already exist.
|
||||
*/
|
||||
NSS_EXTERN PRStatus
|
||||
nssPKIObjectCollection_AddInstanceAsObject
|
||||
(
|
||||
nssPKIObjectCollection *collection,
|
||||
nssCryptokiObject *instance
|
||||
);
|
||||
|
||||
/* nssPKIObjectCollection_GetCertificates
|
||||
*
|
||||
* Get all of the certificates in the collection.
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.41 $ $Date: 2002/04/22 19:09:01 $ $Name: $";
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.42 $ $Date: 2002/04/26 14:34:05 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef DEV_H
|
||||
|
@ -1035,6 +1035,13 @@ NSSTrustDomain_FindUserCertificatesForEmailSigning
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
collector(nssCryptokiObject *instance, void *arg)
|
||||
{
|
||||
nssPKIObjectCollection *collection = (nssPKIObjectCollection *)arg;
|
||||
return nssPKIObjectCollection_AddInstanceAsObject(collection, instance);
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus *
|
||||
NSSTrustDomain_TraverseCertificates
|
||||
(
|
||||
|
@ -1052,6 +1059,7 @@ NSSTrustDomain_TraverseCertificates
|
|||
nssUpdateLevel updateLevel;
|
||||
NSSCertificate **cached = NULL;
|
||||
nssList *certList;
|
||||
|
||||
certList = nssList_Create(NULL, PR_FALSE);
|
||||
if (!certList) return NULL;
|
||||
(void *)nssTrustDomain_GetCertsFromCache(td, certList);
|
||||
|
@ -1073,7 +1081,6 @@ NSSTrustDomain_TraverseCertificates
|
|||
token = nssSlot_GetToken(*slotp);
|
||||
if (token) {
|
||||
nssSession *session;
|
||||
nssCryptokiObject **instances;
|
||||
nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
|
||||
/* get a session for the token */
|
||||
session = nssTrustDomain_GetSessionForToken(td, token);
|
||||
|
@ -1082,21 +1089,15 @@ NSSTrustDomain_TraverseCertificates
|
|||
goto loser;
|
||||
}
|
||||
/* perform the traversal */
|
||||
instances = nssToken_FindCertificates(token,
|
||||
session,
|
||||
tokenOnly,
|
||||
0, &status);
|
||||
status = nssToken_TraverseCertificates(token,
|
||||
session,
|
||||
tokenOnly,
|
||||
collector,
|
||||
collection);
|
||||
nssToken_Destroy(token);
|
||||
if (status != PR_SUCCESS) {
|
||||
goto loser;
|
||||
}
|
||||
/* add the found certificates to the collection */
|
||||
status = nssPKIObjectCollection_AddInstances(collection,
|
||||
instances, 0);
|
||||
nss_ZFreeIf(instances);
|
||||
if (status != PR_SUCCESS) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче