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 |