| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 | |
| 5 #include "pkcs11.h" | |
| 6 | |
| 7 #ifndef DEVM_H | |
| 8 #include "devm.h" | |
| 9 #endif /* DEVM_H */ | |
| 10 | |
| 11 #ifndef CKHELPER_H | |
| 12 #include "ckhelper.h" | |
| 13 #endif /* CKHELPER_H */ | |
| 14 | |
| 15 #include "pk11pub.h" | |
| 16 | |
| 17 /* measured in seconds */ | |
| 18 #define NSSSLOT_TOKEN_DELAY_TIME 1 | |
| 19 | |
| 20 /* this should track global and per-transaction login information */ | |
| 21 | |
| 22 #define NSSSLOT_IS_FRIENDLY(slot) \ | |
| 23 (slot->base.flags & NSSSLOT_FLAGS_FRIENDLY) | |
| 24 | |
| 25 /* measured as interval */ | |
| 26 static PRIntervalTime s_token_delay_time = 0; | |
| 27 | |
| 28 NSS_IMPLEMENT PRStatus | |
| 29 nssSlot_Destroy( | |
| 30 NSSSlot *slot) | |
| 31 { | |
| 32 if (slot) { | |
| 33 if (PR_ATOMIC_DECREMENT(&slot->base.refCount) == 0) { | |
| 34 PZ_DestroyLock(slot->base.lock); | |
| 35 return nssArena_Destroy(slot->base.arena); | |
| 36 } | |
| 37 } | |
| 38 return PR_SUCCESS; | |
| 39 } | |
| 40 | |
| 41 void | |
| 42 nssSlot_EnterMonitor(NSSSlot *slot) | |
| 43 { | |
| 44 if (slot->lock) { | |
| 45 PZ_Lock(slot->lock); | |
| 46 } | |
| 47 } | |
| 48 | |
| 49 void | |
| 50 nssSlot_ExitMonitor(NSSSlot *slot) | |
| 51 { | |
| 52 if (slot->lock) { | |
| 53 PZ_Unlock(slot->lock); | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 NSS_IMPLEMENT void | |
| 58 NSSSlot_Destroy( | |
| 59 NSSSlot *slot) | |
| 60 { | |
| 61 (void)nssSlot_Destroy(slot); | |
| 62 } | |
| 63 | |
| 64 NSS_IMPLEMENT NSSSlot * | |
| 65 nssSlot_AddRef( | |
| 66 NSSSlot *slot) | |
| 67 { | |
| 68 PR_ATOMIC_INCREMENT(&slot->base.refCount); | |
| 69 return slot; | |
| 70 } | |
| 71 | |
| 72 NSS_IMPLEMENT NSSUTF8 * | |
| 73 nssSlot_GetName( | |
| 74 NSSSlot *slot) | |
| 75 { | |
| 76 return slot->base.name; | |
| 77 } | |
| 78 | |
| 79 NSS_IMPLEMENT NSSUTF8 * | |
| 80 nssSlot_GetTokenName( | |
| 81 NSSSlot *slot) | |
| 82 { | |
| 83 return nssToken_GetName(slot->token); | |
| 84 } | |
| 85 | |
| 86 NSS_IMPLEMENT void | |
| 87 nssSlot_ResetDelay( | |
| 88 NSSSlot *slot) | |
| 89 { | |
| 90 slot->lastTokenPing = 0; | |
| 91 } | |
| 92 | |
| 93 static PRBool | |
| 94 within_token_delay_period(NSSSlot *slot) | |
| 95 { | |
| 96 PRIntervalTime time, lastTime; | |
| 97 /* Set the delay time for checking the token presence */ | |
| 98 if (s_token_delay_time == 0) { | |
| 99 s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME); | |
| 100 } | |
| 101 time = PR_IntervalNow(); | |
| 102 lastTime = slot->lastTokenPing; | |
| 103 if ((lastTime) && ((time - lastTime) < s_token_delay_time)) { | |
| 104 return PR_TRUE; | |
| 105 } | |
| 106 slot->lastTokenPing = time; | |
| 107 return PR_FALSE; | |
| 108 } | |
| 109 | |
| 110 NSS_IMPLEMENT PRBool | |
| 111 nssSlot_IsTokenPresent( | |
| 112 NSSSlot *slot) | |
| 113 { | |
| 114 CK_RV ckrv; | |
| 115 PRStatus nssrv; | |
| 116 /* XXX */ | |
| 117 nssSession *session; | |
| 118 CK_SLOT_INFO slotInfo; | |
| 119 void *epv; | |
| 120 /* permanent slots are always present unless they're disabled */ | |
| 121 if (nssSlot_IsPermanent(slot)) { | |
| 122 return !PK11_IsDisabled(slot->pk11slot); | |
| 123 } | |
| 124 /* avoid repeated calls to check token status within set interval */ | |
| 125 if (within_token_delay_period(slot)) { | |
| 126 return ((slot->ckFlags & CKF_TOKEN_PRESENT) != 0); | |
| 127 } | |
| 128 | |
| 129 /* First obtain the slot info */ | |
| 130 epv = slot->epv; | |
| 131 if (!epv) { | |
| 132 return PR_FALSE; | |
| 133 } | |
| 134 nssSlot_EnterMonitor(slot); | |
| 135 ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo); | |
| 136 nssSlot_ExitMonitor(slot); | |
| 137 if (ckrv != CKR_OK) { | |
| 138 slot->token->base.name[0] = 0; /* XXX */ | |
| 139 return PR_FALSE; | |
| 140 } | |
| 141 slot->ckFlags = slotInfo.flags; | |
| 142 /* check for the presence of the token */ | |
| 143 if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) { | |
| 144 if (!slot->token) { | |
| 145 /* token was never present */ | |
| 146 return PR_FALSE; | |
| 147 } | |
| 148 session = nssToken_GetDefaultSession(slot->token); | |
| 149 if (session) { | |
| 150 nssSession_EnterMonitor(session); | |
| 151 /* token is not present */ | |
| 152 if (session->handle != CK_INVALID_SESSION) { | |
| 153 /* session is valid, close and invalidate it */ | |
| 154 CKAPI(epv) | |
| 155 ->C_CloseSession(session->handle); | |
| 156 session->handle = CK_INVALID_SESSION; | |
| 157 } | |
| 158 nssSession_ExitMonitor(session); | |
| 159 } | |
| 160 if (slot->token->base.name[0] != 0) { | |
| 161 /* notify the high-level cache that the token is removed */ | |
| 162 slot->token->base.name[0] = 0; /* XXX */ | |
| 163 nssToken_NotifyCertsNotVisible(slot->token); | |
| 164 } | |
| 165 slot->token->base.name[0] = 0; /* XXX */ | |
| 166 /* clear the token cache */ | |
| 167 nssToken_Remove(slot->token); | |
| 168 return PR_FALSE; | |
| 169 } | |
| 170 /* token is present, use the session info to determine if the card | |
| 171 * has been removed and reinserted. | |
| 172 */ | |
| 173 session = nssToken_GetDefaultSession(slot->token); | |
| 174 if (session) { | |
| 175 PRBool isPresent = PR_FALSE; | |
| 176 nssSession_EnterMonitor(session); | |
| 177 if (session->handle != CK_INVALID_SESSION) { | |
| 178 CK_SESSION_INFO sessionInfo; | |
| 179 ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo); | |
| 180 if (ckrv != CKR_OK) { | |
| 181 /* session is screwy, close and invalidate it */ | |
| 182 CKAPI(epv) | |
| 183 ->C_CloseSession(session->handle); | |
| 184 session->handle = CK_INVALID_SESSION; | |
| 185 } | |
| 186 } | |
| 187 isPresent = session->handle != CK_INVALID_SESSION; | |
| 188 nssSession_ExitMonitor(session); | |
| 189 /* token not removed, finished */ | |
| 190 if (isPresent) | |
| 191 return PR_TRUE; | |
| 192 } | |
| 193 /* the token has been removed, and reinserted, or the slot contains | |
| 194 * a token it doesn't recognize. invalidate all the old | |
| 195 * information we had on this token, if we can't refresh, clear | |
| 196 * the present flag */ | |
| 197 nssToken_NotifyCertsNotVisible(slot->token); | |
| 198 nssToken_Remove(slot->token); | |
| 199 /* token has been removed, need to refresh with new session */ | |
| 200 nssrv = nssSlot_Refresh(slot); | |
| 201 if (nssrv != PR_SUCCESS) { | |
| 202 slot->token->base.name[0] = 0; /* XXX */ | |
| 203 slot->ckFlags &= ~CKF_TOKEN_PRESENT; | |
| 204 return PR_FALSE; | |
| 205 } | |
| 206 return PR_TRUE; | |
| 207 } | |
| 208 | |
| 209 NSS_IMPLEMENT void * | |
| 210 nssSlot_GetCryptokiEPV( | |
| 211 NSSSlot *slot) | |
| 212 { | |
| 213 return slot->epv; | |
| 214 } | |
| 215 | |
| 216 NSS_IMPLEMENT NSSToken * | |
| 217 nssSlot_GetToken( | |
| 218 NSSSlot *slot) | |
| 219 { | |
| 220 if (nssSlot_IsTokenPresent(slot)) { | |
| 221 return nssToken_AddRef(slot->token); | |
| 222 } | |
| 223 return (NSSToken *)NULL; | |
| 224 } | |
| 225 | |
| 226 NSS_IMPLEMENT PRStatus | |
| 227 nssSession_EnterMonitor( | |
| 228 nssSession *s) | |
| 229 { | |
| 230 if (s->lock) | |
| 231 PZ_Lock(s->lock); | |
| 232 return PR_SUCCESS; | |
| 233 } | |
| 234 | |
| 235 NSS_IMPLEMENT PRStatus | |
| 236 nssSession_ExitMonitor( | |
| 237 nssSession *s) | |
| 238 { | |
| 239 return (s->lock) ? PZ_Unlock(s->lock) : PR_SUCCESS; | |
| 240 } | |
| 241 | |
| 242 NSS_EXTERN PRBool | |
| 243 nssSession_IsReadWrite( | |
| 244 nssSession *s) | |
| 245 { | |
| 246 return s->isRW; | |
| 247 } | |
| OLD | NEW |