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