andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: #ifndef PKIT_H andre@0: #include "pkit.h" andre@0: #endif /* PKIT_H */ andre@0: andre@0: #ifndef DEVM_H andre@0: #include "devm.h" andre@0: #endif /* DEVM_H */ andre@0: andre@0: #include "pki3hack.h" andre@0: #include "dev3hack.h" andre@0: #include "pkim.h" andre@0: andre@0: #ifndef BASE_H andre@0: #include "base.h" andre@0: #endif /* BASE_H */ andre@0: andre@0: #include "pk11func.h" andre@0: #include "secmodti.h" andre@0: #include "secerr.h" andre@0: andre@0: NSS_IMPLEMENT nssSession * andre@0: nssSession_ImportNSS3Session(NSSArena *arenaOpt, andre@0: CK_SESSION_HANDLE session, andre@0: PZLock *lock, PRBool rw) andre@0: { andre@0: nssSession *rvSession = NULL; andre@0: if (session != CK_INVALID_SESSION) { andre@0: rvSession = nss_ZNEW(arenaOpt, nssSession); andre@0: if (rvSession) { andre@0: rvSession->handle = session; andre@0: rvSession->lock = lock; andre@0: rvSession->ownLock = PR_FALSE; andre@0: rvSession->isRW = rw; andre@0: } andre@0: } andre@0: return rvSession; andre@0: } andre@0: andre@0: NSS_IMPLEMENT nssSession * andre@0: nssSlot_CreateSession andre@0: ( andre@0: NSSSlot *slot, andre@0: NSSArena *arenaOpt, andre@0: PRBool readWrite andre@0: ) andre@0: { andre@0: nssSession *rvSession; andre@0: andre@0: if (!readWrite) { andre@0: /* nss3hack version only returns rw swssions */ andre@0: return NULL; andre@0: } andre@0: rvSession = nss_ZNEW(arenaOpt, nssSession); andre@0: if (!rvSession) { andre@0: return (nssSession *)NULL; andre@0: } andre@0: andre@0: rvSession->handle = PK11_GetRWSession(slot->pk11slot); andre@0: if (rvSession->handle == CK_INVALID_HANDLE) { andre@0: nss_ZFreeIf(rvSession); andre@0: return NULL; andre@0: } andre@0: rvSession->isRW = PR_TRUE; andre@0: rvSession->slot = slot; andre@0: /* andre@0: * The session doesn't need its own lock. Here's why. andre@0: * 1. If we are reusing the default RW session of the slot, andre@0: * the slot lock is already locked to protect the session. andre@0: * 2. If the module is not thread safe, the slot (or rather andre@0: * module) lock is already locked. andre@0: * 3. If the module is thread safe and we are using a new andre@0: * session, no higher-level lock has been locked and we andre@0: * would need a lock for the new session. However, the andre@0: * current usage of the session is that it is always andre@0: * used and destroyed within the same function and never andre@0: * shared with another thread. andre@0: * So the session is either already protected by another andre@0: * lock or only used by one thread. andre@0: */ andre@0: rvSession->lock = NULL; andre@0: rvSession->ownLock = PR_FALSE; andre@0: return rvSession; andre@0: } andre@0: andre@0: NSS_IMPLEMENT PRStatus andre@0: nssSession_Destroy andre@0: ( andre@0: nssSession *s andre@0: ) andre@0: { andre@0: CK_RV ckrv = CKR_OK; andre@0: if (s) { andre@0: if (s->isRW) { andre@0: PK11_RestoreROSession(s->slot->pk11slot, s->handle); andre@0: } andre@0: nss_ZFreeIf(s); andre@0: } andre@0: return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; andre@0: } andre@0: andre@0: static NSSSlot * andre@0: nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) andre@0: { andre@0: NSSSlot *rvSlot; andre@0: NSSArena *arena; andre@0: arena = nssArena_Create(); andre@0: if (!arena) { andre@0: return NULL; andre@0: } andre@0: rvSlot = nss_ZNEW(arena, NSSSlot); andre@0: if (!rvSlot) { andre@0: nssArena_Destroy(arena); andre@0: return NULL; andre@0: } andre@0: rvSlot->base.refCount = 1; andre@0: rvSlot->base.lock = PZ_NewLock(nssILockOther); andre@0: rvSlot->base.arena = arena; andre@0: rvSlot->pk11slot = nss3slot; andre@0: rvSlot->epv = nss3slot->functionList; andre@0: rvSlot->slotID = nss3slot->slotID; andre@0: /* Grab the slot name from the PKCS#11 fixed-length buffer */ andre@0: rvSlot->base.name = nssUTF8_Duplicate(nss3slot->slot_name,td->arena); andre@0: rvSlot->lock = (nss3slot->isThreadSafe) ? NULL : nss3slot->sessionLock; andre@0: return rvSlot; andre@0: } andre@0: andre@0: NSSToken * andre@0: nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) andre@0: { andre@0: NSSToken *rvToken; andre@0: NSSArena *arena; andre@0: andre@0: /* Don't create a token object for a disabled slot */ andre@0: if (nss3slot->disabled) { andre@0: PORT_SetError(SEC_ERROR_NO_TOKEN); andre@0: return NULL; andre@0: } andre@0: arena = nssArena_Create(); andre@0: if (!arena) { andre@0: return NULL; andre@0: } andre@0: rvToken = nss_ZNEW(arena, NSSToken); andre@0: if (!rvToken) { andre@0: nssArena_Destroy(arena); andre@0: return NULL; andre@0: } andre@0: rvToken->base.refCount = 1; andre@0: rvToken->base.lock = PZ_NewLock(nssILockOther); andre@0: if (!rvToken->base.lock) { andre@0: nssArena_Destroy(arena); andre@0: return NULL; andre@0: } andre@0: rvToken->base.arena = arena; andre@0: rvToken->pk11slot = nss3slot; andre@0: rvToken->epv = nss3slot->functionList; andre@0: rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, andre@0: nss3slot->session, andre@0: nss3slot->sessionLock, andre@0: nss3slot->defRWSession); andre@0: #if 0 /* we should do this instead of blindly continuing. */ andre@0: if (!rvToken->defaultSession) { andre@0: PORT_SetError(SEC_ERROR_NO_TOKEN); andre@0: goto loser; andre@0: } andre@0: #endif andre@0: if (!PK11_IsInternal(nss3slot) && PK11_IsHW(nss3slot)) { andre@0: rvToken->cache = nssTokenObjectCache_Create(rvToken, andre@0: PR_TRUE, PR_TRUE, PR_TRUE); andre@0: if (!rvToken->cache) andre@0: goto loser; andre@0: } andre@0: rvToken->trustDomain = td; andre@0: /* Grab the token name from the PKCS#11 fixed-length buffer */ andre@0: rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name,td->arena); andre@0: rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot); andre@0: if (!rvToken->slot) { andre@0: goto loser; andre@0: } andre@0: rvToken->slot->token = rvToken; andre@0: if (rvToken->defaultSession) andre@0: rvToken->defaultSession->slot = rvToken->slot; andre@0: return rvToken; andre@0: loser: andre@0: PZ_DestroyLock(rvToken->base.lock); andre@0: nssArena_Destroy(arena); andre@0: return NULL; andre@0: } andre@0: andre@0: NSS_IMPLEMENT void andre@0: nssToken_UpdateName(NSSToken *token) andre@0: { andre@0: if (!token) { andre@0: return; andre@0: } andre@0: token->base.name = nssUTF8_Duplicate(token->pk11slot->token_name,token->base.arena); andre@0: } andre@0: andre@0: NSS_IMPLEMENT PRBool andre@0: nssSlot_IsPermanent andre@0: ( andre@0: NSSSlot *slot andre@0: ) andre@0: { andre@0: return slot->pk11slot->isPerm; andre@0: } andre@0: andre@0: NSS_IMPLEMENT PRBool andre@0: nssSlot_IsFriendly andre@0: ( andre@0: NSSSlot *slot andre@0: ) andre@0: { andre@0: return PK11_IsFriendly(slot->pk11slot); andre@0: } andre@0: andre@0: NSS_IMPLEMENT PRStatus andre@0: nssToken_Refresh(NSSToken *token) andre@0: { andre@0: PK11SlotInfo *nss3slot; andre@0: andre@0: if (!token) { andre@0: return PR_SUCCESS; andre@0: } andre@0: nss3slot = token->pk11slot; andre@0: token->defaultSession = andre@0: nssSession_ImportNSS3Session(token->slot->base.arena, andre@0: nss3slot->session, andre@0: nss3slot->sessionLock, andre@0: nss3slot->defRWSession); andre@0: return token->defaultSession ? PR_SUCCESS : PR_FAILURE; andre@0: } andre@0: andre@0: NSS_IMPLEMENT PRStatus andre@0: nssSlot_Refresh andre@0: ( andre@0: NSSSlot *slot andre@0: ) andre@0: { andre@0: PK11SlotInfo *nss3slot = slot->pk11slot; andre@0: PRBool doit = PR_FALSE; andre@0: if (slot->token && slot->token->base.name[0] == 0) { andre@0: doit = PR_TRUE; andre@0: } andre@0: if (PK11_InitToken(nss3slot, PR_FALSE) != SECSuccess) { andre@0: return PR_FAILURE; andre@0: } andre@0: if (doit) { andre@0: nssTrustDomain_UpdateCachedTokenCerts(slot->token->trustDomain, andre@0: slot->token); andre@0: } andre@0: return nssToken_Refresh(slot->token); andre@0: } andre@0: andre@0: NSS_IMPLEMENT PRStatus andre@0: nssToken_GetTrustOrder andre@0: ( andre@0: NSSToken *tok andre@0: ) andre@0: { andre@0: PK11SlotInfo *slot; andre@0: SECMODModule *module; andre@0: slot = tok->pk11slot; andre@0: module = PK11_GetModule(slot); andre@0: return module->trustOrder; andre@0: } andre@0: andre@0: NSS_IMPLEMENT PRBool andre@0: nssSlot_IsLoggedIn andre@0: ( andre@0: NSSSlot *slot andre@0: ) andre@0: { andre@0: if (!slot->pk11slot->needLogin) { andre@0: return PR_TRUE; andre@0: } andre@0: return PK11_IsLoggedIn(slot->pk11slot, NULL); andre@0: } andre@0: andre@0: andre@0: NSSTrustDomain * andre@0: nssToken_GetTrustDomain(NSSToken *token) andre@0: { andre@0: return token->trustDomain; andre@0: } andre@0: andre@0: NSS_EXTERN PRStatus andre@0: nssTrustDomain_RemoveTokenCertsFromCache andre@0: ( andre@0: NSSTrustDomain *td, andre@0: NSSToken *token andre@0: ); andre@0: andre@0: NSS_IMPLEMENT PRStatus andre@0: nssToken_NotifyCertsNotVisible andre@0: ( andre@0: NSSToken *tok andre@0: ) andre@0: { andre@0: return nssTrustDomain_RemoveTokenCertsFromCache(tok->trustDomain, tok); andre@0: } andre@0: