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 |