* keylist.c (print_card_serialno): New.
authorWerner Koch <wk@gnupg.org>
Tue, 30 Sep 2003 17:34:38 +0000 (17:34 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 30 Sep 2003 17:34:38 +0000 (17:34 +0000)
(list_keyblock_print): Use it here.

* card-util.c (toggle_forcesig): New.
(card_edit): New command "forcesig".

* card-util.c (print_name, print_isoname): Use 0 and not LF fro
the max_n arg of tty_print_utf8_string2.

* call-agent.c (agent_scd_getattr): New.
(learn_status_cb): Release values before assignment so that it can
be used by getattr to update the structure.

* card-util.c (change_pin): Simplified.  We now have only a PIN
and an Admin PIN.

g10/ChangeLog
g10/call-agent.c
g10/call-agent.h
g10/card-util.c
g10/keylist.c

index f812023..0e0e715 100644 (file)
@@ -1,3 +1,21 @@
+2003-09-30  Werner Koch  <wk@gnupg.org>
+
+       * keylist.c (print_card_serialno): New.
+       (list_keyblock_print): Use it here.
+
+       * card-util.c (toggle_forcesig): New.
+       (card_edit): New command "forcesig".
+       
+       * card-util.c (print_name, print_isoname): Use 0 and not LF fro
+       the max_n arg of tty_print_utf8_string2.
+
+       * call-agent.c (agent_scd_getattr): New.
+       (learn_status_cb): Release values before assignment so that it can
+       be used by getattr to update the structure.
+       
+       * card-util.c (change_pin): Simplified.  We now have only a PIN
+       and an Admin PIN.
+
 2003-09-27  Werner Koch  <wk@gnupg.org>
 
        * sign.c (do_sign): Removed disabled testcode.
index 00d124f..f07c01f 100644 (file)
@@ -479,14 +479,17 @@ learn_status_cb (void *opaque, const char *line)
 
   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
     {
+      xfree (parm->serialno);
       parm->serialno = store_serialno (line);
     }
   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
     {
+      xfree (parm->disp_name);
       parm->disp_name = unescape_status_string (line);
     }
   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
     {
+      xfree (parm->disp_lang);
       parm->disp_lang = unescape_status_string (line);
     }
   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
@@ -495,10 +498,12 @@ learn_status_cb (void *opaque, const char *line)
     }
   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
     {
+      xfree (parm->pubkey_url);
       parm->pubkey_url = unescape_status_string (line);
     }
   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
     {
+      xfree (parm->login_data);
       parm->login_data = unescape_status_string (line);
     }
   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
@@ -574,6 +579,34 @@ agent_learn (struct agent_card_info_s *info)
   return map_assuan_err (rc);
 }
 
+/* Call the agent to retrieve a data object.  This function returns
+   the data in the same structure as used by the learn command.  It is
+   allowed to update such a structure using this commmand. */
+int
+agent_scd_getattr (const char *name, struct agent_card_info_s *info)
+{
+  int rc;
+  char line[ASSUAN_LINELENGTH];
+
+  if (!*name)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  /* We assume that NAME does not need escaping. */
+  if (12 + strlen (name) > DIM(line)-1)
+    return gpg_error (GPG_ERR_TOO_LARGE);
+  stpcpy (stpcpy (line, "SCD GETATTR "), name); 
+
+  rc = start_agent ();
+  if (rc)
+    return rc;
+
+  memset (info, 0, sizeof *info);
+  rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
+                        learn_status_cb, info);
+  
+  return map_assuan_err (rc);
+}
+
 \f
 /* Send an setattr command to the SCdaemon. */
 int
@@ -809,12 +842,11 @@ agent_scd_pkdecrypt (const char *serialno,
 
 
 /* Change the PIN of an OpenPGP card or reset the retry counter.
-   CHVNO 1: Change the digital signature PIN
-         2: Change the decryption and authentication PIN
+   CHVNO 1: Change the PIN
+         2: Same as 1
          3: Change the admin PIN
-       101: Set a new digital signature PIN and reset the retry counter
-       102: Set a decryption and authentication PIN
-            and reset the retry counter
+       101: Set a new PIN and reset the retry counter
+       102: Same as 101
  */
 int
 agent_scd_change_pin (int chvno)
index e8abfbc..101db95 100644 (file)
@@ -58,6 +58,9 @@ void agent_release_card_info (struct agent_card_info_s *info);
 /* Return card info. */
 int agent_learn (struct agent_card_info_s *info);
 
+/* Update INFO with the attribute NAME. */
+int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
+
 /* Check whether the secret key for the key identified by HEXKEYGRIP
    is available.  Return 0 for yes or an error code. */
 int agent_havekey (const char *hexkeygrip);
index f42efde..1028cd3 100644 (file)
@@ -44,7 +44,6 @@ change_pin (int chvno)
 {
   struct agent_card_info_s info;
   int rc;
-  int reset_mode = 0;
 
   rc = agent_learn (&info);
   if (rc)
@@ -70,17 +69,11 @@ change_pin (int chvno)
       char *answer;
 
       tty_printf ("\n");
-      tty_printf ("1 - change signature PIN\n"
-                  "2 - change decryption and authentication PIN\n"
-                  "3 - change Admin's PIN\n"
-                  "R - toggle reset retry counter mode\n"
+      tty_printf ("1 - change PIN\n"
+                  "2 - unblock PIN\n"
+                  "3 - change Admin PIN\n"
                   "Q - quit\n");
       tty_printf ("\n");
-      if (reset_mode)
-        {
-          tty_printf ("Reset Retry Counter mode active\n");
-          tty_printf ("\n");
-        }
 
       answer = cpr_get("cardutil.change_pin.menu",_("Your selection? "));
       cpr_kill_prompt();
@@ -88,30 +81,35 @@ change_pin (int chvno)
         continue;
 
       rc = 0;
-      if (reset_mode && *answer == '3')
+      if (*answer == '1')
         {
-          tty_printf ("Sorry, reset of the Admin PIN's retry counter "
-                      "is not possible.\n");
+          rc = agent_scd_change_pin (1);
+          if (rc)
+            tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
+          else
+            tty_printf ("PIN changed.\n");
         }
-      else if (*answer == '1'  || *answer == '2' || *answer == '3')
+      else if (*answer == '2')
         {
-          rc = agent_scd_change_pin (*answer - '0' + (reset_mode?100:0));
+          rc = agent_scd_change_pin (101);
           if (rc)
-            tty_printf ("Error changing/resetting the PIN: %s\n",
-                        gpg_strerror (rc));
+            tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc));
           else
-            tty_printf ("New PIN successfully set.\n");
+            tty_printf ("PIN unblocked and new PIN set.\n");
         }
-      else if (*answer == 'r' || *answer == 'R')
+      else if (*answer == '3')
         {
-          reset_mode = !reset_mode;
+          rc = agent_scd_change_pin (3);
+          if (rc)
+            tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
+          else
+            tty_printf ("PIN changed.\n");
         }
       else if (*answer == 'q' || *answer == 'Q')
         {
           break;
         }
     }
-
 }
 
 static const char *
@@ -175,7 +173,7 @@ print_name (FILE *fp, const char *text, const char *name)
       if (fp)
         print_utf8_string2 (fp, name, strlen (name), '\n');
       else
-        tty_print_utf8_string2 (name, strlen (name), '\n');
+        tty_print_utf8_string2 (name, strlen (name), 0);
     }
   else
     tty_fprintf (fp, _("[not set]"));
@@ -207,7 +205,7 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name)
           else if (fp)
             print_utf8_string2 (fp, given, strlen (given), '\n');
           else
-            tty_print_utf8_string2 (given, strlen (given), '\n');
+            tty_print_utf8_string2 (given, strlen (given), 0);
 
           if (opt.with_colons)
             putc (':', fp);
@@ -220,7 +218,7 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name)
       else if (fp)
         print_utf8_string2 (fp, buf, strlen (buf), '\n');
       else
-        tty_print_utf8_string2 (buf, strlen (buf), '\n');
+        tty_print_utf8_string2 (buf, strlen (buf), 0);
       xfree (buf);
     }
   else
@@ -339,7 +337,7 @@ card_status (FILE *fp)
       print_name (fp, "URL of public key : ", info.pubkey_url);
       print_name (fp, "Login data .......: ", info.login_data);
       tty_fprintf (fp,    "Signature PIN ....: %s\n",
-                   info.chv1_cached? _("cached"): _("not cached"));
+                   info.chv1_cached? _("not forced"): _("forced"));
       tty_fprintf (fp,    "Max. PIN lengths .: %d %d %d\n",
                    info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
       tty_fprintf (fp,    "PIN retry counter : %d %d %d\n",
@@ -542,6 +540,30 @@ change_sex (void)
 }
 
 
+static void
+toggle_forcesig (void)
+{
+  struct agent_card_info_s info;
+  int rc;
+  int newstate;
+
+  memset (&info, 0, sizeof info);
+  rc = agent_scd_getattr ("CHV-STATUS", &info);
+  if (rc)
+    {
+      log_error ("error getting current status: %s\n", gpg_strerror (rc));
+      return;
+    }
+  newstate = !info.chv1_cached;
+  agent_release_card_info (&info);
+
+  rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1);
+  if (rc)
+    log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
+}
+
+
+
 /* Menu to edit all user changeable values on an OpenPGP card.  Only
    Key creation is not handled here. */
 void
@@ -551,7 +573,7 @@ card_edit (STRLIST commands)
     cmdNOP = 0,
     cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG,
     cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX,
-
+    cmdFORCESIG,
     cmdINVCMD
   };
 
@@ -572,9 +594,10 @@ card_edit (STRLIST commands)
     { N_("login") , cmdLOGIN , N_("change the login name") },
     { N_("lang")  , cmdLANG  , N_("change the language preferences") },
     { N_("sex")   , cmdSEX   , N_("change card holder's sex") },
+    { N_("forcesig"), cmdFORCESIG, N_("toggle the signature force PIN flag") },
     { NULL, cmdINVCMD } 
   };
-
   enum cmdids cmd = cmdNOP;
   int have_commands = !!commands;
   int redisplay = 1;
@@ -692,6 +715,10 @@ card_edit (STRLIST commands)
           change_sex ();
           break;
 
+        case cmdFORCESIG:
+          toggle_forcesig ();
+          break;
+
         case cmdQUIT:
           goto leave;
 
index f4344f2..50850de 100644 (file)
@@ -41,6 +41,7 @@
 
 static void list_all(int);
 static void list_one( STRLIST names, int secret);
+static void print_card_serialno (PKT_secret_key *sk);
 
 struct sig_stats
 {
@@ -710,6 +711,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
            if( !any ) {
                if( fpr )
                    print_fingerprint( pk, sk, 0 );
+                print_card_serialno (sk);
                if( opt.with_key_data )
                    print_key_data( pk, keyid );
                any = 1;
@@ -755,6 +757,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
                putchar('\n');
                if( fpr )
                    print_fingerprint( pk, sk, 0 ); /* of the main key */
+                print_card_serialno (sk);
                any = 1;
            }
 
@@ -770,7 +773,10 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
              printf(_(" [expires: %s]"), expirestr_from_sk( sk2 ) );
            putchar('\n');
            if( fpr > 1 )
+              {
                print_fingerprint( NULL, sk2, 0 );
+                print_card_serialno (sk);
+              }
        }
        else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
            PKT_signature *sig = node->pkt->pkt.signature;
@@ -813,6 +819,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
                    putchar('\n');
                if( fpr )
                    print_fingerprint( pk, sk, 0 );
+                print_card_serialno (sk);
                any=1;
            }
 
@@ -1398,6 +1405,40 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
         tty_printf ("\n");
 }
 
+
+/* Print the serial number of an OpenPGP card if available. */
+static void
+print_card_serialno (PKT_secret_key *sk)
+{
+  int i;
+
+  if (!sk)
+    return;
+  if (!sk->is_protected || sk->protect.s2k.mode != 1002) 
+    return; /* Not a card. */
+  if (opt.with_colons)
+    return; /* Format not yet defined. */
+
+  fputs (_("      Card serial no. ="), stdout);
+  putchar (' ');
+  if (sk->protect.ivlen == 16
+      && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) )
+    { /* This is an OpenPGP card. Just print the relevant part. */
+      for (i=8; i < 14; i++)
+        {
+          if (i == 10)
+            putchar (' ');
+          printf ("%02X", sk->protect.iv[i]);
+        }
+    }
+  else
+    { /* Something is wrong: Print all. */
+      for (i=0; i < sk->protect.ivlen; i++)
+        printf ("%02X", sk->protect.iv[i]);
+    }
+  putchar ('\n');
+}
+
 void set_attrib_fd(int fd)
 {
   static int last_fd=-1;