Fixed minor card related bugs and enhanced status messages
authorWerner Koch <wk@gnupg.org>
Tue, 18 Oct 2005 17:41:20 +0000 (17:41 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 18 Oct 2005 17:41:20 +0000 (17:41 +0000)
doc/DETAILS
g10/ChangeLog
g10/card-util.c
g10/cardglue.c
g10/cardglue.h
g10/keygen.c

index 8ffd914..df18039 100644 (file)
@@ -330,7 +330,7 @@ more arguments in future versions.
     NEED_PASSPHRASE_SYM <cipher_algo> <s2k_mode> <s2k_hash>
        Issued whenever a passphrase for symmetric encryption is needed.
 
-    NEED_PASSPHRASE_PIN <card_type> <chvno>
+    NEED_PASSPHRASE_PIN <card_type> <chvno> [<serialno>]
         Issued whenever a PIN is requested to unlock a card.
 
     MISSING_PASSPHRASE
@@ -572,10 +572,14 @@ more arguments in future versions.
         This indicates that a signature subpacket was seen.  The
         format is the same as the "spk" record above.
 
-    SC_OP_FAILURE
+    SC_OP_FAILURE [<code>]
         An operation on a smartcard definitely failed.  Currently
         there is no indication of the actual error code, but
         application should be prepared to later accept more arguments.
+        Defined values for CODE are:
+           0 - unspecified error (identically to a missing CODE)
+           1 - canceled
+           2 - bad PIN
 
     SC_OP_SUCCESS
         A smart card operaion succeeded.  This status is only printed
index 272df32..46f0a41 100644 (file)
@@ -1,3 +1,19 @@
+2005-10-18  Werner Koch  <wk@g10code.com>
+
+       * cardglue.c (pin_cb): Fixed prompt for repeated PIN.  Return
+       G10ERR_CANCELED and not just -1.
+       (status_sc_op_failure): New.  Use it where we issue that status.
+       (pin_cb): Append serial number to the need-pin status message.
+       (agent_scd_change_pin): Add arg SERIALNO.  Changed all callers.
+       (agent_scd_writekey): Ditto.
+       (agent_scd_setattr): Ditto.
+       (agent_scd_genkey): Ditto.
+       (agent_scd_checkpin): Pass serialno to the pin_cb.
+
+       * keygen.c (parse_expire_string): Allow setting the expire
+       interval using a "seconds=<n>" syntax.  This is useful for
+       debugging.
+
 2005-10-17  Werner Koch  <wk@g10code.com>
 
        * export.c (do_export_stream): Factored some code out to ...
index 6159512..d9e9d89 100644 (file)
@@ -70,17 +70,16 @@ change_pin (int chvno, int allow_admin)
 
   agent_clear_pin_cache (info.serialno);
 
-  agent_release_card_info (&info);
-
   if (opt.batch)
     {
+      agent_release_card_info (&info);
       log_error (_("can't do this in batch mode\n"));
       return;
     }
 
   if(!allow_admin)
     {
-      rc = agent_scd_change_pin (1);
+      rc = agent_scd_change_pin (1, info.serialno);
       if (rc)
        tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
       else
@@ -109,7 +108,7 @@ change_pin (int chvno, int allow_admin)
        rc = 0;
        if (*answer == '1')
          {
-           rc = agent_scd_change_pin (1);
+           rc = agent_scd_change_pin (1, info.serialno);
            if (rc)
              tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
            else
@@ -120,7 +119,7 @@ change_pin (int chvno, int allow_admin)
          }
        else if (*answer == '2')
          {
-           rc = agent_scd_change_pin (101);
+           rc = agent_scd_change_pin (101, info.serialno);
            if (rc)
              tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc));
            else
@@ -131,7 +130,7 @@ change_pin (int chvno, int allow_admin)
           }
        else if (*answer == '3')
          {
-           rc = agent_scd_change_pin (3);
+           rc = agent_scd_change_pin (3, info.serialno);
            if (rc)
              tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
            else
@@ -145,6 +144,8 @@ change_pin (int chvno, int allow_admin)
            break;
          }
       }
+
+  agent_release_card_info (&info);
 }
 
 static const char *
@@ -561,7 +562,7 @@ change_name (void)
       return -1;
     }
 
-  rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname) );
+  rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname), NULL );
   if (rc)
     log_error ("error setting Name: %s\n", gpg_strerror (rc));
 
@@ -590,7 +591,7 @@ change_url (void)
       return -1;
     }
 
-  rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url) );
+  rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url), NULL );
   if (rc)
     log_error ("error setting URL: %s\n", gpg_strerror (rc));
   xfree (url);
@@ -706,7 +707,7 @@ change_login (const char *args)
       return -1;
     }
 
-  rc = agent_scd_setattr ("LOGIN-DATA", data, n );
+  rc = agent_scd_setattr ("LOGIN-DATA", data, n, NULL );
   if (rc)
     log_error ("error setting login data: %s\n", gpg_strerror (rc));
   xfree (data);
@@ -775,7 +776,7 @@ change_private_do (const char *args, int nr)
       return -1;
     }
 
-  rc = agent_scd_setattr (do_name, data, n );
+  rc = agent_scd_setattr (do_name, data, n, NULL );
   if (rc)
     log_error ("error setting private DO: %s\n", gpg_strerror (rc));
   xfree (data);
@@ -811,7 +812,7 @@ change_lang (void)
       return -1;
     }
 
-  rc = agent_scd_setattr ("DISP-LANG", data, strlen (data) );
+  rc = agent_scd_setattr ("DISP-LANG", data, strlen (data), NULL );
   if (rc)
     log_error ("error setting lang: %s\n", gpg_strerror (rc));
   xfree (data);
@@ -846,7 +847,7 @@ change_sex (void)
       return -1;
     }
      
-  rc = agent_scd_setattr ("DISP-SEX", str, 1 );
+  rc = agent_scd_setattr ("DISP-SEX", str, 1, NULL );
   if (rc)
     log_error ("error setting sex: %s\n", gpg_strerror (rc));
   xfree (data);
@@ -891,7 +892,7 @@ change_cafpr (int fprno)
 
   rc = agent_scd_setattr (fprno==1?"CA-FPR-1":
                           fprno==2?"CA-FPR-2":
-                          fprno==3?"CA-FPR-3":"x", fpr, 20 );
+                          fprno==3?"CA-FPR-3":"x", fpr, 20, NULL );
   if (rc)
     log_error ("error setting cafpr: %s\n", gpg_strerror (rc));
   return rc;
@@ -916,7 +917,7 @@ toggle_forcesig (void)
   newstate = !info.chv1_cached;
   agent_release_card_info (&info);
 
-  rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1);
+  rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1, NULL);
   if (rc)
     log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
 }
@@ -961,7 +962,7 @@ check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1)
     { /* Switch of the forced mode so that during key generation we
          don't get bothered with PIN queries for each
          self-signature. */
-      rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1);
+      rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1, info->serialno);
       if (rc)
         {
           log_error ("error clearing forced signature PIN flag: %s\n",
@@ -989,7 +990,7 @@ restore_forced_chv1 (int *forced_chv1)
 
   if (*forced_chv1)
     { /* Switch back to forced state. */
-      rc = agent_scd_setattr ("CHV-STATUS-1", "", 1);
+      rc = agent_scd_setattr ("CHV-STATUS-1", "", 1, NULL);
       if (rc)
         {
           log_error ("error setting forced signature PIN flag: %s\n",
index 6330b73..c165adc 100644 (file)
@@ -520,6 +520,20 @@ format_cacheid (const char *sn)
   return cacheid;
 }
 
+
+/* If RC is not 0, write an appropriate status message. */
+static void
+status_sc_op_failure (int rc)
+{
+  if (rc == G10ERR_CANCELED)
+    write_status_text (STATUS_SC_OP_FAILURE, "1");
+  else if (rc == G10ERR_BAD_PASS)
+    write_status_text (STATUS_SC_OP_FAILURE, "2");
+  else if (rc)
+    write_status (STATUS_SC_OP_FAILURE);
+}  
+
+
 /* Check that the serial number of the current card (as described by
    APP) matches SERIALNO.  If there is no match and we are not in
    batch mode, present a prompt to insert the desired card.  The
@@ -880,8 +894,18 @@ pin_cb (void *opaque, const char *info, char **retstr)
 
  again:
   if (is_status_enabled())
-    write_status_text (STATUS_NEED_PASSPHRASE_PIN,
-                       isadmin? "OPENPGP 3" : "OPENPGP 1");
+    {
+      if (parm && parm->sn && *parm->sn)
+        {
+          char *buf = xmalloc ( 10 + strlen (parm->sn) + 1);
+          strcpy (stpcpy (buf, isadmin? "OPENPGP 3 ":"OPENPGP 1 "), parm->sn);
+          write_status_text (STATUS_NEED_PASSPHRASE_PIN, buf);
+          xfree (buf);
+        }
+      else  
+        write_status_text (STATUS_NEED_PASSPHRASE_PIN,
+                           isadmin? "OPENPGP 3" : "OPENPGP 1");
+    }
 
   value = ask_passphrase (info, again_text,
                           newpin && isadmin? "passphrase.adminpin.new.ask" :
@@ -898,7 +922,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
   cacheid = NULL;
   again_text = NULL;
   if (!value && canceled)
-    return -1;
+    return G10ERR_CANCELED;
   else if (!value)
     return G10ERR_GENERAL;
 
@@ -906,16 +930,17 @@ pin_cb (void *opaque, const char *info, char **retstr)
     {
       char *value2;
 
-      value2 = ask_passphrase (info, NULL, NULL,
+      value2 = ask_passphrase (info, NULL,
                                "passphrase.pin.repeat", 
                                _("Repeat this PIN: "),
-                              &canceled);
-      if (!value && canceled)
+                               NULL,
+                               &canceled);
+      if (!value2 && canceled)
         {
           xfree (value);
-          return -1;
+          return G10ERR_CANCELED;
         }
-      else if (!value)
+      else if (!value2)
         {
           xfree (value);
           return G10ERR_GENERAL;
@@ -940,10 +965,15 @@ pin_cb (void *opaque, const char *info, char **retstr)
 /* Send a SETATTR command to the SCdaemon. */
 int 
 agent_scd_setattr (const char *name,
-                   const unsigned char *value, size_t valuelen)
+                   const unsigned char *value, size_t valuelen,
+                   const char *serialno)
 {
   app_t app;
   int rc;
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
 
   app = current_app? current_app : open_card ();
   if (!app)
@@ -981,11 +1011,10 @@ agent_scd_setattr (const char *name,
     }
   else
     {
-      rc = app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
+      rc = app->fnc.setattr (app, name, pin_cb, &parm, value, valuelen);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
@@ -1003,11 +1032,17 @@ inq_writekey_parms (void *opaque, const char *keyword)
 
 /* Send a WRITEKEY command to the SCdaemon. */
 int 
-agent_scd_writekey (int keyno, const unsigned char *keydata, size_t keydatalen)
+agent_scd_writekey (int keyno, const char *serialno,
+                    const unsigned char *keydata, size_t keydatalen)
 {
   app_t app;
   int rc;
   char line[ASSUAN_LINELENGTH];
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
+
   app = current_app? current_app : open_card ();
   if (!app)
     return gpg_error (GPG_ERR_CARD);
@@ -1032,12 +1067,11 @@ agent_scd_writekey (int keyno, const unsigned char *keydata, size_t keydatalen)
       snprintf (line, DIM(line)-1, "OPENPGP.%d", keyno);
       line[DIM(line)-1] = 0;
       rc = app->fnc.writekey (app, NULL, line, 0x0001,
-                              pin_cb, NULL,
+                              pin_cb, &parm,
                               keydata, keydatalen);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
@@ -1097,12 +1131,17 @@ genkey_status_cb (void *opaque, const char *line)
 
 /* Send a GENKEY command to the SCdaemon. */
 int 
-agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
+agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
+                  const char *serialno)
 {
   app_t app;
   char line[ASSUAN_LINELENGTH];
   struct ctrl_ctx_s ctrl;
   int rc;
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
 
   app = current_app? current_app : open_card ();
   if (!app)
@@ -1127,11 +1166,10 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
       ctrl.status_cb_arg = info;
       rc = app->fnc.genkey (app, &ctrl, line,
                             force? 1:0,
-                            pin_cb, NULL);
+                            pin_cb, &parm);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
@@ -1213,7 +1251,7 @@ agent_scd_pksign (const char *serialno, int hashalgo,
 
   if (rc)
     {
-      write_status (STATUS_SC_OP_FAILURE);
+      status_sc_op_failure (rc);
       if (!app->assuan_ctx)
         agent_clear_pin_cache (serialno);
     }
@@ -1287,20 +1325,26 @@ agent_scd_pkdecrypt (const char *serialno,
 
   if (rc)
     {
-      write_status (STATUS_SC_OP_FAILURE);
+      status_sc_op_failure (rc);
       if (!app->assuan_ctx)
         agent_clear_pin_cache (serialno);
     }
   return rc;
 }
 
-/* Change the PIN of an OpenPGP card or reset the retry counter. */
+/* Change the PIN of an OpenPGP card or reset the retry
+   counter. SERIALNO may be NULL or a hex string finally passed to the
+   passphrase callback. */
 int 
-agent_scd_change_pin (int chvno)
+agent_scd_change_pin (int chvno, const char *serialno)
 {
   app_t app;
   int reset = 0;
   int rc;
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
 
   reset = (chvno >= 100);
   chvno %= 100;
@@ -1326,11 +1370,10 @@ agent_scd_change_pin (int chvno)
 
       sprintf (chvnostr, "%d", chvno);
       rc = app->fnc.change_pin (app, NULL, chvnostr, reset,
-                                pin_cb, NULL);
+                                pin_cb, &parm);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
@@ -1342,6 +1385,10 @@ agent_scd_checkpin (const char *serialnobuf)
 {
   app_t app;
   int rc;
+  struct pincb_parm_s parm;
+
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialnobuf;
 
   app = current_app? current_app : open_card ();
   if (!app)
@@ -1360,11 +1407,10 @@ agent_scd_checkpin (const char *serialnobuf)
     }
   else
     {
-      rc = app->fnc.check_pin (app, serialnobuf, pin_cb, NULL);
+      rc = app->fnc.check_pin (app, serialnobuf, pin_cb, &parm);
     }
 
-  if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+  status_sc_op_failure (rc);
   return rc;
 }
 
index 5699fe9..b1f2811 100644 (file)
@@ -82,7 +82,7 @@ typedef struct ctrl_ctx_s *ctrl_t;
 
 #define GPG_ERR_GENERAL           G10ERR_GENERAL
 #define GPG_ERR_BAD_PIN           G10ERR_BAD_PASS
-#define GPG_ERR_BAD_KEy           G10ERR_BAD_KEY
+#define GPG_ERR_BAD_KEY           G10ERR_BAD_KEY
 #define GPG_ERR_CARD              G10ERR_GENERAL
 #define GPG_ERR_EEXIST            G10ERR_FILE_EXISTS
 #define GPG_ERR_ENOMEM            G10ERR_RESOURCE_LIMIT
@@ -175,14 +175,16 @@ int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
 
 /* Send a SETATTR command to the SCdaemon. */
 int agent_scd_setattr (const char *name,
-                       const unsigned char *value, size_t valuelen);
+                       const unsigned char *value, size_t valuelen,
+                       const char *serialno);
 
 /* Send a WRITEKEY command to the SCdaemon. */
-int agent_scd_writekey (int keyno,
+int agent_scd_writekey (int keyno, const char *serialno,
                         const unsigned char *keydata, size_t keydatalen);
 
 /* Send a GENKEY command to the SCdaemon. */
-int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force);
+int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
+                      const char *serialno);
 
 /* Send a PKSIGN command to the SCdaemon. */
 int agent_scd_pksign (const char *keyid, int hashalgo,
@@ -195,7 +197,7 @@ int agent_scd_pkdecrypt (const char *serialno,
                          unsigned char **r_buf, size_t *r_buflen);
 
 /* Change the PIN of an OpenPGP card or reset the retry counter. */
-int agent_scd_change_pin (int chvno);
+int agent_scd_change_pin (int chvno, const char *serialno);
 
 /* Send a CHECKPIN command. */
 int agent_scd_checkpin (const char *serialnobuf);
index ae1ac63..d2348c0 100644 (file)
@@ -1492,6 +1492,8 @@ parse_expire_string( const char *string )
 
     if( !*string )
       seconds = 0;
+    else if ( !strncmp (string, "seconds=", 8) )
+      seconds = atoi (string+8);
     else if( (abs_date = scan_isodatestr(string)) && abs_date > curtime )
       seconds = abs_date - curtime;
     else if( (mult=check_valid_days(string)) )
@@ -3274,8 +3276,8 @@ gen_card_key (int algo, int keyno, int is_primary,
 
   assert (algo == PUBKEY_ALGO_RSA);
   
-
-  rc = agent_scd_genkey (&info, keyno, 1);
+  /* Fixme: We don't have the serialnumber available, thus passing NULL. */
+  rc = agent_scd_genkey (&info, keyno, 1, NULL);
 /*    if (gpg_err_code (rc) == GPG_ERR_EEXIST) */
 /*      { */
 /*        tty_printf ("\n"); */
@@ -3550,7 +3552,9 @@ save_unprotected_key_to_card (PKT_secret_key *sk, int keyno)
   sprintf (numbuf, "%lu:", (unsigned long)strlen (numbuf2));
   p = stpcpy (stpcpy (stpcpy (p, numbuf), numbuf2), "))");
 
-  rc = agent_scd_writekey (keyno, sexp, p - sexp);
+  /* Fixme: Unfortunately we don't have the serialnumber available -
+     thus we can't pass it down to the agent. */ 
+  rc = agent_scd_writekey (keyno, NULL, sexp, p - sexp);
 
  leave:
   xfree (sexp);