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