[svn] GnuPG - r4867 - trunk/scd

svn author wk cvs at cvs.gnupg.org
Mon Nov 3 20:09:34 CET 2008


Author: wk
Date: 2008-11-03 20:09:34 +0100 (Mon, 03 Nov 2008)
New Revision: 4867

Modified:
   trunk/scd/ChangeLog
   trunk/scd/app-common.h
   trunk/scd/app.c
   trunk/scd/ccid-driver.c
   trunk/scd/command.c
Log:
Fixed the card removed with cached app bug.  (Famous last fix).


Modified: trunk/scd/ChangeLog
===================================================================
--- trunk/scd/ChangeLog	2008-11-03 10:54:18 UTC (rev 4866)
+++ trunk/scd/ChangeLog	2008-11-03 19:09:34 UTC (rev 4867)
@@ -1,5 +1,20 @@
 2008-11-03  Werner Koch  <wk at g10code.com>
 
+	* app-common.h (app_ctx_s): Remove INITIALIZED.  Make REF_COUNT
+	unsigned. 
+	* app.c (select_application): Remove INITIALIZED.
+	(app_write_learn_status, app_readcert, app_readkey, app_getattr)
+	(app_setattr, app_sign, app_decipher, app_writecert)
+	(app_writekey, app_get_challenge, app_change_pin, app_check_pin):
+	Replace INITIALIZED by REF_COUNT check.
+	(application_notify_card_removed): Rename to ..
+	(application_notify_card_reset): .. this.  Change all callers.
+	* command.c (do_reset): Call application_notify_card_reset after
+	sending a reset.
+	(update_reader_status_file): Add arg SET_CARD_REMOVED.
+	(scd_update_reader_status_file): Pass true for new flag.
+	(do_reset): Pass false for new flag.
+
 	* app.c (app_get_serial_and_stamp): Use bin2hex.
 	* app-help.c (app_help_get_keygrip_string): Ditto.
 	* app-p15.c (send_certinfo, send_keypairinfo, do_getattr): Ditto.

Modified: trunk/scd/app-common.h
===================================================================
--- trunk/scd/app-common.h	2008-11-03 10:54:18 UTC (rev 4866)
+++ trunk/scd/app-common.h	2008-11-03 19:09:34 UTC (rev 4867)
@@ -38,15 +38,14 @@
 struct app_local_s;  /* Defined by all app-*.c.  */
 
 struct app_ctx_s {
-  int initialized;  /* The application has been initialied and the
-                       function pointers may be used.  Note that for
-                       unsupported operations the particular
-                       function pointer is set to NULL */
+  unsigned int ref_count;  /* Number of connections currently using
+                              this application context.  If this is
+                              not 0 the application has been
+                              initialized and the function pointers
+                              may be used.  Note that for unsupported
+                              operations the particular function
+                              pointer is set to NULL */
 
-  int ref_count;    /* Number of connections currently using this
-                       application context.  fixme: We might want to
-                       merg this witghn INITIALIZED above. */
-
   int slot;         /* Used reader. */
 
   /* If this is used by GnuPG 1.4 we need to know the assuan context
@@ -138,7 +137,7 @@
 
 /*-- app.c --*/
 void app_dump_state (void);
-void application_notify_card_removed (int slot);
+void application_notify_card_reset (int slot);
 gpg_error_t check_application_conflict (ctrl_t ctrl, const char *name);
 gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name,
                                 app_t *r_app);

Modified: trunk/scd/app.c
===================================================================
--- trunk/scd/app.c	2008-11-03 10:54:18 UTC (rev 4866)
+++ trunk/scd/app.c	2008-11-03 19:09:34 UTC (rev 4867)
@@ -161,9 +161,9 @@
 }
 
 
-/* This may be called to tell this module about a removed card. */
+/* This may be called to tell this module about a removed or resetted card. */
 void
-application_notify_card_removed (int slot)
+application_notify_card_reset (int slot)
 {
   app_t app;
 
@@ -369,8 +369,8 @@
       return err;
     }
 
-  app->initialized = 1;
   app->ref_count = 1;
+  log_debug ("USING application context (refcount=%u) (new)\n", app->ref_count);
   lock_table[slot].app = app;
   *r_app = app;
   unlock_reader (slot);
@@ -405,7 +405,7 @@
   if (!app)
     return;
 
-  if (app->ref_count < 1)
+  if (!app->ref_count)
     log_bug ("trying to release an already released context\n");
   if (--app->ref_count)
     return;
@@ -500,7 +500,7 @@
 
   if (!app)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.learn_status)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -529,7 +529,7 @@
 
   if (!app)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.readcert)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -561,7 +561,7 @@
 
   if (!app || !keyid || !pk || !pklen)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.readkey)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -582,7 +582,7 @@
 
   if (!app || !name || !*name)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
 
   if (app->apptype && name && !strcmp (name, "APPTYPE"))
@@ -626,7 +626,7 @@
 
   if (!app || !name || !*name || !value)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.setattr)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -652,7 +652,7 @@
 
   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.sign)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -684,7 +684,7 @@
 
   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.auth)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -716,7 +716,7 @@
 
   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.decipher)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -746,7 +746,7 @@
 
   if (!app || !certidstr || !*certidstr || !pincb)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.writecert)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -774,7 +774,7 @@
 
   if (!app || !keyidstr || !*keyidstr || !pincb)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.writekey)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -801,7 +801,7 @@
 
   if (!app || !keynostr || !*keynostr || !pincb)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.genkey)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -827,7 +827,7 @@
 
   if (!app || !nbytes || !buffer)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   err = lock_reader (app->slot);
   if (err)
@@ -849,7 +849,7 @@
 
   if (!app || !chvnostr || !*chvnostr || !pincb)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.change_pin)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -877,7 +877,7 @@
 
   if (!app || !keyidstr || !*keyidstr || !pincb)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (!app->initialized)
+  if (!app->ref_count)
     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
   if (!app->fnc.check_pin)
     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);

Modified: trunk/scd/ccid-driver.c
===================================================================
--- trunk/scd/ccid-driver.c	2008-11-03 10:54:18 UTC (rev 4866)
+++ trunk/scd/ccid-driver.c	2008-11-03 19:09:34 UTC (rev 4867)
@@ -1707,6 +1707,8 @@
 }
 
 
+/* Return the ATR of the card.  This is not a cached value and thus an
+   actual reset is done.  */
 int 
 ccid_get_atr (ccid_driver_t handle,
               unsigned char *atr, size_t maxatrlen, size_t *atrlen)
@@ -1730,7 +1732,6 @@
   if (statusbits == 2)
     return CCID_DRIVER_ERR_NO_CARD;
 
-    
   /* For an inactive and also for an active card, issue the PowerOn
      command to get the ATR.  */
  again:

Modified: trunk/scd/command.c
===================================================================
--- trunk/scd/command.c	2008-11-03 10:54:18 UTC (rev 4866)
+++ trunk/scd/command.c	2008-11-03 19:09:34 UTC (rev 4867)
@@ -81,7 +81,7 @@
                  done.  This is set once to indicate that the status
                  tracking for the slot has been initialized.  */
   unsigned int status;  /* Last status of the slot. */
-  unsigned int changed; /* Last change counter of teh slot. */
+  unsigned int changed; /* Last change counter of the slot. */
 };
 
 
@@ -134,7 +134,7 @@
 
 
 /*-- Local prototypes --*/
-static void update_reader_status_file (void);
+static void update_reader_status_file (int set_card_removed_flag);
 
 
 
@@ -171,7 +171,7 @@
       }
   /* Let the card application layer know about the removal.  */
   if (value)
-    application_notify_card_removed (slot);
+    application_notify_card_reset (slot);
 }
 
 
@@ -256,7 +256,8 @@
 
 
 /* Reset the card and free the application context.  With SEND_RESET
-   set to true actually send a RESET to the reader. */
+   set to true actually send a RESET to the reader; this is the normal
+   way of calling the function.  */
 static void
 do_reset (ctrl_t ctrl, int send_reset)
 {
@@ -265,18 +266,22 @@
   if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
     BUG ();
 
+  /* If there is an active application, release it. */
   if (ctrl->app_ctx)
     {
       release_application (ctrl->app_ctx);
       ctrl->app_ctx = NULL;
     }
 
+  /* If we want a real reset for the card, send the reset APDU and
+     tell the application layer about it.  */
   if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
     {
       if (apdu_reset (slot)) 
         {
           slot_table[slot].reset_failed = 1;
         }
+      application_notify_card_reset (slot);
     }
 
   /* If we hold a lock, unlock now. */
@@ -286,23 +291,23 @@
       log_info ("implicitly unlocking due to RESET\n");
     }
 
-  /* Reset card removed flag for the current reader.  We need to take
-     the lock here so that the ticker thread won't concurrently try to
-     update the file.  Note that the update function will set the card
-     removed flag and we will later reset it - not a particualar nice
-     way of implementing it but it works. */
+  /* Reset the card removed flag for the current reader.  We need to
+     take the lock here so that the ticker thread won't concurrently
+     try to update the file.  Calling update_reader_status_file is
+     required to get hold of the new status of the card in the slot
+     table.  */
   if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
     {
       log_error ("failed to acquire status_fle_update lock\n");
       ctrl->reader_slot = -1;
       return;
     }
-  update_reader_status_file ();
-  update_card_removed (slot, 0);
+  update_reader_status_file (0);  /* Update slot status table.  */
+  update_card_removed (slot, 0);  /* Clear card_removed flag.  */
   if (!pth_mutex_release (&status_file_update_lock))
     log_error ("failed to release status_file_update lock\n");
 
-  /* Do this last, so that update_card_removed does its job.  */
+  /* Do this last, so that the update_card_removed above does its job.  */
   ctrl->reader_slot = -1;
 }
 
@@ -1875,7 +1880,7 @@
         }
     }
 
-  /* Cleanup.  */
+  /* Cleanup.  We don't send an explicit reset to the card.  */
   do_reset (ctrl, 0); 
 
   /* Release the server object.  */
@@ -1951,9 +1956,9 @@
 
 
 /* This is the core of scd_update_reader_status_file but the caller
-   needs to take care of the locking. */
+   needs to take care of the locking.  */
 static void
-update_reader_status_file (void)
+update_reader_status_file (int set_card_removed_flag)
 {
   int idx;
   unsigned int status, changed;
@@ -1990,7 +1995,7 @@
 	  /* FIXME: Should this be IDX instead of ss->slot?  This
 	     depends on how client sessions will associate the reader
 	     status with their session.  */
-          sprintf (templ, "reader_%d.status", ss->slot);
+          snprintf (templ, sizeof templ, "reader_%d.status", ss->slot);
           fname = make_filename (opt.homedir, templ, NULL );
           fp = fopen (fname, "w");
           if (fp)
@@ -2047,7 +2052,7 @@
           /* Set the card removed flag for all current sessions.  We
              will set this on any card change because a reset or
              SERIALNO request must be done in any case.  */
-          if (ss->any)
+          if (ss->any && set_card_removed_flag)
             update_card_removed (idx, 1);
           
           ss->any = 1;
@@ -2090,7 +2095,7 @@
 {
   if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
     return; /* locked - give up. */
-  update_reader_status_file ();
+  update_reader_status_file (1);
   if (!pth_mutex_release (&status_file_update_lock))
     log_error ("failed to release status_file_update lock\n");
 }




More information about the Gnupg-commits mailing list