Back to index

lightning-sunbird  0.9+nobinonly
devslot.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: devslot.c,v $ $Revision: 1.22.2.1 $ $Date: 2007/11/16 05:25:07 $";
00039 #endif /* DEBUG */
00040 
00041 #ifndef NSSCKEPV_H
00042 #include "nssckepv.h"
00043 #endif /* NSSCKEPV_H */
00044 
00045 #ifndef DEVM_H
00046 #include "devm.h"
00047 #endif /* DEVM_H */
00048 
00049 #ifndef CKHELPER_H
00050 #include "ckhelper.h"
00051 #endif /* CKHELPER_H */
00052 
00053 /* measured in seconds */
00054 #define NSSSLOT_TOKEN_DELAY_TIME 1
00055 
00056 /* this should track global and per-transaction login information */
00057 
00058 #define NSSSLOT_IS_FRIENDLY(slot) \
00059   (slot->base.flags & NSSSLOT_FLAGS_FRIENDLY)
00060 
00061 /* measured as interval */
00062 static PRIntervalTime s_token_delay_time = 0;
00063 
00064 /* The flags needed to open a read-only session. */
00065 static const CK_FLAGS s_ck_readonly_flags = CKF_SERIAL_SESSION;
00066 
00067 NSS_IMPLEMENT PRStatus
00068 nssSlot_Destroy (
00069   NSSSlot *slot
00070 )
00071 {
00072     if (slot) {
00073        if (PR_AtomicDecrement(&slot->base.refCount) == 0) {
00074            PZ_DestroyLock(slot->base.lock);
00075            return nssArena_Destroy(slot->base.arena);
00076        }
00077     }
00078     return PR_SUCCESS;
00079 }
00080 
00081 void
00082 nssSlot_EnterMonitor(NSSSlot *slot)
00083 {
00084     if (slot->lock) {
00085        PZ_Lock(slot->lock);
00086     }
00087 }
00088 
00089 void
00090 nssSlot_ExitMonitor(NSSSlot *slot)
00091 {
00092     if (slot->lock) {
00093        PZ_Unlock(slot->lock);
00094     }
00095 }
00096 
00097 NSS_IMPLEMENT void
00098 NSSSlot_Destroy (
00099   NSSSlot *slot
00100 )
00101 {
00102     (void)nssSlot_Destroy(slot);
00103 }
00104 
00105 NSS_IMPLEMENT NSSSlot *
00106 nssSlot_AddRef (
00107   NSSSlot *slot
00108 )
00109 {
00110     PR_AtomicIncrement(&slot->base.refCount);
00111     return slot;
00112 }
00113 
00114 NSS_IMPLEMENT NSSUTF8 *
00115 nssSlot_GetName (
00116   NSSSlot *slot
00117 )
00118 {
00119     return slot->base.name;
00120 }
00121 
00122 NSS_IMPLEMENT NSSUTF8 *
00123 nssSlot_GetTokenName (
00124   NSSSlot *slot
00125 )
00126 {
00127     return nssToken_GetName(slot->token);
00128 }
00129 
00130 NSS_IMPLEMENT void
00131 nssSlot_ResetDelay (
00132   NSSSlot *slot
00133 )
00134 {
00135     slot->lastTokenPing = 0;
00136 }
00137 
00138 static PRBool
00139 within_token_delay_period(NSSSlot *slot)
00140 {
00141     PRIntervalTime time, lastTime;
00142     /* Set the delay time for checking the token presence */
00143     if (s_token_delay_time == 0) {
00144        s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME);
00145     }
00146     time = PR_IntervalNow();
00147     lastTime = slot->lastTokenPing;
00148     if ((lastTime) && ((time - lastTime) < s_token_delay_time)) {
00149        return PR_TRUE;
00150     }
00151     slot->lastTokenPing = time;
00152     return PR_FALSE;
00153 }
00154 
00155 NSS_IMPLEMENT PRBool
00156 nssSlot_IsTokenPresent (
00157   NSSSlot *slot
00158 )
00159 {
00160     CK_RV ckrv;
00161     PRStatus nssrv;
00162     /* XXX */
00163     nssSession *session;
00164     CK_SLOT_INFO slotInfo;
00165     void *epv;
00166     /* permanent slots are always present */
00167     if (nssSlot_IsPermanent(slot)) {
00168        return PR_TRUE;
00169     }
00170     /* avoid repeated calls to check token status within set interval */
00171     if (within_token_delay_period(slot)) {
00172        return (PRBool)((slot->ckFlags & CKF_TOKEN_PRESENT) != 0);
00173     }
00174 
00175     /* First obtain the slot info */
00176     epv = slot->epv;
00177     if (!epv) {
00178        return PR_FALSE;
00179     }
00180     nssSlot_EnterMonitor(slot);
00181     ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo);
00182     nssSlot_ExitMonitor(slot);
00183     if (ckrv != CKR_OK) {
00184        slot->token->base.name[0] = 0; /* XXX */
00185        return PR_FALSE;
00186     }
00187     slot->ckFlags = slotInfo.flags;
00188     /* check for the presence of the token */
00189     if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) {
00190        if (!slot->token) {
00191            /* token was ne'er present */
00192            return PR_FALSE;
00193        }
00194        session = nssToken_GetDefaultSession(slot->token);
00195        nssSession_EnterMonitor(session);
00196        /* token is not present */
00197        if (session->handle != CK_INVALID_SESSION) {
00198            /* session is valid, close and invalidate it */
00199            CKAPI(epv)->C_CloseSession(session->handle);
00200            session->handle = CK_INVALID_SESSION;
00201        }
00202        nssSession_ExitMonitor(session);
00203        if (slot->token->base.name[0] != 0) {
00204            /* notify the high-level cache that the token is removed */
00205            slot->token->base.name[0] = 0; /* XXX */
00206            nssToken_NotifyCertsNotVisible(slot->token);
00207        }
00208        slot->token->base.name[0] = 0; /* XXX */
00209        /* clear the token cache */
00210        nssToken_Remove(slot->token);
00211        return PR_FALSE;
00212     }
00213     /* token is present, use the session info to determine if the card
00214      * has been removed and reinserted.
00215      */
00216     session = nssToken_GetDefaultSession(slot->token);
00217     nssSession_EnterMonitor(session);
00218     if (session->handle != CK_INVALID_SESSION) {
00219        CK_SESSION_INFO sessionInfo;
00220        ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo);
00221        if (ckrv != CKR_OK) {
00222            /* session is screwy, close and invalidate it */
00223            CKAPI(epv)->C_CloseSession(session->handle);
00224            session->handle = CK_INVALID_SESSION;
00225        }
00226     }
00227     nssSession_ExitMonitor(session);
00228     /* token not removed, finished */
00229     if (session->handle != CK_INVALID_SESSION) {
00230        return PR_TRUE;
00231     } else {
00232        /* the token has been removed, and reinserted, or the slot contains
00233         * a token it doesn't recognize. invalidate all the old
00234         * information we had on this token, if we can't refresh, clear
00235         * the present flag */
00236        nssToken_NotifyCertsNotVisible(slot->token);
00237        nssToken_Remove(slot->token);
00238        /* token has been removed, need to refresh with new session */
00239        nssrv = nssSlot_Refresh(slot);
00240        if (nssrv != PR_SUCCESS) {
00241            slot->token->base.name[0] = 0; /* XXX */
00242            slot->ckFlags &= ~CKF_TOKEN_PRESENT;
00243            return PR_FALSE;
00244        }
00245        return PR_TRUE;
00246     }
00247 }
00248 
00249 NSS_IMPLEMENT void *
00250 nssSlot_GetCryptokiEPV (
00251   NSSSlot *slot
00252 )
00253 {
00254     return slot->epv;
00255 }
00256 
00257 NSS_IMPLEMENT NSSToken *
00258 nssSlot_GetToken (
00259   NSSSlot *slot
00260 )
00261 {
00262     if (nssSlot_IsTokenPresent(slot)) {
00263        return nssToken_AddRef(slot->token);
00264     }
00265     return (NSSToken *)NULL;
00266 }
00267 
00268 NSS_IMPLEMENT PRStatus
00269 nssSession_EnterMonitor (
00270   nssSession *s
00271 )
00272 {
00273     if (s->lock) PZ_Lock(s->lock);
00274     return PR_SUCCESS;
00275 }
00276 
00277 NSS_IMPLEMENT PRStatus
00278 nssSession_ExitMonitor (
00279   nssSession *s
00280 )
00281 {
00282     return (s->lock) ? PZ_Unlock(s->lock) : PR_SUCCESS;
00283 }
00284 
00285 NSS_EXTERN PRBool
00286 nssSession_IsReadWrite (
00287   nssSession *s
00288 )
00289 {
00290     return s->isRW;
00291 }
00292