Bug 1756271 - Remove token member from NSSSlot struct. r=rrelyea
authorJohn M. Schanck <jschanck@mozilla.com>
Wed, 23 Mar 2022 17:51:52 +0000
changeset 16161 55052f78244cb4a39ef2a19aebd19fbface06829
parent 16160 b83ad33acd678c78c91b836ad42310e75cac3361
child 16162 800111fa3bf8225fd45a50cc192a032b62b54fc6
push id4108
push userjschanck@mozilla.com
push dateWed, 23 Mar 2022 17:53:58 +0000
reviewersrrelyea
bugs1756271
Bug 1756271 - Remove token member from NSSSlot struct. r=rrelyea Differential Revision: https://phabricator.services.mozilla.com/D139547
lib/dev/dev.h
lib/dev/devslot.c
lib/dev/devt.h
lib/dev/devtoken.c
lib/pk11wrap/dev3hack.c
--- a/lib/dev/dev.h
+++ b/lib/dev/dev.h
@@ -141,17 +141,16 @@ NSS_EXTERN PRInt32
 nssModule_GetCertOrder(
     NSSModule *module);
 
 /* NSSSlot
  *
  * nssSlot_Destroy
  * nssSlot_AddRef
  * nssSlot_GetName
- * nssSlot_GetTokenName
  * nssSlot_IsTokenPresent
  * nssSlot_IsPermanent
  * nssSlot_IsFriendly
  * nssSlot_IsHardware
  * nssSlot_Refresh
  * nssSlot_GetModule
  * nssSlot_GetToken
  * nssSlot_Login
@@ -171,20 +170,16 @@ nssSlot_AddRef(
 NSS_EXTERN void
 nssSlot_ResetDelay(
     NSSSlot *slot);
 
 NSS_EXTERN NSSUTF8 *
 nssSlot_GetName(
     NSSSlot *slot);
 
-NSS_EXTERN NSSUTF8 *
-nssSlot_GetTokenName(
-    NSSSlot *slot);
-
 NSS_EXTERN NSSModule *
 nssSlot_GetModule(
     NSSSlot *slot);
 
 NSS_EXTERN NSSToken *
 nssSlot_GetToken(
     NSSSlot *slot);
 
--- a/lib/dev/devslot.c
+++ b/lib/dev/devslot.c
@@ -7,17 +7,19 @@
 #ifndef DEVM_H
 #include "devm.h"
 #endif /* DEVM_H */
 
 #ifndef CKHELPER_H
 #include "ckhelper.h"
 #endif /* CKHELPER_H */
 
-#include "pk11pub.h"
+#include "pkim.h"
+#include "dev3hack.h"
+#include "pk11func.h"
 
 /* measured in seconds */
 #define NSSSLOT_TOKEN_DELAY_TIME 1
 
 /* this should track global and per-transaction login information */
 
 #define NSSSLOT_IS_FRIENDLY(slot) \
     (slot->base.flags & NSSSLOT_FLAGS_FRIENDLY)
@@ -74,23 +76,16 @@ nssSlot_AddRef(
 
 NSS_IMPLEMENT NSSUTF8 *
 nssSlot_GetName(
     NSSSlot *slot)
 {
     return slot->base.name;
 }
 
-NSS_IMPLEMENT NSSUTF8 *
-nssSlot_GetTokenName(
-    NSSSlot *slot)
-{
-    return nssToken_GetName(slot->token);
-}
-
 NSS_IMPLEMENT void
 nssSlot_ResetDelay(
     NSSSlot *slot)
 {
     PZ_Lock(slot->isPresentLock);
     slot->lastTokenPingState = nssSlotLastPingState_Reset;
     PZ_Unlock(slot->isPresentLock);
 }
@@ -118,21 +113,23 @@ token_status_checked(const NSSSlot *slot
 }
 
 NSS_IMPLEMENT PRBool
 nssSlot_IsTokenPresent(
     NSSSlot *slot)
 {
     CK_RV ckrv;
     PRStatus nssrv;
+    NSSToken *nssToken = NULL;
     /* XXX */
     nssSession *session;
     CK_SLOT_INFO slotInfo;
     void *epv;
     PRBool isPresent = PR_FALSE;
+    PRBool doUpdateCachedCerts = PR_FALSE;
 
     /* permanent slots are always present unless they're disabled */
     if (nssSlot_IsPermanent(slot)) {
         return !PK11_IsDisabled(slot->pk11slot);
     }
 
     /* avoid repeated calls to check token status within set interval */
     PZ_Lock(slot->isPresentLock);
@@ -164,59 +161,60 @@ nssSlot_IsTokenPresent(
     }
     /* this is the winning thread, block all others until we've determined
      * if the token is present and that it needs initialization. */
     slot->lastTokenPingState = nssSlotLastPingState_Update;
     slot->isPresentThread = PR_GetCurrentThread();
 
     PZ_Unlock(slot->isPresentLock);
 
+    nssToken = PK11Slot_GetNSSToken(slot->pk11slot);
+    if (!nssToken) {
+        isPresent = PR_FALSE;
+        goto done;
+    }
+
     nssSlot_EnterMonitor(slot);
     ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo);
     nssSlot_ExitMonitor(slot);
     if (ckrv != CKR_OK) {
-        slot->token->base.name[0] = 0; /* XXX */
+        nssToken->base.name[0] = 0; /* XXX */
         isPresent = PR_FALSE;
         goto done;
     }
     slot->ckFlags = slotInfo.flags;
     /* check for the presence of the token */
     if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) {
-        if (!slot->token) {
-            /* token was never present */
-            isPresent = PR_FALSE;
-            goto done;
-        }
-        session = nssToken_GetDefaultSession(slot->token);
+        session = nssToken_GetDefaultSession(nssToken);
         if (session) {
             nssSession_EnterMonitor(session);
             /* token is not present */
             if (session->handle != CK_INVALID_HANDLE) {
                 /* session is valid, close and invalidate it */
                 CKAPI(epv)
                     ->C_CloseSession(session->handle);
                 session->handle = CK_INVALID_HANDLE;
             }
             nssSession_ExitMonitor(session);
         }
-        if (slot->token->base.name[0] != 0) {
+        if (nssToken->base.name[0] != 0) {
             /* notify the high-level cache that the token is removed */
-            slot->token->base.name[0] = 0; /* XXX */
-            nssToken_NotifyCertsNotVisible(slot->token);
+            nssToken->base.name[0] = 0; /* XXX */
+            nssToken_NotifyCertsNotVisible(nssToken);
         }
-        slot->token->base.name[0] = 0; /* XXX */
+        nssToken->base.name[0] = 0; /* XXX */
         /* clear the token cache */
-        nssToken_Remove(slot->token);
+        nssToken_Remove(nssToken);
         isPresent = PR_FALSE;
         goto done;
     }
     /* token is present, use the session info to determine if the card
      * has been removed and reinserted.
      */
-    session = nssToken_GetDefaultSession(slot->token);
+    session = nssToken_GetDefaultSession(nssToken);
     if (session) {
         PRBool tokenRemoved;
         nssSession_EnterMonitor(session);
         if (session->handle != CK_INVALID_HANDLE) {
             CK_SESSION_INFO sessionInfo;
             ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo);
             if (ckrv != CKR_OK) {
                 /* session is screwy, close and invalidate it */
@@ -232,27 +230,41 @@ nssSlot_IsTokenPresent(
             isPresent = PR_TRUE;
             goto done;
         }
     }
     /* the token has been removed, and reinserted, or the slot contains
      * a token it doesn't recognize. invalidate all the old
      * information we had on this token, if we can't refresh, clear
      * the present flag */
-    nssToken_NotifyCertsNotVisible(slot->token);
-    nssToken_Remove(slot->token);
-    /* token has been removed, need to refresh with new session */
-    nssrv = nssSlot_Refresh(slot);
-    isPresent = PR_TRUE;
+    nssToken_NotifyCertsNotVisible(nssToken);
+    nssToken_Remove(nssToken);
+    if (nssToken->base.name[0] == 0) {
+        doUpdateCachedCerts = PR_TRUE;
+    }
+    if (PK11_InitToken(slot->pk11slot, PR_FALSE) != SECSuccess) {
+        isPresent = PR_FALSE;
+        goto done;
+    }
+    if (doUpdateCachedCerts) {
+        nssTrustDomain_UpdateCachedTokenCerts(nssToken->trustDomain,
+                                              nssToken);
+    }
+    nssrv = nssToken_Refresh(nssToken);
     if (nssrv != PR_SUCCESS) {
-        slot->token->base.name[0] = 0; /* XXX */
+        nssToken->base.name[0] = 0; /* XXX */
         slot->ckFlags &= ~CKF_TOKEN_PRESENT;
         isPresent = PR_FALSE;
+        goto done;
     }
+    isPresent = PR_TRUE;
 done:
+    if (nssToken) {
+        (void)nssToken_Destroy(nssToken);
+    }
     /* Once we've set up the condition variable,
      * Before returning, it's necessary to:
      *  1) Set the lastTokenPingTime so that any other threads waiting on this
      *     initialization and any future calls within the initialization window
      *     return the just-computed status.
      *  2) Indicate we're complete, waking up all other threads that may still
      *     be waiting on initialization can progress.
      */
@@ -278,22 +290,17 @@ nssSlot_GetCryptokiEPV(
 
 NSS_IMPLEMENT NSSToken *
 nssSlot_GetToken(
     NSSSlot *slot)
 {
     NSSToken *rvToken = NULL;
 
     if (nssSlot_IsTokenPresent(slot)) {
-        /* Even if a token should be present, check `slot->token` too as it
-         * might be gone already. This would happen mostly on shutdown. */
-        nssSlot_EnterMonitor(slot);
-        if (slot->token)
-            rvToken = nssToken_AddRef(slot->token);
-        nssSlot_ExitMonitor(slot);
+        rvToken = PK11Slot_GetNSSToken(slot->pk11slot);
     }
 
     return rvToken;
 }
 
 NSS_IMPLEMENT PRStatus
 nssSession_EnterMonitor(
     nssSession *s)
--- a/lib/dev/devt.h
+++ b/lib/dev/devt.h
@@ -76,17 +76,16 @@ typedef enum {
                                       * our cache */
     nssSlotLastPingState_Update = 1, /* we are updating the lastTokenPingTime */
     nssSlotLastPingState_Valid = 2,  /* lastTokenPingTime is valid */
 } nssSlotLastPingState;
 
 struct NSSSlotStr {
     struct nssDeviceBaseStr base;
     NSSModule *module; /* Parent */
-    NSSToken *token;   /* Peer */
     CK_SLOT_ID slotID;
     CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */
     struct nssSlotAuthInfoStr authInfo;
     PRIntervalTime lastTokenPingTime;
     nssSlotLastPingState lastTokenPingState;
     PZLock *lock;
     void *epv;
     PK11SlotInfo *pk11slot;
--- a/lib/dev/devtoken.c
+++ b/lib/dev/devtoken.c
@@ -27,23 +27,16 @@ NSS_IMPLEMENT PRStatus
 nssToken_Destroy(
     NSSToken *tok)
 {
     if (tok) {
         if (PR_ATOMIC_DECREMENT(&tok->base.refCount) == 0) {
             PK11_FreeSlot(tok->pk11slot);
             PZ_DestroyLock(tok->base.lock);
             nssTokenObjectCache_Destroy(tok->cache);
-
-            /* We're going away, let the nssSlot know in case it's held
-             * alive by someone else. Usually we should hold the last ref. */
-            nssSlot_EnterMonitor(tok->slot);
-            tok->slot->token = NULL;
-            nssSlot_ExitMonitor(tok->slot);
-
             (void)nssSlot_Destroy(tok->slot);
             return nssArena_Destroy(tok->base.arena);
         }
     }
     return PR_SUCCESS;
 }
 
 NSS_IMPLEMENT void
--- a/lib/pk11wrap/dev3hack.c
+++ b/lib/pk11wrap/dev3hack.c
@@ -174,17 +174,16 @@ nssToken_CreateFromPK11SlotInfo(NSSTrust
     }
     rvToken->trustDomain = td;
     /* Grab the token name from the PKCS#11 fixed-length buffer */
     rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name, td->arena);
     rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot);
     if (!rvToken->slot) {
         goto loser;
     }
-    rvToken->slot->token = rvToken;
     if (rvToken->defaultSession)
         rvToken->defaultSession->slot = rvToken->slot;
     return rvToken;
 loser:
     PZ_DestroyLock(rvToken->base.lock);
     nssArena_Destroy(arena);
     return NULL;
 }
@@ -223,34 +222,16 @@ nssToken_Refresh(NSSToken *token)
         nssSession_ImportNSS3Session(token->slot->base.arena,
                                      nss3slot->session,
                                      nss3slot->sessionLock,
                                      nss3slot->defRWSession);
     return token->defaultSession ? PR_SUCCESS : PR_FAILURE;
 }
 
 NSS_IMPLEMENT PRStatus
-nssSlot_Refresh(NSSSlot *slot)
-{
-    PK11SlotInfo *nss3slot = slot->pk11slot;
-    PRBool doit = PR_FALSE;
-    if (slot->token && slot->token->base.name[0] == 0) {
-        doit = PR_TRUE;
-    }
-    if (PK11_InitToken(nss3slot, PR_FALSE) != SECSuccess) {
-        return PR_FAILURE;
-    }
-    if (doit) {
-        nssTrustDomain_UpdateCachedTokenCerts(slot->token->trustDomain,
-                                              slot->token);
-    }
-    return nssToken_Refresh(slot->token);
-}
-
-NSS_IMPLEMENT PRStatus
 nssToken_GetTrustOrder(NSSToken *tok)
 {
     PK11SlotInfo *slot;
     SECMODModule *module;
     slot = tok->pk11slot;
     module = PK11_GetModule(slot);
     return module->trustOrder;
 }