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