* g10.c: New command --card-status.
authorWerner Koch <wk@gnupg.org>
Thu, 24 Jul 2003 09:06:43 +0000 (09:06 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 24 Jul 2003 09:06:43 +0000 (09:06 +0000)
* card-util.c (card_status): New.
* call-agent.c (learn_status_cb): Parse more information.

* keylist.c (print_pubkey_info): Add FP arg for optinal printing
to a stream.  Changed all callers.

g10/ChangeLog
g10/call-agent.c
g10/call-agent.h
g10/card-util.c
g10/delkey.c
g10/g10.c
g10/keygen.c
g10/keylist.c
g10/main.h
g10/revoke.c

index f7fdea7..a7f8d4e 100644 (file)
@@ -1,3 +1,12 @@
+2003-07-24  Werner Koch  <wk@gnupg.org>
+
+       * g10.c: New command --card-status.
+       * card-util.c (card_status): New.
+       * call-agent.c (learn_status_cb): Parse more information.
+
+       * keylist.c (print_pubkey_info): Add FP arg for optinal printing
+       to a stream.  Changed all callers.
+
 2003-07-23  Werner Koch  <wk@gnupg.org>
 
        * keygen.c (generate_keypair): Create an AUTHKEYTYPE entry for cards.
index 3b40cd0..ed4fa90 100644 (file)
@@ -458,7 +458,9 @@ agent_release_card_info (struct agent_card_info_s *info)
 
   xfree (info->serialno); info->serialno = NULL;
   xfree (info->disp_name); info->disp_name = NULL;
+  xfree (info->disp_lang); info->disp_lang = NULL;
   xfree (info->pubkey_url); info->pubkey_url = NULL;
+  xfree (info->login_data); info->login_data = NULL;
   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
 }
 
@@ -468,6 +470,7 @@ learn_status_cb (void *opaque, const char *line)
   struct agent_card_info_s *parm = opaque;
   const char *keyword = line;
   int keywordlen;
+  int i;
 
   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
     ;
@@ -482,10 +485,59 @@ learn_status_cb (void *opaque, const char *line)
     {
       parm->disp_name = unescape_status_string (line);
     }
+  else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
+    {
+      parm->disp_lang = unescape_status_string (line);
+    }
+  else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
+    {
+      parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
+    }
   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
     {
       parm->pubkey_url = unescape_status_string (line);
     }
+  else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
+    {
+      parm->login_data = unescape_status_string (line);
+    }
+  else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
+    {
+      parm->sig_counter = strtoul (line, NULL, 0);
+    }
+  else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
+    {
+      char *p, *buf;
+
+      buf = p = unescape_status_string (line);
+      if (buf)
+        {
+          while (spacep (p))
+            p++;
+          parm->chv1_cached = atoi (p);
+          while (!spacep (p))
+            p++;
+          while (spacep (p))
+            p++;
+          for (i=0; *p && i < 3; i++)
+            {
+              parm->chvmaxlen[i] = atoi (p);
+              while (!spacep (p))
+                p++;
+              while (spacep (p))
+                p++;
+            }
+          for (i=0; *p && i < 3; i++)
+            {
+              parm->chvretry[i] = atoi (p);
+              while (!spacep (p))
+                p++;
+              while (spacep (p))
+                p++;
+            }
+          xfree (buf);
+        }
+    }
   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
     {
       int no = atoi (line);
index 434295e..e8abfbc 100644 (file)
@@ -25,13 +25,22 @@ struct agent_card_info_s {
   int error;         /* private. */
   char *serialno;    /* malloced hex string. */
   char *disp_name;   /* malloced. */
+  char *disp_lang;   /* malloced. */
+  int  disp_sex;     /* 0 = unspecified, 1 = male, 2 = female */
   char *pubkey_url;  /* malloced. */
+  char *login_data;  /* malloced. */
   char fpr1valid;
   char fpr2valid;
   char fpr3valid;
   char fpr1[20];
   char fpr2[20];
   char fpr3[20];
+  unsigned long sig_counter;
+  int chv1_cached;   /* True if a PIN is not required for each
+                        signing.  Note that the gpg-agent might cache
+                        it anyway. */
+  int chvmaxlen[3];  /* Maximum allowed length of a CHV. */
+  int chvretry[3];   /* Allowed retries for the CHV; 0 = blocked. */
 };
 
 struct agent_card_genkey_s {
index 36c432a..9f665cc 100644 (file)
@@ -28,6 +28,8 @@
 #include "gpg.h"
 #include "util.h"
 #include "i18n.h"
+#include "ttyio.h"
+#include "status.h"
 #include "options.h"
 #include "main.h"
 #include "call-agent.h"
@@ -64,7 +66,6 @@ change_pin (int chvno)
   for (;;)
     {
       char *answer;
-      int reread = 0;
 
       tty_printf ("\n");
       tty_printf ("1 - change signature PIN\n"
@@ -111,6 +112,149 @@ change_pin (int chvno)
 
 }
 
+static const char *
+get_manufacturer (unsigned int no)
+{
+  switch (no)
+    {
+    case 0:
+    case 0xffff: return "test card";
+    case 0x0001: return "PPC Card Systems";
+    default: return "unknown";
+    }
+}
+
+
+static void
+print_sha1_fpr (FILE *fp, const unsigned char *fpr)
+{
+  int i;
+
+  if (fpr)
+    {
+      for (i=0; i < 20 ; i+=2, fpr += 2 )
+        {
+          if (i == 10 )
+            putc (' ', fp);
+          fprintf (fp, " %02X%02X", *fpr, fpr[1]);
+        }
+    }
+  else
+    fputs (" [none]", fp);
+  putc ('\n', fp);
+}
+
+
+static void
+print_name (FILE *fp, const char *text, const char *name)
+{
+  fputs (text, fp);
+
+  if (name && *name)
+    print_utf8_string2 (fp, name, strlen (name), '\n');
+  else
+    fputs (_("[not set]"), fp);
+  putc ('\n', fp);
+}
+
+static void
+print_isoname (FILE *fp, const char *text, const char *name)
+{
+  fputs (text, fp);
+
+  if (name && *name)
+    {
+      char *p, *given, *buf = xstrdup (name);
+
+      given = strstr (buf, "<<");
+      for (p=buf; *p; p++)
+        if (*p == '<')
+          *p = ' ';
+      if (given && given[2])
+        {
+          *given = 0;
+          given += 2;
+          print_utf8_string2 (fp, given, strlen (given), '\n');
+          if (*buf)
+            putc (' ', fp);
+        }
+      print_utf8_string2 (fp, buf, strlen (buf), '\n');
+      xfree (buf);
+    }
+  else
+    fputs (_("[not set]"), fp);
+  putc ('\n', fp);
+}
+
+
+/* Print all available information about the current card. */
+void
+card_status (FILE *fp)
+{
+  struct agent_card_info_s info;
+  PKT_public_key *pk = xcalloc (1, sizeof *pk);
+  int rc;
+
+  rc = agent_learn (&info);
+  if (rc)
+    {
+      log_error (_("OpenPGP card not available: %s\n"),
+                  gpg_strerror (rc));
+      return;
+    }
+  
+  fprintf (fp, "Application ID ...: %s\n",
+         info.serialno? info.serialno : "[none]");
+  if (!info.serialno || strncmp (info.serialno, "D27600012401", 12) 
+      || strlen (info.serialno) != 32 )
+    {
+      log_info ("not an OpenPGP card\n");
+      agent_release_card_info (&info);
+    }
+  fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n",
+           info.serialno[12] == '0'?"":info.serialno+12,
+           info.serialno[13],
+           info.serialno[14] == '0'?"":info.serialno+14,
+           info.serialno[15]);
+  fprintf (fp, "Manufacturer .....: %s\n", 
+           get_manufacturer (xtoi_2(info.serialno+16)*256
+                             + xtoi_2 (info.serialno+18)));
+  fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20);
+  
+  print_isoname (fp, "Name of cardholder: ", info.disp_name);
+  print_name (fp, "Language prefs ...: ", info.disp_lang);
+  fprintf (fp,    "Sex ..............: %s\n", info.disp_sex == 1? _("male"):
+           info.disp_sex == 2? _("female") : _("unspecified"));
+  print_name (fp, "URL of public key : ", info.pubkey_url);
+  print_name (fp, "Login data .......: ", info.login_data);
+  fprintf (fp,    "Signature PIN ....: %s\n",
+           info.chv1_cached? _("cached"): _("not cached"));
+  fprintf (fp,    "Max. PIN lengths .: %d %d %d\n",
+           info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
+  fprintf (fp,    "PIN retry counter : %d %d %d\n",
+           info.chvretry[0], info.chvretry[1], info.chvretry[2]);
+  fputs ("Signature key ....:", fp);
+  print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
+  fputs ("Encryption key....:", fp);
+  print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
+  fputs ("Authentication key:", fp);
+  print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
+  fputs ("General key info..: ", fp); 
+  if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20))
+    print_pubkey_info (fp, pk);
+  else
+    fputs ("[none]\n", fp);
+  fprintf (fp,    "Signature counter : %lu\n", info.sig_counter);
+  
+  free_public_key (pk);
+  agent_release_card_info (&info);
+}
+
+
+
+
+
+
 
 
 
index 34a2e1b..6263dec 100644 (file)
@@ -130,7 +130,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
         if( secret )
             print_seckey_info( sk );
         else
-            print_pubkey_info( pk );
+            print_pubkey_info (NULL, pk );
        tty_printf( "\n" );
 
        yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"
index b7ad9d7..2f0a78c 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -128,6 +128,7 @@ enum cmd_and_opt_values { aNull = 0,
     aPipeMode,
     aRebuildKeydbCaches,
     aRefreshKeys,
+    aCardStatus,
     aChangePIN,
 
     oTextmode,
@@ -363,6 +364,7 @@ static ARGPARSE_OPTS opts[] = {
     { aExportSecretSub, "export-secret-subkeys" , 256, "@" },
     { aImport, "import",      256     , N_("import/merge keys")},
     { aFastImport, "fast-import",  256 , "@"},
+    { aCardStatus,  "card-status", 256, N_("print the card status")},
     { aChangePIN,  "change-pin", 256, N_("change a card's PIN")},
 
     { aListPackets, "list-packets",256,N_("list only the sequence of packets")},
@@ -1444,6 +1446,7 @@ main( int argc, char **argv )
           case aPipeMode: set_cmd( &cmd, aPipeMode); break;
           case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break;
 
+          case aCardStatus: set_cmd (&cmd, aCardStatus); break;
           case aChangePIN: set_cmd (&cmd, aChangePIN); break;
 
          case oArmor: opt.armor = 1; opt.no_armor=0; break;
@@ -2346,6 +2349,7 @@ main( int argc, char **argv )
       case aDeArmor:
       case aEnArmor:
       case aFixTrustDB:
+      case aCardStatus:
       case aChangePIN:
        break;
       case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break;
@@ -2867,6 +2871,12 @@ main( int argc, char **argv )
         keydb_rebuild_caches ();
         break;
 
+    case aCardStatus:
+      if (argc)
+        wrong_args ("--card-status");
+      card_status (stdout);
+      break;
+
     case aChangePIN:
       if (!argc)
         change_pin (0);
index e255208..515d486 100644 (file)
@@ -2712,7 +2712,7 @@ show_smartcard (struct agent_card_info_s *info)
   show_sha1_fpr (info->fpr3valid? info->fpr3:NULL);
 
   if (info->fpr1valid && !get_pubkey_byfprint (pk, info->fpr1, 20))
-    print_pubkey_info (pk);
+    print_pubkey_info (NULL, pk);
 
   free_public_key( pk );
 }
index ef2cb56..b5549fb 100644 (file)
@@ -93,25 +93,39 @@ print_seckey_info (PKT_secret_key *sk)
     tty_printf ("\n");   
 }
 
+/* Print information about the public key.  With FP passed as NULL,
+   the tty output interface is used, otherwise output is directted to
+   the given stream. */
 void
-print_pubkey_info (PKT_public_key *pk)
+print_pubkey_info (FILE *fp, PKT_public_key *pk)
 {
   u32 pk_keyid[2];
   size_t n;
   char *p;
 
   keyid_from_pk (pk, pk_keyid);
-  tty_printf ("\npub  %4u%c/%08lX %s   ",
-              nbits_from_pk (pk),
-              pubkey_letter (pk->pubkey_algo),
-              (ulong)pk_keyid[1], datestr_from_pk (pk));
-
+  if (fp)
+    fprintf (fp, "pub  %4u%c/%08lX %s   ",
+             nbits_from_pk (pk),
+             pubkey_letter (pk->pubkey_algo),
+             (ulong)pk_keyid[1], datestr_from_pk (pk));
+  else
+    tty_printf ("\npub  %4u%c/%08lX %s   ",
+                nbits_from_pk (pk),
+                pubkey_letter (pk->pubkey_algo),
+                (ulong)pk_keyid[1], datestr_from_pk (pk));
 
   p = get_user_id (pk_keyid, &n);
-  tty_print_utf8_string (p, n);
+  if (fp)
+    print_utf8_string2 (fp, p, n, '\n');
+  else
+    tty_print_utf8_string (p, n);
   xfree (p);
   
-  tty_printf ("\n\n"); 
+  if (fp)
+    putc ('\n', fp);
+  else
+    tty_printf ("\n\n"); 
 }
 
 /*
index 991c09a..cb81192 100644 (file)
@@ -236,7 +236,7 @@ void dump_attribs(const PKT_user_id *uid,
                  PKT_public_key *pk,PKT_secret_key *sk);
 void set_attrib_fd(int fd);
 void print_seckey_info (PKT_secret_key *sk);
-void print_pubkey_info (PKT_public_key *pk);
+void print_pubkey_info (FILE *fp, PKT_public_key *pk);
 
 /*-- verify.c --*/
 void print_file_status( int status, const char *name, int what );
@@ -256,6 +256,8 @@ void run_in_pipemode (void);
 
 /*-- card-util.c --*/
 void change_pin (int no);
+void card_status (FILE *fp);
+
 
 /*-- signal.c --*/
 void init_signals(void);
index 80e32a3..cf1bfe1 100644 (file)
@@ -264,7 +264,7 @@ gen_desig_revoke( const char *uname )
 
            any = 1;
 
-            print_pubkey_info (pk);
+            print_pubkey_info (NULL, pk);
            tty_printf ("\n");
 
            tty_printf (_("To be revoked by:\n"));