cleanup; add nssSession type to allow multiple sessions accessing the token API

This commit is contained in:
mcgreer%netscape.com 2001-09-18 20:54:28 +00:00
Родитель 75f90bba49
Коммит 4ddecbc706
7 изменённых файлов: 351 добавлений и 228 удалений

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

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:07 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
#endif /* DEBUG */
#ifndef PKIT_H
@ -55,20 +55,25 @@ static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.1 $ $Da
#include "base.h"
#endif /* BASE_H */
NSS_IMPLEMENT_DATA const CK_BBOOL
g_ck_true = CK_TRUE;
static const CK_BBOOL s_true = CK_TRUE;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) };
NSS_IMPLEMENT_DATA const CK_BBOOL
g_ck_false = CK_FALSE;
static const CK_BBOOL s_false = CK_FALSE;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) };
NSS_IMPLEMENT_DATA const CK_OBJECT_CLASS
g_ck_obj_class_cert = CKO_CERTIFICATE;
static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) };
NSS_IMPLEMENT_DATA const CK_OBJECT_CLASS
g_ck_obj_class_pubkey = CKO_PUBLIC_KEY;
static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) };
NSS_IMPLEMENT_DATA const CK_OBJECT_CLASS
g_ck_obj_class_privkey = CKO_PRIVATE_KEY;
static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) };
NSS_IMPLEMENT PRStatus
NSSCKObject_GetAttributes
@ -77,16 +82,16 @@ NSSCKObject_GetAttributes
CK_ATTRIBUTE_PTR obj_template,
CK_ULONG count,
NSSArena *arenaOpt,
nssSession *session,
NSSSlot *slot
)
{
nssArenaMark *mark;
CK_SESSION_HANDLE session;
CK_SESSION_HANDLE hSession;
CK_ULONG i;
CK_RV ckrv;
PRStatus nssrv;
/* use the default session */
session = slot->token->session.handle;
hSession = session->handle;
#ifdef arena_mark_bug_fixed
if (arenaOpt) {
mark = nssArenaMark(arenaOpt);
@ -96,7 +101,7 @@ NSSCKObject_GetAttributes
}
#endif
/* Get the storage size needed for each attribute */
ckrv = CKAPI(slot)->C_GetAttributeValue(session,
ckrv = CKAPI(slot)->C_GetAttributeValue(hSession,
object, obj_template, count);
if (ckrv != CKR_OK) {
/* set an error here */
@ -111,7 +116,7 @@ NSSCKObject_GetAttributes
}
}
/* Obtain the actual attribute values. */
ckrv = CKAPI(slot)->C_GetAttributeValue(session,
ckrv = CKAPI(slot)->C_GetAttributeValue(hSession,
object, obj_template, count);
if (ckrv != CKR_OK) {
/* set an error here */

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

@ -41,7 +41,7 @@
#define CKHELPER_H
#ifdef DEBUG
static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile: ckhelper.h,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:08 $ $Name: $";
static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile: ckhelper.h,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
#endif /* DEBUG */
#ifndef NSSCKT_H
@ -59,120 +59,21 @@ PR_BEGIN_EXTERN_C
*/
/* Boolean values */
NSS_EXTERN_DATA const CK_BBOOL g_ck_true;
NSS_EXTERN_DATA const CK_BBOOL g_ck_false;
NSS_EXTERN_DATA const NSSItem g_ck_true;
NSS_EXTERN_DATA const NSSItem g_ck_false;
/* Object classes */
NSS_EXTERN_DATA const CK_OBJECT_CLASS g_ck_obj_class_cert;
NSS_EXTERN_DATA const CK_OBJECT_CLASS g_ck_obj_class_pubkey;
NSS_EXTERN_DATA const CK_OBJECT_CLASS g_ck_obj_class_privkey;
/*
* Helpers for building templates.
*/
/*
* NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, i, ckattr, global_value)
*
* used to set one of the global attributes defined above.
*/
#define NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, i, ckattr, global_value) \
(cktmpl)[i].type = ckattr; \
(cktmpl)[i].pValue = (CK_VOID_PTR)&(global_value); \
(cktmpl)[i].ulValueLen = (CK_ULONG)sizeof(global_value);
/*
* NSS_SET_CK_ATTRIB_TRUE(cktmpl, i, ckattr)
*
* Set an attribute to CK_TRUE in a template
*/
#define NSS_SET_CK_ATTRIB_TRUE(cktmpl, i, ckattr) \
NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, i, ckattr, g_ck_true)
/*
* NSS_SET_CK_ATTRIB_FALSE(cktmpl, i, ckattr)
*
* Set an attribute to CK_FALSE in a template
*/
#define NSS_SET_CK_ATTRIB_FALSE(cktmpl, i, ckattr) \
NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, i, ckattr, g_ck_false)
/*
* NSS_SET_CK_ATTRIB_ITEM(cktmpl, i, ckattr, item)
*
* Set an attribute in a template to use data from an item
*/
#define NSS_SET_CK_ATTRIB_ITEM(cktmpl, i, ckattr, item) \
(cktmpl)[i].type = ckattr; \
(cktmpl)[i].pValue = (CK_VOID_PTR)(item)->data; \
(cktmpl)[i].ulValueLen = (CK_ULONG)(item)->len;
/* Create Templates */
/* Certificate template
*
* NSS_CK_CERTIFICATE_CREATE4(cktmpl, subject, id, der)
*
* CKA_CLASS = CKO_CERTIFICATE
* CKA_SUBJECT = subject->data
* CKA_ID = id->data
* CKA_VALUE = der->data
*/
#define NSS_CK_CERTIFICATE_CREATE4(cktmpl, subject, id, der) \
NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, 0, CKA_CLASS, g_ck_obj_class_cert) \
NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_SUBJECT, subject) \
NSS_SET_CK_ATTRIB_ITEM(cktmpl, 2, CKA_ID, id) \
NSS_SET_CK_ATTRIB_ITEM(cktmpl, 3, CKA_VALUE, der)
/* Search Templates */
/* NSS_CK_CERTIFICATE_SEARCH(cktmpl)
*
* Set up a search template for any cert object
*/
#define NSS_CK_CERTIFICATE_SEARCH(cktmpl) \
NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, 0, CKA_CLASS, g_ck_obj_class_cert)
/* NSS_CK_CERTIFICATE_SEARCH_LABEL2(cktmpl, label)
*
* Set up a search template for a cert using label->data
*/
#define NSS_CK_CERTIFICATE_SEARCH_LABEL2(cktmpl, label) \
NSS_CK_CERTIFICATE_SEARCH(cktmpl) \
NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_LABEL, label)
/* NSS_CK_CERTIFICATE_SEARCH_SUBJECT2(cktmpl, subject)
*
* Set up a search template for a cert using subject->data
*/
#define NSS_CK_CERTIFICATE_SEARCH_SUBJECT2(cktmpl, subject) \
NSS_CK_CERTIFICATE_SEARCH(cktmpl) \
NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_SUBJECT, subject)
/* NSS_CK_CERTIFICATE_SEARCH_ID2(cktmpl, id)
*
* Set up a search template for a cert using id->data
*/
#define NSS_CK_CERTIFICATE_SEARCH_ID2(cktmpl, id) \
NSS_CK_CERTIFICATE_SEARCH(cktmpl) \
NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_ID, id)
/* NSS_CK_CERTIFICATE_SEARCH_DER2(cktmpl, der)
*
* Set up a search template for a cert using der->data
*/
#define NSS_CK_CERTIFICATE_SEARCH_DER2(cktmpl, der) \
NSS_CK_CERTIFICATE_SEARCH(cktmpl) \
NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_VALUE, der)
NSS_EXTERN_DATA const NSSItem g_ck_class_cert;
NSS_EXTERN_DATA const NSSItem g_ck_class_pubkey;
NSS_EXTERN_DATA const NSSItem g_ck_class_privkey;
/* NSS_CK_ATTRIBUTE_TO_ITEM(attrib, item)
*
* Convert a CK_ATTRIBUTE to an NSSItem.
*/
#define NSS_CK_ATTRIBUTE_TO_ITEM(attrib, item) \
(item)->data = (void *)(attrib)->pValue; \
(item)->size = (PRUint32)(attrib)->ulValueLen; \
#define NSS_CK_ATTRIBUTE_TO_ITEM(attrib, item) \
(item)->data = (void *)(attrib)->pValue; \
(item)->size = (PRUint32)(attrib)->ulValueLen; \
/* Get an array of attributes from an object. */
NSS_EXTERN PRStatus
@ -182,6 +83,7 @@ NSSCKObject_GetAttributes
CK_ATTRIBUTE_PTR obj_template,
CK_ULONG count,
NSSArena *arenaOpt,
nssSession *session,
NSSSlot *slot
);

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

@ -35,7 +35,7 @@
#define DEV_H
#ifdef DEBUG
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:08 $ $Name: $";
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
#endif /* DEBUG */
#ifndef DEVT_H
@ -60,6 +60,11 @@ static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.1 $ $Dat
* |-----------|---> NSSSlot <--> NSSToken
*/
/* XXX These should probably all be "nss" not "NSS". Though the types are
* exposed, the API's should not be (with the exception of functions
* put in a friend header.
*/
#ifndef DEVT_H
#include "devt.h"
#endif /* DEVT_H */
@ -162,6 +167,14 @@ NSSSlot_Logout
* NSSSlot_ChangePassword
*/
NSS_EXTERN nssSession *
NSSSlot_CreateSession
(
NSSSlot *slot,
NSSArena *arenaOpt,
PRBool readOnly /* so far, this is the only flag used */
);
NSS_EXTERN NSSToken *
NSSToken_Create
(
@ -184,41 +197,47 @@ NSS_EXTERN NSSCertificate *
NSSToken_ImportCertificate
(
NSSToken *tok,
CK_ATTRIBUTE *cktemplate
nssSession *sessionOpt,
CK_ATTRIBUTE_PTR cktemplate
);
NSS_EXTERN NSSPublicKey *
NSSToken_ImportPublicKey
(
NSSToken *tok,
CK_ATTRIBUTE *cktemplate
nssSession *sessionOpt,
CK_ATTRIBUTE_PTR cktemplate
);
NSS_EXTERN NSSPrivateKey *
NSSToken_ImportPrivateKey
(
NSSToken *tok,
CK_ATTRIBUTE *cktemplate
nssSession *sessionOpt,
CK_ATTRIBUTE_PTR cktemplate
);
NSS_EXTERN NSSSymmetricKey *
NSSToken_ImportSymmetricKey
(
NSSToken *tok,
CK_ATTRIBUTE *cktemplate
nssSession *sessionOpt,
CK_ATTRIBUTE_PTR cktemplate
);
NSS_EXTERN NSSPublicKey *
NSSToken_GenerateKeyPair
(
NSSToken *tok
NSSToken *tok,
nssSession *sessionOpt
/* algorithm and parameters */
);
NSS_EXTERN NSSSymmetricKey *
NSSToken_GenerateSymmetricKey
(
NSSToken *tok
NSSToken *tok,
nssSession *sessionOpt
/* algorithm and parameters */
);
@ -227,18 +246,49 @@ NSS_EXTERN PRStatus
NSSToken_DeleteStoredObject
(
NSSToken *tok,
nssSession *sessionOpt,
CK_OBJECT_HANDLE object
);
NSS_EXTERN NSSCertificate **
NSSToken_FindCertificatesByTemplate
(
NSSToken *tok,
nssSession *sessionOpt,
CK_ATTRIBUTE_PTR cktemplate,
CK_ULONG ctsize
);
/* again, a questionable function. maybe some tokens allow this? */
NSS_EXTERN PRStatus *
NSSToken_TraverseCertificates
(
NSSToken *tok,
nssSession *sessionOpt,
PRStatus (*callback)(NSSCertificate *c, void *arg),
void *arg
);
NSS_EXTERN PRStatus
nssSession_Destroy
(
nssSession *s
);
/* would like to inline */
NSS_EXTERN PRStatus
nssSession_EnterMonitor
(
nssSession *s
);
/* would like to inline */
NSS_EXTERN PRStatus
nssSession_ExitMonitor
(
nssSession *s
);
#ifdef DEBUG
void NSSModule_Debug(NSSModule *m);
#endif

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

@ -35,7 +35,7 @@
#define DEVT_H
#ifdef DEBUG
static const char DEVT_CVS_ID[] = "@(#) $RCSfile: devt.h,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:09 $ $Name: $";
static const char DEVT_CVS_ID[] = "@(#) $RCSfile: devt.h,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
#endif /* DEBUG */
/*
@ -64,6 +64,8 @@ typedef struct NSSSlotStr NSSSlot;
typedef struct NSSTokenStr NSSToken;
typedef struct nssSessionStr nssSession;
/* The list of boolean flags used to describe properties of a
* module.
*/
@ -89,34 +91,34 @@ struct NSSModuleStr {
struct NSSSlotStr
{
NSSArena *arena;
PRInt32 refCount;
NSSModule *module; /* Parent */
NSSToken *token; /* Child (or peer, if you will) */
NSSUTF8 *name;
void *epv;
CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */
PRUint32 flags;
NSSArena *arena;
PRInt32 refCount;
NSSModule *module; /* Parent */
NSSToken *token; /* Child (or peer, if you will) */
NSSUTF8 *name;
CK_SLOT_ID slotID;
void *epv;
CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */
PRUint32 flags;
};
struct NSSTokenStr
{
NSSArena *arena;
PRInt32 refCount;
NSSSlot *slot; /* Parent (or peer, if you will) */
NSSUTF8 *name;
CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */
PRUint32 flags;
struct {
/* according to PK11SlotInfoStr, a default session for "quick-and-dirty"
* functions
*/
CK_SESSION_HANDLE handle;
PZLock *lock;
} session;
NSSArena *arena;
PRInt32 refCount;
NSSSlot *slot; /* Parent (or peer, if you will) */
NSSUTF8 *name;
CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */
PRUint32 flags;
nssSession *defaultSession;
};
struct NSSTokenStr;
struct nssSessionStr
{
PZLock *lock;
CK_SESSION_HANDLE handle;
NSSSlot *slot;
};
PR_END_EXTERN_C

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

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: module.c,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:10 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: module.c,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
#endif /* DEBUG */
#ifndef DEV_H
@ -318,7 +318,8 @@ NSSModule_TraverseCertificates
PRUint32 i;
for (i=0; i<mod->numSlots; i++) {
/* might as well skip straight to token, right? or is this slot? */
NSSToken_TraverseCertificates(mod->slots[i]->token, callback, arg);
NSSToken_TraverseCertificates(mod->slots[i]->token,
NULL, callback, arg);
}
return NULL;
}

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

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.2 $ $Date: 2001-09-13 22:14:22 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.3 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
#endif /* DEBUG */
#ifndef DEV_H
@ -55,6 +55,21 @@ static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.2 $ $Date:
#include "base.h"
#endif /* BASE_H */
/* The flags needed to open a read-only session. */
static const CK_FLAGS s_ck_readonly_flags = CKF_SERIAL_SESSION;
/* In pk11slot.c, this was a no-op. So it is here also. */
static CK_RV PR_CALLBACK
nss_ck_slot_notify
(
CK_SESSION_HANDLE session,
CK_NOTIFICATION event,
CK_VOID_PTR pData
)
{
return CKR_OK;
}
/* maybe this should really inherit completely from the module... I dunno,
* any uses of slots where independence is needed?
*/
@ -123,6 +138,7 @@ NSSSlot_Create
rvSlot->epv = parent->epv;
rvSlot->module = parent;
rvSlot->name = slotName;
rvSlot->slotID = slotID;
rvSlot->ckFlags = slotInfo.flags;
/* Initialize the token if present. */
if (slotInfo.flags & CKF_TOKEN_PRESENT) {
@ -166,3 +182,85 @@ NSSSlot_Destroy
return PR_SUCCESS;
}
NSS_IMPLEMENT nssSession *
NSSSlot_CreateSession
(
NSSSlot *slot,
NSSArena *arenaOpt,
PRBool readOnly /* so far, this is the only flag used */
)
{
CK_RV ckrv;
CK_FLAGS ckflags;
CK_SESSION_HANDLE session;
nssSession *rvSession;
ckflags = s_ck_readonly_flags;
if (!readOnly) {
ckflags |= CKF_RW_SESSION;
}
/* does the opening and closing of sessions need to be done in a
* threadsafe manner? should there be a "meta-lock" controlling
* calls like this?
*/
ckrv = CKAPI(slot)->C_OpenSession(slot->slotID, ckflags,
slot, nss_ck_slot_notify, &session);
if (ckrv != CKR_OK) {
/* set an error here, eh? */
return (nssSession *)NULL;
}
rvSession = nss_ZNEW(arenaOpt, nssSession);
if (!rvSession) {
return (nssSession *)NULL;
}
if (slot->module->flags & NSSMODULE_FLAGS_NOT_THREADSAFE) {
/* If the parent module is not threadsafe, create lock to manage
* session within threads.
*/
rvSession->lock = PZ_NewLock(nssILockOther);
if (!rvSession->lock) {
/* need to translate NSPR error? */
if (arenaOpt) {
} else {
nss_ZFreeIf(rvSession);
}
}
}
rvSession->handle = session;
rvSession->slot = slot;
return rvSession;
}
NSS_IMPLEMENT PRStatus
nssSession_Destroy
(
nssSession *s
)
{
if (s) {
if (s->lock) {
PZ_DestroyLock(s->lock);
}
nss_ZFreeIf(s);
}
return PR_SUCCESS;
}
NSS_IMPLEMENT PRStatus
nssSession_EnterMonitor
(
nssSession *s
)
{
if (s->lock) PZ_Lock(s->lock);
return PR_SUCCESS;
}
NSS_IMPLEMENT PRStatus
nssSession_ExitMonitor
(
nssSession *s
)
{
return (s->lock) ? PZ_Unlock(s->lock) : PR_SUCCESS;
}

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

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:10 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: $";
#endif /* DEBUG */
#ifndef DEV_H
@ -59,30 +59,6 @@ static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.1 $ $Date:
#include "base.h"
#endif /* BASE_H */
/* If the token cannot manage threads, we have to. The following detect
* a non-threadsafe token and lock/unlock its session handle.
*/
#define NSSTOKEN_ENTER_MONITOR(token) \
if ((token)->session.lock) PZ_Lock((token)->session.lock)
#define NSSTOKEN_EXIT_MONITOR(token) \
if ((token)->session.lock) PZ_Unlock((token)->session.lock)
/* The flags needed to open a read-only session. */
static const CK_FLAGS s_ck_readonly_flags = CKF_SERIAL_SESSION;
/* In pk11slot.c, this was a no-op. So it is here also. */
CK_RV PR_CALLBACK
nss_ck_slot_notify
(
CK_SESSION_HANDLE session,
CK_NOTIFICATION event,
CK_VOID_PTR pData
)
{
return CKR_OK;
}
/* maybe this should really inherit completely from the module... I dunno,
* any uses of slots where independence is needed?
*/
@ -97,12 +73,12 @@ NSSToken_Create
NSSArena *arena;
nssArenaMark *mark;
NSSToken *rvToken;
nssSession *session;
NSSUTF8 *tokenName = NULL;
PRUint32 length;
PRBool newArena;
PRStatus nssrv;
CK_TOKEN_INFO tokenInfo;
CK_SESSION_HANDLE session;
CK_RV ckrv;
if (arenaOpt) {
arena = arenaOpt;
@ -124,16 +100,8 @@ NSSToken_Create
if (!rvToken) {
goto loser;
}
if (parent->module->flags & NSSMODULE_FLAGS_NOT_THREADSAFE) {
/* If the parent module is not threadsafe, create lock to manage
* session within threads.
*/
rvToken->session.lock = PZ_NewLock(nssILockOther);
}
/* Get token information */
NSSTOKEN_ENTER_MONITOR(rvToken);
ckrv = CKAPI(parent)->C_GetTokenInfo(slotID, &tokenInfo);
NSSTOKEN_EXIT_MONITOR(rvToken);
if (ckrv != CKR_OK) {
/* set an error here, eh? */
goto loser;
@ -147,13 +115,9 @@ NSSToken_Create
goto loser;
}
}
/* Open a session handle for the token. */
NSSTOKEN_ENTER_MONITOR(rvToken);
ckrv = CKAPI(parent)->C_OpenSession(slotID, s_ck_readonly_flags,
parent, nss_ck_slot_notify, &session);
NSSTOKEN_EXIT_MONITOR(rvToken);
if (ckrv != CKR_OK) {
/* set an error here, eh? */
/* Open a default session handle for the token. */
session = NSSSlot_CreateSession(parent, arena, PR_TRUE);
if (session == NULL) {
goto loser;
}
/* TODO: seed the RNG here */
@ -167,7 +131,7 @@ NSSToken_Create
rvToken->slot = parent;
rvToken->name = tokenName;
rvToken->ckFlags = tokenInfo.flags;
rvToken->session.handle = session;
rvToken->defaultSession = session;
#ifdef arena_mark_bug_fixed
nssrv = nssArena_Unmark(arena, mark);
if (nssrv != PR_SUCCESS) {
@ -176,6 +140,9 @@ NSSToken_Create
#endif
return rvToken;
loser:
if (session) {
nssSession_Destroy(session);
}
if (newArena) {
nssArena_Destroy(arena);
} else {
@ -185,9 +152,6 @@ loser:
}
#endif
}
if (rvToken && rvToken->session.lock) {
PZ_DestroyLock(rvToken->session.lock);
}
return (NSSToken *)NULL;
}
@ -198,63 +162,164 @@ NSSToken_Destroy
)
{
if (--tok->refCount == 0) {
if (tok->defaultSession) {
nssSession_Destroy(tok->defaultSession);
}
return NSSArena_Destroy(tok->arena);
}
return PR_SUCCESS;
}
NSS_IMPLEMENT PRStatus *
NSSToken_TraverseCertificates
/* This is only used by the Traverse function. If we ditch traversal,
* ditch this.
*/
struct certCallbackStr {
PRStatus (*callback)(NSSCertificate *c, void *arg);
void *arg;
};
/* also symmKeyCallbackStr, pubKeyCallbackStr, etc. */
/*
* This callback examines each matching certificate by passing it to
* a higher-level callback function.
*/
static PRStatus
examine_cert_callback(NSSToken *t, nssSession *session,
CK_OBJECT_HANDLE h, void *arg)
{
PRStatus cbrv;
NSSCertificate *cert;
struct certCallbackStr *ccb = (struct certCallbackStr *)arg;
/* maybe it should be NSSToken_CreateCertificate(token, handle); */
cert = NSSCertificate_CreateFromHandle(h, session, t->slot);
if (!cert) {
goto loser;
}
cbrv = (*ccb->callback)(cert, ccb->arg);
if (cbrv != PR_SUCCESS) {
goto loser;
}
return PR_SUCCESS;
loser:
return PR_FAILURE;
}
static PRStatus
collect_certs_callback(NSSToken *t, nssSession *session,
CK_OBJECT_HANDLE h, void *arg)
{
NSSCertificate *cert;
void *certList; /* nssList soon */
certList = (void *)arg;
cert = NSSCertificate_CreateFromHandle(h, session, t->slot);
if (!cert) {
goto loser;
}
/* XXX add cert to list */
return PR_SUCCESS;
loser:
return PR_FAILURE;
}
static PRStatus *
nsstoken_TraverseObjects
(
NSSToken *tok,
PRStatus (*callback)(NSSCertificate *c, void *arg),
nssSession *session,
CK_ATTRIBUTE_PTR obj_template,
CK_ULONG otsize,
PRStatus (*callback)(NSSToken *t, nssSession *session,
CK_OBJECT_HANDLE h, void *arg),
void *arg
)
{
NSSSlot *slot;
NSSCertificate *cert;
CK_OBJECT_HANDLE object;
CK_ATTRIBUTE cert_template[1];
CK_SESSION_HANDLE session;
CK_ULONG count;
CK_RV ckrv;
PRStatus cbrv;
CK_RV ckrv;
CK_ULONG count;
CK_OBJECT_HANDLE object;
CK_SESSION_HANDLE hSession;
slot = tok->slot;
session = tok->session.handle;
NSS_CK_CERTIFICATE_SEARCH(cert_template);
NSSTOKEN_ENTER_MONITOR(tok);
ckrv = CKAPI(slot)->C_FindObjectsInit(session, cert_template, 1);
hSession = session->handle;
ckrv = CKAPI(slot)->C_FindObjectsInit(hSession, obj_template, otsize);
if (ckrv != CKR_OK) {
goto loser;
}
while (PR_TRUE) {
ckrv = CKAPI(slot)->C_FindObjects(session, &object, 1, &count);
/* this could be sped up by getting 5-10 at a time? */
ckrv = CKAPI(slot)->C_FindObjects(hSession, &object, 1, &count);
if (ckrv != CKR_OK) {
goto loser;
}
if (count == 0) {
break;
}
/* it would be better if the next two were done outside of the
* monitor. but we don't want this function anyway, right?
*/
cert = NSSCertificate_CreateFromHandle(object, slot);
if (!cert) {
goto loser;
}
cbrv = (*callback)(cert, arg);
cbrv = (*callback)(tok, session, object, arg);
if (cbrv != PR_SUCCESS) {
goto loser;
}
}
ckrv = CKAPI(slot)->C_FindObjectsFinal(session);
ckrv = CKAPI(slot)->C_FindObjectsFinal(hSession);
if (ckrv != CKR_OK) {
goto loser;
}
NSSTOKEN_EXIT_MONITOR(tok);
return NULL; /* for now... */
loser:
NSSTOKEN_EXIT_MONITOR(tok);
return NULL; /* for now... */
}
NSS_IMPLEMENT PRStatus *
NSSToken_TraverseCertificates
(
NSSToken *tok,
nssSession *sessionOpt,
PRStatus (*callback)(NSSCertificate *c, void *arg),
void *arg
)
{
PRStatus *rvstack;
nssSession *session;
struct certCallbackStr ccb;
CK_ATTRIBUTE cert_template[] = {
{ CKA_CLASS, g_ck_class_cert.data, g_ck_class_cert.size }
};
CK_ULONG ctsize = sizeof(cert_template) / sizeof(cert_template[0]);
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
ccb.callback = callback;
ccb.arg = arg;
nssSession_EnterMonitor(session);
rvstack = nsstoken_TraverseObjects(tok, session, cert_template, ctsize,
examine_cert_callback, (void *)&ccb);
nssSession_ExitMonitor(session);
return rvstack;
}
NSS_IMPLEMENT NSSCertificate **
NSSToken_FindCertificatesByTemplate
(
NSSToken *tok,
nssSession *sessionOpt,
CK_ATTRIBUTE_PTR cktemplate,
CK_ULONG ctsize
)
{
PRStatus *rvstack;
nssSession *session;
void *certList; /* nssList soon */
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
nssSession_EnterMonitor(session);
rvstack = nsstoken_TraverseObjects(tok, session, cktemplate, ctsize,
collect_certs_callback,
(void *)certList);
nssSession_ExitMonitor(session);
if (rvstack) {
/* examine the errors */
goto loser;
}
/* XXX get an array from the list, return it */
return (NSSCertificate **)NULL;
loser:
/* clean out the list */
return (NSSCertificate **)NULL;
}