/security/nss/lib/dev/devslot.c

http://github.com/zpao/v8monkey · C · 296 lines · 209 code · 27 blank · 60 comment · 34 complexity · a8178ff6e269d456b61a0d9f39d9c9b9 MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. #ifdef DEBUG
  37. static const char CVS_ID[] = "@(#) $RCSfile: devslot.c,v $ $Revision: 1.27 $ $Date: 2010/04/03 18:27:30 $";
  38. #endif /* DEBUG */
  39. #include "pkcs11.h"
  40. #ifndef DEVM_H
  41. #include "devm.h"
  42. #endif /* DEVM_H */
  43. #ifndef CKHELPER_H
  44. #include "ckhelper.h"
  45. #endif /* CKHELPER_H */
  46. #include "pk11pub.h"
  47. /* measured in seconds */
  48. #define NSSSLOT_TOKEN_DELAY_TIME 1
  49. /* this should track global and per-transaction login information */
  50. #define NSSSLOT_IS_FRIENDLY(slot) \
  51. (slot->base.flags & NSSSLOT_FLAGS_FRIENDLY)
  52. /* measured as interval */
  53. static PRIntervalTime s_token_delay_time = 0;
  54. /* The flags needed to open a read-only session. */
  55. static const CK_FLAGS s_ck_readonly_flags = CKF_SERIAL_SESSION;
  56. NSS_IMPLEMENT PRStatus
  57. nssSlot_Destroy (
  58. NSSSlot *slot
  59. )
  60. {
  61. if (slot) {
  62. if (PR_ATOMIC_DECREMENT(&slot->base.refCount) == 0) {
  63. PZ_DestroyLock(slot->base.lock);
  64. return nssArena_Destroy(slot->base.arena);
  65. }
  66. }
  67. return PR_SUCCESS;
  68. }
  69. void
  70. nssSlot_EnterMonitor(NSSSlot *slot)
  71. {
  72. if (slot->lock) {
  73. PZ_Lock(slot->lock);
  74. }
  75. }
  76. void
  77. nssSlot_ExitMonitor(NSSSlot *slot)
  78. {
  79. if (slot->lock) {
  80. PZ_Unlock(slot->lock);
  81. }
  82. }
  83. NSS_IMPLEMENT void
  84. NSSSlot_Destroy (
  85. NSSSlot *slot
  86. )
  87. {
  88. (void)nssSlot_Destroy(slot);
  89. }
  90. NSS_IMPLEMENT NSSSlot *
  91. nssSlot_AddRef (
  92. NSSSlot *slot
  93. )
  94. {
  95. PR_ATOMIC_INCREMENT(&slot->base.refCount);
  96. return slot;
  97. }
  98. NSS_IMPLEMENT NSSUTF8 *
  99. nssSlot_GetName (
  100. NSSSlot *slot
  101. )
  102. {
  103. return slot->base.name;
  104. }
  105. NSS_IMPLEMENT NSSUTF8 *
  106. nssSlot_GetTokenName (
  107. NSSSlot *slot
  108. )
  109. {
  110. return nssToken_GetName(slot->token);
  111. }
  112. NSS_IMPLEMENT void
  113. nssSlot_ResetDelay (
  114. NSSSlot *slot
  115. )
  116. {
  117. slot->lastTokenPing = 0;
  118. }
  119. static PRBool
  120. within_token_delay_period(NSSSlot *slot)
  121. {
  122. PRIntervalTime time, lastTime;
  123. /* Set the delay time for checking the token presence */
  124. if (s_token_delay_time == 0) {
  125. s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME);
  126. }
  127. time = PR_IntervalNow();
  128. lastTime = slot->lastTokenPing;
  129. if ((lastTime) && ((time - lastTime) < s_token_delay_time)) {
  130. return PR_TRUE;
  131. }
  132. slot->lastTokenPing = time;
  133. return PR_FALSE;
  134. }
  135. NSS_IMPLEMENT PRBool
  136. nssSlot_IsTokenPresent (
  137. NSSSlot *slot
  138. )
  139. {
  140. CK_RV ckrv;
  141. PRStatus nssrv;
  142. /* XXX */
  143. nssSession *session;
  144. CK_SLOT_INFO slotInfo;
  145. void *epv;
  146. /* permanent slots are always present unless they're disabled */
  147. if (nssSlot_IsPermanent(slot)) {
  148. return !PK11_IsDisabled(slot->pk11slot);
  149. }
  150. /* avoid repeated calls to check token status within set interval */
  151. if (within_token_delay_period(slot)) {
  152. return ((slot->ckFlags & CKF_TOKEN_PRESENT) != 0);
  153. }
  154. /* First obtain the slot info */
  155. epv = slot->epv;
  156. if (!epv) {
  157. return PR_FALSE;
  158. }
  159. nssSlot_EnterMonitor(slot);
  160. ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo);
  161. nssSlot_ExitMonitor(slot);
  162. if (ckrv != CKR_OK) {
  163. slot->token->base.name[0] = 0; /* XXX */
  164. return PR_FALSE;
  165. }
  166. slot->ckFlags = slotInfo.flags;
  167. /* check for the presence of the token */
  168. if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) {
  169. if (!slot->token) {
  170. /* token was never present */
  171. return PR_FALSE;
  172. }
  173. session = nssToken_GetDefaultSession(slot->token);
  174. if (session) {
  175. nssSession_EnterMonitor(session);
  176. /* token is not present */
  177. if (session->handle != CK_INVALID_SESSION) {
  178. /* session is valid, close and invalidate it */
  179. CKAPI(epv)->C_CloseSession(session->handle);
  180. session->handle = CK_INVALID_SESSION;
  181. }
  182. nssSession_ExitMonitor(session);
  183. }
  184. if (slot->token->base.name[0] != 0) {
  185. /* notify the high-level cache that the token is removed */
  186. slot->token->base.name[0] = 0; /* XXX */
  187. nssToken_NotifyCertsNotVisible(slot->token);
  188. }
  189. slot->token->base.name[0] = 0; /* XXX */
  190. /* clear the token cache */
  191. nssToken_Remove(slot->token);
  192. return PR_FALSE;
  193. }
  194. /* token is present, use the session info to determine if the card
  195. * has been removed and reinserted.
  196. */
  197. session = nssToken_GetDefaultSession(slot->token);
  198. if (session) {
  199. PRBool isPresent = PR_FALSE;
  200. nssSession_EnterMonitor(session);
  201. if (session->handle != CK_INVALID_SESSION) {
  202. CK_SESSION_INFO sessionInfo;
  203. ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo);
  204. if (ckrv != CKR_OK) {
  205. /* session is screwy, close and invalidate it */
  206. CKAPI(epv)->C_CloseSession(session->handle);
  207. session->handle = CK_INVALID_SESSION;
  208. }
  209. }
  210. isPresent = session->handle != CK_INVALID_SESSION;
  211. nssSession_ExitMonitor(session);
  212. /* token not removed, finished */
  213. if (isPresent)
  214. return PR_TRUE;
  215. }
  216. /* the token has been removed, and reinserted, or the slot contains
  217. * a token it doesn't recognize. invalidate all the old
  218. * information we had on this token, if we can't refresh, clear
  219. * the present flag */
  220. nssToken_NotifyCertsNotVisible(slot->token);
  221. nssToken_Remove(slot->token);
  222. /* token has been removed, need to refresh with new session */
  223. nssrv = nssSlot_Refresh(slot);
  224. if (nssrv != PR_SUCCESS) {
  225. slot->token->base.name[0] = 0; /* XXX */
  226. slot->ckFlags &= ~CKF_TOKEN_PRESENT;
  227. return PR_FALSE;
  228. }
  229. return PR_TRUE;
  230. }
  231. NSS_IMPLEMENT void *
  232. nssSlot_GetCryptokiEPV (
  233. NSSSlot *slot
  234. )
  235. {
  236. return slot->epv;
  237. }
  238. NSS_IMPLEMENT NSSToken *
  239. nssSlot_GetToken (
  240. NSSSlot *slot
  241. )
  242. {
  243. if (nssSlot_IsTokenPresent(slot)) {
  244. return nssToken_AddRef(slot->token);
  245. }
  246. return (NSSToken *)NULL;
  247. }
  248. NSS_IMPLEMENT PRStatus
  249. nssSession_EnterMonitor (
  250. nssSession *s
  251. )
  252. {
  253. if (s->lock) PZ_Lock(s->lock);
  254. return PR_SUCCESS;
  255. }
  256. NSS_IMPLEMENT PRStatus
  257. nssSession_ExitMonitor (
  258. nssSession *s
  259. )
  260. {
  261. return (s->lock) ? PZ_Unlock(s->lock) : PR_SUCCESS;
  262. }
  263. NSS_EXTERN PRBool
  264. nssSession_IsReadWrite (
  265. nssSession *s
  266. )
  267. {
  268. return s->isRW;
  269. }